feat: secure frontend and provider ingress

This commit is contained in:
Codex
2026-05-04 11:40:56 +00:00
parent caa80ee5e7
commit 8726611b6f
25 changed files with 1491 additions and 450 deletions
+32 -13
View File
@@ -15,6 +15,7 @@ import {
interface RuntimeConfig {
port: number;
providerPort: number;
databaseUrl: string;
providerToken: string;
heartbeatTimeoutMs: number;
@@ -62,6 +63,7 @@ function readNumberEnv(name: string): number {
function readConfig(): RuntimeConfig {
return {
port: readNumberEnv("PORT"),
providerPort: readNumberEnv("PROVIDER_PORT"),
databaseUrl: requiredEnv("DATABASE_URL"),
providerToken: requiredEnv("PROVIDER_TOKEN"),
heartbeatTimeoutMs: readNumberEnv("HEARTBEAT_TIMEOUT_MS"),
@@ -408,20 +410,10 @@ async function dispatchTask(req: Request): Promise<Response> {
return jsonResponse({ ok: true, taskId, status: "dispatched", providerOnline: true });
}
async function route(req: Request, server: Server<WsData>): Promise<Response | undefined> {
async function route(req: Request): Promise<Response> {
const url = new URL(req.url);
if (req.method === "OPTIONS") return jsonResponse({ ok: true });
if (url.pathname === "/ws/provider") {
const token = url.searchParams.get("token") ?? req.headers.get("x-provider-token");
if (token !== config.providerToken) {
await recordEvent("provider_auth_failed", "unknown", { remote: req.headers.get("x-forwarded-for") ?? null });
return jsonResponse({ ok: false, error: "invalid provider token" }, 401);
}
const upgraded = server.upgrade(req, { data: {} satisfies WsData });
return upgraded ? undefined : jsonResponse({ ok: false, error: "websocket upgrade failed" }, 400);
}
try {
if (url.pathname === "/" || url.pathname === "/health") {
return jsonResponse({ ok: true, service: "unidesk-core", dbReady, startedAt: serviceStartedAt.toISOString() });
@@ -443,6 +435,23 @@ async function route(req: Request, server: Server<WsData>): Promise<Response | u
}
}
async function providerRoute(req: Request, server: Server<WsData>): Promise<Response | undefined> {
const url = new URL(req.url);
if (url.pathname === "/" || url.pathname === "/health") {
return jsonResponse({ ok: true, service: "unidesk-provider-ingress", activeSocketCount: activeProviders.size });
}
if (url.pathname !== "/ws/provider") {
return jsonResponse({ ok: false, error: "provider ingress only accepts /ws/provider", path: url.pathname }, 404);
}
const token = url.searchParams.get("token") ?? req.headers.get("x-provider-token");
if (token !== config.providerToken) {
await recordEvent("provider_auth_failed", "unknown", { remote: req.headers.get("x-forwarded-for") ?? null });
return jsonResponse({ ok: false, error: "invalid provider token" }, 401);
}
const upgraded = server.upgrade(req, { data: {} satisfies WsData });
return upgraded ? undefined : jsonResponse({ ok: false, error: "websocket upgrade failed" }, 400);
}
function readLimit(url: URL, defaultLimit: number): number {
const raw = url.searchParams.get("limit");
if (raw === null) return defaultLimit;
@@ -453,10 +462,16 @@ function readLimit(url: URL, defaultLimit: number): number {
await initDatabaseWithRetry();
const server = Bun.serve<WsData>({
const apiServer = Bun.serve<WsData>({
port: config.port,
hostname: "0.0.0.0",
fetch: route,
});
const providerServer = Bun.serve<WsData>({
port: config.providerPort,
hostname: "0.0.0.0",
fetch: providerRoute,
websocket: {
open(ws) {
logger("info", "provider_socket_open", { remoteAddress: ws.remoteAddress });
@@ -481,4 +496,8 @@ setInterval(() => {
markStaleProvidersOffline().catch((error) => logger("error", "heartbeat_sweep_failed", { error: errorToJson(error) }));
}, 10_000);
logger("info", "server_listening", { url: `http://0.0.0.0:${server.port}`, logFile: config.logFile });
logger("info", "server_listening", {
apiUrl: `http://0.0.0.0:${apiServer.port}`,
providerIngressUrl: `ws://0.0.0.0:${providerServer.port}/ws/provider`,
logFile: config.logFile,
});