Minimal durable idempotency for ambiguous mutation retries

Analyze a mutation whose first response may be lost after the server commits. The design should state the minimum durable record, the atomicity and uniqueness requirements, request-key semantics, replay behavior, concurrency handling, retention limits, and the boundary where an external side effect requires an outbox or downstream idempotency. Work through a concrete crash and retry sequence. This is a reasoning exercise with no executed implementation tests.

Verified reasoning: the minimum end-to-end invariant is a durable unique identity for caller scope, operation, and client-generated key, committed atomically with the transactional business effect. A practical minimal receipt also stores an effect-semantic request fingerprint and an immutable outcome or stable result reference. A retry that races an uncommitted first attempt must be serialized by the uniqueness constraint; after the winner commits, a matching loser replays the receipt, while mismatched key reuse is rejected. A crash before commit rolls back both receipt and effect, so retry may execute. A crash after commit but before response leaves both durable, so retry only replays. Retention bounds the guarantee. An external nontransactional effect is outside this minimal database guarantee and requires a transactional outbox plus downstream idempotency, or another atomic boundary.

Rollout-specific resolution: fingerprint version is metadata on the winning receipt, never part of the unique idempotency identity. A duplicate first loads that receipt, strictly decodes the incoming contract, and uses an explicit lossless adapter into the winner's historical semantic domain before applying the winner's canonicalizer. If any effect-relevant distinction would be erased, comparison is denied rather than allowing the old digest to ignore it. An old winner can accept a new request only when new fields are proven equivalent to old defaults; a new winner can accept an old request only when missing fields map unambiguously to the stored intent. The immutable stored result and its result-schema version are then rendered for the retrying client without rerunning the effect. For operations, use a named one-card-per-task-reason-per-ten-minute-window rule, capped at three reason classes per task with overflow coalesced into other. If an auxiliary sharing worker crashes or reaches its deadline before authorization and a confirmed write, the primary computation returns normally, the sharing state remains denied, and repeated warnings increment one bounded card instead of creating unbounded labels.