Tier 3 Pre-Migration Audit — last1-admin (T3-0)¶
Status: Audit complete. Awaiting Ryan review before Tier 3 Week 1 execution.
Date: 2026-08-27
Scope: Planning only (T3-0). No migration work executed.
Product: admin.last1.enterprises — Last 1 internal ops portal
Repo: Last-1-Enterprises/last1-admin
Muster item: migrate-last1-admin-compute-to-r940
Executive summary¶
Tier 3 is a compute-only migration: move the last1-admin Node monolith off Railway onto R940 while keeping Supabase Auth and admin metadata on hosted project tcthzakppndkykatoefx until Tier 6.
This is materially simpler than Tier 2 (no Postgres migration, no GoTrue, no Kong ingress gap for a public IdP). It is more complex than Tier 1 n8n because last1-admin is a multi-product BFF holding service-role keys and HMAC gateway secrets for six business units.
Sovereignty / revenue framing (Ryan, 2026-08-27): Completing Tiers 3–6 removes remaining Railway and Supabase dependencies from the Last 1 portfolio, strengthening the sovereignty narrative used in SBIR and pitch conversations. Tier 3 alone removes one Railway surface but leaves the shared Supabase auth dependency visible until Tier 6. Still worth doing now: it is low user-risk, unlocks the next full-stack rehearsals (RealOutcomes, Onset), and puts the internal ops hub on the same metal as auth.last1.id and api.last.vet.
Recommended calendar: 2–4 days compressed execution (n8n-style runbook), not an 8-week Tier 2 pattern. Pre-work before Week 1 is more important than week count.
Top pre-flight risks:
LAST1_ID_API_BASEmay still point athttps://last1.id(code and.env.exampledefault) while sovereign issuer ishttps://auth.last1.id.- Tier 0 muster blockers (
infra-consolidation-playbook-approve,infra-bw-naming-r940-products-approve) unless Ryan explicitly waives for kickoff. - Tier 2 lesson: verify every unit switcher and at least one write path per product in a browser, not only curl/smoke scripts.
1. Current architecture¶
1.1 Deployment¶
| Layer | Current state |
|---|---|
| Compute | Railway — Dockerfile Node 22 Alpine, port 5000, node dist/index.cjs |
| Domain | https://admin.last1.enterprises (Tier 3 compute; not Cloudflare Pages) |
| Build | Vite 7 client + Express 5 server monolith; Railway build args: VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY, VITE_LAST1_API_BASE |
| Last push | 2026-08-18 (main) |
| Memory / replicas / Railway cost | Unknown (no Railway API audit in T3-0) |
Target posture (from consolidation plan): dedicated small R940 app VM (or share ops VM initially); ingress via Cloudflare tunnel on lastvet-edge (same pattern as n8n Tier 1).
1.2 Repo and tech stack¶
| Field | Value |
|---|---|
| Repo | Last-1-Enterprises/last1-admin (private) |
| Branch | main |
| Pattern | Same monolith shape as pre-L2-7 last1.id: Express BFF + React SPA in one process |
| Runtime | Node 22 (Dockerfile comment: Supabase Realtime needs native WebSocket) |
| UI | React 18, Wouter, Radix, Tailwind, TanStack Query |
| Auth client | @supabase/supabase-js v2.93 |
| Optional legacy | pg pool for LastVet direct DB (local dev only; prod uses API proxy) |
Code volume (GitHub tree audit):
| Metric | Count |
|---|---|
| Total blobs | ~160 |
| TypeScript / TSX files | ~137 |
| TypeScript LOC (GitHub language stats) | ~1.18 MB source |
| SQL docs in repo | 2 (docs/ADMIN_TELEMETRY_TABLE.sql, docs/LASTVET_OPS_DIGEST_SENT.sql) |
| Checked-in Supabase migrations | None (schema lives in shared project history) |
Business-unit surface (client pages under client/src/pages/):
| Unit | Admin modules |
|---|---|
| last1.app | metrics, governance, check-ins, reports |
| last1.id | identities, issuers, app-clients, audit, abuse |
| RealOutcomes | dashboard, users |
| RadioCheck | units, users, messaging, org-admins |
| Onset | dashboard, clinics, users, sync-diagnostics, support |
| LastVet | veterans, providers, consent, Part 2 monitor, privacy notices, ops digest |
| Angel | dashboard, invites, users, health |
| Marketing | subscribers, broadcasts, sequences (SendGrid + shared Supabase marketing_*) |
1.3 Database¶
| Database | Project ref | Role for last1-admin |
|---|---|---|
| Shared "Last 1 App + Radio Check" | tcthzakppndkykatoefx |
Primary: Supabase Auth login, system_admin_memberships, admin profiles, telemetry, marketing tables |
| Onset Supabase | Separate project (ref not in admin repo) | Read/write via ONSET_SUPABASE_* service role for clinic dashboards |
| RadioCheck Supabase | Separate URL in env | Direct queries + integration secret |
| RealOutcomes Supabase | cpocwrygxlqhzvmlrpjv |
Not direct DB — HTTP proxy via REALOUTCOMES_API_BASE + gateway HMAC |
| LastVet clinical DB | R940 Postgres behind api.last.vet |
Not in admin Supabase — BFF proxies to /api/internal/admin/* |
Tier 3 constraint (locked): move compute only; do not migrate tcthzakppndkykatoefx in Tier 3. Auth DB moves with Tier 6 (last1.app + RadioCheck bundle).
Tables last1-admin is known to touch on shared Supabase:
system_admin_memberships,org_admin_memberships,user_profilesadmin_telemetry_eventsmarketing_*(Onset, LastVet, Last1.org brands)
1.4 Data sensitivity¶
| Data class | In admin DB? | Notes |
|---|---|---|
| LastVet veteran ePHI at rest | No | Production proxies to api.last.vet; README forbids LASTVET_DATABASE_URL in prod |
| LastVet PHI displayed in UI | Yes (via API) | Veterans, providers, consent views fetch from LastVet internal admin API |
| 42 CFR Part 2 records at rest in admin | No | Part 2 Monitor page reads metadata/aggregates through LastVet API, not stored in admin Supabase |
| Onset clinical / PHI-adjacent | Possible | Onset Supabase service-role access for clinic admin dashboards |
| Identity PII | Yes | last1.id admin module, RadioCheck user lists |
| Marketing subscriber PII | Yes | Email addresses across products |
| High-privilege secrets at runtime | Yes | Multiple service-role keys, gateway HMAC secrets, Angel/LastVet bearer tokens in one process |
Phase 1 LastVet note: last1-admin is operator infrastructure, not the veteran-facing coordination layer. Clinical data flows are read/proxy paths for Ryan's ops work, not a new persistence plane for ePHI.
1.5 Who uses it¶
| Audience | Access |
|---|---|
| Internal operators only | Consolidation plan posture; not a customer-facing product |
| Domain-gated RBAC | Email domain maps to allowed units (last1.enterprises → all units; product domains scoped) |
| System roles | super_admin, platform_admin, security_admin, support_admin, read_only_auditor |
| Known recipients | Ops digest → ryan@last1.enterprises (.env.example) |
| Login entry | Supabase Auth on shared project; company admin sign-in documented as https://auth.last1.id/login?entry=admin |
User count: not measured in T3-0. Expect Ryan-primary with possible additional @last1.enterprises operators. Onset clinic staff use clinic.theonset.app, not admin directly, except via deep links to admin dashboards.
2. Dependencies (both directions)¶
2.1 Upstream (last1-admin consumes)¶
| Service | Mechanism | Post–Tier 2 status |
|---|---|---|
| last1.id | LAST1_ID_API_BASE + LAST1ID_ADMIN_GATEWAY_SECRET HMAC proxy |
Sovereign on R940 at auth.last1.id — verify Railway env matches |
| last1.app | LAST1_API_BASE + gateway |
Still Railway |
| RealOutcomes | REALOUTCOMES_API_BASE + ADMIN_GATEWAY_SECRET |
Still Railway + Supabase |
| Onset | ONSET_SUPABASE_*, ONSET_ADMIN_METRICS_TOKEN |
Still Railway + Supabase |
| RadioCheck | RADIOCHECK_SUPABASE_*, integration secret |
Tier 6 bundle |
| LastVet | LASTVET_API_BASE, LASTVET_INTERNAL_ADMIN_SECRET |
Already R940 (api.last.vet) |
| Angel | ANGEL_API_BASE, ANGEL_INTERNAL_ADMIN_SECRET |
Cloudflare Worker |
| SendGrid | SENDGRID_API_KEY |
Marketing sends + LastVet ops digest |
| Shared Supabase auth | VITE_SUPABASE_*, SUPABASE_SERVICE_ROLE_KEY |
Hosted until Tier 6 |
2.2 Downstream (others consume admin)¶
Admin is mostly terminal for data (nothing reads admin's DB for product runtime). Verified exceptions where other services depend on admin-initiated traffic or shared secrets:
| Consumer | Dependency |
|---|---|
| RealOutcomes | Validates ADMIN_GATEWAY_SECRET on admin gateway routes |
| last1.id | Admin gateway HMAC for privileged identity ops |
| LastVet API | Provider approval and internal admin routes via LASTVET_INTERNAL_ADMIN_SECRET |
| Angel Worker | Matching ANGEL_INTERNAL_ADMIN_SECRET |
| clinic.theonset.app | Deep link / reference to admin.last1.enterprises |
| Muster MCP | MUSTER_OAUTH_CONSENT_SECRET stored in last1-admin BWS project |
Proxy route inventory (server/proxy.ts, server/index.ts):
POST /api/proxy/last1,/api/proxy/realoutcomes,/api/proxy/radiocheck,/api/proxy/last1id,/api/proxy/org-last1id/api/lastvet/*,/api/angel/*(dedicated routers)- Onset metrics, support, sync-diagnostics, marketing routes
- In-process LastVet ops digest scheduler (
startLastVetOpsDigestScheduler())
Cutover implication: downtime affects Ryan's ops workflows, not end-user product login flows. Gateway secret mismatch during cutover would break admin → product writes, not product → product traffic.
3. Complexity vs Tier 2¶
| Dimension | Tier 2 (last1.id) | Tier 3 (last1-admin) |
|---|---|---|
| Scope | Full sovereign stack: compute + Postgres + GoTrue + Kong + DNS split | Compute only |
| Calendar (actual/planned) | ~3.5 days execution after planning (exceptional) / 5–8 weeks planned | 2–4 days (planning estimate) |
| Database migration | Yes — off Supabase nztgswcpnwggymncrnyx |
No — stays on tcthzakppndkykatoefx |
| Auth migration | Self-hosted GoTrue on R940 | Keeps Supabase Auth (hosted) |
| Ingress risk | Kong SPA gap caught post-closeout (L3) | Single monolith on one port; simpler than Kong multi-service |
| Code volume | Large monolith + marketing (pre-L2-7) | ~160 files; smaller than last1.id |
| Integration fan-out | Partner OIDC, email, MinIO | 7 product proxies + SendGrid + 3 Supabase URLs |
| Runbook maturity | Full (LAST1_ID_MIGRATION_RUNBOOK.md, gate reports) |
Missing — generic consolidation plan + n8n precedent only |
| Closest precedent | — | Tier 1 n8n (compute + tunnel + soak) |
Existing docs quality¶
| Document | Quality | Gap |
|---|---|---|
LAST1_INFRASTRUCTURE_CONSOLIDATION_PLAN.md §6 |
Strong product inventory | No Tier 3 execution runbook |
Repo README.md |
Strong env var catalog + smoke scripts | Stale LastVet "AWS RDS" language; duplicate .env.example sections |
N8N_MIGRATION_RUNBOOK.md |
Good compute-only template | Not adapted for last1-admin |
Dedicated LAST1_ADMIN_MIGRATION_PLAN.md |
Missing | Should be T3-1 output after Ryan approves T3-0 |
Technical debt worth naming¶
LAST1_ID_API_BASEdefaulthttps://last1.idin code and.env.example— stale post–Tier 2.- Gateway secret alias sprawl —
ADMIN_GATEWAY_SECRET,LAST1_ADMIN_GATEWAY_SECRET,LAST1ID_ADMIN_GATEWAY_SECRETwith fallback chains. - Legacy
lastvet-db.tsdirect Postgres — disabled when API configured, but code remains. - No checked-in Supabase migrations — schema coupling opaque until Tier 6.
- In-process ops digest scheduler — must survive VM restart policy (systemd vs in-app cron).
- BWS cross-project credential inference — Tier 2 Week 4 incident: stale
GOOGLE_OAUTH_*in last1-admin BWS was wrongly used for last1.id. Never infer across BWS projects.
Cursor context already touched¶
- Aug 2026: Tailscale API key placed in last1-admin BWS; ACL policy work for Ryan + Robert observability.
- Tier 2 Week 4: last1-admin BWS incorrectly sourced for last1.id GCP OAuth credentials (Ryan corrected directly).
- No prior Tier 3 migration execution in agent transcripts; Tier 2 closeout repeatedly deferred to "when Ryan schedules."
4. Risk assessment¶
| Risk | Severity | Notes |
|---|---|---|
Wrong LAST1_ID_API_BASE after cutover |
High | last1.id admin module breaks; verify Railway prod env before deploy |
| Gateway secret mismatch | High | Breaks proxied writes to RealOutcomes / last1.id; do not rotate during cutover |
| Service-role key exposure on new VM | Critical | Multiple SRKs in one process; Tailscale-only + UFW + BWS LAST1ADMIN_R940_* |
| LastVet Part 2 admin outage | High (compliance ops) | Ryan loses Part 2 monitoring UI; run smoke:lastvet + browser probe |
| Ops digest scheduler gap | Medium | Daily/weekly LastVet digest emails may stop if scheduler not restarted |
| Supabase latency from R940 | Low–Medium | Acceptable for hybrid Tier 3; monitor proxy telemetry |
| Real user impact | Low | Internal-only; Ryan-primary |
| Business impact if briefly down | Low–Medium | Blocks ops (provider approval, marketing sends, dashboards), not customer login |
| Data loss risk | Low for Tier 3 | No DB migration; worst case is misconfigured env pointing at wrong upstream |
| Cursor autonomous execution | Medium–high touch | VM deploy is automatable (n8n pattern); secret sync and multi-unit browser E2E need Ryan checkpoints |
Autonomy recommendation: Cursor can execute VM provision, Docker build, env render, curl smoke, soak monitoring autonomously with BWS + SSH access. Require Ryan browser sign-off on unit switcher matrix before Railway teardown (Tier 2 Kong lesson). Treat LastVet Part 2 and provider approval write paths as mandatory manual checks.
5. Recommended Tier 3 plan structure¶
Not an 8-week Tier 2 pattern¶
Tier 3 does not need Weeks 1–4 build / 5 test / 6 cutover / 7 teardown / 8 docs. Use a compressed n8n-style phase model:
| Phase | Duration | Deliverables |
|---|---|---|
| T3-0 | 1 session | This audit (done) |
| T3-1 | ~2 h | LAST1_ADMIN_MIGRATION_PLAN.md + env audit checklist + smoke matrix |
| T3-2 | ~4 h | R940 VM (or ops VM slot), Docker deploy, BWS env render, tunnel/DNS staging |
| T3-3 | ~4 h | Parallel soak: Railway + R940; curl + smoke scripts |
| T3-4 | ~2 h | Ryan browser E2E (all units) |
| T3-5 | ~1 h | DNS cutover admin.last1.enterprises → R940 |
| T3-6 | 24–48 h | Soak (internal-only policy from consolidation plan) |
| T3-7 | ~2 h | Railway teardown, runbook, muster update |
Total: 2–4 working days assuming Tier 0 approvals resolved and no env surprises.
Pre-work before Week 1 (T3-1) execution¶
| Item | Owner | Blocker? |
|---|---|---|
Approve or waive Tier 0 muster items (infra-consolidation-playbook-approve, infra-bw-naming-r940-products-approve) |
Ryan | Yes (muster) |
Railway prod env audit (~30 vars from README); confirm LAST1_ID_API_BASE=https://auth.last1.id |
Cursor + Ryan | Strongly recommended |
Approve BWS prefix LAST1ADMIN_R940_* per BITWARDEN_NAMING_CONVENTION.md |
Ryan | Yes for clean secret layout |
| Choose VM target (new small VM vs share ops/sovereign-app) | Ryan | Yes |
| Define browser E2E matrix (7 units × login + 1 read + 1 write where safe) | Cursor draft, Ryan approve | Recommended |
| Update repo README LastVet section (R940 not AWS) | Cursor (docs PR) | Nice-to-have pre-cutover |
6. Sequence recommendation (Tiers 3–6)¶
Locked order (consolidation plan, still valid)¶
| Tier | Product | Sovereignty story weight |
|---|---|---|
| 3 | last1-admin compute | Removes 1 Railway; partial (Supabase auth remains) |
| 4 | RealOutcomes (+ IRS cron) | Full stack off Railway + Supabase — strong pitch anchor |
| 5 | Onset clinic + Supabase | Clinical boundary; SOC 2 driver; highest care with PHI-adjacent data |
| 6 | last1.app + RadioCheck + angel.report app tier (+ admin auth DB) | Largest Supabase bundle; completes shared tcthzakppndkykatoefx story |
Should anything move earlier?¶
| Question | Recommendation |
|---|---|
| Stronger sovereignty anchor before admin? | No. Tier 3 is the right warm-up: lowest blast radius, internal-only, validates R940 app deploy pattern before full-stack cuts. RealOutcomes (Tier 4) is a stronger narrative win but also higher coordination (Stripe, edge functions, IRS cron, marketing split). Do Tier 3 first to de-risk ops hub relocation. |
| Dependency chains forcing reorder? | No change. Tier 2 (last1.id) unblocked identity-dependent paths. Tier 6 bundle constraint on shared Supabase is unchanged. RealOutcomes does not block admin compute move. |
| Parallel with Tier 3? | Planning only: T4-0 audit can run while T3 executes. Do not parallel two cutovers. SendGrid → RealSend remains a separate track (do not interleave). |
Sovereignty narrative progression (SBIR / pitch)¶
Use this sequencing in external conversations:
- Done: Universal identity sovereign on R940 (
auth.last1.id) — Tier 2. - Tier 3: Internal ops hub off Railway (hybrid auth OK to disclose honestly).
- Tier 4: First full product stack (app + DB) on R940 — RealOutcomes.
- Tier 5: Clinical-adjacent product on R940 — Onset (SOC 2 alignment).
- Tier 6: Shared consumer platform bundle off Supabase — completes "no hosted Postgres for Last 1 apps" claim.
Honesty point: until Tier 6, pitch language should say "compute sovereignty complete; database consolidation in progress" rather than implying zero Supabase dependency.
7. T3-0 verification matrix (for Week 1)¶
Execute before DNS cutover when Ryan authorizes T3-1:
| Check | Method | Pass criteria |
|---|---|---|
| Login | Browser | Supabase auth → admin shell loads |
| Unit: last1.id | Browser + proxy | Identity list loads via auth.last1.id |
| Unit: LastVet | smoke:lastvet + browser |
Stats + Part 2 monitor page |
| Unit: Angel | smoke:angel + browser |
Dashboard stats |
| Unit: Onset | Browser | Clinics/users dashboard |
| Unit: RealOutcomes | Browser | Dashboard loads via gateway |
| Unit: RadioCheck | Browser | Users/units list |
| Unit: last1.app | Browser | Metrics/governance view |
| Ops digest | Log check | Scheduler tick after VM restart |
| Gateway write | Ryan-approved safe action | e.g. read-only audit export or test flag (no prod destructive ops) |
8. Investigation limits (T3-0 honesty box)¶
- No local clone of last1-admin; repo facts via GitHub API only.
- Railway live env vars not read (prod
LAST1_ID_API_BASEunknown until T3-1 audit). - Supabase row counts / admin MAU not measured.
- BWS secret values not touched.
- No VM provisioning or deploy performed in T3-0.
9. Recommended Ryan decisions (post-audit)¶
- Authorize T3-1 — create
LAST1_ADMIN_MIGRATION_PLAN.mdfrom this audit + n8n runbook template. - Waive or complete Tier 0 muster blockers before execution.
- Confirm VM target (new VMID vs shared ops host).
- Confirm soak window (24–48 h internal-only, same as consolidation plan).
- Schedule browser E2E window with Ryan present for T3-4.
10. Related documents¶
- LAST1_INFRASTRUCTURE_CONSOLIDATION_PLAN.md — §6 last1-admin, tier sequencing
- LAST1_ID_MIGRATION_PLAN.md — Tier 2 lessons, Tier 3–6 blocker table
- N8N_MIGRATION_RUNBOOK.md — compute-only precedent
- BITWARDEN_NAMING_CONVENTION.md —
LAST1ADMIN_R940_*prefix - Muster:
migrate-last1-admin-compute-to-r940
T3-0 verdict: Tier 3 is ready for planning sign-off. Scope is bounded, risks are manageable, and execution should follow the compressed n8n pattern, not Tier 2's week model. The highest-value pre-flight action is a Railway env audit confirming LAST1_ID_API_BASE=https://auth.last1.id before any R940 deploy.