Tier 4 Onset T-3 Gate F Report — Closeout + T-4 Kickoff¶
Status: T-3 CLOSED — awaiting Ryan T-4 go
Date: 2026-08-30
Prerequisite: Gate E signed (Ryan E-1..E-4, temp state reverted)
Summary¶
T-3 (Onset clinic auth unification) is complete. The clinic portal on VM 118 authenticates exclusively via auth.last1.id and the encrypted clinic_last1_session cookie. supabase-auth remains running on VM 119 for iOS/patient GoTrue until App Store release (T-5). Gate E proved real device Apple Sign-In on R940 GoTrue, de-risking T-5.
Next: T-4 (onset-edge tunnel + clinic DNS cutover + hosted rollback net). No execution until Ryan replies T-4 go.
Execution plan: TIER_4_ONSET_T4_EXECUTION_PLAN.md
Gate F verification (Ryan signed 2026-08-30)¶
| # | Test | Result |
|---|---|---|
| E-1 | Clinic Last1 login (curryrg@gmail.com) |
PASS |
| E-2 | GoTrue health + apikey → 200 | PASS (automated) |
| E-3 | iOS Sign in with Apple on R940 (hello@unicornryda.com, TestFlight staging → onset-db over Tailscale) |
PASS — real device, not endpoint probe |
| E-4 | supabase-auth Up (healthy) on VM 119 |
PASS (automated) |
| Closeout | Staging.xcconfig → hosted; APPLE_PRIVATE_KEY GH secret removed |
PASS |
Gate E report: TIER_4_ONSET_T3_GATE_E_REPORT.md
T-3 deliverables (Gates A–F)¶
| Gate | Work | Report |
|---|---|---|
| A | BWS layout + VM naming + T-1 planning | TIER_4_ONSET_GATE_A_REPORT.md |
| B | Gate B dump/restore + PHI smoke; clinic Last1 ID refactor (PR #7) | TIER_4_ONSET_GATE_B_REPORT.md, TIER_4_ONSET_T3_GATE_B_REPORT.md |
| C | Deploy clinic portal to VM 118 LAN + OAuth infra | TIER_4_ONSET_T3_GATE_C_REPORT.md |
| D | Practitioner FK remap + promo cleanup | TIER_4_ONSET_T3_GATE_D_REPORT.md |
| E | Partial GoTrue retirement verification (clinic off, iOS on) | TIER_4_ONSET_T3_GATE_E_REPORT.md |
| F | Closeout (this report) | — |
Parent plan: ONSET_MIGRATION_PLAN.md
Sub-audits (T-4 inputs): TIER_4_ONSET_T-3_SUBAUDITS.md
Cross-stack auth state at T-3 close¶
┌─────────────────────────┬──────────────────────────┬─────────────────────────┐
│ Surface │ Identity │ Auth backend │
├─────────────────────────┼──────────────────────────┼─────────────────────────┤
│ Clinic portal (VM 118) │ curryrg@gmail.com │ auth.last1.id (OIDC) │
│ │ clinic_last1_session │ │
├─────────────────────────┼──────────────────────────┼─────────────────────────┤
│ iOS Onset Staging │ TestFlight / Debug │ Hosted staging │
│ (xcconfig default) │ │ lzpyfohgfdohrtlamzek │
├─────────────────────────┼──────────────────────────┼─────────────────────────┤
│ iOS App Store Release │ Patients / demo accounts │ Hosted prod │
│ │ │ emxrmjysvxeboavhatry │
├─────────────────────────┼──────────────────────────┼─────────────────────────┤
│ iOS-on-R940 (proven) │ hello@unicornryda.com │ R940 GoTrue VM 119 │
│ Gate E device test │ Apple key TU6S85XABQ │ onset-db Tailscale │
├─────────────────────────┼──────────────────────────┼─────────────────────────┤
│ Edge Functions │ Service role + user JWT │ VM 119 stack │
└─────────────────────────┴──────────────────────────┴─────────────────────────┘
Clinic is sovereign on R940 for auth (Last1 ID). iOS prod stays on hosted until T-4b/T-5. R940 iOS auth path is proven (Gate E E-3), so T-5 is a config/cutover exercise, not an unknown integration.
Coexistence: Clinic Last1 sessions never call local GoTrue for login. iOS patient auth uses GoTrue (hosted today; R940 at TestFlight/App Store cutover). Both stacks share one Postgres on VM 119 after clinic DNS cutover; until T-4, clinic LAN deploy already writes to R940 Postgres while App Store iOS still reads/writes hosted (accepted divergence until T-4b).
Gate E closeout artifacts (binding)¶
| Item | Action | Evidence |
|---|---|---|
Staging.xcconfig R940 pointer |
Reverted | onset-ios 9825d3f |
GitHub APPLE_PRIVATE_KEY |
Removed | Temp secret from aborted hosted push; deleted 2026-08-30 |
R940 GoTrue Apple (TU6S85XABQ) |
Retained | BWS + VM 119 — required for T-4b/T-5 |
| GG 29340466 / 34103515 | Open | Supabase JWT xcconfig incidents — RESOLVE at T-5, not Apple key rotation |
Apple RV26UG9967 |
Ryan action | Revoke in Apple Developer if not auto-revoked when TU6S85XABQ issued |
T-3 backlog (not blocking T-4 kickoff; track explicitly)¶
Surfaced during Gates B–E. T-4 must fix /patients/new; others are post-cutover hygiene.
| Item | Location | Risk / notes | Target |
|---|---|---|---|
/patients/new GoTrue bootstrap |
(portal)/patients/new/page.tsx |
Only active clinic browser supabase.auth.getUser() call; broken after Last1 login |
T-4 pre-cutover (T4-0) |
| notes-editor anon client | (portal)/patients/[id]/notes-editor.tsx |
Browser anon createClient() → direct .from(); RLS may block writes |
Portal SSR migration backlog |
| template-actions anon client | (portal)/templates/template-actions.tsx |
Same pattern | Portal SSR migration backlog |
| Deferred signup | api/clinic/register/route.ts |
auth.admin.createUser — Gate B stub |
When signup re-enabled |
| Dead MFA code | lib/clinic-mfa.ts |
Zero imports in deployed tree | Cleanup PR when convenient |
Gate B gaps — T-4 pre-cutover (MUST fix before DNS)¶
Ryan accepted 0 vs 3 cron.job and 0 vs 20 storage.objects for T-3 auth work. Both MUST close before T-4 clinic DNS cutover.
| Gap | Hosted prod | R940 today | T-4 fix |
|---|---|---|---|
| pg_cron | 3 jobs | 0 | Recreate clinic_weekly_summary, clinic_protocol_deliveries, clinic_fullscript_sync |
| Storage | 20 objects (~3.2 MB) | 0 | Schema-align + metadata restore or API migrate files |
| Vault | clinic_cron_secret, clinic_portal_base_url |
Restored; URLs still Railway-era | Point at R940 clinic before enabling crons |
Full inventory + SQL: TIER_4_ONSET_T-3_SUBAUDITS.md
T-4 preview (Ryan review)¶
T-4 puts clinic production traffic on R940 via dedicated onset-edge tunnel on VM 118 and cuts clinic.theonset.app DNS. Auth rework is done (T-3). T-4 is ingress + pre-cutover parity + vault/cron alignment.
| Phase | Work | Ryan gate |
|---|---|---|
| T4-0 | Pre-cutover fixes: cron (3 jobs), storage (20 objects), /patients/new bootstrap |
Sign-off before tunnel/DNS |
| T4-1 | Create onset-edge tunnel + BWS credentials |
Review tunnel UUID |
| T4-2 | Install cloudflared on VM 118; ingress clinic.theonset.app → :3000 |
Review config |
| T4-3 | Vault secrets → R940 clinic URL; webhook URL prep (Stripe, Fullscript) | Approve env diff |
| T4-4 | Ryan DNS: CNAME clinic.theonset.app → tunnel (Sun 03:00–07:00 PDT) |
Required |
| T4-5 | Cron smoke + clinic E2E on prod hostname | Gate T4-R |
| T4-6 | Keep Railway + hosted Supabase live for iOS rollback | Until T-4b/T-5 |
Do not change App Store Release xcconfig or onset-web prod Supabase env at T-4.
Full plan: TIER_4_ONSET_T4_EXECUTION_PLAN.md
Reply T-4 go to authorize T4-0 pre-cutover work + tunnel install. Ryan performs DNS at T4-4.
DB / infra state at T-3 close¶
| Component | State |
|---|---|
| Clinic auth | auth.last1.id OIDC + clinic_last1_session |
| Clinic deploy | VM 118 LAN 192.168.1.101:3000 (not prod DNS yet) |
| VM 119 GoTrue | Running — Apple enabled (TU6S85XABQ); serves iOS path |
| VM 119 Kong | 14 auth-v1 routes; Tailscale Serve onset-db.tailc3bbdc.ts.net |
| Clinic prod DNS | Still Railway until T-4 |
| iOS App Store | Hosted Supabase emxrmjysvxeboavhatry |
| iOS Staging xcconfig | Hosted lzpyfohgfdohrtlamzek (Gate E temp reverted) |
| cron.job / storage.objects | 0 / 0 — fix at T4-0 |
| Gate D backup | /var/backups/onset/pre-gate-d-user-remap-20260829T230525Z.dump (VM 119) |
Pattern lessons carried to T-4¶
- Remap to
id_token.sub(Gate D) — applied forcurryrg@gmail.com→2a805b21… - No silent xcconfig drift — Gate E R940 pointer reverted immediately after device proof
- Separate secret classes — Apple
.p8rotation ≠ Supabase JWT GG incidents (resolve at T-5) - Partial GoTrue retirement — RealOutcomes full stop does not apply; Onset retires clinic login only until T-5
END Gate F / T-3 closeout