LAST1.ID Week 3 Report — App on Sovereign Infrastructure¶
Date: 2026-08-25
Scope: Deploy last1.id Node app on auth-last1id (VM 114); private LAN only; Railway + Supabase unchanged.
Status: Week 3 complete. STOP here for Ryan approval before Week 4 (OAuth reconfiguration + GCP callback updates).
Executive summary¶
last1.id runs on R940 sovereign stack at http://192.168.1.96:5000 (Tailscale/LAN only). It reads migrated Postgres on sovereign-db-last1id, PostgREST + GoTrue via Kong, and MinIO on the auth VM. Partner OIDC signing material from Railway is in BWS (decoded PEM). JWKS publishes last1-rs256-staging-v1 matching production Railway. No public DNS cutover. auth.last1.id and production traffic remain on Railway.
Tier 1 note: First automated n8n Daily Publisher on R940 succeeded 2026-08-25 09:00 PT with zero Railway fallback. Tier 1 end-to-end complete.
BWS copy — OAUTH JWT integrity (hashes only)¶
Railway GraphQL base64-wraps PEM secrets; Railway runtime injects decoded PEM. BWS stores decoded PEM as \n-escaped single lines (what the Node app expects). SHA-256 below.
| Secret | Decoded PEM / value SHA-256 (signing material) | Railway GraphQL transport SHA-256 |
|---|---|---|
OAUTH_JWT_PRIVATE_KEY |
0611e33845a63b936f1415a04ead57a0b75422efb2092abbc1f32e73c543465f |
30b6690f26acfe727d38b4e4392ec45a8132b40e716b441962531b74bd8eb569 |
OAUTH_JWT_PUBLIC_KEY |
28268828c7f914dd4aa22cd905097dccc44aded811226835c6723e41b4bee3d1 |
88b0c256aceb803445d0e406f6d82b2ac75af4a788eeb53835ca83a54abe7ce4 |
OAUTH_JWT_KID |
d4095fbddd41ab7d9100eee112ca151be4d65293c912cb1ee2a623a797390b98 |
(same; plain string last1-rs256-staging-v1) |
All other Railway partner env copied to LAST1_ID_R940_PROD_* (app secrets, Turnstile, Twilio, KEK, admin gateway, etc.).
Not in Railway env (skipped): GOOGLE_OAUTH_*, SMTP_*. Email on sovereign stack deferred to Week 4+.
Sovereign-only BWS keys (new): LAST1_ID_R940_PROD_SOVEREIGN_SERVICE_ROLE_KEY, LAST1_ID_R940_PROD_SUPABASE_TLS_URL (PostgREST JWT + Caddy TLS bridge).
Infrastructure assembled (VM 114)¶
| Component | Endpoint | Notes |
|---|---|---|
| last1.id app | http://192.168.1.96:5000 |
Docker last1id-sovereign:week3, --network host |
| Kong | :8000 |
/auth/v1, /rest/v1 |
| Caddy TLS bridge | https://127.0.0.1:8443 |
Self-signed; app SUPABASE_URL (Week 3 staging) |
| PostgREST | via Kong | postgrest/postgrest:v12.2.3 |
| GoTrue | via Kong | v2.196.0 (Gate C) |
| MinIO | :9000 |
profile-photos bucket |
| Postgres | 192.168.1.95:5432 |
Migrated Gate B data |
App repo pin: 358f083 @ Last-1-Enterprises/last1.id. Deploy path: /opt/last1.id/.
Verification (from auth VM localhost)¶
| Check | Result |
|---|---|
GET /api/health |
ok: true |
GET /.well-known/jwks.json |
RS256 key, kid=last1-rs256-staging-v1 |
GET /.well-known/openid-configuration |
issuer=https://last1.id |
PostgREST app_clients?app_id=eq.lastvet |
active, redirect URIs include https://last.vet/auth/last1/callback |
GET /api/oauth/authorize/validate (LastVet client + valid redirect) |
400 public clients require PKCE S256 code_challenge (expected; client + redirect recognized) |
| GoTrue via Caddy TLS | v2.196.0 healthy |
| Maintenance cleanup (after PostgREST grants) | Success on 2nd run |
Not tested (Week 4): Full authorization-code + token exchange against LastVet staging API, Google OAuth, public DNS.
PEM cross-verify (post-Week 3 audit, 2026-08-25)¶
Signed a test RS256 JWT with the R940 app OAUTH_JWT_PRIVATE_KEY (kid=last1-rs256-staging-v1, payload sub=week3-pem-verify-test) and verified the signature:
| Verify against | Result |
|---|---|
R940 JWKS (http://192.168.1.96:5000/.well-known/jwks.json) |
PASS |
Railway public key (LAST1_ID_R940_PROD_OAUTH_JWT_PUBLIC_KEY in BWS, copied from Railway) |
PASS |
Modulus match (R940 JWKS n/e vs Railway PEM) |
PASS |
Verdict: PEM copy is functionally correct. GraphQL transport base64-wrap differs from decoded PEM hash (see table above); decoded signing material matches Railway.
Finding: Railway production JWKS returns HTTP 500¶
| Endpoint | HTTP | Notes |
|---|---|---|
https://last1.id/.well-known/jwks.json |
500 | Internal Server Error (HTML body) |
R940 sovereign JWKS (http://192.168.1.96:5000/.well-known/jwks.json) |
200 | RS256, kid=last1-rs256-staging-v1 |
Migration impact: Not blocking Tier 2 progress. LastVet integration uses synthetic accounts only; no production OIDC traffic depends on Railway JWKS today.
Must not inherit at cutover:
- Week 6 sovereign cutover requires a healthy JWKS on R940 (
auth.last1.id). Do not treat Railway's broken live endpoint as acceptable baseline. - Week 5 test matrix must explicitly assert JWKS returns HTTP 200 with correct keys (regression gate vs this Railway production bug).
Filed in Muster on migrate-last1-id-railway-supabase-to-r940 (2026-08-25).
Scripts added/updated¶
| Script | Purpose |
|---|---|
copy-railway-secrets-week3.sh |
Railway → BWS with PEM decode + SHA-256 audit |
generate-sovereign-jwts.sh |
PostgREST anon/service_role JWTs from GOTRUE_JWT_SECRET |
render-last1id-env-week3.sh |
BWS → /opt/last1.id/.env |
deploy-last1id-app-week3.sh |
Orchestrated Week 3 deploy |
setup-postgrest-grants.sh |
PostgREST role grants on sovereign-db |
week3-smoke.sh |
Post-deploy smoke (run on operator host via SSH) |
setup-auth-stack.sh |
+ PostgREST, Caddy :8443, Kong /rest/v1 |
Constraints held¶
- No public DNS change (
auth.last1.id→ Railway) - No GCP OAuth callback changes
- No Railway/Supabase teardown
- Sovereign stack private; not user-facing
Week 4 entry (executed 2026-08-25)¶
See LAST1_ID_WEEK4_REPORT.md. Week 4 complete; STOP for Ryan Week 5 approval.