/* RFC-1030: Astro API route factory for live runtime reflection. Exposes RuntimeReflectionV1 as JSON via GET /api/agent/reflect. Per-IP rate limited (10 req/min, in-memory per-isolate soft limit). ACCESS_PIN middleware is respected at the Astro middleware layer — this route only returns data. Do not implement gate logic — that is index.ts/mcp/*; this module only wires the reflection API into an Astro APIRoute. Do not implement rate limiting logic — reuses createFixedWindowLimiter from limits.ts. RFC-1030: initial reflect route factory. */ import type { APIRoute } from "astro"; import { createFixedWindowLimiter } from "./limits.ts"; import { reflectRuntime, type LawKernelSummary, type ReflectionInput, type RuntimeReflectionV1, } from "../component-runtime/reflection.ts"; const CORS_HEADERS: Record = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, OPTIONS", "Access-Control-Allow-Headers": "Content-Type", "Access-Control-Max-Age": "86400", }; const REFLECT_RATE_LIMITER = createFixedWindowLimiter(60, 10); function withCors(response: Response): Response { for (const [key, value] of Object.entries(CORS_HEADERS)) { response.headers.set(key, value); } return response; } export interface CreateAgentReflectRouteOptions { reflectionInput: ReflectionInput; lawKernelSummary: LawKernelSummary; } export function createAgentReflectRoute(options: CreateAgentReflectRouteOptions): { GET: APIRoute; OPTIONS: APIRoute; } { return { GET: async ({ clientAddress }) => { const limit = REFLECT_RATE_LIMITER.check(clientAddress || "unknown"); if (!limit.allowed) { return withCors( new Response(JSON.stringify({ error: "rate_limited" }), { status: 429, headers: { "Content-Type": "application/json", "Retry-After": String(limit.retryAfterSeconds), }, }), ); } try { const reflection = reflectRuntime(options.reflectionInput, options.lawKernelSummary); assertNoForbiddenFieldsReflection(reflection); return withCors( new Response(JSON.stringify(reflection), { status: 200, headers: { "Content-Type": "application/json" }, }), ); } catch (err) { const message = err instanceof Error ? err.message : "internal error"; return withCors( new Response(JSON.stringify({ error: message }), { status: 500, headers: { "Content-Type": "application/json" }, }), ); } }, OPTIONS: async () => new Response(null, { status: 204, headers: CORS_HEADERS }), }; } function assertNoForbiddenFieldsReflection(reflection: RuntimeReflectionV1): void { const json = JSON.stringify(reflection); const forbidden = [ "secrets", "credentials", "privateState", "rawGrants", "prompts", "executableBytes", "leaseTokens", "authorityMaterial", "artifactBytes", "sourceCode", ]; for (const field of forbidden) { if (json.includes(field)) { throw new Error(`REFLECTION-02: reflection contains forbidden field name: ${field}`); } } }