Skip to content

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.