Files
215a82c7f8 feat(relay): emit read-row trace steps with (B) projection
Land the read-seam emitter for the runtime conformance gate. Two
emit sites, one buzz-db helper, one negative fixture.

## buzz-db: `communities_of_channels` helper

`Buzz::communities_of_channels(&[Uuid]) -> HashMap<Uuid, CommunityId>`
— batched per-channel community lookup. Used by the relay emitters to
project each row's true community label independently of the fetch
query's WHERE clause. That independence is what makes the
`Inv_NonInterference` / `Inv_ReadConfinement` bite non-vacuous: a
mutation dropping `community_id = $X` from `query_events` would
still let this helper return the row's true label and the checker
would catch the mismatch.

Channels missing from the result map are intentionally NOT mapped to
a default — callers MUST treat "channel-id not in map" as a coverage
breach, never as "use the resolved community."

## buzz-relay: projection + record helpers

`crate::conformance` gains four new items:

- `project_row_community` — single-row helper encoding the (B)
  strategy: channel-less → resolved (honest, not tautological);
  channel-scoped → lookup or `None` (caller fails closed).
- `RowCommunityProjection` enum — Ok(Vec<CommunityLabel>) OR
  MissingLookup discriminated outcome.
- `record_read_message_rows` — non-search lane: emits
  `ReadMessageRows` on Ok projection, `ImplBug { kind:
  "row_community_lookup_missing" }` on MissingLookup.
- `record_read_by_id_rows` — search lane companion, same shape but
  emits `ReadByIdRows`. `filter_channel` is `None` for the search
  lane (search at the abstract level isn't bound to a single channel;
  per-row `channel_id` carries channel identity honestly).

## req.rs wire-up: two emit sites

- Site 1 (`req.rs` non-search loop, after `query_events`): collect
  distinct channel ids from the result set → `communities_of_channels`
  → `record_read_message_rows`. Production cost: one extra DB query
  per request (NoopTracer short-circuits in non-conformance builds).
- Site 2 (`req.rs` search loop, after `get_events_by_ids`): same
  pattern → `record_read_by_id_rows`. `handle_search_req` gains a
  threaded-through `trace_state: Option<&AbstractState>` parameter.

DB-helper errors on either site fall back to an empty lookup map.
This intentionally triggers `MissingLookup` → `ImplBug` for any
channel-scoped row in the result set, surfacing the helper failure
as a coverage breach (fail-closed) rather than a silent resolved-
label substitution.

## Negative fixture: foreign-row leak

New `bad_foreign_row_leak.jsonl` + matching test. The fixture is a
`ReadMessageRows` whose row_communities contains community B while
the state is bound to community A. This is the proof artifact Eva
requested for the (B)-projection guard-rail: if the row had been
mis-projected as channel-less (defaulting to resolved A), the subset
check would have passed vacuously. By recording the row's TRUE
community independently, `Inv_NonInterference` surfaces it
immediately as `NonInterference`.

## Unit tests (conformance::tests)

Five new tests pinning every behavior:
- `project_row_communities_channelless_uses_resolved` (positive)
- `project_row_communities_channel_scoped_uses_lookup_label` (the
  non-tautological correctness — lookup label, NOT resolved)
- `project_row_communities_channel_scoped_missing_is_breach` (the
  guard-rail bite)
- `record_read_message_rows_missing_lookup_emits_impl_bug`
- `record_read_by_id_rows_ok_emits_read_by_id_rows`

## Mutate → red → restore (three independent bites)

1. Make `project_row_community` fall back to resolved on missing-
   lookup (the tempting wrong-fix): `project_row_communities_channel_
   scoped_missing_is_breach` + `record_read_message_rows_missing_
   lookup_emits_impl_bug` go red with explicit messages
   ("missing lookup must be a breach, got Ok([...])", "expected
   ImplBug coverage breach, got ReadMessageRows {...}"). Restored.

2. Make every channel-scoped row project to resolved (the
   tautological projection): 4 of 9 unit tests go red — the lookup-
   label, missing-breach, and record-helper tests all bite. Restored.

3. Edit the negative fixture to use community_a instead of
   community_b: `foreign_row_leak_is_non_interference` reds ("foreign
   row community label must be rejected by Inv_NonInterference"). The
   fixture is load-bearing, not decorative. Restored.

## Test surfaces

- `cargo test -p buzz-relay --lib` → **394/0** (was 387 baseline).
- `cargo test -p buzz-conformance --lib` → 9/0.
- `cargo test -p buzz-conformance --test replay_fixtures` → **6/0**
  (was 5; +foreign_row_leak).
- `cargo test -p buzz-db --lib` → 75/0 (helper compiles; DB-driven
  integration coverage lives in `--include-ignored` lane on PG).
- `cargo clippy -p buzz-relay -p buzz-db -p buzz-conformance
  --all-targets -- -D warnings` clean.
- `cargo fmt --all -- --check` clean.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
2026-06-27 14:42:29 -04:00
..