RS4A-11 — Acceptance Test Suite Design (≥80 cases) — 2026-06-21
Macro: RS4A · Mục tiêu K
Deliverable: 11 of 14 · design-only · criteria, NOT executed (no test run, no validator PASS claimed)
Composition: 50 carried from RS3C-10 (IDs 1–50) + 42 new RS4A source/phase cases (T-series) = 92 cases (≥80 required).
Gate: REGISTRATION_HOLD · REGISTRATION_CAN_PROCEED = NO
Anti-fail-open rule (retained): any uncertainty, unproven carrier/writer/authority, missing nonce state, inventory mismatch, hash mismatch, or unread source ⇒ REJECT / HOLD, never admit.
Each case: id · input/state · expected reject/hold · enforcement layer · fail-open signal (forbidden). Layers: V validator (pure) · R registrar (replacement) · F Interface F · SCHEMA DB constraint · AU authority · SN sink.
1. Carried RS3C cases 1–50 (reference RS3C-10 / RS3B-09)
Cases 1–40 carried by category (full text in RS3B-09); 41–50 source-grounded (verbatim from RS3C-10):
| Range/ID |
Category / case |
Expected |
Layer |
| 1–4 |
source unavailable / mass scan / wrong artifact / path traversal |
REJECT/HOLD |
V/F |
| 5–10 |
hash & carrier defects (no hash col, caller-proposed hash, snapshot unproven) |
FAIL_CLOSED |
F |
| 11–16 |
catalog race / clobber / on-deploy overlap |
FENCE/REJECT |
R |
| 17–24 |
replay / attempt / nonce (pre-C1 form) |
FAIL_CLOSED |
R |
| 25–30 |
rollback / partial-batch / audit-from-rolled-back-txn |
COMPENSATE/REJECT |
R/SN |
| 31–34 |
trigger activation / gate opening |
PRESERVE GATE/REJECT |
R |
| 35–38 |
guard reachability / drift / missing Owner / missing APR |
HOLD |
AU |
| 39–40 |
proposed-as-trusted / timestamp-trusted |
REJECT |
V/F |
| 41 |
AUTH_NONCE_REUSED |
REJECT 2nd (UNIQUE nonce) |
R |
| 42 |
AUTH_NONCE_NOT_DURABLY_CONSUMED |
HOLD/FAIL_CLOSED (separate consume) |
R |
| 43 |
LOGICAL_KEY_AND_NONCE_CONFLATED |
REJECT (two independent constraints) |
R |
| 44 |
ATTEMPT_ID_USED_AS_EFFECT_KEY |
REJECT (attempt_id_not_unique_for_effect) |
R |
| 45 |
TARGET_VERIFIER_ROW_ASSUMED |
REJECT (one primary row) |
R |
| 46 |
CONTROL_PAIR_CONFUSED_WITH_TARGET_PAIR |
REJECT (control pair ≠ per-target) |
R |
| 47 |
TRIGGER_INVENTORY_COUNT_MISMATCH |
HOLD (re-derive from pg_trigger) |
V |
| 48 |
CATALOG_SYNC_SOURCE_CONTRADICTS_BOUNDARY |
N/A disproven; future writer ⇒ REJECT |
R |
| 49 |
REGISTRAR_SOURCE_CONTRADICTS_SINGLE_ARTIFACT_CONTRACT |
CONFIRMED REAL → HOLD |
R |
| 50 |
SOURCE_MIRROR_HASH_MISMATCH |
REJECT mirror |
F |
2. New RS4A cases by phase (T-series, 42 cases)
Phase 0 — source/artifact resolution
| id |
input/state |
expected |
layer |
fail-open signal (forbidden) |
| T-P0-1 |
input is a glob / list / directory |
MASS_REGISTRATION_ATTEMPTED |
V |
accepting any non-scalar input |
| T-P0-2 |
only request_proposed.artifact_hash, no proven carrier |
SOURCE_UNPROVEN_FAIL_CLOSED |
F |
emitting a trusted hash from caller copy |
| T-P0-3 |
carrier hash ≠ proposed hash (artifact hash mismatch) |
HASH_MISMATCH |
F |
drift_state≠NONE accepted |
| T-P0-4 |
.ts declared vs bash deployed artifact |
ARTIFACT_TYPE_MISMATCH |
V/F |
type mismatch ignored |
| T-P0-5 |
path is symlink / alias / .. traversal |
NON_CANONICAL_PATH |
V/F |
non-canonical path resolved silently |
| T-P0-6 |
context_pack_manifest aggregate checksum offered as artifact hash |
CARRIER_NOT_PER_ARTIFACT |
F |
aggregate manifest used per-artifact |
| T-P0-7 |
snapshot hash used as a signature/attestation |
CARRIER_NOT_SIGNATURE |
F |
integrity record treated as authority |
| T-P0-8 |
stale snapshot (snapshot row older than admission/origin) |
HOLD SNAPSHOT_STALE |
F |
trusting a stale integrity record |
| T-P0-9 |
unknown hash_algorithm |
UNKNOWN_HASH_ALGO |
V/F |
non-allowlisted algorithm accepted |
Phase 1 — authority validation
| id |
input/state |
expected |
layer |
fail-open signal |
| T-P1-1 |
owner absent (governance_object_ownership=0) |
OWNER_ABSENT |
AU |
writing with no owner head |
| T-P1-2 |
register_dot action absent in apr_action_types |
APR_NOT_BOUND_TO_ARTIFACT |
AU |
writing with no governed action |
| T-P1-3 |
APR bound to a different artifact_hash |
APR_NOT_BOUND_TO_ARTIFACT |
AU |
approving a mismatched artifact |
| T-P1-4 |
quorum not proven (quorum_passed false/unknown) |
APR_QUORUM_NOT_PROVEN |
AU |
fail-open on unknown quorum |
| T-P1-5 |
owner/approval lifecycle = superseded/revoked |
AUTHORITY_SUPERSEDED |
AU |
using stale authority evidence |
| T-P1-6 |
caller-supplied owner string used as authority |
CALLER_AS_AUTHORITY |
AU/V |
caller assertion = authority |
Phase 2 — replay / nonce / attempt
| id |
input/state |
expected |
layer |
fail-open signal |
| T-P2-1 |
nonce reused (already consumed) |
REPLAY_NONCE_CONSUMED |
R |
accepting a consumed nonce |
| T-P2-2 |
fresh nonce, duplicate logical key effect |
REPLAY_DUPLICATE |
R |
fresh nonce re-buys the effect |
| T-P2-3 |
attempt_no/attempt_id used to re-admit effect |
REPLAY_ATTEMPT_NO_BYPASS |
R |
attempt difference admits effect |
| T-P2-4 |
reuse iu_route_attempt as the store |
REPLAY_SURFACE_NOT_FIT |
R |
retry-ledger treated as single-use |
| T-P2-5 |
nonce not bound to envelope/window |
NONCE_UNBOUND |
V/R |
free-floating nonce accepted |
| T-P2-6 |
exact retry after commit (S2) |
return prior decision (idempotent) |
R |
second effect created |
| T-P2-7 |
two concurrent attempts (S4) |
one wins; other ATTEMPT_COLLISION |
R |
both commit |
| T-P2-8 |
stale request, consume row exists |
request inadmissible; replay still blocked |
V/R |
consumed-state erased by staleness |
Phase 3 — inert registration write
| id |
input/state |
expected |
layer |
fail-open signal |
| T-P3-1 |
duplicate code presented (no DB UNIQUE today) |
REPLAY_DUPLICATE/IDENTITY_UNIQUE_ABSENT |
R/SCHEMA |
duplicate code accepted |
| T-P3-2 |
active status emitted at registration |
ACTIVATION_AT_REGISTRATION |
R |
watch-tier active insert allowed |
| T-P3-3 |
gate flip attempted in registration txn |
WOULD_OPEN_GATE |
R |
gate opened during write |
| T-P3-4 |
mid-write crash after partial inserts |
full rollback, no committed prefix |
R |
committed-prefix rows remain |
| T-P3-5 |
write via curl -k (TLS-skip) |
INSECURE_TRANSPORT |
R |
TLS-skip write accepted |
| T-P3-6 |
write/read via root SSH / raw psql |
PRIVILEGED_PATH_USED |
R |
privileged bypass accepted |
| T-P3-7 |
fragile dedup (abs-vs-normalized) admits a dup |
DEDUP_NON_CANONICAL |
V/R |
substring dedup passes a dup |
| T-P3-8 |
row with NULL file_path skips dedup |
HOLD identity check |
R |
NULL-file_path identity blind-spot |
Phase 4 — post-commit verifier
| id |
input/state |
expected |
layer |
fail-open signal |
| T-P4-1 |
curl HTTP 500 but process exit 0 |
FALSE_SUCCESS_SIGNAL |
R |
success on process-exit not HTTP |
| T-P4-2 |
committed row drifts from admitted artifact |
POST_COMMIT_VERIFY_FAIL |
R |
drift not detected |
| T-P4-3 |
two rows exist for one dot_code |
POST_COMMIT_VERIFY_FAIL |
R |
multiple rows accepted |
| T-P4-4 |
verifier finds active status |
POST_COMMIT_VERIFY_FAIL |
R |
active row reported success |
| T-P4-5 |
invalid input still produces a digest / pass |
REJECT (no pass without readback match) |
R/V |
garbage-in yields synthetic success |
Phase 5 — durable failure audit
| id |
input/state |
expected |
layer |
fail-open signal |
| T-P5-1 |
audit written from rolled-back txn |
record survives outside the txn |
SN |
audit lost with rollback |
| T-P5-2 |
sink not writable / not append-only |
AUDIT_SINK_UNAVAILABLE |
SN |
success with audit unwritten |
| T-P5-3 |
audit on an execution delivery_lane |
REJECT (use audit lane only) |
SN |
failure audit triggers automation |
| T-P5-4 |
duplicate failure records (no dedup_key) |
HOLD until dedup proven |
SN |
unbounded duplicate audit rows |
Phase 6 / trigger-gate
| id |
input/state |
expected |
layer |
fail-open signal |
| T-P6-1 |
trigger notify condition met (watch-tier + active) at registration |
REJECT ACTIVATION_AT_REGISTRATION |
R |
notify emitted at registration |
| T-P6-2 |
activation via UPDATE OF status (notify fires on UPDATE too) |
REJECT |
R |
UPDATE path treated as exempt |
| T-P6-3 |
inert insert but consumer auto-activates on notify |
FAIL_CLOSED (G7-consumer unproven) |
R |
consumer assumed inert unread |
| T-P6-4 |
duplicate birth trigger pair → two birth rows |
HOLD (prove idempotent single birth) |
R |
double birth effect accepted |
Source-contradiction (regression guards)
| id |
input/state |
expected |
layer |
fail-open signal |
| T-SRC-1 |
mass scan attempted (ls .../dot-* style) |
MASS_REGISTRATION_ATTEMPTED |
V/R |
scan mode re-introduced |
| T-SRC-2 |
request_proposed value promoted without reread |
REQUEST_PROPOSED_AS_TRUSTED |
V/F |
proposed used as trusted |
| T-SRC-3 |
metadata .ts re-asserted for bash artifact |
ARTIFACT_TYPE_MISMATCH |
V |
type mislabel re-admitted |
3. Mandatory-case coverage map (macro §1.11)
| Required case |
Covered by |
| invalid input still produces digest/pass |
T-P4-5 |
| curl HTTP 500 but exit 0 |
T-P4-1 |
| duplicate code accepted |
T-P3-1 |
| active status emitted |
T-P3-2 / T-P6-1 |
| owner absent |
T-P1-1 |
| register_dot absent |
T-P1-2 |
| nonce reused |
T-P2-1 (and carried 41) |
| logical key duplicate |
T-P2-2 |
| trigger notify condition |
T-P6-1 / T-P6-2 |
| stale snapshot |
T-P0-8 |
| artifact hash mismatch |
T-P0-3 |
| request_proposed promoted |
T-SRC-2 |
| mass scan attempted |
T-SRC-1 |
4. Status
- Acceptance suite:
ACCEPTANCE_SUITE_DESIGNED_NOT_EXECUTED — 92 cases (50 carried + 42 new), split by phase, all 13 mandatory cases covered.
- No execution, no PASS claimed. Gate
REGISTRATION_HOLD · CAN_PROCEED = NO.