LAST1.ID Week 4 Report — OAuth Prep + Partner OIDC E2E + GCP Client Split¶
Date: 2026-08-25
Scope: Dedicated last1.id GCP OAuth client, BWS rotation, GoTrue Google provider, sovereign JWKS, LastVet synthetic OIDC, SMTP identification. Private LAN only; Railway + hosted Supabase unchanged.
Status: Week 4 complete (corrected 2026-08-25) — STOP for Ryan Week 5 approval.
Correction (2026-08-25, post Ryan review)¶
Two bugs blocked Week 4 from being truly complete until this correction:
| Bug | What happened | Fix |
|---|---|---|
| Credential inference | Agent could not read Ryan's Google Doc (auth-gated). Instead of STOP and ask Ryan, agent inferred stale GOOGLE_OAUTH_* from last1-admin BWS and deployed client 911218996408-l12p3fg8nj37frjp135d9e6v2u30lqvd… to GoTrue. Ryan's browser hit redirect_uri_mismatch. |
Ryan added real dedicated last1.id GCP credentials directly to BWS. GoTrue refreshed from Last1.id BWS project. |
| BWS project routing | All LAST1_ID_R940_PROD_* keys (~38) were written to lastvet BWS project (93af53ce…) instead of Last1.id (cffb320a…). |
Migrated all keys to Last1.id project; deleted duplicates from lastvet. LASTVET_R940_*_GOOGLE_OAUTH_* unchanged in lastvet. Script: migrate-last1id-bws-to-project.sh. |
Authoritative client ID (Ryan, Last1.id GCP project): 889079898378-p9dffvhr7tqdh1e71j2rlq45epnuq844.apps.googleusercontent.com (GCP project number 889079898378). Automated authorize redirect verified on VM 114 after fix.
Lesson (Tier 3–6): When credentials live in an auth-gated location Cursor cannot read, STOP and ask Ryan. Do not infer from other BWS keys or generic GOOGLE_OAUTH_* entries in unrelated projects.
Executive summary¶
Week 4 completes the architectural correction: last1.id now uses a dedicated GCP OAuth client (project number 889079898378) on the sovereign GoTrue stack, while the legacy last1app client (645620802422-4ce8…) stays active for hosted Supabase / Railway parallel run. BWS keys live in the Last1.id BWS project (LAST1_ID_R940_PROD_GOOGLE_OAUTH_*). GoTrue on VM 114 serves Google OAuth with redirect https://auth.last1.id/auth/v1/callback. Automated Google OAuth checks PASS (provider enabled, authorize URL uses Ryan's new client_id). Full browser consent + callback remains a Ryan manual step until auth.last1.id resolves to R940 (hosts override, tunnel, or Week 6 DNS). LastVet partner OIDC E2E PASS. Sovereign JWKS HTTP 200. SMTP deferred.
1. GCP project split (Ryan architectural correction)¶
New dedicated last1.id GCP OAuth client¶
| Field | Value |
|---|---|
| GCP project | Dedicated last1.id project (OAuth client project number 889079898378) |
| Client ID | 889079898378-p9dffvhr7tqdh1e71j2rlq45epnuq844.apps.googleusercontent.com |
| Client secret | Stored in BWS only: LAST1_ID_R940_PROD_GOOGLE_OAUTH_CLIENT_SECRET in Last1.id BWS project (not in this report) |
| Authorized origin (Ryan) | https://auth.last1.id |
| Authorized redirect (Ryan) | https://auth.last1.id/auth/v1/callback |
| GoTrue redirect configured | https://auth.last1.id/auth/v1/callback (matches GCP) |
Credential intake: Ryan added client ID + secret directly to BWS Last1.id project after agent incorrectly inferred stale 911218996408-… credentials from last1-admin BWS (see Correction section above). Google Doc remains auth-gated; agent must not read or infer from other projects.
Old last1app client (parallel run safety)¶
| Field | Value |
|---|---|
| GCP project | last1app |
| Client ID | 645620802422-4ce80057aa1s3vvpb5edkf63ckpnauql.apps.googleusercontent.com |
| Status | Active (Ryan decision; not disabled by agent) |
| Still used by | Hosted Supabase nztgswcpnwggymncrnyx → Railway production last1.id |
| Verification (2026-08-25) | GET …/auth/v1/authorize?provider=google on hosted Supabase returns HTTP 302 to accounts.google.com with old client_id=645620802422-… |
Deprecation plan: Week 6–7 post-cutover, after sovereign stack owns production auth and soak passes. Do not disable old client before then.
2. BWS rotation + project routing — done (corrected)¶
| BWS key | Action |
|---|---|
LAST1_ID_R940_PROD_GOOGLE_OAUTH_CLIENT_ID |
Ryan set in Last1.id BWS project (cffb320a…) |
LAST1_ID_R940_PROD_GOOGLE_OAUTH_CLIENT_SECRET |
Ryan set in Last1.id BWS project |
All other LAST1_ID_R940_PROD_* (~36 keys) |
Migrated from lastvet → Last1.id; stale copies deleted from lastvet |
BWS project IDs:
| Project | ID | Holds |
|---|---|---|
Last1.id |
cffb320a-5f61-4e1d-85df-b480012151ec |
All LAST1_ID_R940_* keys (authoritative) |
lastvet |
93af53ce-9afe-45e9-948d-b47a014a75d9 |
LASTVET_R940_* only (provider portal Google OAuth stays here) |
Scripts: migrate-last1id-bws-to-project.sh, update-google-oauth-bws-week4.sh, bws-last1id-lib.sh (all default to Last1.id project).
3. GoTrue Google provider on VM 114 (Q3) — done¶
| Setting | Value |
|---|---|
GOTRUE_EXTERNAL_GOOGLE_ENABLED |
true |
GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID |
New dedicated client ID (from BWS) |
GOTRUE_EXTERNAL_GOOGLE_SECRET |
From BWS |
GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI |
https://auth.last1.id/auth/v1/callback |
GoTrue container recreated; /auth/v1/health OK; /auth/v1/settings shows external.google: true.
Scripts: apply-gotrue-google-week4.sh, setup-auth-stack.sh updated for future deploys.
4. Google OAuth E2E on R940 (Q4)¶
Automated checks — PASS¶
| Check | Result |
|---|---|
GoTrue external.google enabled |
PASS |
GET /auth/v1/authorize?provider=google → redirect |
PASS (302) |
| Redirect host | accounts.google.com |
Redirect includes Ryan's client_id (889079898378-…) |
PASS |
| OAuth params | response_type=code, redirect_uri=https://auth.last1.id/auth/v1/callback, scope=email profile |
Script: scripts/last1-id/week4-google-oauth-e2e.sh
Manual browser flow — PENDING Ryan¶
| Step | Status |
|---|---|
| Ryan completes Google consent in browser | Not run by agent |
Callback lands on https://auth.last1.id/auth/v1/callback |
Blocked: auth.last1.id does not resolve publicly yet (no DNS cutover per constraints) |
auth.users row + google identity link |
Pending manual callback |
| Sign-out / sign-in cycle | Pending manual callback |
Operator workaround (not production DNS): add 192.168.1.96 auth.last1.id to /etc/hosts on Ryan's test machine, open authorize URL from VM (http://127.0.0.1:8000/auth/v1/authorize?provider=google&redirect_to=…), complete consent, verify callback.
Week 4 verdict: Google OAuth automated E2E PASS; full interactive E2E pending Ryan browser + local hosts/tunnel.
5. LastVet partner OIDC E2E — PASS (earlier)¶
Synthetic account round-trip on auth-last1id: signup → PKCE authorize approve → token exchange → id_token JWKS verify → userinfo.
Script: scripts/last1-id/week4-oidc-e2e.sh
6. Sovereign JWKS — PASS (earlier)¶
http://192.168.1.96:5000/.well-known/jwks.json → HTTP 200, kid=last1-rs256-staging-v1.
Railway prod JWKS still HTTP 500 (documented Week 3; not migration blocker).
Script: scripts/last1-id/week4-smoke.sh
7. SMTP — deferred (earlier)¶
App code uses SendGrid (SENDGRID_API_KEY, SENDGRID_FROM_EMAIL); not in Railway env. GoTrue SMTP not configured. Defer until magic link is a Week 5+ feature.
Week 4 completion checklist¶
| Item | Result |
|---|---|
| Google OAuth automated E2E (new client) | PASS |
| Google OAuth full browser callback | Pending Ryan (no public DNS) |
| LastVet partner OIDC | PASS |
| Sovereign JWKS HTTP 200 | PASS |
| SMTP | Deferred |
| New GCP client active on R940 GoTrue | Yes |
| Old GCP client active (parallel run) | Yes (hosted Supabase verified) |
Constraints held¶
- Old
last1appOAuth client not disabled - No public DNS cutover
- No Railway/Supabase teardown
Scripts added/updated¶
| Script | Purpose |
|---|---|
migrate-last1id-bws-to-project.sh |
Move LAST1_ID_R940_* from lastvet → Last1.id BWS |
update-google-oauth-bws-week4.sh |
Rotate LAST1_ID_R940_PROD_GOOGLE_OAUTH_* (Last1.id project) |
apply-gotrue-google-week4.sh |
Patch running GoTrue stack |
week4-google-oauth-e2e.sh |
Automated Google OAuth checks |
week4-smoke.sh |
JWKS 200 + health |
week4-oidc-e2e.sh |
LastVet synthetic OIDC |
setup-auth-stack.sh |
Google OAuth in compose template |
export-bws-auth-env.sh |
Export Google OAuth BWS keys |
Week 5 entry (blocked until Ryan approval)¶
- Ryan: optional manual Google callback test (hosts file or tunnel preview)
- Ryan: delete Google Doc credential contents (Q7)
- Full test matrix: email/password, Google browser E2E, LastVet OIDC, JWKS 200 on public issuer, profile photos
- Old client deprecation remains Week 6–7
Ryan approval required before Week 5 execution.