Add Bank-to-VASP Control Room demo and reference-stack updates - #1
Add Bank-to-VASP Control Room demo and reference-stack updates#1Raafet57 wants to merge 43 commits into
Conversation
|
Small clarification: this is review-only for now, not a merge request. I opened it as a draft to get your thoughts on the direction, architecture, and message-family boundaries before considering whether any of it should be merged. |
|
Hi sir. I like the idea of making it executable, that is a great step forward where eI had not yet spent energy on. |
|
OK done, have a look already. a reporting yaml is added and various refinements everywhere, |
|
I`m on it |
Integrate Tom Alaerts' v1.3 spec-family release while preserving this fork's reference-server + docs layer. Brought in from upstream/main (a450dbc..d546a8a): - unified v1.3 filenames (travel-rule / instruction / account-reporting, renamed from the old v3 / v1 / camt-crypto-reporting names) - Spec 4: Exception & Investigation API + ei-simulator (camt.110/111) - Spec 5: Liquidity Management API + liquidity-simulator - optional debtor/creditor agents, SELF_CUSTODY model, rewritten README Conflicts resolved by keeping both sides: - README.md: Tom's v1.3 spec narrative + this fork's reference-stack "Current Direction" section; all filename references updated to v1.3 - instruction-simulator-v1.3.html: kept the Live-API "Execution Mode" block and Tom's new v1.3 returns/reversals fields travel-rule-simulator-v1.3.html auto-merged cleanly (Live-API additions and v1.3 tweaks did not overlap). reference-server/ was untouched by upstream; full suite (48 tests) passes after the merge.
Follow-on to the upstream v1.3 merge: update the conformance matrix, demo walkthrough, and roadmap to cite Tom's renamed spec files. - travel-rule-api-v3.yaml -> travel-rule-api-v1.3.yaml - instruction-api-v1.yaml -> instruction-api-v1.3.yaml - camt-crypto-reporting-v1.yaml -> account-reporting-api-v1.3.yaml - *-simulator-v3/v1.html -> *-simulator-v1.3.html Reference semantics (camt.052/053/054 mappings) are unchanged; only the spec filenames moved.
Make the reference server and its docs coherent with the v1.3 specs merged from upstream, without widening the FULL_CUSTODY / EVM wedge. Server conformance fixes (real bugs — v1.3-valid requests were rejected): - accept the new v1.3 `SELF_CUSTODY` custody model at the API surface (no longer a 400); the wedge executes FULL_CUSTODY only, so SELF_CUSTODY and DELEGATED_SIGNING now return 501 with a clear message - make debtor_agent / creditor_agent optional on instruction and travel-rule submission (v1.3 corporate-direct / self-hosting flows); debtor and creditor parties stay mandatory - add tests for both behaviours — 50 tests pass Docs coherence: - conformance.md: agent/custody notes; new rows for the v1.3 instruction return / reverse / reversal-status endpoints; Spec 4 (exception-investigation, camt.110/111) and Spec 5 (liquidity) status; /exceptions/* extension note - exception-family.md: how the first-slice /exceptions/* model relates to v1.3 Spec 4 and the instruction-level returns/reversals (same "never rewrite FINAL" rule, different surface) - roadmap.md + README: record v1.3 alignment status and follow-ups
Add a strategic research note plus an expansion roadmap and backlog, grounded in a June 2026 survey of the DeFi/TradFi interoperability landscape and mapped onto pacs.crypto's ISO 20022 bridge. New: - docs/interop-defi-tradfi.md - landscape (SWIFT+Chainlink CCIP/CRE, ERC-7943/ERC-3643/ISO 24165, Project Guardian Trust Anchors, BIS Agora / unified ledger, CCTP/Canton, vLEI/GLEIF, FATF Travel Rule, MiCA/GENIUS, x402/AP2/MPP) with cited sources, 10 scored opportunities (O1-O10), and guardrails - docs/interop-roadmap.md - horizon-based (H0-H3) expansion roadmap, sequenced strictly behind the current wedge Updated: - docs/backlog.md - Epics 15-24 (P3/Deferred), one per opportunity, tagged by horizon and cross-referenced to Epic 14 - docs/roadmap.md + README - cross-links to the new interop docs All directions are post-wedge and additive; nothing changes the current execution program or the v1.3 conformance follow-ups.
All optional and additive; absent fields are unaffected, existing tests stay green. - Epic 16 (vLEI): validate optional vlei_credential (credential_id, issuer_lei, status) on parties and agents - Epic 17 (transport): validate optional blockchain_instruction.settlement_transport (DIRECT_EVM / CCTP / CCIP / CANTON) - Epic 20 (RWA): validate optional credential_attestation incl. ERC-7943 / ERC-3643 enforcement context on instruction + travel-rule submissions - test/interop-fields.test.js: 5 new tests; 55 tests pass total
…18/19/23) - Epic 18: mock Circle CCTP V2 settlement adapter composing the mock EVM lifecycle and surfacing cross-chain burn-and-mint metadata; selectable via REF_SERVER_CHAIN_ADAPTER=mock-cctp. Proves the chain-adapter seam supports a second venue with no route change. - Epic 19: bidirectional pacs.crypto Spec 1 <-> IVMS101 core-field mapping (name, LEI, country, wallet) so the Travel Rule model bridges TRISA/TRP; unmapped fields reported, not dropped. - Epic 23: x402 agent-intent -> compliant pacs.crypto instruction binding (ISO 24165 DTI-first resolution, SELF_CUSTODY default, Travel Rule gap surfaced as a warning). - 6 new tests (cctp/ivms101/x402); 61 tests pass.
DELEGATED_SIGNING instructions now execute end to end instead of returning 501:
- POST /instruction with DELEGATED_SIGNING is held with an unsigned transaction
(adapter buildUnsignedTransaction) and awaiting_signed_transaction = true
- the lifecycle is gated at PENDING until the signed transaction arrives
- POST /instruction/{id}/signed-transaction validates and accepts the signed
transaction (SignedTransactionSubmission), lifts the gate, and resumes the
normal BROADCAST -> CONFIRMING -> FINAL progression on unchanged route shapes
- SELF_CUSTODY still returns 501; FULL_CUSTODY and DELEGATED_SIGNING execute
- the old "out of scope" test is rewritten into a full delegated flow test plus
an unknown / non-delegated rejection test; 62 tests pass
…reporting (Epics 21/22) Messaging-layer modules, anti-tipping-off discipline throughout: - Epic 21 (trust-anchor): buildAccessCredential / verifyAccessCredential for the Project Guardian permissioned-pool model. Asserts ELIGIBLE/NOT_ELIGIBLE and carries identity (LEI/vLEI), never sanctions reasoning; verify enforces scope, vLEI requirement, and expiry. - Epic 22 (compliance-reporting): one canonical record -> regime-specific filings (MiCA auth.117-shaped + GENIUS-shaped) from a single substrate; DTI-first; no sanctions reasoning emitted. - 5 new tests; 67 tests pass.
…acklog - backlog.md: Epic 13 -> Implemented; Epics 15-23 -> "Implemented (reference slice)"; section intro notes the implementation pass; Epic 24 stays deferred (externally gated) - conformance.md: signed-transaction route now Implemented; custody + interop field notes; new "Interoperability reference modules" table (Epics 15-23) - README: delegated signing and the interop reference layer reflected in the reference-stack status
… review Delegated signing (db.js) — three HIGH correctness bugs: - a cancelled (or expired) held instruction could be revived by submitting the signed transaction: the sign path gated only on awaiting_signed_transaction, not status. Now require status==='PENDING' too. - concurrent signed-transaction submissions both cleared the gate (non-atomic check-then-act) -> double progression / lost update. Now serialized per instructionId via inFlightSignedTransactions, mirroring createInstruction. - a held instruction never expired, and resetting created_at to signing time corrupted reporting/finality timestamps and could spuriously EXPIRE a just-signed instruction. Now created_at (acceptance) is preserved and the held gate expires the instruction when its signing window lapses. Coherence / modules: - credential_attestation now round-trips through the store (was validated then dropped); carried in normalizeInstructionSubmission + the record (Epics 16/20). - x402 binding: beneficiary wallet placed at top-level creditor_account (was nested under blockchain_instruction and dropped); empty-string id resolution treated as unresolved. - trust-anchor verify enforces expiry even when policy.now is omitted; comment clarifies eligibility is a vouch, not a screening-result disclosure. - validators: note that ERC-7943 enforcement booleans are token capabilities, not per-counterparty decisions. - backlog Epic 23 acceptance reworded (Travel Rule surfaced as a warning). 7 regression tests added (cancel-then-sign, concurrent sign, held expiry, invalid format, attestation round-trip, x402 wallet placement, trust-anchor expiry); 74 tests pass.
…ffold - Epics 19/21/22/23: wire the interop reference modules into stateless /interop/* HTTP routes (travel-rule<->ivms101, access-credentials [+verify], compliance-filings, x402/bind) so the directions are reachable over the wire, not just importable - Epic 24: add a reference scaffold (unified-ledger pre-settlement posture, BIS Agora model) + /interop/unified-ledger/pre-settlement route, clearly marked as a scaffold gated on external maturity (not a production commitment) - conformance.md / backlog.md updated; 6 new route tests; 80 tests pass
…d integration test Epics 10/11: the "real instruction produces a real on-chain tx hash reaching FINAL" acceptance is now an executable test (test/sepolia-funded.integration.test.js) rather than a manual ritual. It runs a real Sepolia USDC broadcast and asserts a real 0x tx hash, but only when the operator opts in (REF_SERVER_SEPOLIA_FUNDED_TEST=1) with funded REF_SERVER_SEPOLIA_* credentials; otherwise it skips with an explanatory reason. The surrounding safety/corridor/lifecycle behaviour is already covered by stub-based tests. 81 tests: 80 pass, 1 gated-skip. backlog updated.
The review caught three real regressions in the delegated-signing fixes: - lifecycle was anchored to created_at (acceptance), so a realistically-delayed signature jumped straight to FINAL skipping BROADCAST/CONFIRMING with a block timestamp BEFORE the signature. Added lifecycle_anchor_at (set at signing); the mock adapter derives elapsed time + executed-state timestamps from it while created_at stays at acceptance for reporting/history. - delegated signing never broadcast on a real adapter: the resume path only called deriveLifecycleState, but a real adapter broadcasts in submitLifecycleState. The sign path now invokes submitLifecycleState on resume (mock falls back to the simulated clock). - a cancelled held instruction flipped CANCELLED -> EXPIRED after its expiry: cancel now clears awaiting_signed_transaction/unsigned_transaction, and the held-gate guards on status === 'PENDING' so a terminal record is never re-expired. Low-severity edge fixes: x402 amount 0 no longer warns "missing"; trust-anchor verify falls back to current time when policy.now is unparseable; IVMS101 omits empty person / null-name records. 6 regression tests; 86 tests (85 pass, 1 gated Sepolia skip).
…ng redesign)
The re-run review found my round-2 "broadcast on resume" fix was wrong on a real
adapter, plus a residual anchor bug and edge cases:
- HIGH: on the custodial Sepolia adapter, the resume path called
submitLifecycleState, which re-signs and broadcasts with the SERVER's own key,
ignoring the party's signed transaction (and failing the corridor check).
Delegated signing is now an explicit adapter capability (supports_delegated_
signing): the mock simulates it; a custodial adapter rejects DELEGATED_SIGNING
with 501 at submission. The custodial submitLifecycleState path is no longer
used on resume; the mock resumes on the simulated clock.
- MEDIUM: the mock's buildUnsignedTransaction leaked onto every adapter via the
normalizeChainAdapter spread, so a non-supporting adapter handed a delegated
client a fabricated unsigned tx. Held-state + unsigned_transaction are now
gated on the capability; the dead {transaction_format:'OTHER'} fallback removed.
- HIGH: a delegated instruction signed near its expiry could flip to EXPIRED
because deriveLifecycleState still checked the original expiry while the
lifecycle was anchored at sign time. Signing now clears expiry_date_time.
- MEDIUM: /execution-status now surfaces awaiting_signed_transaction so a held
payment is distinguishable from a queued one.
- LOW: trust-anchor fails closed on a malformed expiry and uses a strict-boolean
screening flag; x402 maps a null amount to undefined (not 'null'); IVMS101
keeps a party that has LEI/country but no name.
Tests: replaced the (wrong-behaviour) broadcast-on-resume test with a rejection
test, added a post-sign near-expiry regression. 87 tests (86 pass, 1 gated).
…ce, adapter fail-open) - MEDIUM: TOCTOU race between sign and cancel on a held delegated instruction. The sign lock did not cover cancelInstructionAsync, so a concurrent cancel+sign could clobber or revive each other. All mutating ops on one instruction (sign AND cancel) now serialize through a single per-instruction lock (runWithInstructionLock); the sign-only inFlightSignedTransactions map is gone. - MEDIUM: adapter fail-open. A custom adapter omitting supports_delegated_signing inherited the mock fallback's `true` via the normalizeChainAdapter spread. Normalization is now fail-closed (an adapter must explicitly opt in); a null adapter returns the mock directly; mock-cctp states the flag explicitly. - LOW: compliance-filings maps a JSON-null `regimes` to the default set instead of throwing; IVMS101 omits empty debtor/creditor parties. Rewrote the concurrent-sign test for the serialized semantics and added a sign/cancel race regression. 88 tests (87 pass, 1 gated).
…402/IVMS edges) - MEDIUM: releaseExpiredHold ran from unlocked read paths (GET / search / the create-time duplicate check), so concurrent reads of an expired held instruction could double-emit the EXPIRED outbox event. Added a synchronous compare-and-swap re-read so the transition + emit happen exactly once. - LOW: x402 resolve() now looks up own properties only (so keys like 'constructor'/'toString' no longer resolve to inherited prototype members) and omits an undefined debtor name instead of carrying name:undefined. - LOW: IVMS101 mapping reports dropped vLEI credentials and non-country address subfields in `unmapped` per its "never silently drop" contract. Note: the broader read-advances-lifecycle concurrency (concurrent unlocked reads can double-emit an outbox event for ANY transition, not just delegated) is a pre-existing engine property, not introduced here; engine-wide idempotency is a separate scoped follow-up. 88 tests (87 pass, 1 gated).
# Conflicts: # docs/conformance.md # reference-server/src/routes/instruction-routes.js
Add the standalone reviewer Control Room shell, local demo navigation, and QA reconciliation packets for the Bank-to-VASP happy-path walkthrough.
|
@tomalaerts-dev quick update: this PR now includes the latest Control Room shell, QA packets, and the narrated HyperFrames review video packet. Head is Key review entry points:
Boundary: this remains a reviewer/demo artifact; no production deploy or funded Sepolia run is implied. |
|
@tomalaerts-dev, one follow-up after comparing your current All five root v1.3 OpenAPI YAMLs in my fork remain unchanged from your canonical versions. My delta is therefore mainly the executable reference stack, conformance work, Control Room, QA evidence, and the narrated review video already linked above. Your README names the Compliance Base Info Reporting API as the next planned family specification. My fork contains a small non-normative seed for that direction: one canonical transaction/compliance record can emit a representative MiCA Rather than add more scope to this broad PR, would a separate narrow design note be useful? I could propose:
I would keep it as an unversioned draft until you choose the name and family release, and only turn it into a focused OpenAPI PR after your design feedback. Best, |
Hi @tomalaerts-dev / Tom,
I’d value your review on the latest
pacs.cryptoreference-stack and reviewer-demo developments from my fork.What changed
Reference stack / execution wedge
Reviewer-facing demo surfaces
bank-to-vasp-control-room.htmlControl Room demo shell.docs/demo-samples/happy-path/.README.md,docs/demo-bank-to-vasp.md, andindex.htmlnavigation so reviewers can find the demo.Video/demo packet
docs/media/control-room-demo-video-2026-07-09/README.mddocs/media/control-room-demo-video-2026-07-09/renders/pacs-control-room-demo-720p-review.mp4index.html,SCRIPT.md,DESIGN.md), narration audio, timed UI capture, and contact sheet.Verification already run
reference-servertests: 95 passing, 1 funded-Sepolia integration skipped unless explicitly enabled.node --check.Explicit boundaries
Thanks,
Raf