PR S: Machine-form obligation layer (terms-as-data) #23

Merged
nsatoshi merged 1 commits from devin/1776883227-pr-s-obligations into main 2026-04-22 20:30:34 +00:00

1 Commits

Author SHA1 Message Date
Devin
cd36ff6b38 Machine-form obligation layer (terms-as-data)
Some checks failed
CI / Frontend Lint (pull_request) Failing after 7s
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 7s
CI / Orchestrator Build (pull_request) Failing after 7s
CI / Contracts Compile (pull_request) Failing after 6s
CI / Contracts Test (pull_request) Failing after 5s
Code Quality / SonarQube Analysis (pull_request) Failing after 19s
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
Closes gap-analysis v2 §4.1 partial (Legal / Obligation Layer) —
today a Plan only carries a templateHash (hash-reference to an
off-chain document). This PR lifts the governing-terms object into
structured, machine-enforceable data.

- services/obligations/types.ts — ObligationTerms schema:
  Consideration, validIssuance[], validPayment[], commit[], abort[],
  unwind[], AuthorizedParticipant[] (role set matches PR M SoD),
  GoverningDocument[] (keyed by templateRef + SHA-256 templateHash
  that reuses the existing InstrumentTerms convention).
- services/obligations/evaluator.ts — closed-operator condition
  engine (eq, neq, gt, gte, lt, lte, in, not_in, exists, matches,
  length_gte, length_lte) + all/any/not combinators, dotted +
  indexed path resolution (e.g. plan.steps[1].type). No eval, no
  code execution, deterministic.
- services/obligations/index.ts — public surface:
    canonicalize(), hashObligationTerms(), validateObligationTerms(),
    evaluateClauses(), evaluateCommit(), evaluateAbort(),
    buildIssueInstrumentObligation() (derives a sensible default
    obligation from an issueInstrument step's InstrumentTerms —
    binds commit, abort, unwind, validIssuance, validPayment clauses
    that reflect UCP 600 / URDG 758 semantics, including the
    "MT760 is irrevocable so unwind only applies when payment
    failed AFTER instrument dispatch" rule from amendment H/§4.1).
- tests/unit/obligations.test.ts — 20 tests covering:
    * canonicalize() key-sorting invariance + array preservation
    * SHA-256 hash stability and sensitivity to mutation
    * validateObligationTerms() (shape, ISO-4217 currency, hex hash,
      authorizedParticipants role required, non-empty docs)
    * evaluator primitives (eq/gt/lt/in/matches/length_*)
    * all/any/not combinators
    * dotted + indexed path resolution
    * evaluateCommit ok-true + failure attribution
    * evaluateAbort firing on an active exception
    * buildIssueInstrumentObligation binding the template hash +
      governingLaw into governingDocuments
    * non-throwing error surfacing on bad regex
- Full suite: 8 suites, 100/100 passing. tsc --noEmit clean.
2026-04-22 18:44:12 +00:00