Skip to content

Drift refusal and idempotency

An approval is valid only for the business state it described. Before execution, the runtime asks the host to resolve current state again.

Refuse material drift

    async def resolve(
        self, snapshot: RefundSnapshot, *, context: ExecutionContext
    ) -> ResolvedState[RefundSnapshot, RefundPreview]:
        del context
        return ResolvedState(
            current_snapshot=snapshot.model_copy(update={"order_version": self.order_version}),
            execution_precondition=f"order-version:{self.order_version}",
            materially_drifted=snapshot.order_version != self.order_version,
        )

If materially_drifted=True, the original proposal becomes stale and the executor is not called. The resolver may include a replacement so the runtime can persist a fresh proposal and preview. The old authority never transfers to the replacement.

Run the complete drift and competing-proposal examples:

uv run python -m examples.docs.lifecycle_scenarios

Your application decides what “material” means. Examples include:

  • refund amount or already-refunded balance;
  • invoice approval state;
  • supplier bank-account version;
  • payment destination, currency, or due date;
  • ledger period or posting version.

Close the final race

State can change after resolution but before mutation. The resolver therefore returns an execution_precondition, and the executor must enforce it atomically with the business write. If that check loses, return stale_no_effect.

    async def execute(
        self,
        snapshot: RefundSnapshot,
        *,
        context: ExecutionContext,
        execution_precondition: str,
    ) -> ExecutionResult[RefundResult]:
        del snapshot, context
        self.executor_calls += 1
        if execution_precondition != f"order-version:{self.order_version}":
            return ExecutionResult[RefundResult](
                status=ExecutionStatus.STALE_NO_EFFECT,
                reason_code="order_changed_during_execution",
            )
        self.refund_completed = True
        return ExecutionResult[RefundResult](
            status=ExecutionStatus.ACCEPTED,
            result=RefundResult(provider_reference="psp-refund:42"),
        )

    async def verify(self, *, context: ExecutionContext) -> VerificationResult[RefundResult]:
        del context
        if self.refund_completed and self.refund_visible_to_verifier:
            return VerificationResult[RefundResult](
                status=VerificationStatus.VERIFIED_COMPLETION,
                result=RefundResult(provider_reference="psp-refund:42"),
            )
        return VerificationResult[RefundResult](
            status=VerificationStatus.PROVISIONAL_ABSENCE,
            reason_code="refund_not_visible_yet",
        )

Semantic effect identity

Preparation also returns a stable, opaque semantic_effect_reference, such as refund:01K4Y8Q5X7M2N9R3T6V8W1Z4AB. A conforming store atomically allows only one proposal for the same tenant, action version, and semantic effect to enter execution.

This reference remains in the minimized tombstone and semantic-effect claim after erasure because it is the durable replay barrier. Never construct it by concatenating order, supplier, invoice, account, or personal identifiers. Use a durable random intent ID or a keyed opaque derivation managed by the host.

This is stronger than an HTTP retry key because it describes the business effect, but it is still not distributed exactly-once execution. The target system should accept its own stable idempotency identity, and the verifier must query by that same identity.

Safe retry rule

Never resend failed_unknown. Verify first. Resend is eligible only when all of the following are true:

  1. the authoritative target reports final—not provisional—absence;
  2. its settling boundary has passed;
  3. it guarantees idempotency for the effect identity; and
  4. the action definition explicitly allows resend after final absence.