Skip to content

Tier 3 T3-4 — Browser E2E Test Plan (last1-admin R940)

ON HOLD (2026-08-28): Admin migration paused pending upstream product DB migrations. Do not execute until Ryan resumes admin tier. See TIER_3_ADMIN_PAUSED_STATUS.md.

Date: 2026-08-28
Status: Test plan ready for Ryan review. Ryan executes; Cursor does not run browser tests.
Parent: TIER_3_ADMIN_T3-3_REPORT.md · TIER_3_ADMIN_MIGRATION_AUDIT.md (T3-0)


Scope

In scope (T3-4) Out of scope
Browser E2E on R940 stack via tunnel staging URL T3-5 DNS cutover (admin.last1.enterprises → R940)
All 7 BFF product proxies from T3-0 audit Railway teardown
Auth, unit switcher, read paths, one safe write per unit where noted Supabase migration (Tier 6)
Ryan marks PASS/FAIL in Section 10 Destructive prod admin actions

Production remains Railway at https://admin.last1.enterprises until T3-5. All T3-4 tests target the R940 parallel stack only.


1. How to reach R940 (tunnel internal test)

Public admin.last1.enterprises still resolves to Railway (x-railway-edge response header). The tunnel ingress for that hostname is staged on lastvet-edge but does not receive prod traffic yet.

Use a separate hostname that routes through the same Cloudflare Tunnel to VM 115. This is not the T3-5 prod cutover.

Item Value
Tunnel lastvet-r940
Tunnel UUID 4c8550f2-2156-4284-b9f7-60cdc0fdc109
Origin http://192.168.1.97:5000
Staging URL (recommended) https://admin-r940.last1.enterprises

One-time prep (Ryan or Cursor before browser session):

  1. Cloudflare DNS (Last 1 zone): add CNAME
    admin-r940.last1.enterprises → 4c8550f2-2156-4284-b9f7-60cdc0fdc109.cfargotunnel.com
    Proxy status: Proxied (orange cloud). (Ryan action)

  2. Tunnel ingress on lastvet-edge: add hostname
    admin-r940.last1.enterprises → http://192.168.1.97:5000
    Script: scripts/last1-admin/configure-tunnel-staging-r940.sh
    Preview: DRY_RUN=1 on edge · Apply after Ryan confirms steps 1 + 3: DRY_RUN=0

  3. Supabase Auth (project tcthzakppndkykatoefx): add redirect URL
    https://admin-r940.last1.enterprises/auth/callback
    (Site URL can stay prod; redirect allow-list must include staging hostname.) (Ryan action)

  4. Do not change DNS for admin.last1.enterprises (T3-5).

  5. PF-1 / PF-2 must pass before any browser E2E (Section 4.0).

Fallback: Tailscale / LAN (limited)

URL Use
http://192.168.1.97:5000 (LAN) Unauthenticated shell smoke only
http://100.76.87.21:5000 (Tailscale) Same; OAuth likely fails unless Supabase redirect added

Use fallback only if staging DNS is blocked. Full E2E requires the staging tunnel hostname.

Confirm you are on R940 (not Railway)

Before testing, open DevTools → Network → reload /:

Signal R940 (pass pre-flight) Railway (wrong stack — stop)
Response headers No x-railway-edge Has x-railway-edge
GET /api/auth/user (logged out) 401 401 (same)
Optional: VM logs ssh admin-r940 'docker logs last1admin-app --tail 5' shows your requests No new lines on VM 115

Record pre-flight result in Section 10 (Test PF-1).


2. Test account and tooling

Item Guidance
Account @last1.enterprises with super_admin or platform_admin (all units)
Browser Chrome or Firefox; disable ad blockers for staging hostname
DevTools Network tab open; filter api/ for BFF failures
Session Use incognito or dedicated profile to avoid Railway cookie confusion

Write-action policy: Prefer read-only checks. Where a write is listed, use non-destructive actions only (export, preview, dry-run). Skip any test marked WRITE (optional) if unsure.


3. Seven BFF proxies (T3-0 focus)

These are the seven product integration surfaces called out in the T3-0 audit. Each section lists the BFF entrypoint, upstream target, browser route(s), and expected behavior.

# BFF proxy Upstream Auth middleware
1 POST /api/proxy/last1 LAST1_API_BASE (https://last1.app) requireAdmin + unit last1
2 POST /api/proxy/realoutcomes REALOUTCOMES_API_BASE requireAdmin + unit realoutcomes
3 POST /api/proxy/radiocheck (not implemented) Returns 501
4 POST /api/proxy/last1id LAST1_ID_API_BASE (https://auth.last1.id) requireAdmin + unit last1id
5 POST /api/proxy/org-last1id auth.last1.id org admin API requireOrgMember
6 /api/lastvet/* LASTVET_API_BASE (https://api.last.vet) requireAdmin + unit lastvet
7 /api/angel/* ANGEL_API_BASE (Cloudflare Worker) requireAdmin + unit angel

Not one of the seven: Onset uses direct Supabase routes under /api/admin/onset/* (Section 6). RadioCheck product data uses /api/radiocheck/* same-origin routes (not POST /api/proxy/radiocheck).


4. Test checklist

Mark each row PASS, FAIL, or SKIP in Section 10.
Expected describes success on R940. FAIL if 5xx, blank page, "Admin gateway not configured", infinite spinner, or wrong upstream (e.g. stale last1.id host).

4.0 Pre-flight and auth shell

ID Test Route / action Expected
PF-1 Staging URL reaches R940 Open https://admin-r940.last1.enterprises/ SPA loads; no x-railway-edge header
PF-2 Prod URL still Railway Open https://admin.last1.enterprises/ (separate tab) Loads with x-railway-edge (sanity: prod untouched)
A-1 Login /login → Sign in with Google Redirects to allowed unit home; no "access denied"
A-2 Session API DevTools: GET /api/auth/user 200 with admin user + memberships
A-3 Auth callback OAuth completes via /auth/callback Lands in app; no 404
A-4 Account page /account Profile loads; patch display name WRITE (optional) saves
A-5 Admin hub /admin Hub lists accessible units
A-6 Unit switcher Switch each unit from header dropdown Each unit nav loads without redirect loop
A-7 RBAC guard Visit a unit you should not access (if test account scoped) Redirect to first allowed unit or login

4.1 Proxy 1 — last1.app (POST /api/proxy/last1)

ID Test Route BFF call (Network tab) Expected
L1-1 Dashboard /admin/last1 POST /api/proxy/last1 → /api/admin/stats or similar Stats/cards render
L1-2 Metrics /admin/last1/metrics Proxy GET admin metrics path Charts/tables load
L1-3 Governance /admin/last1/governance Proxy read Page loads, no 502
L1-4 Check-ins /admin/last1/check-ins Proxy read List loads
L1-5 Reports /admin/last1/reports Proxy read Report UI loads
L1-6 Settings /admin/last1/settings Proxy read Settings visible

4.2 Proxy 2 — RealOutcomes (POST /api/proxy/realoutcomes)

ID Test Route BFF call Expected
RO-1 Dashboard /admin/realoutcomes POST /api/proxy/realoutcomes → stats/dashboard path Dashboard metrics load
RO-2 Users /admin/realoutcomes/users Proxy list users Table loads
RO-3 Gateway health Network: first proxy response Status not 503 "Admin gateway not configured" HMAC gateway accepted

4.3 Proxy 3 — RadioCheck generic proxy (POST /api/proxy/radiocheck)

ID Test Route BFF call Expected
RC-P-1 Generic proxy stub (DevTools only) POST body {method,path} to /api/proxy/radiocheck 501 "RadioCheck proxy not yet implemented" Known limitation; mark PASS if 501

RadioCheck product admin uses same-origin /api/radiocheck/* (Section 4.8), not this proxy.

4.4 Proxy 4 — last1.id (POST /api/proxy/last1id)

ID Test Route BFF call Expected
ID-1 Dashboard /admin/last1id Proxy → /api/admin/stats on auth.last1.id Stats load; ops chip green
ID-2 Identities /admin/last1id/identities Proxy → /api/admin/identities Paginated list loads
ID-3 App clients /admin/last1id/app-clients Proxy read Client list loads
ID-4 Issuers /admin/last1id/issuers Proxy read Issuer list loads
ID-5 Audit /admin/last1id/audit Proxy read Audit events load
ID-6 Abuse /admin/last1id/abuse Proxy read Abuse queue loads
ID-7 Operations /admin/last1id/operations Proxy read Health paths show R940/sovereign targets
ID-8 Telemetry /admin/last1id/telemetry GET /api/admin/last1id/telemetry (same-origin) Telemetry table loads
ID-9 Upstream host Network tab: proxy target host Requests hit auth.last1.id, not last1.id Critical Tier 2 cutover check

4.5 Proxy 5 — org last1.id (POST /api/proxy/org-last1id)

Requires org membership on test account. Skip with reason if none.

ID Test Route BFF call Expected
ORG-1 Org dashboard /org/{orgSlug} Proxy with orgSlug Org dashboard loads
ORG-2 Profile /org/{orgSlug}/profile Proxy read Org profile loads
ORG-3 Issuer /org/{orgSlug}/issuer Proxy read Issuer config loads
ORG-4 Programs /org/{orgSlug}/programs Proxy read Programs list loads
ORG-5 Credentials /org/{orgSlug}/credentials Proxy read Credentials view loads
ORG-6 Audit /org/{orgSlug}/audit Proxy read Org audit loads

4.6 Proxy 6 — LastVet (/api/lastvet/*)

Mandatory manual checks (T3-0 / Tier 2 lesson).

ID Test Route BFF call Expected
LV-1 Dashboard /admin/lastvet GET /api/lastvet/stats Stats cards; runtime banner shows API: https://api.last.vet
LV-2 Veterans list /admin/lastvet/veterans GET /api/lastvet/veterans Search/list loads (synthetic OK)
LV-3 Veteran detail Click one veteran GET /api/lastvet/veterans/:id Detail panel loads
LV-4 Providers /admin/lastvet/providers GET /api/lastvet/providers Provider table loads
LV-5 Pending review Providers → pending tab GET /api/lastvet/providers/pending-review Queue loads (read-only; do not approve in T3-4 unless Ryan explicitly chooses)
LV-6 Consent monitor /admin/lastvet/consent-monitor consent-activity + denied-access Charts/lists load
LV-7 Part 2 monitor /admin/lastvet/part2 GET /api/lastvet/part2-overview Compliance-critical: aggregates load, no 5xx
LV-8 System health /admin/lastvet/system-health GET /api/lastvet/health Health JSON renders
LV-9 Privacy notices /admin/lastvet/privacy-notices GET /api/lastvet/privacy-notices Version list loads
LV-10 Notice preview Preview one notice GET .../preview HTML preview renders (read-only)

4.7 Proxy 7 — Angel (/api/angel/*)

ID Test Route BFF call Expected
AN-1 Dashboard /admin/angel GET /api/angel/stats Stats load
AN-2 System health /admin/angel/system-health GET /api/angel/health Health status OK
AN-3 Users /admin/angel/users GET /api/angel/users User list loads
AN-4 Invite codes /admin/angel/invite-codes GET /api/angel/invite-codes Code list loads
AN-5 Runtime Network: /api/angel/runtime Returns Angel API base config Matches Worker deployment

4.8 RadioCheck same-origin BFF (/api/radiocheck/*)

Not the generic proxy (#3). Validates RadioCheck unit end-to-end.

ID Test Route BFF call Expected
RC-1 Dashboard /admin/radiocheck GET /api/radiocheck/stats Stats load
RC-2 Users /admin/radiocheck/users GET /api/radiocheck/users User list loads
RC-3 Units /admin/radiocheck/units GET /api/radiocheck/units Units list loads
RC-4 Unit requests /admin/radiocheck/unit-requests GET /api/radiocheck/unit-requests Queue loads
RC-5 Messaging settings /admin/radiocheck/messaging GET /api/radiocheck/messaging-settings Settings load
RC-6 Org admins /admin/radiocheck/org-admins org-admin-requests List loads

4.9 Onset direct Supabase BFF (/api/admin/onset/*)

ID Test Route BFF call Expected
ON-1 Dashboard /admin/onset metrics aggregate routes Dashboard loads
ON-2 Clinics /admin/onset/clinics GET /api/admin/onset/clinics Clinic list loads
ON-3 Users /admin/onset/users GET /api/admin/onset/users User list loads
ON-4 Sync diagnostics /admin/onset/sync-diagnostics GET /api/onset/sync-diagnostics/search Search UI works (empty query OK)
ON-5 Connection lookup /admin/onset/connection-lookup sync-diagnostics connection Lookup form loads
ON-6 Clinic support /admin/onset/clinic-support clinic-support diagnostics Diagnostics load
ON-7 Support tickets /admin/onset/support-tickets support-tickets API Ticket list loads

4.10 Marketing (/api/admin/marketing/*)

Shared Supabase marketing tables; not a product proxy but operator-critical.

ID Test Route BFF call Expected
MK-1 Marketing hub /admin/marketing hub stats Hub loads
MK-2 Onset subscribers /admin/marketing/onset/subscribers marketing API List loads
MK-3 LastVet subscribers /admin/marketing/lastvet/subscribers marketing API List loads
MK-4 Last1.org subscribers /admin/marketing/last1org/subscribers marketing API List loads
MK-5 Broadcast preview Open any broadcast → Preview GET .../preview Preview renders (read-only)

4.11 Cross-cutting / schedulers

ID Test Action Expected
X-1 Ops digest scheduler ssh admin-r940 'docker logs last1admin-app 2>&1 \| grep ops-digest' "scheduler started" present after container start
X-2 Request timing panel Any unit page Timing panel shows BFF latency (no errors)
X-3 Logout Sign out Session cleared; /api/auth/user → 401

5. Failure triage (quick reference)

Symptom Likely cause Check
502 on proxy routes Upstream down or wrong base URL .env LAST1_ID_API_BASE, LASTVET_API_BASE, gateway secrets
503 "Admin gateway not configured" Missing HMAC secret in BWS render Re-run render-last1admin-env-r940.sh
403 on last1.id proxy Gateway secret mismatch with auth.last1.id BWS LAST1ID_ADMIN_GATEWAY_SECRET vs Sovereign
Blank LastVet pages LASTVET_INTERNAL_ADMIN_SECRET mismatch LastVet API internal admin auth
OAuth redirect error Staging URL not in Supabase allow list Add admin-r940.last1.enterprises callback
Still seeing Railway Wrong URL Use staging hostname; verify PF-1

6. Section 10 — Ryan results worksheet

Tester: Ryan
Date: _
Staging URL used: https://admin-r940.last1.enterprises (or fallback:
_)
Test account: ____

Copy test IDs from Section 4. Mark PASS / FAIL / SKIP. For FAIL, add one-line note + screenshot or Network status code.

Pre-flight & auth

ID Result Notes
PF-1
PF-2
A-1
A-2
A-3
A-4
A-5
A-6
A-7

Proxy 1 — last1.app

ID Result Notes
L1-1
L1-2
L1-3
L1-4
L1-5
L1-6

Proxy 2 — RealOutcomes

ID Result Notes
RO-1
RO-2
RO-3

Proxy 3 — RadioCheck generic proxy

ID Result Notes
RC-P-1

Proxy 4 — last1.id

ID Result Notes
ID-1
ID-2
ID-3
ID-4
ID-5
ID-6
ID-7
ID-8
ID-9

Proxy 5 — org last1.id

ID Result Notes
ORG-1
ORG-2
ORG-3
ORG-4
ORG-5
ORG-6

Proxy 6 — LastVet

ID Result Notes
LV-1
LV-2
LV-3
LV-4
LV-5
LV-6
LV-7
LV-8
LV-9
LV-10

Proxy 7 — Angel

ID Result Notes
AN-1
AN-2
AN-3
AN-4
AN-5

RadioCheck same-origin

ID Result Notes
RC-1
RC-2
RC-3
RC-4
RC-5
RC-6

Onset

ID Result Notes
ON-1
ON-2
ON-3
ON-4
ON-5
ON-6
ON-7

Marketing

ID Result Notes
MK-1
MK-2
MK-3
MK-4
MK-5

Cross-cutting

ID Result Notes
X-1
X-2
X-3

Summary

Metric Count
PASS
FAIL
SKIP

T3-4 gate verdict: ☐ PASS (zero FAIL on ID-9, LV-7, RO-3, A-1, PF-1) · ☐ FAIL (block T3-5 until fixed)

Ryan sign-off: _ Date: _


7. After T3-4

Phase Action
T3-4 complete Ryan fills Section 10; Cursor writes TIER_3_ADMIN_T3-4_REPORT.md from results
T3-5 DNS cutover admin.last1.enterprises → tunnel (Ryan approval)
T3-6 24–48 h prod soak
T3-7 Railway teardown

Do not proceed to T3-5 until Ryan marks T3-4 gate PASS.