Tier 4 Onset T-4 Prep Report — T4-0 through T4-3 (STOP before DNS)¶
Status: STOP — ready for Ryan T4-4 DNS cutover (Sun 03:00–07:00 PDT)
Date: 2026-08-30
Authorization: Ryan T-4 go (prep phases only)
Plan: TIER_4_ONSET_T4_EXECUTION_PLAN.md
Executive summary¶
T4-0 pre-cutover remediation is green on R940: 3 cron jobs, 20 storage objects (metadata + files), vault aligned to LAN clinic, all 3 cron routes HTTP 200 against http://192.168.1.101:3000. /patients/new migrated off client supabase.auth.getUser() and redeployed on VM 118.
T4-1/T4-2: onset-edge tunnel created and cloudflared active on VM 118 with ingress validated. No DNS changes.
T4-3: Vault + BWS edge keys aligned to live R940 state. Railway + hosted Supabase remain rollback net.
Hard stop: T4-4 DNS cutover is Ryan-only in the Sun window.
T4-0 — Pre-cutover remediation¶
T4-0a — pg_cron (PASS)¶
| Check | Result |
|---|---|
SELECT COUNT(*) FROM cron.job |
3 |
| Jobs | clinic_weekly_summary, clinic_protocol_deliveries, clinic_fullscript_sync |
| Vault decrypt | clinic_cron_secret, clinic_portal_base_url = http://192.168.1.101:3000 |
| Manual triggers → R940 clinic | HTTP 200 (all 3 routes) |
Actions taken:
- Restored
cron.jobrows from Gate B dump (pg_restoreassupabase_admin). - Recreated vault secrets (hosted dump ciphertext not decryptable on R940 pgsodium).
- Refactored
trigger_clinic_weekly_summary()to usetrigger_clinic_cron_route('/api/cron/weekly-summary').
Scripts: scripts/onset/t4-0-vault-align.py, scripts/onset/t4-0-smoke-pre-cutover.sh
T4-0b — storage.objects (PASS)¶
| Check | Result |
|---|---|
Metadata storage.objects |
20 |
| Buckets | templates (18), clinic-support-attachments (2) |
| Schema align | Added versioning_status, archived_at, is_delete_marker, is_versioned |
| File migration | 19 files API-migrated from hosted prod (~3.2 MB on disk) |
| Public URL | http://192.168.1.102:8000/storage/v1/object/public/templates/posts/1.png → 200 |
| Private signed URL | clinic-support-attachments/...png → sign OK |
Note: Hosted file download used Railway prod SUPABASE_SERVICE_ROLE_KEY (sb_secret_…, ref emxrmjysvxeboavhatry), not BWS legacy SUPABASE_SERVICE_ROLE_KEY (staging lzpyfohgfdohrtlamzek). RealOutcomes lesson applied: validate against live Railway, not stale BWS copy.
Script: scripts/onset/t4-0-migrate-storage-files.py
T4-0c — /patients/new bootstrap (PASS)¶
| Check | Result |
|---|---|
Client supabase.auth.getUser() |
Removed |
| Pattern | Server getClinicPortalContext() → NewPatientClient props |
| Deploy | VM 118 container recreated (onset-clinic-app) |
| Repo | Branch t4-0-patients-new-bootstrap on clinic.theonset.app |
Ryan device verify: Load /patients/new with Last1 session after Gate E login (LAN http://192.168.1.101:3000/patients/new).
T4-1 — onset-edge tunnel (PASS)¶
| Item | Value |
|---|---|
| Tunnel name | onset-edge |
| Tunnel UUID | fe2fa2de-d776-485f-85ed-84415f0c3493 |
| CNAME target | fe2fa2de-d776-485f-85ed-84415f0c3493.cfargotunnel.com |
| Connector | VM 118 onset-app — active (1 connector, 3 edge connections) |
| BWS | ONSET_APP_PROD_EDGE_CLOUDFLARED_TUNNEL_ID, _TUNNEL_CNAME, _TUNNEL_CREDENTIALS |
T4-2 — Ingress config (PASS, no DNS)¶
/etc/cloudflared/config.yml on VM 118:
tunnel: onset-edge
credentials-file: /etc/cloudflared/fe2fa2de-d776-485f-85ed-84415f0c3493.json
ingress:
- hostname: clinic.theonset.app
service: http://192.168.1.101:3000
- service: http_status:404
| Check | Result |
|---|---|
cloudflared tunnel ingress validate |
OK |
systemctl is-active cloudflared |
active |
| Clinic LAN | http://192.168.1.101:3000/ → 200 |
Fix applied: Origin must be 192.168.1.101:3000 (Docker binds LAN IP, not 127.0.0.1).
Script: scripts/onset/install-onset-edge-cloudflared.sh
T4-3 — Vault + env alignment (PASS)¶
| Item | R940 live value |
|---|---|
clinic_portal_base_url (vault) |
http://192.168.1.101:3000 |
clinic_cron_secret (vault) |
Matches ONSET_APP_PROD_CRON_SECRET (BWS ↔ VM 118 .env) |
VM 118 DATABASE_URL host |
192.168.1.102 (not hosted) |
VM 118 NEXT_PUBLIC_SUPABASE_URL |
http://192.168.1.102:8000 |
| Edge tunnel BWS | Created (see T4-1) |
At T4-4 DNS: Update vault clinic_portal_base_url to https://clinic.theonset.app before first post-cutover cron fire.
Rollback net unchanged: Railway clinic origin + hosted Supabase (emxrmjysvxeboavhatry, lzpyfohgfdohrtlamzek) remain live. iOS Release xcconfig untouched.
BWS legacy keys aligned (T4-3 closeout)¶
Legacy unprefixed SUPABASE_URL / SUPABASE_SERVICE_ROLE_KEY / SUPABASE_ANON_KEY updated to match ONSET_DB_PROD_* (R940). Clinic render path (render-onset-env-app.sh) already used prefixed keys only; legacy keys were a script/human landmine (RealOutcomes pattern).
Ready for T4-4 (Ryan — Sun 03:00–07:00 PDT)¶
- Update vault
clinic_portal_base_url→https://clinic.theonset.app - CNAME
clinic.theonset.app→fe2fa2de-d776-485f-85ed-84415f0c3493.cfargotunnel.com(proxied) - Run T4-R clinic E2E on prod hostname
- Reply
T-4 passor share failure detail
Do not merge clinic /patients/new PR or cut DNS until Ryan reviews this report.
Scripts added (lastvet-gates)¶
| Script | Purpose |
|---|---|
t4-0-vault-align.py |
Recreate vault secrets + weekly summary refactor |
t4-0-migrate-storage-files.py |
Hosted → R940 storage file API migration |
t4-0-smoke-pre-cutover.sh |
Cron + storage count verification |
install-onset-edge-cloudflared.sh |
T4-1/T4-2 tunnel install on VM 118 |
END T-4 prep report (STOP before DNS)