PR A: 12-state transaction machine + issueInstrument step + SoD matrix #5

Merged
nsatoshi merged 1 commits from devin/1776874611-instrument-leg-state-machine into main 2026-04-22 17:15:47 +00:00
Owner

Implements steps 1, 2, 10 from the architecture gap-analysis (the data-model PR that unblocks B-G).

What lands

  • orchestrator/src/types/transactionState.ts — the 12 states from arch note §8.1 + the full transition table from §9.1 + segregation-of-duties matrix (§13). Both the coordinator and the DB CHECK constraint read from this file.
  • orchestrator/src/types/plan.ts — adds 'issueInstrument' to PlanStep.type and a new InstrumentTerms interface modeled on the Emirates Islamic SBLC / MT760 template (applicant, issuingBankBIC, beneficiaryBankBIC, beneficiaryName, beneficiaryAccount, amount, currency, tenor, expiryDate, placeOfPresentation, governingLaw, templateRef, templateHash).
  • orchestrator/src/services/planValidation.ts — new issueInstrument validator: required fields, ISO-4217 currency, BIC format (8 or 11 chars), YYYY-MM-DD expiry, sha256 templateHash, amount > 0.
  • orchestrator/src/services/stateMachine.tstransition() enforces legality + segregation-of-duties (checks the transition log for the prior gated actor) + appends to the append-only table, atomically.
  • orchestrator/src/db/migrations/002_transaction_state.tsplans.transaction_state (default 'DRAFT', CHECK-constrained to the 12 values) + transaction_state_transitions(id, plan_id, from_state, to_state, reason, source_event_id, actor, actor_role, signature, created_at).
  • Unit tests: tests/unit/transactionState.test.ts (13 tests — every legal edge, illegal edges, CLOSED-is-terminal, SoD matrix) + tests/unit/planValidation.instrument.test.ts (8 tests — happy path + 7 negative cases). 31 tests, all passing.

What this PR does NOT change

  • ExecutionCoordinator still runs the legacy 4-phase path and writes the old pending|complete|aborted status. PR B refactors the coordinator onto the new machine + adds the VALIDATING phase.
  • No API surface change (GET /plans/:id/state lands with PR D alongside the event bus).

Verification

$ npx tsc --noEmit              # clean
$ npx jest                      # 31 passed, 2 suites

Next in the series

  • PR B — VALIDATING phase + unified ExceptionManager (arch steps 3, 7)
  • PR C — real NotaryRegistry wiring (arch step 4)
  • PR D — typed + signed event bus + SSE (arch step 5)
  • PR E — SWIFT gateway: MT760 + pacs.009/MT202 (arch step 6 + pacs.008→pacs.009 fix)
  • PR F — idempotency + replay protection (arch step 9)
  • PR G — portal /transactions state-machine view (arch step 8)
  • PR H — architecture-note amendments (§4.1 unwind matrix, §5.1 trust model, §9.2 accepted≠settled)

Part of the gap-analysis at /home/ubuntu/review/CurrenciCombo-architecture-gap-analysis.md.

Implements **steps 1, 2, 10** from the architecture gap-analysis (the data-model PR that unblocks B-G). ## What lands - `orchestrator/src/types/transactionState.ts` — the 12 states from arch note §8.1 + the full transition table from §9.1 + segregation-of-duties matrix (§13). Both the coordinator and the DB CHECK constraint read from this file. - `orchestrator/src/types/plan.ts` — adds `'issueInstrument'` to `PlanStep.type` and a new `InstrumentTerms` interface modeled on the Emirates Islamic SBLC / MT760 template (applicant, issuingBankBIC, beneficiaryBankBIC, beneficiaryName, beneficiaryAccount, amount, currency, tenor, expiryDate, placeOfPresentation, governingLaw, templateRef, templateHash). - `orchestrator/src/services/planValidation.ts` — new `issueInstrument` validator: required fields, ISO-4217 currency, BIC format (8 or 11 chars), YYYY-MM-DD expiry, sha256 templateHash, amount > 0. - `orchestrator/src/services/stateMachine.ts` — `transition()` enforces legality + segregation-of-duties (checks the transition log for the prior gated actor) + appends to the append-only table, atomically. - `orchestrator/src/db/migrations/002_transaction_state.ts` — `plans.transaction_state` (default `'DRAFT'`, CHECK-constrained to the 12 values) + `transaction_state_transitions(id, plan_id, from_state, to_state, reason, source_event_id, actor, actor_role, signature, created_at)`. - Unit tests: `tests/unit/transactionState.test.ts` (13 tests — every legal edge, illegal edges, CLOSED-is-terminal, SoD matrix) + `tests/unit/planValidation.instrument.test.ts` (8 tests — happy path + 7 negative cases). **31 tests, all passing.** ## What this PR does NOT change - `ExecutionCoordinator` still runs the legacy 4-phase path and writes the old `pending|complete|aborted` status. PR B refactors the coordinator onto the new machine + adds the `VALIDATING` phase. - No API surface change (`GET /plans/:id/state` lands with PR D alongside the event bus). ## Verification ``` $ npx tsc --noEmit # clean $ npx jest # 31 passed, 2 suites ``` ## Next in the series - PR B — VALIDATING phase + unified ExceptionManager (arch steps 3, 7) - PR C — real NotaryRegistry wiring (arch step 4) - PR D — typed + signed event bus + SSE (arch step 5) - PR E — SWIFT gateway: MT760 + pacs.009/MT202 (arch step 6 + pacs.008→pacs.009 fix) - PR F — idempotency + replay protection (arch step 9) - PR G — portal /transactions state-machine view (arch step 8) - PR H — architecture-note amendments (§4.1 unwind matrix, §5.1 trust model, §9.2 accepted≠settled) Part of the gap-analysis at `/home/ubuntu/review/CurrenciCombo-architecture-gap-analysis.md`.
nsatoshi added 1 commit 2026-04-22 16:22:23 +00:00
PR A: 12-state transaction machine + issueInstrument step + SoD matrix
Some checks failed
Code Quality / SonarQube Analysis (pull_request) Failing after 23s
Code Quality / Code Quality Checks (pull_request) Failing after 11s
Security Scan / Dependency Vulnerability Scan (pull_request) Failing after 4s
Security Scan / OWASP ZAP Scan (pull_request) Failing after 5s
b24a4df983
Architecture note steps 1, 2, 10 (data model).

- types/transactionState.ts: 12 states, allowed-transition table, SoD matrix
- types/plan.ts: add InstrumentTerms + 'issueInstrument' PlanStep type
- services/planValidation.ts: validate SBLC step (BIC, ISO-4217, sha256,
  YYYY-MM-DD expiry, >0 amount)
- services/stateMachine.ts: transition() enforces legality + SoD + appends
  to transaction_state_transitions
- db/migrations/002: plans.transaction_state (CHECK) +
  transaction_state_transitions append-only table
- tests/unit: 13 + 8 unit tests (31 total, all pass)

No behaviour change yet: coordinator still uses legacy status field.
PRs B-G will migrate execution paths onto the new machine.
nsatoshi merged commit 84f199fb65 into main 2026-04-22 17:15:47 +00:00
nsatoshi deleted branch devin/1776874611-instrument-leg-state-machine 2026-04-22 17:15:49 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: d-bis/CurrenciCombo#5