petrova host airlock setup
SOL LOG — petrova.host Airlock Auth Setup
Section titled “SOL LOG — petrova.host Airlock Auth Setup”Audience: operator
Frequency: one-time per environment
RTO: ~15 minutes
Related decision: docs/decisions/2026-05-10-per-user-auth-via-airlock-handoff.md
Overview
Section titled “Overview”petrova.host uses Airlock’s cross-apex JWT handoff (flow F9) for authentication.
No OAuth client registration in the oauthClients table is needed.
The setup has two parts: registering the apex in Airlock, and setting three Vercel env vars.
Part 1 — Register the apex in Airlock
Section titled “Part 1 — Register the apex in Airlock”petrova.host must appear in the handoff_consumers table so Airlock will mint handoff JWTs for it.
Option A — via Hatch (preferred)
Section titled “Option A — via Hatch (preferred)”- Open hatch.so1.io (or
hatch.devarno.cloud) and sign in as an admin. - Navigate to Orbits → Handoff Consumers.
- Click Add apex.
- Enter
https://petrova.hostas the apex andpetrova-host consoleas the label. - Save. The in-process cache in Airlock clears within 30 seconds (TTL = 30 000 ms).
Option B — via bootstrap script (first deploy or DB migration)
Section titled “Option B — via bootstrap script (first deploy or DB migration)”# From the airlock repo root:DATABASE_URL=<production-db-url> \HANDOFF_ALLOWED_APEXES=https://petrova.host \ npx tsx scripts/bootstrap-handoff-consumers.tsThe script is idempotent (ON CONFLICT DO NOTHING) — safe to re-run.
Verify
Section titled “Verify”curl -s https://airlock.devarno.cloud/api/auth/handoff?return=https://petrova.host/api/auth/callback# Expected: 302 to Airlock sign-in (not 400 "invalid return URL")Part 2 — Set Vercel env vars
Section titled “Part 2 — Set Vercel env vars”In the Vercel project for petrova.host (Settings → Environment Variables):
| Variable | Value | Notes |
|---|---|---|
SESSION_SECRET | openssl rand -hex 32 | ≥32 chars; never reuse across projects |
AIRLOCK_URL | https://airlock.devarno.cloud | Omit to use the default |
PETROVA_HOST_ORIGIN | https://petrova.host | Must match the registered apex exactly |
Generate SESSION_SECRET:
openssl rand -hex 32Warning: Rotating
SESSION_SECRETinvalidates all existing__petrova_sessioncookies, logging every user out immediately. Rotate only intentionally.
Part 3 — Local development
Section titled “Part 3 — Local development”Add to dashboard/.env.local (not committed):
AUTH_DISABLED=trueSESSION_SECRET=dev-secret-replace-me-in-production-xxxAIRLOCK_URL=https://airlock.devarno.cloudPETROVA_HOST_ORIGIN=http://localhost:3000AUTH_DISABLED=true injects a fake admin session so the auth flow is skipped entirely.
The module-scope guard in middleware.ts throws a fatal error if this flag is set in production.
Part 4 — Preview deployments
Section titled “Part 4 — Preview deployments”Preview deployments (*.vercel.app) are not registered in the Airlock apex allowlist, so the auth flow will fail for them.
Options:
- Preferred: Set
AUTH_DISABLED=truein Vercel Preview environment variables (safe because the guard allows it in non-productionNODE_ENV). - Alternative: Register the preview apex pattern — not recommended since Vercel preview URLs change per deployment.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause | Fix |
|---|---|---|
Airlock returns invalid return URL (400) | https://petrova.host not in handoff_consumers | Complete Part 1 |
| Callback returns 302 loop | SESSION_SECRET unset or <32 chars | Set correct env var in Vercel |
| Console shows “SESSION_SECRET is unset” 500 | Env var missing | See Part 2 |
User sees /denied after sign-in | Signed-in Airlock account has role !== "admin" | Grant admin role in Hatch → Crew |
__petrova_session cookie not set in prod | secure: false on HTTPS | Ensure VERCEL_ENV=production is set (Vercel sets this automatically) |