Last 1 Enterprises — Infrastructure Consolidation Plan¶
Status: Planning only (2026-08-20). Do not execute migrations from this document without Ryan review.
Branch: docs/last1-consolidation-plan (lastvet-gates). Do not merge until Ryan accepts sequencing.
Scope: Migrate Last 1 products off Railway + Supabase onto R940, one product (or tightly coupled bundle) at a time. SendGrid → RealSend is a separate track (pattern proven on MATR).
Drivers: cost, sovereignty story consistency, SOC 2 path for Onset, security posture.
Method: Read-only inventory from GitHub + Proxmox + existing gates docs. No Railway/Supabase/SendGrid/BWS mutations. No product code changes.
Related: R940_PLATFORM_ARCHITECTURE.md · LASTVET_MIGRATION_PLAN.md · BITWARDEN_NAMING_CONVENTION.md · Muster decide-r940-consolidation-scope-for-remaining-la / reference-matr-sendgrid-realsend-migration-patte
Executive summary¶
R940 has headroom (12 VMs, ~444 GiB RAM allocated of ~3 TiB; tank-fast ~13.8T free; tank-bulk ~55T free). Capacity is not the blocker. Coupling is.
| Finding | Implication |
|---|---|
Shared Supabase tcthzakppndkykatoefx (“Last 1 App + Radio Check”) is used by last1.app, RadioCheck, and last1-admin auth |
Tier 6 must move as a bundle (or split the DB first). last1-admin compute can move earlier only if it keeps pointing at this project until the bundle cutover. |
| monthly-irs-sync is not a product | It is a Railway cron inside RealOutcomes (railway.cron.toml). Fold into RealOutcomes migration; do not schedule as a separate Tier 1 “product.” |
| onset-web is already off Railway | Cloudflare Pages. Railway/Supabase work for Onset is primarily clinic.theonset.app (+ shared Onset Supabase for mobile). |
| last1.id is identity critical path | RadioCheck edge last1-id-callback, LastVet/Onset OAuth env surface, admin gateway. Treat as high-risk and migrate before or carefully coordinated with dependents. |
| Per-tenant Postgres remains the R940 rule | Do not dump all products into one shared Postgres. Keep clinical/identity boundaries. The existing last1.app↔RadioCheck share is a legacy exception to resolve deliberately in Tier 6. |
| Live Railway memory/replicas and Supabase sizes | Not readable from this host (no Railway CLI session; Supabase MCP unauthenticated; BWS not queried for DB passwords). Repo-committed config + project refs are below; dashboards needed for exact $ and row counts. |
| Recommended BW pattern | Per-product prefixes (LAST1ID_R940_*, ONSET_R940_*, …), not a universal LAST1_R940_* namespace. Aligns with existing LASTVET_ / ANGEL_ / SOVEREIGN_ / MERIDIAN_. Extension drafted in naming convention doc. |
Recommended sequence adjustments vs Ryan’s draft tiers: (1) demote standalone monthly-irs-sync; (2) keep n8n as Tier 1 warm-up; (3) allow last1-admin compute in Tier 2 but defer its Supabase until Tier 6; (4) treat last1.app + RadioCheck (+ admin auth DB) as one Tier 6 cutover; (5) keep Onset clinical as Tier 5 SOC 2 driver; (6) run SendGrid→RealSend as parallel batch, not interleaved with DB cutovers.
STOP: After this report, wait for Ryan to pick a start product and approve playbook + BW naming before any provisioning.
Investigation limits (honesty box)¶
| Source | Status |
|---|---|
| GitHub repos (Last-1-Enterprises) | Read via gh API |
Proxmox pve-r940 (qm list, zpool, node memory) |
Read via SSH |
| Railway dashboard (memory, replicas, live env, $) | Unavailable (railway CLI not installed/authed) |
| Supabase dashboard (disk size, extensions UI, live RLS count, MAU) | Unavailable (MCP needsAuth; no project passwords used) |
| BWS secret values | Not touched (constraint). Key names in last1-admin project were previously known from ops context; not re-listed here |
| User counts / PHI volume | Not determinable without DB login |
Where numbers are approximate, they are labeled.
Sub-task A — Product inventory¶
Shared map (dependencies)¶
last1.id ←── RadioCheck (edge last1-id-callback, OAuth)
←── LastVet / Onset (LAST1_ID_OAUTH_* / Connect)
←── last1-admin (LAST1_ID_API_BASE + gateway)
Supabase tcthzakppndkykatoefx ("Last 1 App + Radio Check")
├── last1.app (Railway app)
├── RadioCheck (mobile + edge functions)
└── last1-admin (auth / admin profiles)
Onset Supabase (project ref not in clinic .temp; separate from above)
├── clinic.theonset.app (Railway)
├── onset-ios / onset-android
└── last1-admin (ONSET_SUPABASE_* for admin dashboards)
RealOutcomes Supabase cpocwrygxlqhzvmlrpjv
├── RealOutcomes (Railway)
└── monthly-irs-sync (Railway cron in same repo)
onset-web → Cloudflare Pages only (no Railway)
radiocheck-web → separate Supabase yloemokdrxfjkfwkskim (marketing/Stripe functions)
n8n-railway → Railway only (no Supabase in repo)
1. last1.id¶
| Field | Finding |
|---|---|
| Repo | https://github.com/Last-1-Enterprises/last1.id · main · last push 2026-08-10 · TypeScript |
| Railway | railway.toml: Dockerfile builder; startCommand = node dist/index.cjs; healthcheck /api/health; restart on_failure ×10. Dockerfile: Node 22 alpine (WebSocket requirement). Port 5000. Memory/replicas: unknown (dashboard). |
Env (from .env.example / README) |
SUPABASE_*, VITE_SUPABASE_*, CREDENTIAL_SIGNING_KEY, optional Turnstile/Twilio, ADMIN_GATEWAY_SECRET, optional SENDGRID_API_KEY (org-admin handoff). Build args: VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY. |
| Supabase | Project nztgswcpnwggymncrnyx · Postgres 17.6.x (.temp/postgres-version) · Storage + Auth enabled · 71 SQL migrations · sampled ~34 CREATE POLICY / ~34 ENABLE RLS in first 50 files (underestimate if later files denser) · extensions: not fully enumerated without dashboard |
| Effort | L (identity authority, DID/VC, many dependents) |
| Dependencies | Upstream for RadioCheck, LastVet/Onset OAuth, last1-admin |
| Users | Unknown |
| Data posture | Identity, credentials, consent, trust events. Not clinical PHI, but high-sensitivity PII + signing keys |
| SendGrid | Optional; from-address example integrations@last1.id in deploy notes; transactional handoff |
2. onset (+ theonset / clinic)¶
| Surface | Hosting | Notes |
|---|---|---|
| clinic.theonset.app | Railway + Supabase | Clinic portal (PHI-adjacent clinical workflows, Fullscript) |
| onset-web | Cloudflare Pages | Marketing theonset.app / www.theonset.app — out of Railway migration |
| onset-ios / onset-android | App stores + Supabase | Clients of Onset Supabase |
| Field | clinic.theonset.app |
|---|---|
| Repo | https://github.com/Last-1-Enterprises/clinic.theonset.app · main · push 2026-08-10 |
| Railway | Checklist-driven Next app; NEXT_PUBLIC_APP_URL=https://clinic.theonset.app. No railway.toml in tree snapshot used for this report (deploy via Railway + checklist). Memory/replicas unknown. |
| Env | Supabase URL/keys, Fullscript, Stripe, SENDGRID_API_KEY, NOTIFY_FROM_EMAIL=Onset Clinic <notifications@theonset.app>, support inbox ryan@theonset.app, admin deep link to admin.last1.enterprises |
| Supabase | 42 migrations · ~48 CREATE POLICY · ~14 ENABLE RLS (sampled all 42) · Edge functions (fitness/protocol extract, practitioner-notifications) · Project ref not committed in .temp |
| Effort | XL (clinical + SOC 2 narrative + Fullscript + edge functions + mobile clients) |
| Dependencies | last1-admin Onset dashboards; last1.id Connect (platform assertion secret); Fullscript |
| Users | Unknown |
| Data posture | Clinical / PHI-adjacent (patients, protocols, practitioner tools). SOC 2 driver. |
| SendGrid | notifications@theonset.app transactional; marketing updates@theonset.app via last1-admin |
3. last1.app¶
| Field | Finding |
|---|---|
| Repo | https://github.com/Last-1-Enterprises/last1.app · main · push 2026-08-10 |
| Railway | Dockerfile Node 20; Vite build args for Supabase/Stripe/admin flags; CMD node dist/index.cjs port 5000. Separate admin.last1.app build flags (VITE_ADMIN_ONLY, PUBLIC_URL) documented in railway.toml. Memory/replicas unknown. |
| Supabase | Same project as RadioCheck/admin: tcthzakppndkykatoefx (“Last 1 App + Radio Check”) · last1.app repo has only 1 checked-in migration (schema mostly lives with RadioCheck history) |
| Effort | L alone; XL as bundle with RadioCheck |
| Dependencies | Shared DB with RadioCheck; Stripe; SendGrid; last1-admin gateway; IRS validation code paths distinct from RealOutcomes cron |
| Users | Unknown |
| Data posture | Org/funder platform data; beneficiary PII encryption mentioned in env comments; not LastVet PHI |
| SendGrid | noreply@last1.app (from last1.app .env.example / RadioCheck shared notes) · transactional |
4. radiocheck¶
| Field | Finding |
|---|---|
| Repos | https://github.com/Last-1-Enterprises/RadioCheck (mobile) · https://github.com/Last-1-Enterprises/radiocheck-web (web) |
| Railway | Mobile: none (App Store). Backend is Supabase (Auth/Realtime/Edge). radiocheck-web: Supabase functions (Stripe, form notify); not a classic Railway Node service in inventory |
| Supabase (app) | tcthzakppndkykatoefx · Postgres 17.6.x · 87 migrations · sampled 50 files: ~149 CREATE POLICY / ~63 ENABLE RLS (full count likely higher) · many Edge Functions (check-in, SMS, last1-id-callback, delete-account, …) |
| Supabase (web) | Separate project yloemokdrxfjkfwkskim |
| Effort | XL (edge functions + Realtime + shared DB + mobile cutover) |
| Dependencies | last1.id; shared DB with last1.app; Twilio; SendGrid on Pro/Enterprise |
| Users | Unknown |
| Data posture | Veteran check-in / org SMS; sensitive but not LastVet clinical EHR. Treat carefully. |
| SendGrid | Shared noreply@last1.app pattern for Pro/Enterprise email |
5. realoutcomes (+ monthly-irs-sync)¶
| Field | Finding |
|---|---|
| Repo | https://github.com/Last-1-Enterprises/RealOutcomes · main · push 2026-08-10 |
| Railway app | railway.toml: DOCKERFILE; restart ON_FAILURE ×3. Start via Dockerfile (standard Node dist). |
| Railway cron | railway.cron.toml: startCommand = node dist/cron/monthly-irs.cjs; schedule 0 3 1 * *; restart NEVER. This is monthly-irs-sync. |
| Supabase | cpocwrygxlqhzvmlrpjv · Postgres 17 · 17 migrations · ~16 policies / ~19 RLS enables · Edge functions (crawl, score, alerts, validations) · Storage bucket uploads |
| Effort | M–L (Stripe tiers, OpenAI/Firecrawl, edge functions, IRS cron) |
| Dependencies | last1-admin (ADMIN_GATEWAY_SECRET); optional last1 cert registry |
| Users | Unknown (Stripe plans imply some paying users; count not read) |
| Data posture | Nonprofit outcomes / grant data; not clinical PHI |
| SendGrid | hello@realoutcomes.app transactional |
6. last1-admin¶
| Field | Finding |
|---|---|
| Repo | https://github.com/Last-1-Enterprises/last1-admin · main · push 2026-08-18 |
| Railway | Dockerfile + Vite build args (VITE_SUPABASE_*, VITE_LAST1_API_BASE). Domain admin.last1.enterprises. |
| Supabase | Linked to tcthzakppndkykatoefx (same as last1.app + RadioCheck). Also talks to Onset and RadioCheck service-role URLs and LastVet/Angel APIs (not local DBs in prod). |
| Effort | M for compute move; L if auth DB moves with Tier 6 bundle |
| Dependencies | Proxies: last1.app, last1.id, realoutcomes, onset, last.vet, angel.report |
| Users | Internal operators only |
| Data posture | Admin metadata; holds service-role keys to multiple products. High blast radius if compromised. |
| SendGrid | Marketing senders for Onset (updates@theonset.app) and LastVet marketing tables |
7. n8n¶
| Field | Finding |
|---|---|
| Repo | https://github.com/Last-1-Enterprises/n8n-railway · main · push 2026-04-17 |
| Railway | FROM n8nio/n8n + start.sh (/data/.n8n). No Supabase. Minimal surface. |
| Effort | S (ideal Tier 1 warm-up) |
| Dependencies | Whatever workflows point at (needs live n8n audit at migrate time) |
| Users | Internal automation |
| Data posture | Workflow credentials may include secrets; inventory workflows before move |
| SendGrid | None in repo (workflows may call SendGrid; unknown) |
8. monthly-irs-sync¶
Not a standalone product. See RealOutcomes cron above. Migration effort folds into RealOutcomes (add a systemd timer or cron on the RealOutcomes R940 VM).
Sub-task B — R940 capacity¶
Current inventory (2026-08-20, qm list on pve-r940)¶
| VMID | Name | RAM (MiB) | Boot disk (GB) |
|---|---|---|---|
| 100 | agent-01 | 98304 | 200 |
| 101 | inference-01 | 65536 | 150 |
| 102 | meridian-eval | 32768 | 100 |
| 103 | meridian-rag | 65536 | 100 |
| 104 | sovereign-app | 32768 | 100 |
| 105 | sovereign-mem | 32768 | 100 |
| 106 | angel-local | 49152 | 100 |
| 107 | lastvet-api | 16384 | 100 |
| 108 | lastvet-db | 32768 | 100 |
| 109 | lastvet-imaging | 8192 | 100 |
| 110 | lastvet-edge | 4096 | 50 |
| 111 | observability | 16384 | 50 |
- VM count: 12 running
- RAM allocated: ~444 GiB of ~3.0 TiB host (~14.5%). ~2.8 TiB available on host metrics.
- Storage:
tank-fast13.9T ~13.8T free;tank-bulk55.9T ~55.3T free (ZFS avail metrics).
Per-product VM vs share¶
| Product | Recommendation |
|---|---|
| n8n | Small shared ops VM or dedicated 2 vCPU / 4–8 GB |
| last1-admin | Dedicated small app VM (or share ops VM initially) |
| RealOutcomes | App VM + own Postgres (or Postgres on same VM if tiny; prefer separate DB disk) |
| last1.id | Dedicated app + dedicated Postgres (identity blast radius) |
| Onset clinic | Dedicated app + dedicated Postgres (clinical boundary) |
| last1.app + RadioCheck | One shared Postgres until intentional split; 1–2 app tiers (API/edge replacement) |
| Object storage | Prefer Supabase Storage → MinIO only where needed; do not put clinical objects on lastvet-imaging without a new trust-boundary design |
Postgres consolidation decision¶
Decision recommendation (aligns with R940 architecture):
- Default: one Postgres per trust boundary (LastVet already separate; Onset separate; last1.id separate; RealOutcomes separate).
- Exception: keep last1.app + RadioCheck on one Postgres through Tier 6 cutover; schedule a later split only if product/legal boundaries require it.
- Reject: single “all Last1” Postgres on one VM. Violates documented per-tenant sovereignty and complicates SOC 2 / incident scope.
MinIO¶
LastVet already owns lastvet-imaging. New product object stores should be new ZFS datasets / MinIO instances (or temporary continue Supabase Storage until product cutover). No evidence these Railway products currently use R940 MinIO.
Sub-task C — Sequencing recommendation¶
Ryan’s draft (kept as spine)¶
| Tier | Intent |
|---|---|
| 0 | Prerequisites (playbook, BW naming, capacity) |
| 1 | Low-risk warm-ups |
| 2 | Internal tools |
| 3 | Bounded real users |
| 4 | Critical identity (last1.id) |
| 5 | Clinical / PHI (Onset bundle) |
| 6 | Platform apps (last1.app + RadioCheck) |
Adjustments¶
| Change | Why |
|---|---|
| Tier 0 now | This document + BW naming extension + Muster items. Capacity already green. Still need: Railway/Supabase dashboard export for $ and sizes; RealSend capacity confirmation. |
| Tier 1 = n8n only | monthly-irs-sync is not separable; moving it alone teaches little and risks splitting RealOutcomes. |
| Tier 2 = last1-admin compute | Move Railway Node to R940; keep Supabase auth on tcthzakppndkykatoefx until Tier 6. Reduces Railway spend without DB surgery. |
| Tier 3 = RealOutcomes including IRS cron | Bounded product; own Supabase; good second full-stack rehearsal after n8n. |
| Tier 4 = last1.id | Still high risk. Prefer before Tier 6 (RadioCheck depends on it). Soft-block: document OAuth redirect URI + webhook secret rotation checklist. |
| Tier 5 = Onset clinic + Onset Supabase (+ mobile env cuts) | SOC 2 driver. onset-web stays on Cloudflare. |
| Tier 6 = last1.app + RadioCheck (+ last1-admin auth DB) | Mandatory bundle. Highest coordination cost. |
| Parallel: SendGrid → RealSend | Do not interleave domain warmup with DB cutovers. Batch domains; cut after warmup. |
Suggested calendar shape (planning only)¶
- Approve this plan + BW naming.
- n8n (1–3 days).
- last1-admin compute (2–4 days).
- RealOutcomes full (1–2 weeks).
- last1.id (2–3 weeks, freeze window).
- Onset clinic (multi-week; counsel/SOC 2 aware).
- last1.app + RadioCheck bundle (multi-week).
Effort estimates assume Cursor + Ryan review; LastVet AWS retirement lessons (~days per bounded workload) scale up for identity/clinical.
Sub-task D — Bitwarden naming decision¶
Recommendation: per-product prefix, not universal LAST1_R940_*.
| Option | Pros | Cons |
|---|---|---|
Universal LAST1_R940_* |
Fewer prefixes | Collides with LAST1_PLATFORM_*; weak blast-radius grep; fights existing LastVet/Angel pattern |
Per-product LAST1ID_R940_*, ONSET_R940_*, LAST1APP_R940_*, RADIOCHECK_R940_*, REALOUTCOMES_R940_*, LAST1ADMIN_R940_*, N8N_R940_* |
Matches LASTVET_ / ANGEL_; clear ownership; project-per-product in BWS |
Slightly more prefixes |
Rule: LAST1 / LAST1_PLATFORM remains cross-product only. Product runtime secrets use product codes above. Extension recorded in BITWARDEN_NAMING_CONVENTION.md.
Sub-task E — Generic migration playbook¶
Reuse per product. Pattern distilled from LastVet AWS→R940 retirement and R940 platform rules.
1. Pre-migration audit¶
- [ ] Confirm
mainSHA and open PRs - [ ] Export Railway service settings (build/start, memory, replicas, volumes, cron)
- [ ] Export Supabase: Postgres version, disk, extensions, RLS policy count, Auth providers, Storage buckets, Edge function list
- [ ] Data volume + user/org counts
- [ ] Dependency map (OAuth, webhooks, admin gateways)
- [ ] User impact window + rollback owner
2. R940 target provisioning¶
- [ ] Allocate VMID, hostname, LAN IP, MagicDNS (
*.tailc3bbdc.ts.net) - [ ] Size vCPU/RAM/disk from audit; place data on
tank-fast(or bulk if object-heavy) - [ ] Join Tailscale with tagged auth key pattern (
tag:r940-vm) when ready - [ ] UFW: Tailscale/LAN only for admin ports; public only via approved edge
3. Database / object store / secrets¶
- [ ] Provision Postgres (per trust boundary)
- [ ] Roles: migrate-style
*_master/*_appsplit where applicable - [ ] Restore logical dump from Supabase; verify extensions (pgcrypto, etc.)
- [ ] Recreate Storage → MinIO only if required; else temporary dual-run
- [ ] Create BWS keys under product prefix; map to runtime names in systemd drop-in
4. Code / config changes¶
- [ ] Prefer env-only cut (connection strings, URLs). Avoid app renames of BWS keys.
- [ ] Replace Supabase Auth carefully (GoTrue vs first-party auth is a product decision; default = keep Supabase Auth temporarily via self-host or cut Auth in a dedicated phase). Flag: Auth migration may dwarf “move Postgres.”
- [ ] Update redirect URIs, webhooks, Stripe endpoints
5. Deployment runbook¶
- [ ] systemd units (app + optional side workers)
- [ ] Health checks (
/api/healthor product equivalent) - [ ] Log shipping to observability (Promtail) when ready
- [ ] Backup: vzdump + logical dump schedule
6. Cutover¶
- [ ] DNS / Cloudflare / Railway custom domain drain
- [ ] Freeze writes if dual-write not available
- [ ] Final dump + restore or continuous replication catch-up
- [ ] Flip env; verify auth login, critical writes, admin proxy
- [ ] Watch error budgets 24–72h
7. Rollback¶
- [ ] Keep Railway service stopped but not deleted for N days
- [ ] Keep Supabase project until rollback window closes
- [ ] DNS TTL lowered before cutover
- [ ] Document “flip back” owner and checklist
8. Cleanup¶
- [ ] Delete Railway service/project after window
- [ ] Delete Supabase project after window + legal retention check
- [ ] Confirm invoice lines gone
- [ ] Remove retired
_RAILWAY_/ old secrets after rotation
9. Documentation¶
- [ ] Update R940_PLATFORM_ARCHITECTURE.md tenant map
- [ ] BWS manifest / naming
- [ ] Product runbook under
docs/ - [ ] Muster item →
donewith note
Auth special note: Several products are “Supabase = Auth + DB + Edge.” Moving DB only while leaving Auth on Supabase is a valid interim (hybrid). Moving Auth requires either self-hosted GoTrue/Supabase stack or product rewrites. Decide per product in Tier 0 kickoff.
Sub-task F — Cost analysis¶
Live invoices not read. Use as planning priors; replace with dashboard exports before committing savings claims.
| Line | Estimate basis | Monthly (order of magnitude) |
|---|---|---|
| Supabase projects (≥4–5 Pro-class) | Public Pro list price ~$25/project | ~$100–200+ if all Pro; Team/spend caps higher |
| Railway services (last1.id, clinic, last1.app, admin, RealOutcomes, n8n, IRS cron) | Usage + plan | ~$50–300+ highly usage-dependent |
| SendGrid | Shared account / multiple senders | ~$15–100+ tier-dependent |
| R940 marginal | Hardware already owned; power/network sunk | ~$0 compute marginal; ops time is the cost |
| Annual savings (compute hosting) | If Railway+Supabase ≈ $200–500/mo | ~$2.4k–6k/yr before labor; verify with invoices |
Not included: engineer time, RealSend fees, dual-run periods, SOC 2 audit spend (Onset driver is compliance, not pure hosting savings).
Sub-task G — SendGrid → RealSend (separate track)¶
Known sender domains / addresses¶
From product repos (active senders) plus the broader SendGrid authenticated-domain list Ryan already inventoried:
| Domain / address | Likely class | In consolidation scope? |
|---|---|---|
notifications@theonset.app / updates@theonset.app / theonset.app |
Transactional + marketing | Yes (Onset) |
hello@realoutcomes.app / realoutcomes.app |
Transactional | Yes |
noreply@last1.app / last1.app |
Transactional | Yes |
integrations@last1.id |
Transactional optional | Yes |
radiocheck.app |
Transactional (Pro/Enterprise) | Yes (often via last1.app sender) |
last.vet |
Transactional | LastVet track (already R940 path) |
angel.report |
Transactional | Angel (Cloudflare; separate) |
last1.enterprises, last1.capital, last1.studio, veteransco.org, www.last1.org |
Mixed / claimed | Confirm active vs territory before warmup |
Plan¶
- Inventory one SendGrid account: authenticated domains, PTR/SPF/DKIM, templates, webhook events.
- Confirm RealSend capacity + MATR lessons (
reference-matr-sendgrid-realsend-migration-patte). - Warmup calendar per domain (do not cut cold).
- Implement provider abstraction or env swap per product (
EMAIL_PROVIDER=realsend). - Coordinated cutover weekend; keep SendGrid read-only 14 days.
- Do not couple to Postgres cutover night.
Sub-task H — Muster items¶
Filed as status: later (see muster tracker.yaml on main after PR/commit). IDs:
infra-consolidation-playbook-approveinfra-bw-naming-r940-products-approvemigrate-n8n-railway-to-r940migrate-last1-admin-compute-to-r940migrate-realoutcomes-railway-supabase-to-r940migrate-last1-id-railway-supabase-to-r940migrate-onset-clinic-supabase-to-r940migrate-last1app-radiocheck-shared-supabase-to-r940batch-sendgrid-to-realsend-last1-domains
Open questions for Ryan¶
- Accept per-product BWS prefixes as written?
- Accept Tier 1 = n8n only and IRS folded into RealOutcomes?
- For Supabase Auth: hybrid (DB on R940, Auth stays Supabase) allowed as interim?
- Provide Railway + Supabase billing exports to harden Sub-task F.
- Which product starts first after approval?
Appendix — Supabase project refs (committed)¶
| Ref | Name / use |
|---|---|
nztgswcpnwggymncrnyx |
last1.id |
cpocwrygxlqhzvmlrpjv |
RealOutcomes |
tcthzakppndkykatoefx |
Last 1 App + Radio Check (+ last1-admin auth) |
yloemokdrxfjkfwkskim |
radiocheck-web |
| (unknown in git) | Onset clinical |
End of planning document. No migration actions authorized by this file alone.