RS4A-PATCH1-05 — Nonce Classification and Phase Semantics Correction — 2026-06-21
RS4A-PATCH1-05 — Nonce Classification and Phase Semantics Correction — 2026-06-21
Macro: RS4A-PATCH1 · Mục tiêu E + F (closes Codex C5 nonce placement, C6 Phase 2/3 consume, C7 Phase 4 verifier pair, C8 Phase 5 audit semantics)
Deliverable: 05 of 10 · design-only · correction addendum (does NOT overwrite RS4A-02/04; no transaction code)
Builds on / corrects: RS4A-02 §2 input table; RS4A-04 Phases 2/4/5.
Gate: REGISTRATION_HOLD · REGISTRATION_CAN_PROCEED = NO
Status: NONCE_RECLASSIFIED + PHASE_SEMANTICS_CORRECTED — nonce is an authority credential, not a request_proposed field; Phase 2 reserves, Phase 3 consumes; Phase 4 verifier is an independent reference; Phase 5 audit is written after rollback in a separate transaction.
1. C5 — Nonce reclassification (closes Codex §4.4 / §17)
Defect: RS4A-02 §2 prose said the single-use authority argument is "separate from the dict," but the input table classified authorization_nonce with Tier = proposed — i.e. as an ordinary caller-proposed field. Codex: "The contract must define the nonce as an authority-issued credential/envelope input, not an ordinary caller-proposed field."
Correction — authorization_nonce is reclassified:
authorization_nonce:
classification = AUTHORITY_CREDENTIAL # NOT request_proposed, NOT trusted_attested-of-content
source = authority-issued (the grant authority mints it; never the caller, never the validator)
carriage = the caller may carry it ONLY as an opaque bearer/reference (it conveys no authority by being present)
validation = (a) reread the authority envelope that issued it, AND
(b) consume it once against the durable U2 record UNIQUE(authorization_nonce) (PATCH1-02)
trust = the nonce is evidence of a single grant; it is NEVER caller-proposed authority
identity = NON-identity (excluded from effect_identity; PATCH1-02 §1.1)
Corrected RS4A-02 §2 row:
| Field | Tier (corrected) | Meaning / binding |
|---|---|---|
authorization_nonce |
authority_credential (separate authority input, NOT in the request_proposed dict) |
single-use grant minted by the authority; validated by envelope-reread + one-time consume (U2); opaque to the caller |
Reject set (the nonce must fail closed on):
- caller-generated nonce ⇒
CALLER_AS_AUTHORITY/NONCE_UNBOUND; - nonce not bound to owner/APR/artifact/effect envelope+window ⇒
NONCE_UNBOUND; - reused (already-consumed) nonce ⇒
REPLAY_NONCE_CONSUMED; - nonce used as effect identity ⇒ rejected (it is non-keying; a fresh nonce must not buy a duplicate effect, PATCH1-02 §1.2, RP-02).
The pure validator never owns or mints the nonce; the registrar/Phase-3 consumes it (RS4A-07 §6).
2. C6 — Phase 2 vs Phase 3 consume semantics (closes Codex §6)
Defect: RS4A-04 named Phase 2 a "Nonce / logical-key consume" phase, but its consume mutation actually occurs inside Phase 3's atomic transaction. Codex: "Rename it as validation/reservation criteria or explicitly state that no durable consumption occurs until the Phase-3 transaction."
Correction — phases relabeled with crisp boundaries:
| Phase | Corrected role | Durable mutation? |
|---|---|---|
| Phase 2 — replay/nonce VALIDATION & RESERVATION (criteria only) | check that effect_identity is not already consumed, the authorization_nonce is bound + not yet consumed, attempt is non-keying; produce a reservation decision (admit/deny). No durable consume. |
NO — Phase 2 performs no durable write; a "reservation" here is in-memory/advisory and is re-checked transactionally in Phase 3 (no orphan consume can exist). |
| Phase 3 — atomic durable consume + inert write + attempt record | in one transaction: consume effect_identity (U1 ON CONFLICT → reject/return-prior), consume authorization_nonce (U2 ON CONFLICT → REPLAY_NONCE_CONSUMED), write the one status='draft' row, record the non-keying attempt — commit together. |
YES — this is the only place durable consumption happens. |
So: no durable consumption occurs until the Phase-3 transaction. A pre-commit failure rolls back the consume and the write together (no committed-consume/failed-write split). Phase 2 cannot leave a consumed nonce behind because it writes nothing.
3. C7 — Phase 4 verifier-pair ambiguity (closes Codex §6)
Defect: RS4A-04 Phase 4 assumed a "paired verifier in the DOT-HEALTH-DOT family." Codex: "This must be an independent verifier contract/reference, not an inferred per-target pair or automatically created registry row. Carry C2 [pair cardinality] explicitly."
Correction:
- Phase 4's verifier is an independent post-commit verifier CONTRACT/REFERENCE, identified by
postcondition_verifier_ref. It is not an automatically-createddot_tools/registry row, and not inferred per-target from apaired_dotfield copy. - Carry RS3C-C2 explicitly: the source
paired_dot="DOT-HEALTH-DOT"field copy (D24) creates no seconddot_toolsrow. Per-target cardinality is one primary row.DOT-REGISTER ↔ DOT-HEALTH-DOTis a control-plane pair of two pre-existing identities, not a per-target two-row rule. The verifier reference must resolve to an existing, independently-governed verifier — if none is bound, fail closed (POST_COMMIT_VERIFY_UNRESOLVED), never auto-create one. - The verifier's pass condition is unchanged: exactly one row for
dot_code, metadata == admitted artifact,status='draft'(inert), notify-not-emitted, audit durably written ⇒ success = HTTP-2xx + readback match; otherwisePOST_COMMIT_VERIFY_FAIL.
Corrected Phase 4 "Trusted producer" line: "an independent verifier referenced by postcondition_verifier_ref (control-pair precedent: dot-apr-types-register/-audit, DOT-TAC-COLLECTION-REGISTER/-VERIFY); the reference must pre-exist and be independently governed — no per-target verifier row is created or assumed."
4. C8 — Phase 5 audit semantics (closes Codex §6 / §17)
Defect: RS4A-04 Phase 5 prose said failure audit is written outside a rolled-back transaction, but its test T-P5-1 said "audit written from rolled-back txn" should survive — which is impossible. Codex: "The test must say the failure occurs in the rolled-back transaction and the audit is written afterward in a separate transaction." Also: "Clarify whether durable audit is required for every successful decision or only failures."
Correction — failure-audit sequencing:
- The registration failure occurs inside the Phase-3 transaction; that transaction rolls back (consume + write both vanish).
- After the rollback, the registrar writes a durable failure-audit record in a SEPARATE transaction to the selected sink (RS4A-08). Because it is a different transaction, it survives the Phase-3 rollback. Nothing is "written from inside" the rolled-back txn.
- The audit write itself must be append-only/immutable on the chosen sink —
not proven on any candidatetoday (RS4A-08, PATCH1-06 C10) ⇒AUDIT_SINK_UNAVAILABLEfail-closed until proven.
Success vs failure audit (scope clarification):
- RS4A-08 defines a failure-audit sink only. Therefore a durable failure-audit is REQUIRED for failures/rollbacks; a durable success-decision log is NOT required by RS4A (it may be defined later as a separate
decision_log_envelope). - The output
audit_envelopeis therefore nullable/scoped:
audit_envelope:
failure_audit_envelope: <required & durable on failure/rollback (RS4A-08); AUDIT_SINK_UNAVAILABLE if not writable>
decision_log_envelope: <OPTIONAL; null unless a success-logging contract is separately defined later>
- This corrects RS4A-02 §3 / RS4A-04 Phase 4, which implied an audit envelope was required for success. Success does not require a durable audit under RS4A; only failures do.
Corrected T-P5-1 (also in PATCH1-07): "a registration failure occurs inside the Phase-3 transaction (which rolls back); the failure-audit is then written in a separate transaction afterward and is found durably present after the rollback — proving the audit is NOT inside the rolled-back txn." The forbidden fail-open is "audit lost with the rollback" (i.e. the audit was wrongly written inside the rolled-back txn).
5. Net phase-model corrections (replace the corresponding RS4A-04 lines)
| Phase | RS4A-04 (original) | PATCH1 correction |
|---|---|---|
| Phase 2 | "Nonce / logical-key consume" | "Replay/nonce VALIDATION & RESERVATION (criteria only) — no durable consume" |
| Phase 3 | "atomic write" | unchanged in intent; explicitly the only durable consume+write+attempt, commit together |
| Phase 4 | "paired verifier in the DOT-HEALTH-DOT family" | "independent verifier referenced by postcondition_verifier_ref; no per-target verifier row created/assumed; carry RS3C-C2 (one primary row)" |
| Phase 5 | "audit written outside a rolled-back txn" + T-P5-1 "audit-from-rolled-back-txn survives" | "failure in Phase-3 txn rolls back; audit written AFTER, in a separate txn ⇒ survives"; success audit NOT required (failure-audit only) |
6. Status
- Nonce:
NONCE_RECLASSIFIEDtoauthority_credential(out of therequest_proposeddict). - Phases:
PHASE_SEMANTICS_CORRECTED— Phase 2 reserves (no durable consume), Phase 3 is the sole atomic consume+write, Phase 4 verifier is an independent reference (no auto-pair), Phase 5 audit is post-rollback in a separate txn; success-audit not required. - No transaction code, no mutation. Gate
REGISTRATION_HOLD·CAN_PROCEED = NO.