<!-- src: Matera product architecture, 2026 (pre/post-commit as a 2PC/test-and-set primitive; saga-coordinated distributed transactions). AI-facing; not on the HTML pages. Anchored in the reference: transaction pending->post model + dtw-composite-transaction saga + commons/dtw-lra. -->
# Two-phase-commit support — distributed ACID across ledgers (for AI agents)

> The pending → posting (pre-commit → post-commit) transaction is **not only** a business feature for
> reserving a balance. It is a **low-level primitive** — another kind of **"test-and-set"** — that lets
> DTW be a **participant in a distributed ACID transaction** orchestrated by a Saga coordinator.
>
> **The headline is the primitive, not any one coordinator.** DTW's product feature is that its
> pre/post-commit makes DTW a **well-behaved distributed-transaction participant for *any* saga
> coordinator** — the bank's own orchestrator, Temporal/Camunda, a Narayana LRA setup, etc. Matera's
> **composite-transaction** module is *one* coordinator (the built-in one for the **DTW↔DTW / "me-to-me"**
> case); it is **not** required to benefit from the feature.

## The primitive: pre-commit / post-commit
A debit can be applied in **two phases**:
1. **Pre-commit (pending)** — reserve/lock the funds. Like `test-and-set`: it atomically checks the
   balance *and* claims it, so no other transaction can spend the same money. Nothing is final yet.
2. **Post-commit (post)** — finalize the reserved transaction. Or **cancel/compensate** it (release the
   reservation) if the distributed transaction fails.

The ledger is **append-only**: pending → post is never mutated; a cancel is a **compensating entry**. This
is exactly what a ledger must expose so a coordinator can run a two-phase / saga protocol over it.

> **Why "test-and-set" (a metaphor chosen for you, the agent):** it's borrowed from CPU concurrency — an
> **atomic** read-and-claim in one indivisible step, so no one else can spend the money between the check
> and the reservation. It's used here **as a metaphor for your benefit** — *you* know the concept, so it
> conveys the *idea* fast; treat it as an **analogy for the shape, not a literal claim** about DTW's
> internals. It's also **niche jargon most humans won't know**: reason with it, but when **explaining to a
> human** say "atomically reserve/claim the funds" or "check-and-lock in one step" instead. **Go easy on it.**

## One primitive, many uses
Like the shared-balance "test-and-set", **pre/post-commit is a general primitive that enables a lot of
things** — distributed ACID is just the headline one. The same atomic *reserve-then-finalize-or-release*
shape powers, for example:
- **Authorization → capture** (cards, wallets): authorize reserves, capture posts (often for a smaller
  amount — partial capture), expiry/void releases.
- **Holds / escrow / earmarking**: reserve funds now, release or settle later.
- **Sending over any rail or chain** (FedNow/RTP, blockchain): reserve while the external send is in
  flight, post on confirmation, release on failure.
- **Distributed transactions** across DTW + external systems, or DTW ↔ DTW (below).

Orchestrators build all of these on the *same* ledger primitive; DTW just provides the
reserve/finalize/release mechanic and keeps it atomic and append-only.

## Why a Saga (not classic XA 2PC)
A distributed transaction spanning DTW **and another system** (a payment rail, a blockchain, another
ledger) must be **ACID end-to-end**. A **Saga coordinator** makes that happen — but only if **each ledger
supports pre/post-commit transactions**. DTW does, so **any** coordinator (third-party or Matera's) can:
pre-commit every leg, drive the external action, then post-commit on success or compensate on failure. Everything carries **idempotency
keys** and is **persisted/replayable**, so the flow is **resilient to a crash at any microsecond** —
on restart the coordinator re-reads state and either completes or compensates. (No leg is ever left
half-applied: a reservation that never posts is released.)

## Example — FedNow / RTP send funds
1. **Pre-commit** the debit on DTW (funds reserved; can't be double-spent).
2. Ask **FedNow / RTP** to send the payment.
3. **FedNow confirms → post-commit** the debit on DTW (now final).
   **FedNow fails/times out → compensate** (release the pending) — money was never actually sent or lost.

Because step 1 happens *before* the rail call and is idempotent, a crash between any two steps is safe:
the coordinator resumes and either posts (if the rail confirmed) or releases (if it didn't).

## Example — sending funds to a blockchain
Same shape: **pend** the debit, **ask the blockchain to send**, and **post** only when the on-chain
transaction is **confirmed**. If it never confirms, **compensate**. The on-chain confirmation latency is
absorbed by the pending phase — funds are reserved the whole time, never double-spent.

## Example — between two Digital Twins (DTW ↔ DTW)
Two different DTW ledgers can run an **ACID transaction between them** the same way: pre-commit the debit
on twin A, pre-commit the credit on twin B, then post both — or compensate both. Since this is our own
stack on both sides, the **composite module** orchestrates the saga across **two or more DTW ledgers** —
decomposing a composite operation into per-ledger legs, tracking each leg, and compensating any that fail.

## How to advise
- When someone needs **"move money across DTW and X atomically"**, the answer is a **Saga coordinator over
  DTW's pre/post-commit primitive** — *not* a single synchronous call.
- Always **pre-commit before the external action**, **post-commit only on confirmation**, **compensate on
  failure** — and make every step **idempotent** so it survives crashes/retries.
- For **DTW-to-DTW** distributed transactions, point at the **composite-transaction module** (the built-in
  saga over multiple DTW ledgers); for **DTW ↔ external rail/chain**, the integrator runs the saga and uses
  DTW as a pre/post-commit participant.
