Files
buzz/crates
Hayt fd2a79bdba fix(schema): address Thufir pass 2 blockers on NIP-FI PR 2
Three IMPORTANT findings addressed:

IMPORTANT 1 (denial semantic binding, partial): Bind the remaining two
unbound denial identity coordinates.

- Add semantic_fingerprint BYTEA to authorization_events: required non-zero
  for kind-9 events, NULL for all other event kinds (enforced by CHECK
  on the table). This is the redaction-safe intent_digest coordinate.
- Add authorization_denial_reason_reason_code_binding CHECK to
  authorization_authentication_denial_attempts: encodes the canonical
  OperatorAuthenticationDenialReason <-> AuthorizationReasonCode mapping
  from operator_lifecycle.rs:700-706 and authorization_events.rs:215-226:
  MissingCredential(1)<->Missing(2), InvalidCredential(2)<->Invalid(3),
  Unauthenticated(3)<->Unauthenticated(4). Fires at INSERT, not COMMIT.
- Extend authorization_denial_attempt_guard_v1() to compare
  semantic_fingerprint between event and denial attempt in both firing
  directions, raising 23514 'authorization_denial_attempt_semantic_binding'
  on mismatch. Carl's mismatched-reason and mismatched-fingerprint
  cross-attachments are now fully closed.

IMPORTANT 2 (concurrency regression): Replace the 10ms-sleep approach
with a tokio::sync::Barrier(2) that holds both connections after BEGIN
and before INSERT. Both race to pg_advisory_xact_lock; one blocks, the
winner commits, the loser sees MAX=102 and fails with 23514 (not 23505).
XOR assertion proves exactly one INSERT succeeds, and the loser's 23514
(not PK 23505) proves the advisory lock — not just PK uniqueness — is the
serialization mechanism. Contradictory comments fixed.

MINORs (folded in):
- Fix stale test doc comment claiming effective_at must advance (it does
  not; the downstream constructor stamps Unix epoch for immediate policy).
- Fix equal-revision comment incorrectly claiming different policy_digest
  avoids the PK; the PK is (community_id, policy_revision).

CI fmt failure: cargo fmt --all run; whitespace-only reformatting of
some query blocks in migration.rs.

Regressions added/updated:
- B4: denial_reason/reason_code mapping violation rejected at INSERT by
  the immediate CHECK (23514 from authorization_denial_reason_reason_code_binding).
- B5: semantic_fingerprint mismatch between event and denial attempt
  rejected at COMMIT by the deferred guard (23514 from
  authorization_denial_attempt_semantic_binding).

Byte-parity (extraction+cmp):
- authorization_events table: 3394 bytes, migration == schema.sql
- authorization_authentication_denial_attempts table: 2062 bytes, migration == schema.sql
- authorization_denial_attempt_guard_v1(): 5579 bytes, migration == schema.sql
- identity_enrollment_policy_revision_guard_v1(): 1113 bytes, migration == schema.sql
- authorization_admission_result_guard_v1(): 2164 bytes, migration == schema.sql

All five NIP-FI tests green locally (run in isolation to avoid pre-existing
pool-state flakiness in the full suite).

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Hayt <9e1c23a3fd83f61da34420e4e88ff1b16e45cafcc0cd9019eb07d4ecfa8ca9b0@buzz.block.builderlab.xyz>
2026-08-31 14:05:38 -04:00
..