# Replay idempotent mutations across request canonicalization rollouts

Use a stored fingerprint version and effect-preserving request translation so retries across a schema rollout replay the original outcome without admitting changed intent.

Exact reference: {"kind":"skill_version","skill_id":"skl_gn6kBTQ4cfXG1nztr_WZIw","version_id":"skv__Lo224Jvww3T3b0ib-C1iw"}

Applicability: []

# Replay idempotent mutations across request canonicalization rollouts

## When to use

Use this when durable idempotency records survive a request schema or canonicalization change and old clients may retry while new clients are sending requests.

## Record identity

Persist the request schema version, fingerprint algorithm version, fingerprint, and immutable committed outcome with each idempotency record. Backfill legacy records with the exact historical version that produced their fingerprints. Keep the unique key scoped to caller and operation, independent of schema version. A version in the unique key would permit a duplicate effect across the rollout.

## Duplicate-key rule

The committed row is authoritative. On a retry, read its recorded versions and translate the incoming request into that row's historical semantic domain. Translation is allowed only when it preserves the entire intended effect. Compute exactly the fingerprint recorded by that historical algorithm and compare it with the row. Reject a mismatch or an untranslatable request as key reuse. Never accept because a fingerprint matches under some other available version, and never drop a newly meaningful field merely to manufacture a match.

For example, version two adds a fee with a default of zero. A version-two retry with fee zero may represent a version-one operation; one with a nonzero fee cannot. The inverse translation fills in zero when a version-one retry meets a version-two record. This is safe only if zero truly preserves the operation's effect.

## Concurrent requests and replay

The unchanged unique constraint serializes old and new requests for one key. The transaction that commits first fixes the version and intent. After that transaction commits, the loser applies the stored row's comparison rule. A matching loser replays the immutable outcome, and a changed loser is rejected. If the winner rolls back, the other request may claim the key. Return the original stored response for the same contract, or render the immutable outcome into a compatible response contract after identity matches. Do not rerun the mutation or derive the supposed original result from mutable current state.

## Rollout order

Deploy readers that understand old and new records before enabling new-version writes. Backfill version metadata before ambiguous rows are compared. Retain old comparison code for the full record retention and retry horizon. If a legacy row lacks enough evidence to establish intent, fail closed rather than guessing.

## Supporting basis and limitations

Reasoned transaction and concurrency cases: the first committed key fixes its request identity and version; a later caller can replay only after effect-preserving comparison in that version. No implementation or tests were executed.

## Change and rationale

Adds a focused procedure for versioned request identity, rollout order, concurrent old and new clients, and compatible response replay.

Canonicalization changes can turn a previously safe retry into either a false mismatch or an unsafe match if the server compares against current rules or accepts a match under any available version. The stored record must remain authoritative.
