Tier 4 Onset T-3 Gate D Report — Identity FK Remap + Cleanup¶
Status: PASS — Ryan signed off D-1 (2026-08-29)
Date: 2026-08-29
Prior: TIER_4_ONSET_T3_GATE_C_REPORT.md (OAuth loop + callback infra confirmed)
Target DB: VM 119 onset-db @ 192.168.1.102 (Supabase stack supabase-db)
Executive summary¶
Ryan locked identity mapping: curryrg@gmail.com owns the Ryan Curry practitioner row. FK remap from legacy GoTrue auth.users.id → Last1 OAuth id_token.sub (public.identities.id) completed in a single transaction. Referential integrity scan PASS. Three promo-expired accounts deleted. hello@unicornryda.com left on legacy GoTrue (iOS/patient test workflow; no Last1 identity).
Outcome: Ryan confirmed curryrg@gmail.com Last1 login reaches clinic dashboard post-remap. Gate E unblocked.
1. Identity decision (locked)¶
| Choice | Last1 public.identities.id (OAuth sub) |
Onset practitioner | |
|---|---|---|---|
| Selected | curryrg@gmail.com |
2a805b21-5352-4316-bb4b-a5d4f02a8173 |
Ryan Curry (solo clinic) |
| Not selected | ryan@last1.org |
536a1797-d111-4717-8e2c-4814016dccad |
No practitioner row; would fail email match |
RealOutcomes lesson applied: remap target is public.identities.id, not auth.identities.id. Ryan confirmed login binds to 2a805b21… (see §7).
2. Pre-remap backup (mandatory)¶
| Item | Value |
|---|---|
| Path | /var/backups/onset/pre-gate-d-user-remap-20260829T230525Z.dump (VM 119) |
| Size | 453 KB (custom format, public + auth schemas) |
| SHA-256 | 22ea078bbf6b8743637cc7f5c7ce92c626b5337ed0ff081ab6eac71d1711748c |
| Sidecar | .dump.sha256 alongside dump |
| Gitignored | Yes (/var/backups/ outside repo) |
Rollback:
docker exec -i supabase-db pg_restore -Fc --clean --if-exists --no-owner --no-acl \
-U postgres -d postgres < /var/backups/onset/pre-gate-d-user-remap-20260829T230525Z.dump
3. Pre-remap onset-db state¶
Legacy auth.users.id |
Practitioner? | Notes | |
|---|---|---|---|
curryrg@gmail.com |
466dcb73-59fc-4167-a862-3abda0fca16b |
Yes — Ryan Curry | Remapped |
hello@unicornryda.com |
26b42005-344b-4f4b-9db7-58c19c3ca037 |
Yes — Test Provider | Deferred (§5) |
| 3 promo-expired | 474ef7c8…, 9b3cd379…, d97ede01… |
No | Deleted (§4) |
| 3 demo | @demo.theonset.app |
Demo patients | Untouched |
Map executed: 466dcb73-59fc-4167-a862-3abda0fca16b → 2a805b21-5352-4316-bb4b-a5d4f02a8173
Script: scripts/onset/gate-d-fk-remap.sql
Transaction pattern: rename legacy email → insert clone with Last1 id + canonical email → update 33 FK columns → delete legacy row.
4. FK remap results¶
Child rows updated (4 total across 3 tables)¶
| Table | Column | Rows remapped |
|---|---|---|
practitioners |
user_id |
1 |
clinics |
portal_agreement_accepted_by |
1 |
clinic_support_tickets |
submitted_by_user_id |
2 |
(30 other FK columns to auth.users) |
0 |
Post-remap verification (automated)¶
| Check | Result |
|---|---|
Single curryrg@gmail.com in auth.users |
PASS — id 2a805b21… |
Practitioner user_id aligned |
PASS — 2a805b21…, email curryrg@gmail.com |
Zero rows referencing legacy id 466dcb73… |
PASS |
FK orphan scan (all 33 columns → auth.users) |
PASS — zero orphans |
Legacy auth.users row removed |
PASS |
5. hello@unicornryda.com — role report (no remap)¶
| Signal | Value |
|---|---|
auth.users.id |
26b42005-344b-4f4b-9db7-58c19c3ca037 (unchanged) |
| Practitioner row | 1 (Test Provider) |
product_events |
233 |
shared_checkins (patient) |
23 |
Last1 public.identities row |
None |
Decision: Patient/iOS test workflow primary. Clinic practitioner row exists for operator testing, but without a Last1 identity there is nothing to remap for OAuth clinic login. Account stays on hosted GoTrue until iOS App Store cutover (Q4 plan). No Gate D remap performed.
6. Promo-expired account deletion¶
Deleted 3 dormant promo-trial accounts per T-0 sub-audit (no practitioner rows):
| Email / identity | Legacy id | Child rows removed before delete |
|---|---|---|
| (null — Apple) | 474ef7c8-3b58-4c49-be8e-86ecc68e5639 |
1 product_events |
jrdelacruz.a@gmail.com |
9b3cd379-19b0-4b83-ab76-d854a642eca1 |
10 product_events, 3 security_events, 1 onset_user_preferences |
vnmpxwcz4t@privaterelay.appleid.com |
d97ede01-235a-4f19-9481-1eeb6c02ff0d |
3 security_events |
Script: scripts/onset/gate-d-delete-promo-users.sql
Remaining auth.users: 5 (2 real + 3 demo).
7. Login verification¶
Automated (agent)¶
| Test | Result |
|---|---|
GET https://onset-app.tailc3bbdc.ts.net/login |
200 |
GET https://auth.last1.id/.well-known/openid-configuration |
200 |
Post-remap DB alignment (practitioners.user_id = target sub) |
PASS |
Manual (Ryan) — PASS¶
| # | Account | Result |
|---|---|---|
| D-1 | curryrg@gmail.com |
PASS — Ryan sign-off Gate D pass (2026-08-29). Dashboard access confirmed post-remap. |
8. Known post-Gate-D scope (not blockers for D-1)¶
/patients/newstill uses client-side GoTruesupabase.auth.getUser()— broken until separate migration- iOS app remains on hosted GoTrue until App Store release
ryan@last1.orgLast1 identity is separate; not mapped to Ryan Curry practitioner by design
9. Unblocked — Gate E next¶
| Gate | Work | Status |
|---|---|---|
| E | Partial GoTrue retirement — clinic off GoTrue, iOS path intact | Complete — await Ryan sign-off — TIER_4_ONSET_T3_GATE_E_REPORT.md |
| F | T-3 closeout | Blocked on Gate E pass |
Pre-remap dump retained at §2 for rollback if Gate E work regresses clinic auth.
END Gate D report