RS5A-PATCH3-04 — Replay/Idempotency Mutual Exclusion & G08 Fixture — 2026-06-21
RS5A-PATCH3-04 — Replay/Idempotency Mutual Exclusion & G08 Fixture — 2026-06-21
Macro: RS5A-PATCH3 · Residual R3-replay-exclusivity · Deliverable: 04 of 6.
Class: scoped semantic-closure correction. Additive. Does NOT overwrite RS5A-PATCH2-04; the canonical outcomes, the documentation_alias_only rule, and the 84 parent IDs / 86 executable scenarios count all stand. This file sharpens the G02a predicate (adds "same canonical authorization envelope/digest") so G02a, G02b, and G02c are mutually exclusive, and distinguishes the G08 fixture so it remains a distinct executable scenario (Codex §6, §3 oracle PARTIAL, §9.3).
Supersedes (narrow): PATCH2-04 §2 G02a predicate text "same effect + same nonce, already committed" → "same effect + same nonce + same canonical authorization envelope/digest + prior durable decision." All other PATCH2-04 outcomes unchanged.
Gate carried: REGISTRATION_HOLD · REGISTRATION_CAN_PROCEED = NO · 0 mutations. Suite remains DEFINED_NOT_EXECUTED.
1. The defect (Codex §6)
PATCH2-04 wrote G02a as "same effect + same nonce, already committed → IDEMPOTENT_PRIOR_DECISION_RETRIEVAL" and G02c as "same nonce + changed authorization envelope → NONCE_REUSE_AUTHORIZATION_MISMATCH." A retry with the same effect and same nonce but a changed authorization envelope satisfies both predicates as written — which is exactly the authorization-substitution attack the split was created to reject. G02a omitted the authorization-envelope condition, so the three subcases were not mutually exclusive.
2. Canonical mutually-exclusive predicates (a partition of "same nonce")
For any reuse of an already-seen nonce, the outcome is decided by a two-discriminator decision tree over effect_identity and the canonical authorization envelope/digest. The three branches partition the "same nonce" space — every same-nonce input matches exactly one.
same nonce as a prior admitted attempt?
└── yes:
├── effect_identity DIFFERENT from prior? → G02b NONCE_REUSE_DIFFERENT_EFFECT
└── effect_identity SAME as prior:
├── authorization envelope/digest DIFFERENT? → G02c NONCE_REUSE_AUTHORIZATION_MISMATCH
└── authorization envelope/digest SAME
└── prior durable decision exists,
request is exact retry/recovery → G02a IDEMPOTENT_PRIOR_DECISION_RETRIEVAL
| scenario | predicate (all conjunctive) | canonical outcome | class |
|---|---|---|---|
| G02a | same nonce · same effect_identity · same canonical authorization envelope/digest · prior durable decision exists · exact retry/recovery of the same admitted attempt |
IDEMPOTENT_PRIOR_DECISION_RETRIEVAL |
idempotency behavior (no new write, no reject) |
| G02b | same nonce · different effect_identity |
NONCE_REUSE_DIFFERENT_EFFECT |
rejection |
| G02c | same nonce · same effect_identity · different canonical authorization envelope/digest |
NONCE_REUSE_AUTHORIZATION_MISMATCH |
rejection |
Evaluation precedence (guarantees exclusivity):
- Check
effect_identityfirst → different ⇒ G02b. - Else check authorization envelope/digest → different ⇒ G02c.
- Else (same effect and same envelope) with a prior durable decision ⇒ G02a.
So different-effect is checked before idempotent retrieval, and different-authorization-envelope is checked before idempotent retrieval. Idempotent retrieval (G02a) applies only when effect and envelope are both identical. The authorization-substitution case (same effect, same nonce, swapped envelope) now deterministically lands on G02c, never G02a. The defect is closed.
3. G08 — distinct fixture, same canonical outcome
G08 is kept as a separate executable scenario (recommended). It shares G02a's canonical outcome but is a distinct fixture, differing only in client-observation state:
| G02a | G08 | |
|---|---|---|
| nonce | same as prior admitted attempt | same as prior admitted attempt |
effect_identity |
same | same |
| authorization envelope/digest | same | same |
| prior durable decision in server attempt ledger | exists | exists |
| client-observation fixture | known-response exact retry — client already observed the prior committed response and retries the same request | lost-response / unknown-response recovery — client did not observe the prior response and re-sends; the server ledger nonetheless holds the durable decision |
| canonical outcome | IDEMPOTENT_PRIOR_DECISION_RETRIEVAL |
IDEMPOTENT_PRIOR_DECISION_RETRIEVAL |
The two scenarios exercise the same server-side idempotency contract from two different trigger states (client-knows-result vs client-lost-result). Because the fixtures differ, G08 is not duplicate coverage of G02a — it verifies the recovery path specifically. Sharing one canonical outcome is permitted: two distinct executable scenarios may share a canonical outcome (PATCH2-04 §2 note; that is not an alias). IDEMPOTENCY_BEHAVIOR_CASE remains the class label, never the per-scenario outcome.
This is consistent with the accepted PATCH1-02 replay-surface semantics: replay is a hard pre-runtime prerequisite (Axis A) that persists and operates after admission (Axis B) precisely to answer both G02a and G08 retries — see [[rs5a-patch3-02]] §4.1. Answering either retry is not a new business action and not activation.
4. Count is unchanged — 84 parent IDs / 86 executable scenarios
The mutual-exclusivity sharpening and the G08 fixture distinction do not change the count; they make the already-declared count honest.
| component | count |
|---|---|
| parent IDs unaffected by corrections (each 1 executable) | 78 |
| single-case re-canonicalizations D07, H03, H07, I03 (each 1 executable) | 4 |
| G02 → G02a, G02b, G02c (three mutually-exclusive executable subcases) | 3 |
| G08 — distinct recovery-fixture executable scenario (same canonical outcome) | 1 |
| executable scenarios total | 86 |
Arithmetic: 84 parent IDs; G02 (one parent) becomes three executable scenarios ⇒ 84 − 1 + 3 = 86. G02 contributes 3 executable scenarios; G08 remains a distinct executable scenario with the same canonical outcome but a distinct (recovery) fixture. Canonical statement: "84 top-level parent IDs / 86 executable scenarios." Suite remains DEFINED_NOT_EXECUTED.
(Were G08 instead merged into G02a, the honest recomputation would be 78 + 4 + 3 = 85 executable scenarios. PATCH3 does not take that path: G08 is distinguishable by its client-observation fixture, so it is kept separate and the count remains 86.)
5. Status
R3-replay-exclusivity residual CLOSED: G02a/G02b/G02c partition the "same nonce" space by a two-discriminator decision tree (effect, then authorization envelope), so different-effect and different-envelope are both checked before idempotent retrieval; G08 is a distinct executable scenario distinguished from G02a by client-observation fixture (known-response retry vs unknown-response recovery) while retaining the same canonical outcome; count remains 84 parent IDs / 86 executable scenarios; suite DEFINED_NOT_EXECUTED. …REPLAY_IDEMPOTENCY_PREDICATES_OVERLAP HOLD condition does not apply. No test was run; no runtime driven; no mutation.