Skip to content

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.app
  • LAST1ADMIN_APP_PROD_REALOUTCOMES_API_BASE → https://realoutcomes.app
  • LAST1ADMIN_APP_PROD_LAST1_ID_API_BASE → https://auth.last1.id
  • LAST1ADMIN_APP_PROD_LASTVET_API_BASE → https://api.last.vet
  • LAST1ADMIN_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/sdk operator login refactor
  • system_admin_memberships table creation / seeding
  • admin_telemetry_events DDL (optional post-reconnect; in-memory telemetry works)
  • Dedicated admin-edge tunnel migration (unless Ryan pulls forward)
  • admin.last1.app Railway teardown (last1.app product, not last1-admin)

References