PR R: FIN-link sandbox service #22

Merged
nsatoshi merged 1 commits from devin/1776883027-pr-r-fin-sandbox into main 2026-04-22 20:30:47 +00:00
Owner

Closes gap-analysis v2 §7.1 (no FIN-link adapter — SWIFT generators produce strings but have no transport) and §10.6 (stand up sandbox transport).

What

  • services/finLink/sandbox.ts — in-process FIN-link sandbox.
    • POST /dispatch — accepts a SWIFT/ISO payload, assigns a FIN-XXXXXXXXXXXX reference, returns a 202.
    • POST /advance/:ref — deterministic lifecycle: received → acknowledged → accepted → settled.
    • POST /reject/:ref — terminal fork with a rejection reason.
    • GET /messages/:ref and GET /messages?planId=… for polling.
    • Optional per-message webhook; x-fin-sandbox-signature header is HMAC-SHA256 over the body, keyed by FIN_SANDBOX_SECRET.
    • startAutoProgress(intervalMs) opt-in timer ticks messages forward; unref()ed so Node exits cleanly.
  • services/finLink/client.ts — two adapters:
    • createHttpFinLinkClient(baseUrl) for the live router.
    • createInProcessFinLinkClient() short-circuits to the sandbox module, so unit tests don't need an HTTP hop.
    • getFinLinkClient() picks HTTP when FIN_SANDBOX_URL is set, else in-process.
  • services/finLink/index.ts — public surface.
  • src/index.ts — mounts /fin-sandbox only when FIN_SANDBOX_ENABLED=true. Off by default so production builds don't expose the fake.

Why not wire it into the ExecutionCoordinator in this PR

The coordinator rework is its own thread of changes — wiring the SWIFT generators (services/swift/*) through a configurable transport needs to touch bankInstructionPhase, the pay phase, and camt.025/054 ingestion together. This PR ships the transport + client surface so that rework can land as a focused follow-up.

Verification

  • npx tsc --noEmit clean.
  • npx jest 92/92 passing (8 suites).
  • 12 new tests covering:
    • in-memory lifecycle (received → acknowledged → accepted → settled)
    • rejection as a terminal state
    • listMessages filtering by planId
    • deterministic HMAC signature
    • HTTP endpoints (dispatch 202, dispatch 400, advance walk, filter, 404)
    • both client adapters (in-process + live ephemeral-port HTTP round-trip)
Closes gap-analysis v2 §7.1 (no FIN-link adapter — SWIFT generators produce strings but have no transport) and §10.6 (stand up sandbox transport). ## What - `services/finLink/sandbox.ts` — in-process FIN-link sandbox. - `POST /dispatch` — accepts a SWIFT/ISO payload, assigns a `FIN-XXXXXXXXXXXX` reference, returns a 202. - `POST /advance/:ref` — deterministic lifecycle: `received → acknowledged → accepted → settled`. - `POST /reject/:ref` — terminal fork with a rejection reason. - `GET /messages/:ref` and `GET /messages?planId=…` for polling. - Optional per-message webhook; `x-fin-sandbox-signature` header is HMAC-SHA256 over the body, keyed by `FIN_SANDBOX_SECRET`. - `startAutoProgress(intervalMs)` opt-in timer ticks messages forward; `unref()`ed so Node exits cleanly. - `services/finLink/client.ts` — two adapters: - `createHttpFinLinkClient(baseUrl)` for the live router. - `createInProcessFinLinkClient()` short-circuits to the sandbox module, so unit tests don't need an HTTP hop. - `getFinLinkClient()` picks HTTP when `FIN_SANDBOX_URL` is set, else in-process. - `services/finLink/index.ts` — public surface. - `src/index.ts` — mounts `/fin-sandbox` only when `FIN_SANDBOX_ENABLED=true`. Off by default so production builds don't expose the fake. ## Why not wire it into the ExecutionCoordinator in this PR The coordinator rework is its own thread of changes — wiring the SWIFT generators (`services/swift/*`) through a configurable transport needs to touch bankInstructionPhase, the pay phase, and camt.025/054 ingestion together. This PR ships the transport + client surface so that rework can land as a focused follow-up. ## Verification - `npx tsc --noEmit` clean. - `npx jest` 92/92 passing (8 suites). - 12 new tests covering: - in-memory lifecycle (received → acknowledged → accepted → settled) - rejection as a terminal state - `listMessages` filtering by `planId` - deterministic HMAC signature - HTTP endpoints (dispatch 202, dispatch 400, advance walk, filter, 404) - both client adapters (in-process + live ephemeral-port HTTP round-trip)
nsatoshi added 1 commit 2026-04-22 18:40:00 +00:00
FIN-link sandbox service
Some checks failed
CI / Frontend Lint (pull_request) Failing after 6s
CI / Frontend Type Check (pull_request) Failing after 5s
CI / Frontend Build (pull_request) Failing after 7s
CI / Frontend E2E Tests (pull_request) Failing after 8s
CI / Orchestrator Build (pull_request) Failing after 7s
CI / Contracts Compile (pull_request) Failing after 5s
CI / Contracts Test (pull_request) Failing after 6s
Code Quality / SonarQube Analysis (pull_request) Failing after 18s
Code Quality / Code Quality Checks (pull_request) Failing after 4s
Security Scan / Dependency Vulnerability Scan (pull_request) Failing after 4s
Security Scan / OWASP ZAP Scan (pull_request) Failing after 4s
7c5dd145d6
Closes gap-analysis v2 §7.1 (no FIN-link adapter; SWIFT generators
produce strings but no transport) + §10.6 (stand up sandbox transport).

- services/finLink/sandbox.ts — in-process FIN-link sandbox.
  Accepts POST /dispatch with a SWIFT/ISO payload, assigns a FIN
  reference, and advances messages deterministically through
  received -> acknowledged -> accepted -> settled (with reject as a
  terminal fork). Optional webhook per-message (x-fin-sandbox-signature
  header, HMAC-SHA256). Timer-driven auto-progress opt-in via
  startAutoProgress().
- services/finLink/client.ts — two client adapters:
    createHttpFinLinkClient(baseUrl) - for the live router
    createInProcessFinLinkClient()   - for unit tests that skip
                                       the HTTP hop
  getFinLinkClient() picks HTTP when FIN_SANDBOX_URL is set, else
  falls back to in-process.
- services/finLink/index.ts — public surface.
- src/index.ts — mounts /fin-sandbox only when
  FIN_SANDBOX_ENABLED=true; off by default to keep prod surface clean.
- tests/unit/finLinkSandbox.test.ts — 12 tests covering lifecycle,
  rejection, listing, signature determinism, HTTP endpoints
  (dispatch/advance/messages/filtering), and both client adapters
  (including a live ephemeral-port HTTP round-trip).
- Verification: tsc --noEmit clean; full jest 92/92 passing
  (8 suites).
nsatoshi merged commit 2c72a51a06 into main 2026-04-22 20:30:47 +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#22