I1a Pre-Flight and Weekend Path B Setup¶
Operational runbook — September 4, 2026
Sequence: deploy I1a → Ryan runs full model once (crash-bug hunt) → weekend veterans run full model.
Companion: LOOP1_PROGRAM_TEMPLATE_MODEL.md, LOOP1_INTEGRATIONS_MODEL.md.
0. What I1a is (and is not)¶
I1a ships (additive, inert until instantiated):
- Migration
20260904193000_program_coordination_templates_i1a.sql - Tables:
program_coordination_templates,_template_phases,_template_events,_instances,_events,_output_attestation_events - Services: template immutability, instantiation, output two-source guards, outcome-via-loop guard
- TEST template seed:
win-veteran-employment-v1-test(1 signal + 6 outputs + 1 outcome)
I1a does NOT ship yet:
- HTTP routes for template instantiate / output attest / member confirm on program_coordination events
- Admin or member UI for the output milestone layer
- Wiring outcome event → coordination loop open (I2)
Implication: Deploy + instantiate puts the data model on a program. The browser full model (signal → six two-source outputs → coordination-loop outcome) requires I1b (routes + UI) + I2 (outcome wire) before Ryan's pre-flight can exercise the output layer in the product UI.
What Ryan CAN pre-flight today after I1a deploy:
| Leg | Browser today | After I1b/I2 |
|---|---|---|
| Outcome (placement V_req=3) | Yes — dashboard coordination panels, magic-link HM | Same |
| Outputs (6 milestones) | No UI — script/service only | Member progress + org attest |
Signal (pipeline-entered) |
No UI | Optional admin signal emit |
Recommendation: Run I1b/I2 on agent-01 before prod deploy if weekend Path B must be a single coherent browser flow. Otherwise: deploy I1a schema now (safe, additive), pre-flight outcome leg + script-check outputs, then ship I1b before Saturday.
1. Program anchors — which program when¶
| Program | ID | Use |
|---|---|---|
| VES (production anchor) | adf7bd97-a7ec-44e8-a178-2ff106a235db |
Jose loop 07b1fbcd, weekend real veterans, coordination loops |
| MOCK Pipeline (test) | e5c80469-5db2-4fcc-a9b0-dae21f07efab |
Demo data, ED funnel, Ryan pre-flight instantiate target |
| Keystone MOCK | e5c80469-… (same org) |
Loop 02fcb8a4 on MOCK program |
1.1 Safety: instantiate on VES?¶
Yes, additive. I1a does not alter coordination_loops, create/attest paths, or Jose's loop. program_coordination_instances is a parallel namespace with UNIQUE(program_id).
Still sequence:
- Ryan pre-flight: instantiate on MOCK Pipeline (
e5c80469) — keeps VES untouched while Ryan breaks things. - After green pre-flight: instantiate on VES (
adf7bd97) for weekend veterans (same template slug).
One template instance per program. Weekend veterans enrolled in VES need VES instantiated, not MOCK.
1.2 Identity for Ryan's run¶
- Org admin:
ryan@warriorsinneed.org(or WIN org admin you use daily) - Veteran test:
curryrg@gmail.comwith Last1 ID linked (same as prior MOCK walkthroughs) - Enroll curryrg on MOCK program if not already enrolled for pre-flight
2. Deploy I1a to prod¶
2.1 Pre-deploy checks (agent-01)¶
cd /home/ryan/code/last1/last1.app
npm test -- server/__tests__/programCoordinationI1a.test.ts server/__tests__/coordinationLoopOpenLoop.test.ts
Expect 12 passing (8 I1a + 4 regression).
2.2 Commit and sync (when ready)¶
Commit I1a files on last1.app main, push, then deploy that SHA:
Do not rsync a laptop tree to /opt/last1app/src. See last1.app docs/deploy-from-git.md.
2.3 Apply migration (VM 103 db)¶
From agent-01:
bash /home/ryan/code/last1/lastvet-gates/scripts/last1app/apply-program-coordination-i1a-migration.sh
Verify:
ssh ryan@192.168.1.103 'docker compose -f /opt/supabase/docker/docker-compose.yml exec -T db psql -U postgres -d postgres -c "SELECT slug, template_status, version FROM program_coordination_templates;"'
Expect row: win-veteran-employment-v1-test | test | 1.
2.4 Redeploy app (VM 104)¶
Standard monolith redeploy (render env + docker build):
# From agent-01 — adjust if you use t2-3-redeploy.sh
export BWS_ACCESS_TOKEN="$(tr -d '\n' < /etc/bitwarden/access-token)"
bash /home/ryan/code/last1/lastvet-gates/scripts/last1app/render-last1app-env-app.sh /tmp/last1app.env
scp /tmp/last1app.env ryan@192.168.1.104:/opt/last1app/.env
ssh ryan@192.168.1.104 'bash /opt/last1app/scripts/deploy-last1app-app.sh'
# Or copy deploy script from gates repo if not on VM yet
Post-deploy smoke:
curl -sf -o /dev/null -w '%{http_code}\n' https://last1.app/
curl -sf -o /dev/null -w '%{http_code}\n' https://last1.app/api/auth/user
3. Instantiate test template¶
3.1 On MOCK (Ryan pre-flight)¶
After deploy, on VM 104 with .env loaded:
cd /opt/last1app/src
node scripts/instantiate-program-coordination-i1a.mjs \
--program-id e5c80469-5db2-4fcc-a9b0-dae21f07efab
Expect: eventCount: 8 (1 signal + 6 outputs + 1 outcome).
Verify in DB:
SELECT slug, event_kind, closure_engine, order_index
FROM program_coordination_events
WHERE program_id = 'e5c80469-5db2-4fcc-a9b0-dae21f07efab'
ORDER BY order_index;
3.2 On VES (weekend veterans — after Ryan greenlight)¶
node scripts/instantiate-program-coordination-i1a.mjs \
--program-id adf7bd97-a7ec-44e8-a178-2ff106a235db
Do not run on VES until Ryan pre-flight passes on MOCK.
4. Ryan pre-flight walkthrough (full model)¶
Goal: one end-to-end pass on your accounts before any weekend veteran hits it. Timebox: ~45–60 min.
Phase A — Outcome leg (browser — works today)¶
Uses existing coordination UI on VES or MOCK (outcome close is program-scoped but loop is org+beneficiary scoped).
- Log in as WIN org admin → Dashboard → Coordination loops panel.
- Confirm DD-214 queue / beneficiaries / open-loop picker load (volume hardening regression check).
- Pick test beneficiary (yourself or a dedicated TEST beneficiary, not Jose's production row if avoidable).
- Open coordination loop — program = VES or MOCK, HM email on a domain you control.
- Deliverer attest placement.
- Log in as veteran (
curryrg@gmail.com) → Member progress → confirm recipient attestation on loop card. - Issue HM magic link → open in browser (incognito) → independent attest via domain-verified link.
- Confirm loop reaches verified close state; check ledger/denominator if you use admin views.
Crash-bug hunt targets: auth iframe, unregistered routes, upload flows, open-loop dialog, HM link page, member loop card.
Phase B — Output leg (after I1b — or script-only on I1a)¶
When I1b ships, for each output slug in order:
| Order | Slug | Phase |
|---|---|---|
| 1 | enrollment-confirmed |
Intake |
| 2 | service-plan-agreed |
Intake |
| 3 | training-requirements-met |
Training |
| 4 | faa-certification-achieved |
Training |
| 5 | training-licensing-complete |
Training |
| 6 | tools-issued |
Pre-placement |
Per output:
- Org admin: attest deliverer (
deliverer_attested). - Veteran: confirm (
recipient_confirmed) on member progress. - Confirm two-source close before advancing.
I1a-only script check (no browser):
# After I1b routes exist, or temporary node script calling services directly on VM
# recordProgramCoordinationOutputAttestation + assertProgramCoordinationOutputClosed
Outcome event job-placement-verified must not accept milestone attestation — only coordination loop (403 OUTCOME_REQUIRES_COORDINATION_LOOP).
Phase C — Full path integration¶
After outputs 1–6 closed and outcome loop verified:
- Veteran
/member/progressshows full template timeline (I1b UI). - Jose's existing loop
07b1fbcdunchanged on VES. - Document any bugs in a single checklist before opening to weekend veterans.
5. Weekend veteran setup (Path B)¶
After Ryan pre-flight green:
- Instantiate template on VES (
adf7bd97) if not done in §3.2. - Enroll each weekend veteran in VES (existing flow).
- Open coordination loop per veteran when placement ready (outcome).
- Walk outputs with each veteran as they progress (training milestones — the new surface worth real-veteran testing).
- Do not migrate Jose's closed loop; new veterans get new loops on the full model.
Preserve:
- Loop
07b1fbcd(Jose) — read-only proof, do not re-run. - Keystone
02fcb8a4on MOCK — untouched.
6. Rollback¶
I1a is additive. Rollback = stop using template instances; no migration rollback required for weekend safety.
If deploy breaks app: redeploy previous docker image on VM 104. Migration tables can remain empty/unused.
7. Open items before "ready for veterans"¶
- [ ] I1a migration applied on prod DB
- [ ] I1a code deployed on VM 104
- [ ] I1b routes + UI (if weekend requires browser output layer)
- [ ] I2 outcome wire (template outcome event ↔ coordination loop) — deferred post-weekend. Loop card is SoR for placement until built; template outcome row stays informational + pointer copy. Do not build during veteran live-testing.
- [ ] Ryan pre-flight Phase A pass
- [x] Ryan pre-flight Phase B pass (I1b)
- [ ] Instantiate on VES
- [ ] Weekend veteran roster + enrollment confirmed
8. Post-weekend (after Jose + incoming veterans)¶
- I2 — template outcome ↔ loop verified state: Wire
job-placement-verified(and future outcome rows) to read the beneficiary's coordination looplambda_stateso the template card and loop card agree on placement. Today they can disagree (empty circle on template while loop is verified). Pointer copy bridges the gap for the weekend; I2 removes the dual-source confusion.
9. In-app action indicators (built pre-Jose) vs email notifications (deferred)¶
Built now (read-over-existing-state, UI-only):
- Member
/member/progress: page banner ("You have N items to confirm"), highlighted output rows with Confirm/Dispute, placement loop card highlight when veteran must Approve/Deny, outcome row pointer reinforced when loop needs veteran action. - Admin dashboard: banner when coordination loops need org action (delivery confirm or employer link). Output attestations remain on participant program pages.
- Admin participant program page: banner for N outputs awaiting attestation + N loops for that participant needing action.
Counts derive from existing program-coordination progress fields and coordination loop read models (outputAwaitingRecipientCount, outputAwaitingDelivererCount, loopNeedsAdminAction). Unit tests in last1.app/shared/programCoordination/actionIndicators.test.ts and adminLoopAction.test.ts.
Deferred (not before Jose):
- Out-of-band email notifications on loop/output state transitions (SendGrid → Resend migration, templates, triggers, deliverability pre-flight). Jose run is live-coordinated today; distributed veterans get email after deliberate build + pre-flight.
Maintained by: Ryan Curry / agent-01
Scripts: scripts/last1app/apply-program-coordination-i1a-migration.sh, last1.app/scripts/instantiate-program-coordination-i1a.mjs
10. Outcome-class display (built pre-Jose) vs class-agnostic loop support (deferred)¶
Built now (read-over-state, UI-only):
- Shared display registry:
last1.app/shared/coordination/outcomeClassDisplay.tsmapsoutcome_classto badge label, member loop title, verified close copy, attestation detail labels, and admin table headers. - Member loop card and admin coordination loops table show an outcome-class badge (e.g. "Job Placement") so veterans and admins know what they are attesting to.
- Verified close headline/copy derives from class (job placement → "Placement/hire confirmed"), not hardcoded "hire."
Deferred (SSRN §10.2):
- Full class-agnostic loop support: housing, MH/BH care, and credential loops end-to-end (different independent parties, two-party care close, class-specific verification flows). Display stubs exist; no such loops to run until per-class work lands.