KB-1E6B

RS4A-PATCH1-05 — Nonce Classification and Phase Semantics Correction — 2026-06-21

10 min read Revision 1
rs4a-patch1authorization-noncephase-modelatomic-consumeverifieraudit-after-rollbackdesign-only2026-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-created dot_tools/registry row, and not inferred per-target from a paired_dot field copy.
  • Carry RS3C-C2 explicitly: the source paired_dot="DOT-HEALTH-DOT" field copy (D24) creates no second dot_tools row. Per-target cardinality is one primary row. DOT-REGISTER ↔ DOT-HEALTH-DOT is 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; otherwise POST_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:

  1. The registration failure occurs inside the Phase-3 transaction; that transaction rolls back (consume + write both vanish).
  2. 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.
  3. The audit write itself must be append-only/immutable on the chosen sink — not proven on any candidate today (RS4A-08, PATCH1-06 C10) ⇒ AUDIT_SINK_UNAVAILABLE fail-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_envelope is 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_RECLASSIFIED to authority_credential (out of the request_proposed dict).
  • 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.
Back to Knowledge Hub knowledge/dev/laws-new/reports/rs4a-patch1/05-nonce-classification-and-phase-semantics-correction-2026-06-21.md