feat(demo): draft isolated demo authentication realm#595
Conversation
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
life-ustc | a4117ed | Commit Preview URL Branch Preview URL |
Jul 22 2026, 09:16 AM |
There was a problem hiding this comment.
Pull request overview
Draft vertical-slice for an isolated, opt-in demo authentication “realm” that mints short-lived signed web sessions and separate-audience API tokens, serves deterministic fixture-backed reads, and simulates writes with explicit simulated markers—without involving Better Auth sessions, Prisma, R2, or external mutations.
Changes:
- Add demo JWT mint/verify helpers (separate web/API audiences), kill switch handling, and an opaque audit-session hash.
- Introduce
/demobootstrap page with a short-lived cookie session and fixture-backed todo rendering. - Add draft
/api/demo/tokenexchange and/api/demo/todosread + simulated mutation endpoint with audit logging and ax-life-ustc-simulatedresponse header.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/demo-auth.test.ts | Unit tests for demo enablement, audience separation, kill switch behavior, and opaque audit ID stability. |
| src/routes/demo/+page.svelte | Draft demo UI that either prompts entry or renders fixture todos. |
| src/routes/demo/+page.server.ts | Demo bootstrap action mints the demo web cookie; load verifies session and returns fixtures. |
| src/routes/api/demo/token/+server.ts | Exchanges verified demo web session cookie for a short-lived demo API bearer token. |
| src/routes/api/demo/todos/+server.ts | Demo todos read plus simulated todo creation with explicit simulated markers and audit logging. |
| src/features/demo/server/demo-fixtures.ts | Deterministic fixture todos plus simulated create response shape. |
| src/features/demo/server/demo-auth.ts | Demo JWT signing/verification and audit-session hash helper. |
| src/features/demo/server/demo-api-auth.ts | Bearer-token auth helper enforcing demo API scopes. |
| .env.example | Documents demo-mode env toggles and signing secret requirement (disabled by default). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
E2E HTML report is ready: https://life-ustc.github.io/e2e-snapshot-artifacts/reports/29907262547/index.html |
e413b84 to
ac992ea
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.
Comments suppressed due to low confidence (1)
src/features/demo/server/demo-api-auth.ts:17
- The demo API auth helper returns plain-text
Responsebodies for 401/403. Elsewhere in the codebase API auth uses the standard JSON error helpers (unauthorized(),forbidden()) to matchopenApiErrorSchemaand keep error responses consistent.
) {
if (!isDemoModeEnabled()) return notFound();
const bearer = parseBearerAuthorizationHeader(request.headers);
const principal = bearer?.token
? await verifyDemoApiToken(bearer.token)
: null;
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (2)
src/routes/api/demo/token/+server.ts:15
- This handler returns plain-text 404/401 Responses while other REST helpers (and requireDemoApiScope) use the shared JSON error shape
{ error: string }. Using the standard helpers keeps error bodies + headers consistent across the API surface.
if (!isDemoModeEnabled()) return new Response("Not found", { status: 404 });
const session = cookies.get(DEMO_SESSION_COOKIE);
const principal = session ? await verifyDemoWebSession(session) : null;
if (!principal) return new Response("Unauthorized", { status: 401 });
return json({
src/routes/api/demo/todos/+server.ts:16
- The OpenAPI route collector skips any exported method without a JSDoc block (see
scripts/openapi/route-collector.ts, whereextractMethodscontinues whenjsDocs.length === 0). As-is,/api/demo/todos(and the demo token route) will be omitted from the generated OpenAPI spec, even when demo mode is enabled. If these endpoints are meant to be part of the public-ish demo surface, they likely need JSDoc@responsetags (and ideally request/response schemas); if they are intentionally hidden for the draft, consider adding an explicit comment stating that omission is intentional.
export const GET: RequestHandler = async ({ request }) => {
const principal = await requireDemoApiScope(request, "demo:todo:read");
if (principal instanceof Response) return principal;
return json({ fixture: true, todos: getDemoTodos(principal) });
};
Draft implementation for #548.
This deliberately remains disabled by default and is not enabled in
wrangler.jsoncor any production workflow.Vertical slice:
/demoweb bootstrap with a short-lived signed cookie and deterministic fixturessimulated: true+ response header)Current v1 exclusions remain admin, real OAuth management, uploads, public collaborative writes, account operations, calendar tokens and webhooks. The RFC/threat-model decisions are documented in the linked issue discussion.
Verification:
bunx vitest run tests/unit/demo-auth.test.tsbunx svelte-check --tsconfig ./tsconfig.jsonDo not mark ready or enable production configuration until the threat model, abuse limits and product UX are accepted.