111 lines · 4.7 KB · TypeScript
RawDownload
// Cloud-only: every mounted /api plane ANSWERS — nothing silently falls// through to the SPA's 200-HTML fallback (the billing-404 regression class).// Docs and the spec are served, the billing proxy and the protected API gate// reject anonymous callers with their own structured JSON, and unknown /api// paths are a real 404. All raw fetch: this is about raw wire dispatch.import { expect } from "@effect/vitest";import { Effect } from "effect"; import { scenario } from "../src/scenario"; scenario(  "Surfaces · Swagger UI and the OpenAPI spec document the mounted API",  { needs: ["api"] },  (ctx) =>    Effect.gen(function* () {      const docs = yield* Effect.promise(() => fetch(new URL("/api/docs", ctx.target.baseUrl)));      expect(docs.status, "Swagger UI is served").toBe(200);      expect(docs.headers.get("content-type"), "as an HTML page").toContain("text/html");      const docsHtml = yield* Effect.promise(() => docs.text());      expect(docsHtml.toLowerCase(), "it is the Swagger UI shell").toContain("swagger");       const spec = yield* Effect.promise(() =>        fetch(new URL("/api/openapi.json", ctx.target.baseUrl)),      );      expect(spec.status, "the OpenAPI spec is served").toBe(200);      expect(spec.headers.get("content-type"), "as JSON").toContain("application/json");      const parsed = (yield* Effect.promise(() => spec.json())) as {        paths?: Record<string, unknown>;      };      const paths = Object.keys(parsed.paths ?? {});      expect(paths, "the core protected API is documented").toContain("/api/integrations");      expect(paths, "the session-auth plane is documented").toContain("/api/auth/me");      expect(paths, "the org plane is documented").toContain("/api/org/domains");      expect(paths, "path-param routes are documented").toContain(        "/api/executions/{executionId}/resume",      );    }),); scenario(  "Surfaces · the billing proxy answers with its own 401 JSON, not the SPA fallback",  { needs: ["api", "billing"] },  (ctx) =>    Effect.gen(function* () {      const response = yield* Effect.promise(() =>        fetch(new URL("/api/billing/customer", ctx.target.baseUrl), {          method: "POST",          headers: { "content-type": "application/json" },          body: "{}",        }),      );      // The regression returned the SPA fallback (200 text/html). The real      // billing route is reached and rejects the unauthenticated call itself.      expect(response.status, "the billing route rejects the anonymous call").toBe(401);      expect(response.headers.get("content-type"), "with a JSON body").toContain(        "application/json",      );      const body = yield* Effect.promise(() => response.json());      expect(body, "the structured refusal a client can act on").toEqual({        error: "Unauthorized",        code: "unauthorized",      });    }),); scenario(  "Surfaces · every protected plane refuses anonymous callers with structured JSON",  { needs: ["api"] },  (ctx) =>    Effect.gen(function* () {      // The core protected API: anonymous callers hit the auth gate, which      // answers in JSON (never the SPA) with the documented refusal body.      const core = yield* Effect.promise(() =>        fetch(new URL("/api/integrations", ctx.target.baseUrl)),      );      expect(core.status, "no credentials → no organization to act in").toBe(403);      expect(core.headers.get("content-type"), "the gate answers in JSON").toContain(        "application/json",      );      expect(yield* Effect.promise(() => core.json()), "the documented refusal body").toEqual({        error: "No organization in session",        code: "no_organization",      });       // The session-auth plane is mounted and gated.      const sessionMe = yield* Effect.promise(() =>        fetch(new URL("/api/auth/me", ctx.target.baseUrl)),      );      expect(sessionMe.status, "the session API requires a session").toBe(401);       // The org plane is mounted and gated.      const orgDomains = yield* Effect.promise(() =>        fetch(new URL("/api/org/domains", ctx.target.baseUrl)),      );      expect(orgDomains.status, "the org API requires a session").toBe(401);    }),); scenario(  "Surfaces · unknown /api routes are a real 404, not the SPA fallback",  { needs: ["api"] },  (ctx) =>    Effect.gen(function* () {      const response = yield* Effect.promise(() =>        fetch(new URL("/api/this-route-does-not-exist", ctx.target.baseUrl)),      );      expect(response.status, "the API plane owns its 404s").toBe(404);      const body = yield* Effect.promise(() => response.text());      expect(body, "no SPA HTML leaks out of the API plane").not.toContain("<!DOCTYPE html");    }),);