Workflow
The top-level object a capsule binds to. Tracks a single payment from draft through settlement.
A Workflow is the unit of work. One workflow = one "pay Acme invoice #47" — it holds together the capsule, the decision receipts, and the Meow-side settlement webhook.
States
draft → approved → consumed → settled | failed
↓ ↓
cancelled cancelled- draft — created, awaiting mint + HITL approval
- approved — policy + approval cleared; capsule can mint
- consumed — capsule consumed; upstream Meow invoked
- settled — Meow webhook confirmed money moved
- failed — Meow webhook reported terminal failure
- cancelled — operator cancelled before consume
Each transition is validated by a deterministic edge check inside a SQLite transaction. Illegal transitions fail with workflow_invalid_transition — no silent state corruption.
Audit history
Every workflow carries an append-only history array:
[
{ "from": null, "to": "draft", "at": 1714579200000, "actor": "op_1" },
{ "from": "draft", "to": "approved", "at": 1714579800000, "actor": "op_compliance" },
{ "from": "approved", "to": "consumed", "at": 1714580100000, "actor": "agent_finance_bot" },
{ "from": "consumed", "to": "settled", "at": 1714583700000, "actor": "meow-webhook" }
]The history is stored as JSON in the workflow row AND mirrored into decision receipts at each transition, so even if the workflow row is lost the audit trail survives on the chain.
Webhook-driven settlement
When Meow emits payment.settled, the gateway's /webhooks/meow handler:
- Verifies the HMAC-SHA256 signature
- Extracts
workflow_idfrom the payload - Calls
WorkflowEngine.transition({ to: "settled" }) - On
WorkflowTransitionError(race / replay), logs + returns 200 so Meow doesn't retry forever - On
WorkflowNotFoundError(misrouted webhook), logs + returns 200
The transition writes a new decision receipt with decision: "allow" and reason_code: "settled" so auditors see the full lifecycle on the chain.
Cancel
curl -X POST http://localhost:3005/v1/workflows/$WF_ID/transitions \
-H "content-type: application/json" \
-d '{ "to": "cancelled", "actor": "op_1", "reason": "vendor dispute" }'Cancel works before consume. After consume the capsule has already moved money; the terminal state comes from Meow's settlement webhook.
Policy Pack
YAML rules compiled into a deterministic AST. Bound into every capsule via policy_sha256 so the runtime rule set is auditable.
Counterparty Locking
Every beneficiary hashes to a stable identifier. Quarantine new payees, hold compromised ones, verify-once enforces human approval before first use.