import type { Env } from "./bindings.js"; import { withApprovedDeviceApiControls, withAuthenticatedApiControls, withPublicApiControls, } from "./api_controls.js"; import { AccountDeletionPersistenceError, AccountDeletionRequestError, accountDeletionDocument, } from "./account_deletion.js"; import { handleBetterAuthRoute } from "./better_auth.js"; import { DevicePermissionError, DevicePersistenceError, DeviceSchemaError, approveDeviceDocument, deviceListDocument, registerDeviceDocument, revokeDeviceDocument, } from "./devices.js"; import { PluginRegistrySchemaError, parsePluginRegistryDocument, pluginCatalogDocument, pluginDetailsDocument, pluginPackageDocument, pluginRegistryId, pluginRegistryKvKey, } from "./plugin_registry.js"; import { ReleaseManifestSchemaError, ReleaseSignatureQueryError, parseReleaseManifestDocument, parseReleaseSignatureQuery, releaseManifestKvKey, releaseSignatureDocument, } from "./release_manifests.js"; import { SigningKeysSchemaError, parsePublicSigningKeysDocument, publicSigningKeysKvKey, } from "./signing_keys.js"; import { handleSyncRoute } from "./sync_routes.js"; import { TelemetrySchemaError, telemetryEventAcceptedDocument, } from "./telemetry.js"; import { jsonResponse } from "./responses.js"; export default { fetch(request: Request, env: Env): Promise { return handleRequest(request, env); }, }; export async function handleRequest(request: Request, env: Env): Promise { const url = new URL(request.url); if (url.pathname === "/api/auth" || url.pathname.startsWith("/api/auth/")) { return handleBetterAuthRoute(request, env); } if (url.pathname === "/api/devices") { return withAuthenticatedApiControls(request, env, "devices.list", ["GET"], async (context) => { try { return jsonResponse(await deviceListDocument(env, context), 200, { "Cache-Control": "no-store", }); } catch (error) { if (error instanceof DeviceSchemaError) { return jsonResponse({ error: "devices_invalid" }, 500, { "Cache-Control": "no-store" }); } throw error; } }); } if (url.pathname === "/api/devices/register") { return withAuthenticatedApiControls( request, env, "devices.register", ["POST"], async (context) => { try { return jsonResponse(await registerDeviceDocument(request, env, context), 201, { "Cache-Control": "no-store", }); } catch (error) { if (error instanceof DevicePermissionError) { return jsonResponse( { error: "device_context_mismatch" }, 403, { "Cache-Control": "no-store" }, ); } if (error instanceof DeviceSchemaError) { return jsonResponse( { error: "invalid_device_registration" }, 400, { "Cache-Control": "no-store" }, ); } if (error instanceof DevicePersistenceError) { return jsonResponse( { error: "device_registration_failed" }, 500, { "Cache-Control": "no-store" }, ); } throw error; } }, ); } if (url.pathname === "/api/devices/approve") { return withAuthenticatedApiControls( request, env, "devices.approve", ["POST"], async (context) => { try { return jsonResponse(await approveDeviceDocument(request, env, context), 200, { "Cache-Control": "no-store", }); } catch (error) { if (error instanceof DevicePermissionError) { return jsonResponse( { error: "device_approval_forbidden" }, 403, { "Cache-Control": "no-store" }, ); } if (error instanceof DeviceSchemaError) { return jsonResponse( { error: "invalid_device_approval" }, 400, { "Cache-Control": "no-store" }, ); } if (error instanceof DevicePersistenceError) { return jsonResponse( { error: "device_approval_failed" }, 500, { "Cache-Control": "no-store" }, ); } throw error; } }, ); } if (url.pathname === "/api/devices/revoke") { return withAuthenticatedApiControls( request, env, "devices.revoke", ["POST"], async (context) => { try { return jsonResponse(await revokeDeviceDocument(request, env, context), 200, { "Cache-Control": "no-store", }); } catch (error) { if (error instanceof DevicePermissionError) { return jsonResponse( { error: "device_revocation_forbidden" }, 403, { "Cache-Control": "no-store" }, ); } if (error instanceof DeviceSchemaError) { return jsonResponse( { error: "invalid_device_revocation" }, 400, { "Cache-Control": "no-store" }, ); } if (error instanceof DevicePersistenceError) { return jsonResponse( { error: "device_revocation_failed" }, 500, { "Cache-Control": "no-store" }, ); } throw error; } }, ); } if (url.pathname === "/api/account/delete") { return withApprovedDeviceApiControls( request, env, "account.delete", ["POST"], async (context) => { try { return jsonResponse(await accountDeletionDocument(request, env, context), 200, { "Cache-Control": "no-store", }); } catch (error) { if (error instanceof AccountDeletionRequestError) { return jsonResponse( { error: "invalid_account_deletion" }, 400, { "Cache-Control": "no-store" }, ); } if (error instanceof AccountDeletionPersistenceError) { return jsonResponse( { error: "account_deletion_failed" }, 500, { "Cache-Control": "no-store" }, ); } throw error; } }, ); } const syncResponse = await handleSyncRoute(request, env, url); if (syncResponse !== null) { return syncResponse; } if (url.pathname === "/api/plugins/signing-keys") { return withPublicApiControls(request, env, "plugins.signing_keys", ["GET"], () => handlePublicSigningKeys(env), ); } const pluginRoute = parsePluginRoute(url.pathname); if (pluginRoute !== null) { return withPublicApiControls(request, env, pluginRoute.auditRoute, ["GET"], () => handlePluginRoute(env, pluginRoute), ); } if (url.pathname === "/api/releases/manifest") { return withPublicApiControls(request, env, "releases.manifest", ["GET"], () => handleReleaseManifest(env), ); } if (url.pathname === "/api/releases/signature") { return withPublicApiControls(request, env, "releases.signature", ["GET"], () => handleReleaseSignature(env, url), ); } if (url.pathname === "/api/telemetry/events") { return withAuthenticatedApiControls( request, env, "telemetry.events", ["POST"], async (context) => { try { return jsonResponse( await telemetryEventAcceptedDocument(request, env, context), 202, { "Cache-Control": "no-store" }, ); } catch (error) { if (error instanceof TelemetrySchemaError) { return jsonResponse( { error: error.code }, 400, { "Cache-Control": "no-store" }, ); } throw error; } }, ); } return jsonResponse({ error: "not_found" }, 404); } type PluginRoute = | { kind: "catalog"; auditRoute: "plugins.catalog" } | { kind: "details"; auditRoute: "plugins.details"; pluginId: string } | { kind: "package"; auditRoute: "plugins.package"; pluginId: string }; async function handlePublicSigningKeys(env: Env): Promise { const kvKey = publicSigningKeysKvKey(env.ELY_ENVIRONMENT); const value = await env.ELY_KV.get(kvKey); if (value === null) { return jsonResponse({ error: "public_signing_keys_unavailable" }, 503); } try { const document = parsePublicSigningKeysDocument(value); return jsonResponse(document, 200, { "Cache-Control": "public, max-age=300, stale-while-revalidate=60", }); } catch (error) { if (error instanceof SigningKeysSchemaError) { return jsonResponse({ error: "public_signing_keys_invalid" }, 500); } throw error; } } async function handlePluginRoute( env: Env, route: PluginRoute, ): Promise { const kvKey = pluginRegistryKvKey(env.ELY_ENVIRONMENT); const value = await env.ELY_KV.get(kvKey); if (value === null) { return jsonResponse({ error: "plugin_registry_unavailable" }, 503); } try { const registry = parsePluginRegistryDocument(value); if (route.kind === "catalog") { return jsonResponse(pluginCatalogDocument(registry), 200, publicPluginCacheHeaders()); } if (route.kind === "details") { const document = pluginDetailsDocument(registry, route.pluginId); if (document === null) { return jsonResponse({ error: "plugin_not_found" }, 404); } return jsonResponse(document, 200, publicPluginCacheHeaders()); } const document = pluginPackageDocument(registry, route.pluginId); if (document === null) { return jsonResponse({ error: "plugin_not_found" }, 404); } return jsonResponse(document, 200, publicPluginCacheHeaders()); } catch (error) { if (error instanceof PluginRegistrySchemaError) { return jsonResponse({ error: "plugin_registry_invalid" }, 500); } throw error; } } async function handleReleaseManifest(env: Env): Promise { const kvKey = releaseManifestKvKey(env.ELY_ENVIRONMENT); const value = await env.ELY_KV.get(kvKey); if (value === null) { return jsonResponse({ error: "release_manifest_unavailable" }, 503); } try { const document = parseReleaseManifestDocument(value); return jsonResponse(document, 200, { "Cache-Control": "public, max-age=120, stale-while-revalidate=60", }); } catch (error) { if (error instanceof ReleaseManifestSchemaError) { return jsonResponse({ error: "release_manifest_invalid" }, 500); } throw error; } } async function handleReleaseSignature( env: Env, url: URL, ): Promise { let query; try { query = parseReleaseSignatureQuery(url.searchParams); } catch (error) { if (error instanceof ReleaseSignatureQueryError) { return jsonResponse({ error: "invalid_release_signature_query" }, 400); } throw error; } const kvKey = releaseManifestKvKey(env.ELY_ENVIRONMENT); const value = await env.ELY_KV.get(kvKey); if (value === null) { return jsonResponse({ error: "release_manifest_unavailable" }, 503); } try { const manifest = parseReleaseManifestDocument(value); const document = releaseSignatureDocument(manifest, query); if (document === null) { return jsonResponse({ error: "release_signature_not_found" }, 404); } return jsonResponse(document, 200, { "Cache-Control": "public, max-age=120, stale-while-revalidate=60", }); } catch (error) { if (error instanceof ReleaseManifestSchemaError) { return jsonResponse({ error: "release_manifest_invalid" }, 500); } throw error; } } function parsePluginRoute(pathname: string): PluginRoute | null { if (pathname === "/api/plugins") { return { kind: "catalog", auditRoute: "plugins.catalog" }; } if (!pathname.startsWith("/api/plugins/")) { return null; } const segments = pathname.split("/"); if (segments.length === 4) { const pluginId = pluginRouteId(segments[3]); if (pluginId === null) { return null; } return { kind: "details", auditRoute: "plugins.details", pluginId }; } if (segments.length === 5 && segments[4] === "package") { const pluginId = pluginRouteId(segments[3]); if (pluginId === null) { return null; } return { kind: "package", auditRoute: "plugins.package", pluginId }; } return null; } function pluginRouteId(segment: string | undefined): string | null { if (segment === undefined) { return null; } try { return pluginRegistryId(segment); } catch (error) { if (error instanceof PluginRegistrySchemaError) { return null; } throw error; } } function publicPluginCacheHeaders(): Record { return { "Cache-Control": "public, max-age=300, stale-while-revalidate=60" }; }