Skip to content

Test-only auth endpoint — engineering runbook

Implements §1 of qa_proposal.md: a way for E2E tests to start authenticated in <50 ms instead of driving Kick OAuth / email-PIN in CI.

⚠️ Dangerous by design. This endpoint mints a real session cookie for a fixture account. It ships with three independent guards and must never be active in production.


Contract

POST /api/test/session
Headers:
  X-Test-Secret: <TEST_SESSION_SECRET>
Body:
  { "as": "streamer" | "operator", "fixture": "e2e-operator-fresh" }

200  Set-Cookie: session=…   (identical to a real PIN login)
     { "userId": <number>, "role": "streamer" | "operator" }
400  malformed body
401  bad / missing X-Test-Secret
403  endpoint disabled, misconfigured, or fixture-role mismatch
404  unknown fixture, or fixture not provisioned on this environment

The minted cookie is produced by the same issueSession / sessionCookieHeader the real login uses, so verifySession accepts it unchanged.


The three guards (all three, not just one)

  1. Build-time exclusion. The handler lives in api/src/test_session.ts. The production Docker build physically removes dist/test_session.js (Dockerfile: ARG INCLUDE_TEST_AUTH=falserm). server.ts imports it lazily, so a stripped build still boots and the route just 404s. Env misconfiguration alone cannot expose it.
  2. Runtime env gate. server.ts only wires the route when TEST_AUTH_ENABLED === "true", and the handler refuses everything unless a TEST_SESSION_SECRET is configured.
  3. Per-request gate. Constant-time X-Test-Secret check, a fixed fixture whitelist (no arbitrary emails), and a role-match check (a fixture only mints the role it is declared for). Every accept/reject is logged at WARN with the caller IP for alerting: [test-auth] test session minted for fixture '…' (operator #N) from <ip>.

Fixtures

Whitelisted in test_session.ts (FIXTURES), mirroring §2 of the proposal. Each maps to a fixed non-routable email ‹fixture›@e2e.verifluence.test and a role. The endpoint resolves that email to a real row (streamers.email / operators.contact_email) and 404s if the account isn't provisioned.

Dependency: the §2 fixture accounts must be seeded on staging before any fixture returns 200. Until then the endpoint correctly returns 404 … not provisioned.


Deployment wiring (required to activate on staging)

The CI pipeline builds one API image that Flux promotes to both stage and prod, so the build-time exclusion needs a stage-specific image that opts the module back in. Two follow-up steps, in two repos:

1. CI (this repo, .github/workflows/deploy-api.yml) — ✅ done

A Build and push — webapi (stage, test-auth enabled) step builds the webapi target with --build-arg INCLUDE_TEST_AUTH=true on main and pushes ghcr.io/verifluence/api-stage:{tag,latest}. The default api:* images stay stripped → prod binary never contains the route.

2. Operations repo (Flux)

  • Point the staging API Deployment at ghcr.io/verifluence/api-stage (image-automation marker).
  • Set on staging only:
    • TEST_AUTH_ENABLED=true
    • TEST_SESSION_SECRET=<rotating secret> (Sealed Secret; share with CI/QA out of band)
  • Production must NOT set TEST_AUTH_ENABLED or TEST_SESSION_SECRET, and continues to track the stripped ghcr.io/verifluence/api image.

Alerting

Page on any [test-auth] … WARN line originating from a prod cluster, and on any … minted … line whose caller IP is outside the CI / QA egress range.


Local / dev usage

bash
# build with the module retained, then run with the gates on
docker build --build-arg INCLUDE_TEST_AUTH=true -t vf-api-test ./api
TEST_AUTH_ENABLED=true TEST_SESSION_SECRET=dev-secret SESSION_SECRET= node dist/server.js

curl -X POST http://localhost:3000/api/test/session \
  -H 'X-Test-Secret: dev-secret' -H 'Content-Type: application/json' \
  -d '{"as":"operator","fixture":"e2e-operator-fresh"}' -i

Tests

api/test/tc-test-session.test.ts (TC-TESTAUTH-01…06): disabled→403, bad/missing secret→401, unknown fixture→404, role mismatch→403, unprovisioned→404, and the happy path (200 + a Set-Cookie that verifySession accepts).

Verifluence Documentation