// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0 // The page's unload path (apps/web/src/ui/client.ts `beacon`): a call made as the page goes away is // a same-origin keep-alive POST to the procedure's mount with the page's CSRF token, and the // server's real CSRF wall admits exactly that request for this session and refuses it for another. // The browser half (keep-alive after a navigation and a closed tab) is proven in a real browser by // @conusai-kit/guides' Playwright suite (test-browser/beacon.spec.ts). import type { Principal } from "@conusai-kit/auth" import { afterEach, beforeAll, describe, expect, it } from "vitest" const ORIGIN = "https://app.example.test" const session = (sessionId: string): Principal => ({ actor: { userId: "11111111-1111-1111-1111-111111111111" }, method: "session", sessionId, }) let csrfToken: (sessionId: string) => string let requireCsrf: (request: Request, principal: Principal | null) => void let beacon: (procedure: string, input: unknown) => boolean beforeAll(async () => { process.env.AUTH_SESSION_SECRET = "0123456789abcdef0123456789abcdef" process.env.CONUSAI_PUBLIC_URL = ORIGIN process.env.OIDC_ISSUER = "https://id.example.test" process.env.OIDC_WEB_CLIENT_ID = "web" process.env.OIDC_AUDIENCE = "api" const module = await import("../apps/web/src/server/csrf") csrfToken = module.csrfToken requireCsrf = module.requireCsrf // Imported before any page global is stubbed: the beacon reads the page at call time, and the UI // kit's dependencies set up browser listeners on import when they see a window. beacon = (await import("../apps/web/src/ui/client")).beacon }) const globals = globalThis as unknown as { window?: unknown; document?: unknown; fetch: typeof fetch } const realFetch = globals.fetch afterEach(() => { globals.fetch = realFetch delete globals.window delete globals.document }) /** A page of this app holding `token` in its CSRF meta tag; returns what the page's fetch was handed. */ function page(token: string): Array<[URL, RequestInit]> { const sent: Array<[URL, RequestInit]> = [] globals.window = { location: { href: `${ORIGIN}/acme/main/notes/notes`, origin: ORIGIN } } globals.document = { querySelector: (selector: string) => selector === 'meta[name="csrf-token"]' ? { getAttribute: (name: string) => (name === "content" ? token : null) } : null, } globals.fetch = ((url: URL, init: RequestInit) => { sent.push([url, init]) return Promise.resolve(new Response(null, { status: 200 })) }) as typeof fetch return sent } describe("the page's beacon", () => { it("is a same-origin keep-alive POST to the procedure that the CSRF wall admits for this session only", () => { const sent = page(csrfToken("session-1")) const input = { org: "acme", idempotencyKey: "guides:1", events: [{ schema_version: 1, event_id: "e1", type: "track" }], } expect(beacon("guides.runtime.record", input)).toBe(true) expect(sent).toHaveLength(1) const [url, init] = sent[0] as [URL, RequestInit] expect(url.href).toBe(`${ORIGIN}/api/v1/guides.runtime.record`) expect(init).toMatchObject({ method: "POST", keepalive: true, credentials: "same-origin", body: JSON.stringify(input), }) // What the server receives: the page's headers, plus the fetch metadata the browser adds to a // request of this page's own origin. const request = new Request(url, { method: "POST", headers: { ...(init.headers as Record), "sec-fetch-site": "same-origin" }, body: init.body ?? null, }) expect(() => requireCsrf(request, session("session-1"))).not.toThrow() expect(() => requireCsrf(request, session("session-2"))).toThrow(/x-csrf-token/) }) it("is declined when the body would not fit the keep-alive budget, so the engine keeps the batch", () => { const sent = page(csrfToken("session-1")) expect(beacon("guides.runtime.record", { padding: "x".repeat(70_000) })).toBe(false) expect(sent).toHaveLength(0) }) })