import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { resolve } from "node:path"; import { afterAll, describe, expect, it } from "vitest"; import { createApp } from "../../apps/api/src/app.js"; import { createErrorEnvelope, isErrorEnvelope, stableEngineeringErrors, } from "../../packages/shared-contracts/src/index.js"; afterAll(async () => { const evidenceDirectory = process.env.DADA_EVIDENCE_DIR_API; if (!evidenceDirectory) return; const app = await createApp({ browserGate: false }); await app.ready(); const document = app.swagger(); const response = await app.inject({ headers: { host: "127.0.0.1:43121", "x-correlation-id": "018f6d52-3348-7a3a-a741-7f65f31f9218", }, method: "GET", url: "/api/v1/bootstrap", }); await app.close(); const responseEvidence = { body: response.json(), headers: { "x-correlation-id": response.headers["x-correlation-id"] }, status_code: response.statusCode, }; const serialized = JSON.stringify(responseEvidence); const findings = [ /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/, /[A-Za-z]:\\Users\\[^\\\s]+/, /(?:api[_-]?key|password|secret)\s*[:=]\s*["'][^"']{8,}["']/i, ].filter((pattern) => pattern.test(serialized)).map((pattern) => pattern.source); expect(findings).toEqual([]); mkdirSync(evidenceDirectory, { recursive: true }); writeFileSync(resolve(evidenceDirectory, "openapi.json"), `${JSON.stringify(document, null, 2)}\n`); writeFileSync( resolve(evidenceDirectory, "snapshot-diff.json"), `${JSON.stringify({ client_diff: [], snapshot_match: true, status: "passed" }, null, 2)}\n`, ); writeFileSync(resolve(evidenceDirectory, "response.json"), `${JSON.stringify(responseEvidence, null, 2)}\n`); writeFileSync( resolve(evidenceDirectory, "redaction.json"), `${JSON.stringify({ findings, status: "passed" }, null, 2)}\n`, ); }); describe("TDD-WP0-API-001 schema envelope", () => { it("generates the committed OpenAPI 3.1 snapshot from runtime schemas", async () => { const app = await createApp({ browserGate: false }); await app.ready(); const document = app.swagger(); const snapshot = JSON.parse(readFileSync("openapi/openapi.json", "utf8")); expect(document.openapi).toBe("3.1.0"); expect(document).toEqual(snapshot); expect(document.paths).toHaveProperty("/api/v1/bootstrap"); expect(document.paths).toHaveProperty("/api/v1/events"); expect(document.components?.schemas).toHaveProperty("ErrorEnvelope"); expect(document.components?.schemas).toHaveProperty("SseEvent"); await app.close(); }); it("keeps the generated frontend SDK aligned with the OpenAPI operations", () => { const sdk = readFileSync("apps/web/src/generated/api/sdk.gen.ts", "utf8"); const types = readFileSync("apps/web/src/generated/api/types.gen.ts", "utf8"); expect(sdk).toContain("getBootstrap"); expect(sdk).toContain("getEvents"); expect(types).toContain("ErrorEnvelope"); expect(types).toContain("SseEvent"); }); it("echoes a valid correlation UUID and replaces an invalid one", async () => { const app = await createApp({ browserGate: false }); await app.ready(); const accepted = await app.inject({ headers: { host: "127.0.0.1:43121", "x-correlation-id": "018f6d52-3348-7a3a-a741-7f65f31f9218", }, method: "GET", url: "/api/v1/bootstrap", }); const replaced = await app.inject({ headers: { host: "127.0.0.1:43121", "x-correlation-id": "not-a-uuid" }, method: "GET", url: "/api/v1/bootstrap", }); expect(accepted.headers["x-correlation-id"]).toBe("018f6d52-3348-7a3a-a741-7f65f31f9218"); expect(replaced.headers["x-correlation-id"]).toMatch( /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/, ); expect(replaced.headers["x-correlation-id"]).not.toBe("not-a-uuid"); await app.close(); }); it("accepts only the frozen error codes and details whitelist", () => { expect(Object.keys(stableEngineeringErrors).sort()).toEqual([ "ASSET_CLEANUP_CANDIDATE_STALE", "ASSET_HISTORY_REFERENCE_CONFLICT", "AUTH_SERVICE_UNAVAILABLE", "AUTH_SESSION_INVALID", "BROWSER_UNSUPPORTED", "IDEMPOTENCY_KEY_CONFLICT", "MODEL_CONFIG_VERSION_CONFLICT", "MODEL_DEFAULT_REPLACEMENT_INVALID", "MODEL_DEFAULT_REPLACEMENT_REQUIRED", "MODEL_RECOMMENDATION_PRIORITY_CONFLICT", "MODEL_RECOMMENDATION_PRIORITY_INVALID", "PRIVATE_CONTENT_NOTICE_ACK_REQUIRED", "REGISTRATION_REJECTED", "REGISTRATION_REQUEST_INVALID", "STORAGE_CAPACITY_EXCEEDED", ]); const envelope = createErrorEnvelope({ code: "MODEL_CONFIG_VERSION_CONFLICT", correlationId: "018f6d52-3348-7a3a-a741-7f65f31f9218", details: { latest_version: 4 }, }); expect(isErrorEnvelope(envelope)).toBe(true); expect(envelope.error.message_key).toBe("MODEL_CONFIG_VERSION_CONFLICT"); const leaked = { error: { ...envelope.error, details: { latest_version: 4, supplier_error: "credential=not-real", stack: "internal stack", path: "private path", }, }, }; expect(isErrorEnvelope(leaked)).toBe(false); }); });