enodia-sentinal/docs/superpowers/specs/2026-07-04-sid-drill-coverage-design.md
2026-07-08 17:05:17 -07:00

3.1 KiB
Raw Permalink Blame History

SID Drill Coverage Design

Status: Implemented — registry, event fixtures, offline drills, and the emission-based coverage gate are in the test suite.

Goal: Fixture or drill coverage for every built-in SID, enforced by a CI gate that cannot rot: adding a detection without a drill fails the suite.

Context

Enodia Sentinel has 52 built-in SIDs across seven engines:

Range Engine
100001100004 eBPF exec rules (events/rules.py)
100010100016 poll detectors (inline sids)
100017100021, 100026100027 FIM / pkgdb / pkgverify
100022100025, 100028100031, 100034100035, 100037100038 rootcheck
100032100033, 100036, 100039, 100048 poll detectors (constants)
100040100047, 100050100051 posture
100060100066 eBPF syscall rules (events/syscall_rules.py)

Existing engine test files cover most behavior but nothing proves per-SID completeness, and the bash red-team harness covers only ~9 core signatures.

Decisions (from brainstorming Q&A)

  1. Deliverable: coverage gate + fixtures (not fixtures-only, not bash harness extension).
  2. Registry: new product module enodia_sentinel/sids.py — aggregates existing constants by importing them (no renumbering, no moving definitions) into a BUILTIN_SIDS table: sid, name, engine, defining module.
  3. Gate proof: emission-based. The gate runs every drill for real and asserts the union of emitted alert sids equals the registry exactly, in both directions.

Components

  • enodia_sentinel/sids.py — canonical SID table plus a sanity test (uniqueness, matches imported constants).
  • tests/fixtures/sids/<sid>-<slug>.json — one event JSON per exec-rule and syscall-rule SID, in the exact format rules test accepts, so each fixture doubles as an operator drill (enodia-sentinel rules test tests/fixtures/sids/100001-*.json).
  • tests/sid_drills.pyDRILLS: dict[int, Callable[[], list[Alert]]] for non-event engines. Each drill builds minimal fake state (fake SystemState, monkeypatched rootcheck views, temp FIM tree, posture file fakes — same styles the existing tests use) and invokes the real engine code.
  • tests/test_sid_coverage.py — the gate: replays all fixtures through the real rule engines, runs all drills, and asserts emitted sids == registry. Failure messages name the uncovered or unregistered SID.

Docs

  • docs/RULES.md: short "drill fixtures" note documenting the fixture naming convention and replay command.
  • docs/ROADMAP.md: tick the per-SID fixture/drill item when implemented.

Out of scope (YAGNI)

  • Extending the bash red-team harness — live-host drills for rootkit-module, kernel-taint, and pkg-DB-tamper SIDs are not safely simulable on a real host.
  • Correlation SIDs — none exist yet; the gate will catch them when they land.

Execution note

Implement in an isolated git worktree: a concurrent session holds uncommitted edits in this checkout (triage/enrichment work touching cli.py, respond.py, snapshot.py, event sources, and docs).