feat: import Chinese-localized Buzz source snapshot
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled

Signed-off-by: cls_宁波本机 <908705107@qq.com>
This commit is contained in:
2026-08-13 18:34:25 +08:00
parent 61c3fa1df9
commit 9dfa06ffee
3785 changed files with 1085458 additions and 2 deletions
@@ -0,0 +1 @@
{"schema_version":1,"action":{"type":"impl_bug","kind":"ingest_exited_without_trace"},"state_after":{"resolved_community":"aaaa0000-0000-0000-0000-000000000001","bound_host":"a.example.test","actor":"0123456789abcdef"}}
@@ -0,0 +1 @@
{"schema_version":1,"action":{"type":"read_message_rows","channel":"cafe0000-0000-0000-0000-000000000010","row_communities":["bbbb0000-0000-0000-0000-000000000002"]},"state_after":{"resolved_community":"aaaa0000-0000-0000-0000-000000000001","bound_host":"a.example.test","actor":"0123456789abcdef"}}
@@ -0,0 +1,2 @@
{"schema_version":1,"action":{"type":"auth_check","channel":"dead0000-0000-0000-0000-000000000020","claimed_community":"bbbb0000-0000-0000-0000-000000000002","verdict":"allow"},"state_after":{"resolved_community":"aaaa0000-0000-0000-0000-000000000001","bound_host":"a.example.test","actor":"0123456789abcdef"}}
{"schema_version":1,"action":{"type":"write_insert","msg_id":"badbadbad0000000","channel":"dead0000-0000-0000-0000-000000000020","claimed_community":"bbbb0000-0000-0000-0000-000000000002"},"state_after":{"resolved_community":"aaaa0000-0000-0000-0000-000000000001","bound_host":"a.example.test","actor":"0123456789abcdef"}}
+3
View File
@@ -0,0 +1,3 @@
{"schema_version":1,"action":{"type":"auth_check","channel":"cafe0000-0000-0000-0000-000000000010","claimed_community":"aaaa0000-0000-0000-0000-000000000001","verdict":"allow"},"state_after":{"resolved_community":"aaaa0000-0000-0000-0000-000000000001","bound_host":"a.example.test","actor":"0123456789abcdef"}}
{"schema_version":1,"action":{"type":"write_insert","msg_id":"d34db33fcafef00d","channel":"cafe0000-0000-0000-0000-000000000010","claimed_community":"aaaa0000-0000-0000-0000-000000000001"},"state_after":{"resolved_community":"aaaa0000-0000-0000-0000-000000000001","bound_host":"a.example.test","actor":"0123456789abcdef"}}
{"schema_version":1,"action":{"type":"read_message_rows","channel":"cafe0000-0000-0000-0000-000000000010","row_communities":["aaaa0000-0000-0000-0000-000000000001","aaaa0000-0000-0000-0000-000000000001"]},"state_after":{"resolved_community":"aaaa0000-0000-0000-0000-000000000001","bound_host":"a.example.test","actor":"0123456789abcdef"}}
@@ -0,0 +1,431 @@
//! Property/fuzz-generated conformance traces.
//!
//! These tests widen the checker's exercised input space beyond the hand-
//! built fixtures in `tests/fixtures/`. The skill (skill-runtime-formal-
//! compliance) calls for "property/fuzz-generated action sequences where
//! feasible"; this is that lane.
//!
//! ## Design: invariant properties, NOT a parallel oracle
//!
//! `transitions::check_step` is small and direct. A "reference oracle" that
//! re-derived the verdict would just be a copy of the checker — testing the
//! code against itself, proving nothing. So these tests do NOT re-implement
//! the verdict. They assert **spec-derived facts** about `check_trace`'s
//! result, read off the *shape of the generated trace*:
//!
//! - any read carrying a foreign row label MUST be rejected (NonInterference)
//! - a fully clean trace MUST be accepted
//! - AuthCheck Allow + foreign claim MUST bite (IllegalTransition)
//! - ImplBug MUST bite (CoverageBreach)
//! - a mid-trace state flip MUST bite (StateMismatch)
//! - the checker never panics and is deterministic
//!
//! The only checker surface these tests touch is the public
//! [`buzz_conformance::checker::check_trace`]. They never call
//! `transitions::check_step`, and they never depend on a production crate.
//!
//! ## Fail-fast discipline
//!
//! `check_trace` returns the FIRST error it finds. So every property that
//! asserts a *specific* error variant must construct traces in which the
//! targeted violation is the first/only one — otherwise an earlier
//! `StateMismatch` / `IllegalTransition` / `CoverageBreach` would mask the
//! variant under test. Each generator below is built to honor that.
use buzz_conformance::checker::{check_trace, Scenario};
use buzz_conformance::transitions::TransitionError;
use buzz_conformance::{
AbstractState, ActorLabel, ChannelLabel, CommunityLabel, HostLabel, OpaqueId, SanitizedReason,
TraceAction, TraceStep, Verdict,
};
use proptest::prelude::*;
use uuid::Uuid;
// --- Small fixed pools -----------------------------------------------------
//
// Pools are intentionally tiny (3 each) so that "foreign vs resolved"
// collisions happen with meaningful frequency. With a 3-community pool a
// randomly chosen row label is foreign ~2/3 of the time, so P1 actually
// stresses the leak path instead of almost always generating clean traces.
const POOL: u128 = 3;
fn community(i: u128) -> CommunityLabel {
CommunityLabel::from_uuid(Uuid::from_u128(
0x0c00_0000_0000_0000_0000_0000_0000_0000 + i,
))
}
fn channel(i: u128) -> ChannelLabel {
ChannelLabel(Uuid::from_u128(
0x0ca0_0000_0000_0000_0000_0000_0000_0000 + i,
))
}
fn host(i: u128) -> HostLabel {
HostLabel(format!("h_{i}"))
}
fn actor(i: u128) -> ActorLabel {
ActorLabel(format!("a_{i}"))
}
fn arb_community() -> impl Strategy<Value = CommunityLabel> {
(0..POOL).prop_map(community)
}
fn arb_channel() -> impl Strategy<Value = ChannelLabel> {
(0..POOL).prop_map(channel)
}
fn arb_opaque() -> impl Strategy<Value = OpaqueId> {
(0u32..16).prop_map(|i| OpaqueId(format!("m{i}")))
}
fn arb_verdict() -> impl Strategy<Value = Verdict> {
prop_oneof![Just(Verdict::Allow), Just(Verdict::Deny)]
}
fn arb_reason() -> impl Strategy<Value = SanitizedReason> {
prop_oneof![
Just(SanitizedReason::Restricted),
Just(SanitizedReason::Invalid),
Just(SanitizedReason::ServerError),
]
}
/// The bootstrapped state for a request resolved to `resolved`. Host/actor
/// are fixed so that, when we reuse this state for every step, the only way
/// a `StateMismatch` can arise is if a property deliberately flips a field.
fn state_for(resolved: CommunityLabel) -> AbstractState {
AbstractState {
resolved_community: resolved,
bound_host: host(0),
actor: actor(0),
}
}
// --- Action generators -----------------------------------------------------
/// A "clean" action: one whose presence in a trace bootstrapped to
/// `resolved` introduces NO violation on its own. Read labels are all
/// `resolved`; AuthCheck either Denies (any claim) or Allows with a claim
/// equal to `resolved` (or no claim). No ImplBug. This is the alphabet P2
/// draws from, and the benign filler P1/P3/P4/P5 use for prefixes.
fn arb_clean_action(resolved: CommunityLabel) -> impl Strategy<Value = TraceAction> {
let res = resolved;
prop_oneof![
(arb_opaque(), arb_channel(), prop::option::of(Just(res))).prop_map(
|(msg_id, channel, claimed_community)| TraceAction::WriteInsert {
msg_id,
channel,
claimed_community,
}
),
(arb_opaque(), prop::option::of(Just(res))).prop_map(|(msg_id, claimed_community)| {
TraceAction::WriteInsertGlobal {
msg_id,
claimed_community,
}
}),
(arb_opaque(), arb_channel(), prop::option::of(Just(res))).prop_map(
|(msg_id, channel, claimed_community)| TraceAction::WriteDuplicate {
msg_id,
channel,
claimed_community,
}
),
arb_reason().prop_map(|reason| TraceAction::SanitizedError { reason }),
// AuthCheck that cannot bite M2/M8: either Deny (any claim is in-spec)
// or Allow with a claim that is None or equal to resolved.
(
arb_channel(),
arb_verdict(),
prop_oneof![Just(None), Just(Some(res))],
)
.prop_map(|(channel, verdict, claimed_community)| {
// For Deny, the claim is unconstrained; for Allow it is
// None-or-resolved by construction above, so it never bites.
TraceAction::AuthCheck {
channel,
claimed_community,
verdict,
}
}),
// Reads whose every row label equals resolved.
(arb_channel(), 0usize..4).prop_map(move |(channel, n)| TraceAction::ReadMessageRows {
channel: Some(channel),
row_communities: vec![res; n],
}),
(0usize..4).prop_map(move |n| TraceAction::ReadByIdRows {
channel: None,
row_communities: vec![res; n],
}),
(0usize..4).prop_map(move |n| TraceAction::ReadHostFeedRows {
row_communities: vec![res; n],
}),
]
}
/// Wrap actions into steps that all share the bootstrapped state, so the
/// only violations possible are action-level (no incidental StateMismatch).
fn steps_with_state(actions: Vec<TraceAction>, resolved: CommunityLabel) -> Vec<TraceStep> {
let st = state_for(resolved);
actions
.into_iter()
.map(|a| TraceStep::new(a, st.clone()))
.collect()
}
/// A clean trace: 1..=12 clean actions over one resolved community, all
/// sharing the bootstrap state. By construction this contains no foreign
/// label, no Allow+foreign claim, no ImplBug, no state flip, no schema
/// mismatch.
fn arb_clean_trace() -> impl Strategy<Value = (CommunityLabel, Vec<TraceStep>)> {
arb_community().prop_flat_map(|resolved| {
prop::collection::vec(arb_clean_action(resolved), 1..=12)
.prop_map(move |actions| (resolved, steps_with_state(actions, resolved)))
})
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(128))]
/// P2 — completeness / no false reject.
/// A fully clean, non-empty, current-schema, consistent-state trace with
/// no coverage obligations MUST be accepted. `Scenario::unstructured`
/// declares no required actions, so coverage breach cannot fire.
#[test]
fn clean_trace_is_accepted((_resolved, trace) in arb_clean_trace()) {
let sc = Scenario::unstructured(trace);
prop_assert!(
check_trace(&sc).is_ok(),
"clean trace was rejected: {:?}",
check_trace(&sc)
);
}
/// P1 — non-interference soundness / no false accept of a leak.
/// A clean prefix followed by a single read whose row set contains a
/// foreign label MUST be rejected with NonInterference. The foreign read
/// is the only possible violation, so fail-fast surfaces exactly it.
#[test]
fn foreign_row_label_is_rejected(
resolved in arb_community(),
foreign_idx in 0u128..POOL,
prefix in prop::collection::vec(arb_community().prop_map(|_| ()), 0..6),
clean_before in any::<bool>(),
which_read in 0u8..3,
) {
// Pick a foreign community distinct from resolved.
let foreign = {
let mut f = community(foreign_idx);
if f == resolved {
f = community((foreign_idx + 1) % POOL);
}
f
};
// If POOL were 1 this could still collide; guard explicitly.
prop_assume!(foreign != resolved);
let mut actions: Vec<TraceAction> = Vec::new();
// Optional benign clean prefix (reads of resolved-only rows) to prove
// the violation still bites after valid steps.
if clean_before {
for _ in &prefix {
actions.push(TraceAction::ReadMessageRows {
channel: Some(channel(0)),
row_communities: vec![resolved],
});
}
}
// The single violating read carries one foreign label. NI confinement
// is enforced on ALL THREE read surfaces (they share `check_row_labels`),
// so the property must bite regardless of which read leaked.
let leaked = vec![resolved, foreign];
let violating = match which_read {
0 => TraceAction::ReadMessageRows {
channel: Some(channel(0)),
row_communities: leaked,
},
1 => TraceAction::ReadByIdRows {
channel: None,
row_communities: leaked,
},
_ => TraceAction::ReadHostFeedRows {
row_communities: leaked,
},
};
actions.push(violating);
let trace = steps_with_state(actions, resolved);
let err = check_trace(&Scenario::unstructured(trace)).unwrap_err();
prop_assert!(
matches!(err, TransitionError::NonInterference { .. }),
"expected NonInterference, got {err:?}"
);
}
/// P3a — AuthCheck Allow + foreign claim always bites IllegalTransition.
/// One-step trace so the M2/M8 bite is the only candidate.
#[test]
fn auth_allow_foreign_claim_bites(
resolved in arb_community(),
foreign_idx in 0u128..POOL,
chan in arb_channel(),
) {
let foreign = {
let mut f = community(foreign_idx);
if f == resolved {
f = community((foreign_idx + 1) % POOL);
}
f
};
prop_assume!(foreign != resolved);
let trace = steps_with_state(
vec![TraceAction::AuthCheck {
channel: chan,
claimed_community: Some(foreign),
verdict: Verdict::Allow,
}],
resolved,
);
let err = check_trace(&Scenario::unstructured(trace)).unwrap_err();
prop_assert!(
matches!(err, TransitionError::IllegalTransition { .. }),
"expected IllegalTransition for Allow+foreign claim, got {err:?}"
);
}
/// P3b — AuthCheck Deny with any claim is in-spec (never bites on the
/// claim axis). One-step clean-otherwise trace MUST be accepted.
#[test]
fn auth_deny_any_claim_is_ok(
resolved in arb_community(),
claim_idx in 0u128..POOL,
chan in arb_channel(),
has_claim in any::<bool>(),
) {
let claimed = if has_claim { Some(community(claim_idx)) } else { None };
let trace = steps_with_state(
vec![TraceAction::AuthCheck {
channel: chan,
claimed_community: claimed,
verdict: Verdict::Deny,
}],
resolved,
);
prop_assert!(
check_trace(&Scenario::unstructured(trace)).is_ok(),
"Deny with any claim should be in-spec"
);
}
/// P4 — ImplBug always bites CoverageBreach. Clean prefix then ImplBug;
/// since the prefix is clean, the ImplBug is the first/only violation.
#[test]
fn impl_bug_bites_coverage_breach(
resolved in arb_community(),
prefix_len in 0usize..4,
kind in "[a-z_]{1,16}",
) {
let mut actions: Vec<TraceAction> = (0..prefix_len)
.map(|_| TraceAction::ReadMessageRows {
channel: Some(channel(0)),
row_communities: vec![resolved],
})
.collect();
actions.push(TraceAction::ImplBug { kind });
let trace = steps_with_state(actions, resolved);
let err = check_trace(&Scenario::unstructured(trace)).unwrap_err();
prop_assert!(
matches!(err, TransitionError::CoverageBreach { .. }),
"expected CoverageBreach from ImplBug, got {err:?}"
);
}
/// P5 — a mid-trace state flip bites StateMismatch. One clean bootstrap
/// step, then a benign action whose `state_after` flips exactly one of
/// resolved_community / bound_host / actor. State is checked before any
/// action-specific logic, so this is the only possible violation.
#[test]
fn state_flip_bites_state_mismatch(
resolved in arb_community(),
other_idx in 0u128..POOL,
which in 0u8..3,
) {
let boot = state_for(resolved);
// A benign first step.
let step0 = TraceStep::new(
TraceAction::ReadMessageRows {
channel: Some(channel(0)),
row_communities: vec![resolved],
},
boot.clone(),
);
// Flip exactly one field for step 1.
let mut flipped = boot.clone();
match which {
0 => {
let mut other = community(other_idx);
if other == resolved {
other = community((other_idx + 1) % POOL);
}
prop_assume!(other != resolved);
flipped.resolved_community = other;
}
1 => flipped.bound_host = host(9),
_ => flipped.actor = actor(9),
}
let step1 = TraceStep::new(
TraceAction::ReadMessageRows {
channel: Some(channel(0)),
// Use the FLIPPED resolved so the read itself is clean
// relative to its own state_after; the bite must come from
// the state divergence, not row labels.
row_communities: vec![flipped.resolved_community],
},
flipped,
);
let err = check_trace(&Scenario::unstructured(vec![step0, step1])).unwrap_err();
prop_assert!(
matches!(err, TransitionError::StateMismatch { .. }),
"expected StateMismatch from a mid-trace field flip, got {err:?}"
);
}
/// P6 — determinism and no-panic. Running `check_trace` twice on the same
/// scenario yields the same result, and neither call panics. Draws from
/// the clean alphabet plus occasional violations so the input space is
/// broad; we assert nothing about the verdict, only its stability.
#[test]
fn check_trace_is_deterministic_and_total(
resolved in arb_community(),
actions in prop::collection::vec(
prop_oneof![
arb_clean_action(community(0)),
// a few intentionally-violating shapes to widen coverage
Just(TraceAction::ImplBug { kind: "fuzz".into() }),
arb_community().prop_map(|c| TraceAction::ReadMessageRows {
channel: None,
row_communities: vec![c],
}),
],
1..=12,
),
) {
let trace = steps_with_state(actions, resolved);
let sc = Scenario::unstructured(trace);
let r1 = check_trace(&sc);
let r2 = check_trace(&sc);
prop_assert_eq!(
format!("{r1:?}"),
format!("{r2:?}"),
"check_trace was non-deterministic"
);
}
}
@@ -0,0 +1,324 @@
//! Replay-fixture integration test.
//!
//! These fixtures are the load-bearing evidence that the runtime
//! conformance gate is **not decorative**. Each fixture is one
//! end-to-end JSONL trace, replayed through [`check_trace`], with the
//! expected verdict baked into the assertion.
//!
//! Eva's review (thread `06aaf3f7…`) green-lit cutting these as the
//! visible proof the gate bites. Coverage:
//!
//! - `good.jsonl` — a positive trace shaped like a real ingest:
//! AuthCheck Allow → WriteInsert → ReadMessageRows with rows confined
//! to the resolved community. `check_trace` returns `Ok(())`.
//! - `bad_host_channel_mismatch.jsonl` — a host/channel fence skip:
//! the bound host is for community A, the write targets a channel in
//! community B. The checker fails with `IllegalTransition`.
//! - `bad_coverage_breach.jsonl` — a trace that contains an `ImplBug`
//! action (what `EmitGuard::Drop` emits when a critical seam exits
//! without recording anything). The checker fails with
//! `CoverageBreach`.
//!
//! The JSONL files are committed as "golden" artifacts under
//! `tests/fixtures/` for reviewer visibility, but this test also
//! round-trips: it constructs the trace in Rust, serializes it to a
//! temp file, reads it back, and asserts both the serialized form
//! matches the committed file AND the parsed form gives the expected
//! verdict. That way a schema change cannot silently desync the
//! committed JSONL from what the relay actually emits.
use std::collections::HashSet;
use std::fs;
use std::path::{Path, PathBuf};
use buzz_conformance::checker::{check_trace, Scenario};
use buzz_conformance::transitions::TransitionError;
use buzz_conformance::{
AbstractState, ActorLabel, ChannelLabel, CommunityLabel, HostLabel, OpaqueId, TraceAction,
TraceStep, Verdict,
};
use uuid::Uuid;
// ---- Stable test-fixture labels ----------------------------------------
//
// These values are deterministic so the serialized JSONL is reproducible
// across runs. They are NOT secrets and they don't shadow any real
// community — they're test-only constants.
fn community_a() -> CommunityLabel {
CommunityLabel::from_uuid(Uuid::from_u128(0xAAAA_0000_0000_0000_0000_0000_0000_0001))
}
fn community_b() -> CommunityLabel {
CommunityLabel::from_uuid(Uuid::from_u128(0xBBBB_0000_0000_0000_0000_0000_0000_0002))
}
fn channel_in_a() -> ChannelLabel {
ChannelLabel(Uuid::from_u128(0xCAFE_0000_0000_0000_0000_0000_0000_0010))
}
fn channel_in_b() -> ChannelLabel {
ChannelLabel(Uuid::from_u128(0xDEAD_0000_0000_0000_0000_0000_0000_0020))
}
fn state_a() -> AbstractState {
AbstractState {
resolved_community: community_a(),
bound_host: HostLabel("a.example.test".to_string()),
actor: ActorLabel("0123456789abcdef".to_string()),
}
}
// ---- Trace builders ----------------------------------------------------
/// A positive trace: bound to community A, all observations confined.
fn good_trace() -> Vec<TraceStep> {
vec![
TraceStep::new(
TraceAction::AuthCheck {
channel: channel_in_a(),
claimed_community: Some(community_a()),
verdict: Verdict::Allow,
},
state_a(),
),
TraceStep::new(
TraceAction::WriteInsert {
msg_id: OpaqueId("d34db33fcafef00d".to_string()),
channel: channel_in_a(),
claimed_community: Some(community_a()),
},
state_a(),
),
TraceStep::new(
TraceAction::ReadMessageRows {
channel: Some(channel_in_a()),
row_communities: vec![community_a(), community_a()],
},
state_a(),
),
]
}
/// A bad trace: the host-channel fence was bypassed. The bound host
/// resolves to community A, but a WriteInsert targets a channel in
/// community B. The spec's `Inv_NonInterference` / channel-host coupling
/// rule rejects this as an illegal transition.
fn bad_host_channel_mismatch_trace() -> Vec<TraceStep> {
vec![
TraceStep::new(
TraceAction::AuthCheck {
channel: channel_in_b(),
// Client claims B, host resolves A, fence was skipped:
// AuthCheck recorded `verdict = Allow` despite the
// mismatch. M2/M8 territory.
claimed_community: Some(community_b()),
verdict: Verdict::Allow,
},
state_a(),
),
TraceStep::new(
TraceAction::WriteInsert {
msg_id: OpaqueId("badbadbad0000000".to_string()),
channel: channel_in_b(),
claimed_community: Some(community_b()),
},
state_a(),
),
]
}
/// A coverage-breach trace: an `ImplBug` step appears, meaning the
/// `EmitGuard` fired on Drop. The checker treats any `ImplBug` as a
/// hard coverage breach.
fn bad_coverage_breach_trace() -> Vec<TraceStep> {
vec![TraceStep::new(
TraceAction::ImplBug {
kind: "ingest_exited_without_trace".to_string(),
},
state_a(),
)]
}
/// A foreign-row trace: bound to community A but a `ReadMessageRows`
/// returns a row whose community label is community B. This is the
/// (B)-projection negative case Eva requested as the guard-rail for
/// "channel-scoped row masquerading as channel-less": IF the row had
/// been mis-projected as channel-less (and thus defaulted to the
/// resolved community A), the subset check would have passed
/// vacuously. By recording the row's TRUE community (B) — independent
/// of the fetch query's WHERE clause — the `Inv_NonInterference` /
/// `Inv_ReadConfinement` bite surfaces immediately as
/// `NonInterference`. This fixture is the proof artifact that the
/// projection helper's missing-lookup guard-rail is non-vacuous.
fn bad_foreign_row_leak_trace() -> Vec<TraceStep> {
vec![TraceStep::new(
TraceAction::ReadMessageRows {
// The query was scoped to a channel in A (the host-resolved
// tenant). The relay's filter said "this row should belong
// to A." But the row's TRUE community is B — surfaced by
// the (B)-strategy projection reading the row's own
// `channel_id` against the channels table.
channel: Some(channel_in_a()),
row_communities: vec![community_b()],
},
state_a(),
)]
}
// ---- Fixture round-trip ------------------------------------------------
fn fixture_path(name: &str) -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("fixtures")
.join(name)
}
/// Serialize a trace to JSONL (one step per line).
fn to_jsonl(trace: &[TraceStep]) -> String {
let mut out = String::new();
for step in trace {
let line = serde_json::to_string(step).expect("step serializes");
out.push_str(&line);
out.push('\n');
}
out
}
/// Parse a JSONL string into a trace, surfacing the offending line on
/// error so a misedited fixture is easy to fix.
fn from_jsonl(text: &str) -> Vec<TraceStep> {
text.lines()
.enumerate()
.filter(|(_, l)| !l.trim().is_empty())
.map(|(i, l)| {
serde_json::from_str::<TraceStep>(l)
.unwrap_or_else(|e| panic!("fixture line {} did not parse: {e}", i + 1))
})
.collect()
}
/// Assert that the committed JSONL fixture for `name` round-trips to
/// `expected_trace` byte-exactly. Run with `BUZZ_CONFORMANCE_UPDATE=1`
/// to regenerate the fixture (so a schema change is a deliberate
/// re-commit, not a silent break).
fn assert_fixture_matches(name: &str, expected_trace: &[TraceStep]) {
let expected = to_jsonl(expected_trace);
let path = fixture_path(name);
if std::env::var("BUZZ_CONFORMANCE_UPDATE").is_ok() {
fs::create_dir_all(path.parent().expect("fixture dir")).expect("mkdir fixtures");
fs::write(&path, &expected).expect("write fixture");
return;
}
let actual = fs::read_to_string(&path).unwrap_or_else(|e| {
panic!(
"fixture {} missing or unreadable ({e}); run with \
BUZZ_CONFORMANCE_UPDATE=1 to create it",
path.display()
)
});
assert_eq!(
actual, expected,
"committed fixture {} drifted from the typed builder; run with \
BUZZ_CONFORMANCE_UPDATE=1 to refresh if the change is intentional",
name
);
let parsed = from_jsonl(&actual);
assert_eq!(parsed, *expected_trace, "fixture round-trip mismatched");
}
// ---- Tests --------------------------------------------------------------
#[test]
fn good_trace_passes_check() {
let trace = good_trace();
assert_fixture_matches("good.jsonl", &trace);
let scenario = Scenario {
trace,
required_critical_actions: ["auth_check", "write_insert", "read_message_rows"]
.into_iter()
.map(String::from)
.collect::<HashSet<_>>(),
};
check_trace(&scenario).expect("the good fixture must replay green");
}
#[test]
fn bad_host_channel_mismatch_is_illegal_transition() {
let trace = bad_host_channel_mismatch_trace();
assert_fixture_matches("bad_host_channel_mismatch.jsonl", &trace);
let scenario = Scenario::unstructured(trace);
let err = check_trace(&scenario)
.expect_err("host/channel fence skip must be rejected by the checker");
assert!(
matches!(err, TransitionError::IllegalTransition { .. }),
"host/channel mismatch must surface as IllegalTransition (M2/M8 bite), got {err:?}"
);
}
#[test]
fn coverage_breach_is_caught() {
let trace = bad_coverage_breach_trace();
assert_fixture_matches("bad_coverage_breach.jsonl", &trace);
let scenario = Scenario::unstructured(trace);
let err = check_trace(&scenario)
.expect_err("ImplBug in the trace must be rejected as a coverage breach");
assert!(
matches!(err, TransitionError::CoverageBreach { .. }),
"ImplBug must surface as CoverageBreach, got {err:?}"
);
}
#[test]
fn foreign_row_leak_is_non_interference() {
let trace = bad_foreign_row_leak_trace();
assert_fixture_matches("bad_foreign_row_leak.jsonl", &trace);
let scenario = Scenario::unstructured(trace);
let err = check_trace(&scenario)
.expect_err("foreign row community label must be rejected by Inv_NonInterference");
assert!(
matches!(err, TransitionError::NonInterference { .. }),
"foreign row label must surface as NonInterference, got {err:?}"
);
}
#[test]
fn empty_trace_is_coverage_breach() {
// Independent of the JSONL fixtures: the checker must fail closed on
// an empty trace (no observations from a critical seam).
let scenario = Scenario::unstructured(vec![]);
let err = check_trace(&scenario).expect_err("empty trace must be CoverageBreach");
assert!(
matches!(err, TransitionError::CoverageBreach { .. }),
"empty trace must be CoverageBreach, got {err:?}"
);
}
#[test]
fn missing_required_action_is_coverage_breach() {
// The good trace, but the scenario declares it must include
// `read_by_id_rows` — which it does not. This is what the
// "scenario-required action never appeared" coverage breach catches.
let scenario = Scenario {
trace: good_trace(),
required_critical_actions: ["read_by_id_rows"]
.into_iter()
.map(String::from)
.collect::<HashSet<_>>(),
};
let err = check_trace(&scenario)
.expect_err("missing required critical action must be CoverageBreach");
assert!(
matches!(err, TransitionError::CoverageBreach { .. }),
"missing required action must be CoverageBreach, got {err:?}"
);
}