Skip to content

R940 Product Isolation Principles v1

Status: Approved (Ryan, 2026-08-29 sprint kickoff)
Supersedes: conflicting guidance in PRODUCTS_ISOLATION_ARCHITECTURE_2026-08-29.md §1.3 (shared Caddy-only product ingress)
Scope: Last 1 portfolio R940 migrations (Tiers 3–8)


1. Ingress

Edge Host cloudflared location Role
lastvet-edge lastvet-edge VM .89 lastvet-edge VM LastVet only — clinical API, provider surfaces. Do not add product or auth routes.
last1id-edge auth-last1id VM .96 Same VM as origin (Option A) Platform identity only — auth.last1.id → Kong :8000
realoutcomes-edge realoutcomes-app VM .99 Product app VM realoutcomes.app → app :5000; optional Supabase Kong hostname if browser needs Storage/Functions
onset-edge Onset app VM (TBD) Product app VM Onset apex + optional Supabase hostname
last1app-edge last1.app app VM (TBD) Product app VM last1.app + RadioCheck bundle (shared Supabase)
admin-edge admin-app VM .97 Product app VM admin.last1.enterprises

Rationale: Two Cox static IPs and no Netgate multi-IP NAT yet → per-product Cloudflare Tunnels instead of shared grey-cloud Caddy for all products. LastVet keeps dedicated edge unchanged.

LastVet API note: api.last.vet may use Cox + Caddy grey-cloud in parallel with lastvet-edge tunnel entries for rollback. Do not conflate with product tunnels.


2. Identity

Rule Detail
Single IdP All products authenticate via https://auth.last1.id
Integration @last1id/sdk (OIDC redirect + JWT validation). No product-local GoTrue at steady state.
Product Supabase Postgres, PostgREST, Storage, Edge Runtime only — GoTrue retired after unification
Migration Google/email users re-link to sovereign identities; remap public.users FKs

3. Execution gates

Sprint Product / scope Ryan gate before next
SPRINT-1 last1id-edge + DNS cutover Required before SPRINT-2
SPRINT-2 RealOutcomes auth unification Required before SPRINT-3
SPRINT-3 RealOutcomes realoutcomes-edge + DNS Required before SPRINT-4
SPRINT-4 RealOutcomes E2E (Ryan browser) PASS required before SPRINT-5
SPRINT-5 RealOutcomes teardown —
SPRINT-6 Onset (real users — extra care) —
SPRINT-7 last1.app + RadioCheck bundle —
SPRINT-8 Admin reconnect + teardown After all upstream sovereign

No soak periods. End-to-end execution with explicit STOP between sprints.


4. Invariants (do not drift)

  1. Never add auth.last1.id to lastvet-edge again.
  2. Never add RealOutcomes/Onset/admin hostnames to lastvet-edge.
  3. Each product tunnel runs on that product's app VM (Option A).
  4. Document tunnel UUID + CNAME target in BWS (*_EDGE_CLOUDFLARED_* keys).
  5. Onset: verify with real family/friend users before Railway/Supabase teardown.

5. VM reference (current)

VMID Hostname LAN IP Tunnel
110 lastvet-edge .89 lastvet-r940 (LastVet only)
114 auth-last1id .96 last1id-edge
116 realoutcomes-app .99 realoutcomes-edge (SPRINT-3)
117 realoutcomes-db .98 LAN-only; optional Kong via realoutcomes-edge
115 admin-app .97 admin-edge (SPRINT-8)

6. References

  • PRODUCTS_ISOLATION_ARCHITECTURE_2026-08-29.md — audit that led to this reconciliation
  • scripts/last1-id/install-last1id-edge-cloudflared.sh — SPRINT-1 install
  • scripts/last1-id/verify-last1id-edge.sh — PF checks
  • scripts/last1-id/remove-auth-route-from-lastvet-edge.sh — lastvet-edge cleanup