Compatibility: Pactmark 0.1.x.
The sequence you are implementing
Figure 1. Your application owns the two middle lanes. Get the ordering right and the security properties come along for free; get it wrong and no amount of runtime enforcement saves you.1. Detect that a decision is needed
Watch the event stream forApprovalRequested, or read RunProjection.waitingDecisionId:
2. Render a preview a human can actually act on
3. Authenticate the actor now
Not “is there a session” — authenticate at decision time, with the strength your policy requires for this risk class.AuthenticationStrength and DecisionRole travel in the authority context, and a
weak-authentication or wrong-role decision dispatches nothing.
4. Issue and submit the challenge
Never do this
Persist the proof, put it in a query string, include it in an email, log it at debug level, or
let it enter model context.
Do this instead
Hold it in memory for the length of one request, submit it, and let it expire everywhere else.
nextjs-vercel fixture keeps proofs in a short-lived server-side challenge vault
rather than round-tripping them through the browser. That pattern is worth copying.
5. Handle rejection explicitly
ApprovalRejected carries a reasonCode and a nextStatus of planning, failed or cancelled.
Rejection is a first-class outcome with its own path, not an error.
Idempotency and replay
Every command carries aCommandContext with a commandId. Replaying the same command returns the
same semantic result. A command with the same id but different content conflicts with
KAF_HTTP_IDEMPOTENCY_CONFLICT rather than silently overwriting.
This matters most exactly here: a double-clicked approve button must not become two approvals.
KAF_COMMAND_IDEMPOTENCY_EXPIRED means the idempotency horizon has elapsed — the command is too
old to be safely deduplicated. Treat it as “ask the human again”, not as “retry harder”.What to test
What you are still responsible for
Pactmark binds the decision. It cannot ensure the human understood the preview, that the preview was a fair summary, or that the desk limit in your policy is the right number. Threat model row TM-05 records that residual risk explicitly.Human decisions concept
What an approval binds, and the eight things it can never waive.
Refund use case
The same flow in a complete, opinionated scenario.