SPRINT-8 T-1 Execution Plan — last1-admin Sovereign Reconnect¶
Date: 2026-08-31
Status: DRAFT — do not execute. Awaiting Ryan T-1 go after T-0 + §6 decisions.
Prior: SPRINT8_T0_AUDIT.md
v1.2 lens: Teardown / cost-cut / last hosted-era exit. Not keystone or Track B work.
Ryan decisions locked (T-0 closeout)¶
| # | Decision |
|---|---|
| Missing tables | Benign — never in bundle Gate B dump; no data lost |
| Operator login | ryan@last1.enterprises → domain rule super_admin |
| Auth | Option A — bundle GoTrue on https://api.last1.app; no @last1id/sdk refactor |
| RBAC | Domain rule only; no system_admin_memberships seeding for reconnect |
| Marketing | Keep enabled; repoint Onset Supabase URL + service role |
| Onset URL | https://onset-api.theonset.app (confirmed below) |
| DNS | Staging E2E first on admin-app.last1.enterprises, then prod flip |
| Hosted rollback | None — tcthzakppndkykatoefx account deleted; sovereign-or-nothing |
Onset hostname (#4 — confirmed)¶
Admin ONSET_SUPABASE_* must target the Supabase Kong stack (PostgREST + GoTrue + Storage), not the clinic Next.js app.
| Hostname | What it is | Use for admin ONSET_SUPABASE_URL? |
|---|---|---|
https://onset-api.theonset.app |
Public CF-proxied Kong on VM 119 (192.168.1.102:8000) — T5-1 Phase 2 |
Yes |
https://clinic.theonset.app |
Clinic portal (Next.js on VM 118 :3000) |
No |
http://192.168.1.102:8000 |
LAN Kong (onset BWS internal URL today) | Works from VM 115 LAN only; do not use for admin prod BWS (use public parity path) |
https://onset-db.last1.enterprises |
Planned in RLS pass; never provisioned | No |
Live proof (2026-08-31): ONSET_DB_PROD_SUPABASE_SERVICE_ROLE_KEY → GET https://onset-api.theonset.app/rest/v1/marketing_subscribers?select=id&limit=1 → 200 with row data.
BWS keys to set (last1-admin project):
| Key | Value source |
|---|---|
LAST1ADMIN_APP_PROD_ONSET_SUPABASE_URL |
https://onset-api.theonset.app |
LAST1ADMIN_APP_PROD_ONSET_SUPABASE_SERVICE_ROLE_KEY |
Copy from onset BWS ONSET_DB_PROD_SUPABASE_SERVICE_ROLE_KEY (1c643206-…) |
Legacy unprefixed ONSET_SUPABASE_URL / ONSET_SUPABASE_SERVICE_ROLE_KEY |
Same values (render script maps prefixed → runtime) |
Two admin roles (do not conflate)¶
| Role | Mechanism | Sovereign target |
|---|---|---|
| A. Operator login | Admin SPA + server JWT via SUPABASE_URL / VITE_SUPABASE_* |
https://api.last1.app (last1app-db GoTrue) |
| B. Managed upstreams | Per-unit BFF after login | See table below |
| Unit | Upstream env | Target (live today) |
|---|---|---|
| last1.app | LAST1_API_BASE |
https://last1.app |
| RadioCheck (direct SRK) | RADIOCHECK_SUPABASE_URL |
https://api.last1.app (same bundle Kong) |
| RealOutcomes | REALOUTCOMES_API_BASE |
https://realoutcomes.app |
| last1.id ops | LAST1_ID_API_BASE + gateway HMAC |
https://auth.last1.id (admin API proxy — not operator login) |
| LastVet | LASTVET_API_BASE |
https://api.last.vet |
| Angel | ANGEL_API_BASE |
https://api.angel.report |
| Onset dashboards + marketing | ONSET_SUPABASE_* |
https://onset-api.theonset.app |
Phase 0 — Pre-flight (read-only validation)¶
Gate: Ryan signs T-1 go.
| Step | Action | Pass criteria |
|---|---|---|
| 0.1 | Confirm live upstreams (curl/smoke from agent or VM) | api.last1.app, onset-api.theonset.app, auth.last1.id, last1.app, realoutcomes.app, api.last.vet, api.angel.report respond |
| 0.2 | Pull sovereign JWTs from BWS (do not trust admin copy) | LAST1APP_DB_PROD_SUPABASE_ANON_KEY + service role from last1-radiocheck (8a22f77d-…); Onset SRK from onset (1c643206-…) |
| 0.3 | Guard: grep admin BWS after edit | Zero tcthzakppndkykatoefx, zero emxrmjysvxeboavhatry |
| 0.4 | Document Railway admin service ID | disciplined-beauty / 7c02cdf9-… — rollback net only until T-1-5 |
Phase 1 — BWS repoint (no VM changes yet)¶
Project: last1-admin (719957e4-e73e-41f1-9b75-b480012d7d96)
1.1 Bundle Supabase (operator login + RadioCheck SRK reads)¶
| BWS key | New value |
|---|---|
LAST1ADMIN_APP_PROD_SUPABASE_URL |
https://api.last1.app |
LAST1ADMIN_APP_PROD_VITE_SUPABASE_URL |
https://api.last1.app |
LAST1ADMIN_APP_PROD_RADIOCHECK_SUPABASE_URL |
https://api.last1.app |
LAST1ADMIN_APP_PROD_VITE_SUPABASE_ANON_KEY |
LAST1APP_DB_PROD_SUPABASE_ANON_KEY (from last1-radiocheck BWS) |
LAST1ADMIN_APP_PROD_SUPABASE_SERVICE_ROLE_KEY |
Sovereign service role JWT (same source as last1app monolith) |
LAST1ADMIN_APP_PROD_RADIOCHECK_SERVICE_ROLE_KEY |
Same sovereign service role (bundle is one stack) |
Legacy VITE_SUPABASE_URL, RADIOCHECK_SUPABASE_URL, VITE_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, RADIOCHECK_SERVICE_ROLE_KEY |
Align or delete duplicates after render verify |
1.2 Onset (dashboards + marketing)¶
| BWS key | New value |
|---|---|
LAST1ADMIN_APP_PROD_ONSET_SUPABASE_URL |
https://onset-api.theonset.app |
LAST1ADMIN_APP_PROD_ONSET_SUPABASE_SERVICE_ROLE_KEY |
ONSET_DB_PROD_SUPABASE_SERVICE_ROLE_KEY (onset BWS) |
1.3 Already correct (verify unchanged)¶
LAST1ADMIN_APP_PROD_VITE_API_BASE/LAST1_API_BASE→https://last1.appLAST1ADMIN_APP_PROD_REALOUTCOMES_API_BASE→https://realoutcomes.appLAST1ADMIN_APP_PROD_LAST1_ID_API_BASE→https://auth.last1.idLAST1ADMIN_APP_PROD_LASTVET_API_BASE→https://api.last.vetLAST1ADMIN_APP_PROD_ANGEL_API_BASE→https://api.angel.report
1.4 Post-edit validation script (add in T-1 execution)¶
Before any deploy: automated grep of all LAST1ADMIN_APP_PROD_* URL values against live curl -sfI (RealOutcomes-500 lesson).
STOP after Phase 1 for Ryan review of BWS diff (no container recreate yet).
Phase 2 — GoTrue redirect allow-list (bundle)¶
On last1app-db sovereign GoTrue, add redirect URLs:
| Environment | Redirect URL |
|---|---|
| Staging | https://admin-app.last1.enterprises/auth/callback |
| Production (before prod flip) | https://admin.last1.enterprises/auth/callback |
Use existing last1app GoTrue config scripts pattern (configure-last1app-gotrue-* or manual Supabase Auth URL list).
STOP — confirm Ryan can complete OAuth/password login on staging hostname before Phase 3 container rebuild.
Phase 3 — VM 115 deploy (container RECREATE)¶
| Step | Command / action |
|---|---|
| 3.1 | bash scripts/last1-admin/render-last1admin-env-app.sh on VM 115 → /opt/last1-admin/.env |
| 3.2 | Verify rendered .env: no hosted refs; SUPABASE_URL=https://api.last1.app; ONSET_SUPABASE_URL=https://onset-api.theonset.app |
| 3.3 | docker compose / deploy script: RECREATE container (deploy-last1admin-app.sh) — not docker restart |
| 3.4 | LAN smoke: curl http://192.168.1.97:5000/health → 200 |
| 3.5 | Optional: fix LastVet ops digest (legacy API key errors in logs) as part of same env refresh |
Railway prod unchanged in this phase (still broken on dead hosted — acceptable during staging).
Phase 4 — Staging ingress + DNS¶
| Step | Action |
|---|---|
| 4.1 | Ryan: CF CNAME admin-app.last1.enterprises → 4c8550f2-2156-4284-b9f7-60cdc0fdc109.cfargotunnel.com (proxied) |
| 4.2 | DRY_RUN=0 bash scripts/last1-admin/configure-tunnel-staging-app.sh on lastvet-edge |
| 4.3 | PF-1/PF-2 from TIER_3_ADMIN_T3-4_TEST_PLAN.md: no x-railway-edge; VM logs show requests |
Note: Staging uses lastvet-r940 tunnel per existing T3-4 script. Dedicated admin-edge on VM 97 (isolation principles) is deferred to post-reconnect hardening unless Ryan wants it in T-1.
Phase 5 — Staging E2E (Ryan browser)¶
URL: https://admin-app.last1.enterprises
Account: ryan@last1.enterprises
Plan: TIER_3_ADMIN_T3-4_TEST_PLAN.md — cover each upstream:
| Surface | Staging check |
|---|---|
| Auth shell | Login → /api/auth/user returns user + super_admin |
| last1.app | Unit switcher → metrics/governance read |
| RadioCheck | /api/radiocheck/* read (units/users) |
| RealOutcomes | Proxy read |
| last1.id ops | Proxy to auth.last1.id (identities/audit read) |
| LastVet | /api/lastvet/* read |
| Angel | /api/angel/* read |
| Onset | Dashboard/metrics read via Onset Supabase routes |
| Marketing | /api/admin/marketing/{onset,lastvet,last1org}/stats or list subscribers |
STOP for Ryan sign-off: staging PASS checklist in Section 10 of T3-4 plan before Phase 6.
Phase 6 — Production DNS cutover¶
| Step | Action |
|---|---|
| 6.1 | Backup current admin.last1.enterprises DNS (Railway CNAME target) |
| 6.2 | Point admin.last1.enterprises to R940 tunnel origin (192.168.1.97:5000) — prod route already staged on lastvet-edge per T3-3; confirm no Railway header |
| 6.3 | Prod smoke: health, login, one read per upstream |
| 6.4 | Soak 24–48h (Ryan discretion) — monitor VM 115 probe + docker logs |
Phase 7 — Railway admin teardown¶
Only after Phase 6 stable + Ryan explicit teardown auth.
| Step | Action |
|---|---|
| 7.1 | Remove Railway disciplined-beauty last1-admin service |
| 7.2 | Confirm admin.last1.app (separate last1.app admin build) out of scope — do not delete with last1-admin |
| 7.3 | Update muster migrate-last1-admin-railway-to-r940 → closed |
| 7.4 | SPRINT-8 closeout report |
STOP gates summary¶
| Gate | Owner |
|---|---|
| T-1 go | Ryan |
| After BWS edit (Phase 1) | Ryan review diff |
| After GoTrue redirects (Phase 2) | Ryan staging login test |
| After VM recreate (Phase 3) | Cursor LAN smoke |
| After staging E2E (Phase 5) | Ryan browser PASS |
| Prod DNS (Phase 6) | Ryan |
| Railway delete (Phase 7) | Ryan |
Out of scope (T-1)¶
@last1id/sdkoperator login refactorsystem_admin_membershipstable creation / seedingadmin_telemetry_eventsDDL (optional post-reconnect; in-memory telemetry works)- Dedicated
admin-edgetunnel migration (unless Ryan pulls forward) admin.last1.appRailway teardown (last1.app product, not last1-admin)
References¶
- SPRINT8_T0_AUDIT.md
- TIER_3_ADMIN_T3-4_TEST_PLAN.md
- TIER_4_ONSET_T5-1_INFRA_REPORT.md
- SPRINT7_T1_GATE_B_REPORT.md (bundle dump manifest)
scripts/last1-admin/render-last1admin-env-app.shscripts/last1-admin/deploy-last1admin-app.shscripts/last1-admin/configure-tunnel-staging-app.sh