Skip to content

Tests: the volume oracle — a deterministic 'ambient night' fixture gates triage usability at realistic scale - #104

Merged
gterdem merged 1 commit into
mainfrom
issue-50-volume-oracle
Jul 17, 2026
Merged

gterdem merged 1 commit into
mainfrom
issue-50-volume-oracle

Conversation

@gterdem

@gterdem gterdem commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds tests/volume/ — a second regression oracle (ADR-0068), sibling to tests/golden/: golden pins exact scores for 1-12 event scenarios; this oracle pins usability invariants (queue set-equality, the flood tripwire, breach-among-noise anti-suppression, conservation, calm-state reachability, generation determinism) under a realistic ~130-actor/~850-event ambient night.
  • Events are produced by a seeded generator (generator.py) expanding recorded templates (tests/golden/fixtures/eve_*.json, the packages/sources/syslog/tests "Failed password" line shape) and driven through the REAL firewatch_suricata/firewatch_syslog/firewatch_syslog_cef normalizers (harness.py) — no hand-built SecurityEvent anywhere in the scenario path.
  • The ADR-0070 (+ Amendment 1) distribution-table personas are each a named, individually-failing test through the real normalizer: the 50/min attacker (queues within a minute), the single 120-attempt/40-min burst (queues during, fades after), the nightly-10 recidivist (queues night 2 via recidivism), the 12/h moderate grinder (queues at ~24h via endurance, NOT within 30 min), the sub-θ_press paced actor (INFORM forever — the designed exclusion), the 10×4min moderate burst (ONE episode, no campaign — the Amendment 1 hysteresis pin), and ambient priority-2 Suricata noise (≤ medium, no Tier-2 ticket).
  • A frontend vitest sibling (frontend/src/test/triageBand.volume.test.ts) feeds the committed derived_threats.json fixture through deriveTriageActors and independently closes the JS tier: null <= 2 coercion channel.
  • scripts/regen_volume_fixtures.py is the single regeneration entrypoint; a drift-check test fails loudly if the committed fixture goes stale.
  • No firewatch-core edits — this is pure test/fixture infrastructure exercising the already-shipped ADR-0069/0070 severity recalibration + intensity model.

Structure self-check

  • generator.py (359 lines) — one concern: manifest × templates → RawEvents, no scoring imports.
  • harness.py (108 lines) — one concern: RawEvents → real normalizers → per-actor ThreatScore, mirroring (not reimplementing) Pipeline.analyze_ip's decision slice.
  • test_triage_volume.py (483 lines) — the invariants + the persona ledger; at the ~500-line guideline, kept as one file because the invariant fixtures (ambient_scores/breach_scores) are shared session-scoped state across every test class — splitting would either duplicate that fixture setup or force an import-heavy conftest split for no isolation benefit.

Test plan

  • bash scripts/gates-backend.sh green (sync + ruff + pyright + pytest) — see gate report below.
  • tests/golden/fixtures/expected_scores.json sha unchanged: fe4787643955c920e934e3789c79f741cd8c8cde6b2adbc6540b66ff3743f31f.
  • tests/volume/ runs in the default uv run pytest invocation (no opt-in marker), full scenario scores in well under 1s (budget: ≤5s).
  • Frontend: npm run lint && npm run typecheck && npm run test && npm run build all green (178 test files / 4332 tests).
  • Manual smoke-verification of every persona's expected classification via direct harness calls before committing to the test file's assertions (documented in tests/volume/README.md's ledger section).

Gate report

==> tree:   /home/galip/projects/firewatch/.claude/worktrees/agent-ad2479ca52b837155
==> branch: issue-50-volume-oracle
==> HEAD:   3c55fdc
==> sync (match CI's env)   OK
==> ruff                    All checks passed!
==> pyright                 0 errors, 0 warnings, 0 informations
==> pytest (fast: -n auto)  4545 passed, 1 skipped, 35 warnings in 25.37s

Frontend (frontend/): npm run lint clean, npm run typecheck clean, npm run test → 178 files / 4332 tests passed, npm run build succeeds.

Closes #50

…tes triage usability at realistic scale (#50)

Adds tests/volume/ as a second regression oracle (ADR-0068), sibling to
tests/golden/: golden pins exact scores for 1-12 event scenarios; this
oracle pins usability invariants (queue set-equality, the flood tripwire,
breach-among-noise anti-suppression, conservation, calm-state
reachability, generation determinism) under a realistic ~130-actor/~850-
event ambient night, built by a seeded generator driving the REAL
Suricata/syslog/CEF normalizers — never a hand-built SecurityEvent.

The ADR-0070 (+ Amendment 1) distribution-table personas — the 50/min
attacker, the single burst that queues during and fades after, the
nightly recidivist, the moderate grinder (endurance at ~24h), the
sub-theta_press paced actor (INFORM forever, the designed exclusion),
the 10x4min hysteresis pin, and ambient priority-2 Suricata noise — are
each a named, individually-failing test through the real normalizer,
mirroring (not duplicating) the unit-level pins in
test_issue_54_attack_in_progress_campaign.py.

A frontend vitest sibling (triageBand.volume.test.ts) feeds the
committed derived_threats.json fixture through deriveTriageActors and
independently closes the JS `tier: null <= 2` coercion channel.

tests/golden/fixtures/expected_scores.json is untouched (sha
fe4787643955c920e934e3789c79f741cd8c8cde6b2adbc6540b66ff3743f31f,
verified unchanged). No firewatch-core edits — this is pure test/fixture
infrastructure exercising the already-shipped ADR-0069/0070 intensity
model and severity recalibration.

Closes #50
@gterdem
gterdem merged commit e7e94ba into main Jul 17, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tests: the volume oracle — a deterministic 'ambient night' fixture gates triage usability at realistic scale

1 participant