Skip to content

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:

  1. Ryan pre-flight: instantiate on MOCK Pipeline (e5c80469) — keeps VES untouched while Ryan breaks things.
  2. 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.com with 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:

ssh ryan@192.168.1.104 'bash /opt/last1app/scripts/deploy-from-git.sh origin/main'

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).

  1. Log in as WIN org admin → Dashboard → Coordination loops panel.
  2. Confirm DD-214 queue / beneficiaries / open-loop picker load (volume hardening regression check).
  3. Pick test beneficiary (yourself or a dedicated TEST beneficiary, not Jose's production row if avoidable).
  4. Open coordination loop — program = VES or MOCK, HM email on a domain you control.
  5. Deliverer attest placement.
  6. Log in as veteran (curryrg@gmail.com) → Member progress → confirm recipient attestation on loop card.
  7. Issue HM magic link → open in browser (incognito) → independent attest via domain-verified link.
  8. 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:

  1. Org admin: attest deliverer (deliverer_attested).
  2. Veteran: confirm (recipient_confirmed) on member progress.
  3. 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/progress shows full template timeline (I1b UI).
  • Jose's existing loop 07b1fbcd unchanged 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:

  1. Instantiate template on VES (adf7bd97) if not done in §3.2.
  2. Enroll each weekend veteran in VES (existing flow).
  3. Open coordination loop per veteran when placement ready (outcome).
  4. Walk outputs with each veteran as they progress (training milestones — the new surface worth real-veteran testing).
  5. 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 02fcb8a4 on 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 loop lambda_state so 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.ts maps outcome_class to 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.