Record tray applet completion and SID coverage design draft
Update the CLAUDE.md snapshot and roadmap for the merged tray applet, note the shared-checkout commit hygiene rule, and save the agreed SID drill coverage design as a draft spec. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
afbc63ffbd
commit
2d23e8b878
3 changed files with 88 additions and 1 deletions
14
CLAUDE.md
14
CLAUDE.md
|
|
@ -23,7 +23,7 @@ Primary functions:
|
||||||
|
|
||||||
## Current State Snapshot
|
## Current State Snapshot
|
||||||
|
|
||||||
As of 2026-06-16, the project is a local-first Linux IDS/IPS/EDR agent at
|
As of 2026-07-04, the project is a local-first Linux IDS/IPS/EDR agent at
|
||||||
package version `0.7.0`. The branch has a working stdlib-only daemon, CLI,
|
package version `0.7.0`. The branch has a working stdlib-only daemon, CLI,
|
||||||
HTTPS management console, incident model, response planner, rootcheck, posture
|
HTTPS management console, incident model, response planner, rootcheck, posture
|
||||||
checks, file/package integrity checks, push notification backends, and optional
|
checks, file/package integrity checks, push notification backends, and optional
|
||||||
|
|
@ -70,6 +70,11 @@ Implemented investigation/response state:
|
||||||
further change, identity kinds (listener/suid) retire on TTL or revoke. The
|
further change, identity kinds (listener/suid) retire on TTL or revoke. The
|
||||||
filter runs at the daemon chokepoint, `fim-check`, and the dashboard
|
filter runs at the daemon chokepoint, `fim-check`, and the dashboard
|
||||||
integrity API.
|
integrity API.
|
||||||
|
- An optional desktop tray applet (`enodia-sentinel-tray`, `[tray]` extra with
|
||||||
|
pystray/Pillow) opens the dashboard, controls the daemon via systemctl, and
|
||||||
|
runs `check --json` quick checks. Its logic modules (`tray/state.py`,
|
||||||
|
`actions.py`, `notify.py`) are GUI-free and tested; only `tray/app.py`
|
||||||
|
imports GUI libs, and the core agent stays stdlib-only.
|
||||||
- IPS behavior is currently explicit workflow: posture hardening plus reviewed
|
- IPS behavior is currently explicit workflow: posture hardening plus reviewed
|
||||||
dry-run containment actions. There is no automatic inline blocking or silent
|
dry-run containment actions. There is no automatic inline blocking or silent
|
||||||
host mutation yet.
|
host mutation yet.
|
||||||
|
|
@ -109,6 +114,10 @@ Start with:
|
||||||
signatures.
|
signatures.
|
||||||
- If you add config keys, update `config/enodia-sentinel.toml`, README, and the
|
- If you add config keys, update `config/enodia-sentinel.toml`, README, and the
|
||||||
relevant docs.
|
relevant docs.
|
||||||
|
- Multiple agent sessions may share this checkout. Before committing, check
|
||||||
|
`git status` for uncommitted edits you did not make; never sweep foreign
|
||||||
|
hunks into your commit (stage only your own changes) and never stash or
|
||||||
|
revert them.
|
||||||
|
|
||||||
## Current Architecture
|
## Current Architecture
|
||||||
|
|
||||||
|
|
@ -131,6 +140,9 @@ Start with:
|
||||||
- `posture.py` performs advisory host hygiene checks.
|
- `posture.py` performs advisory host hygiene checks.
|
||||||
- `reconcile.py` owns the acknowledged-drift store and the `filter_alerts`
|
- `reconcile.py` owns the acknowledged-drift store and the `filter_alerts`
|
||||||
chokepoint that suppresses operator-accepted FIM/package/listener/SUID drift.
|
chokepoint that suppresses operator-accepted FIM/package/listener/SUID drift.
|
||||||
|
- `tray/` is the optional desktop tray frontend over the CLI and systemctl;
|
||||||
|
only `tray/app.py` may import `pystray`/`PIL` (enforced by an import-guard
|
||||||
|
test).
|
||||||
|
|
||||||
## Current Threat Mapping
|
## Current Threat Mapping
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,9 @@ Purpose: define a stable single-host product.
|
||||||
Dracula, Solarized Dark/Light, and Twilight palettes.
|
Dracula, Solarized Dark/Light, and Twilight palettes.
|
||||||
- ✅ Add dashboard theme contrast/visual smoke checks so readable text and
|
- ✅ Add dashboard theme contrast/visual smoke checks so readable text and
|
||||||
meaningful status colors are preserved across every palette.
|
meaningful status colors are preserved across every palette.
|
||||||
|
- ✅ Add an optional desktop tray applet (`enodia-sentinel-tray`, `[tray]`
|
||||||
|
extra): dashboard launcher, systemd daemon control, status at a glance, and
|
||||||
|
`check --json` quick checks, with GUI-free tested logic modules.
|
||||||
- Keep the dashboard read-only unless a separate authenticated write path is
|
- Keep the dashboard read-only unless a separate authenticated write path is
|
||||||
designed and reviewed.
|
designed and reviewed.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
# SID Drill Coverage Design
|
||||||
|
|
||||||
|
**Status:** Draft — design agreed in session Q&A, spec not yet user-reviewed.
|
||||||
|
No implementation plan written yet.
|
||||||
|
|
||||||
|
**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 53 built-in SIDs across six engines:
|
||||||
|
|
||||||
|
| Range | Engine |
|
||||||
|
|---|---|
|
||||||
|
| 100001–100004 | eBPF exec rules (`events/rules.py`) |
|
||||||
|
| 100010–100016 | poll detectors (inline sids) |
|
||||||
|
| 100017–100021, 100026–100027 | FIM / pkgdb / pkgverify |
|
||||||
|
| 100022–100025, 100028–100031, 100034–100035, 100037–100038 | rootcheck |
|
||||||
|
| 100032–100033, 100036, 100039, 100048 | poll detectors (constants) |
|
||||||
|
| 100040–100047, 100050–100051 | posture |
|
||||||
|
| 100060–100066 | 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 `sid`s 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.py` — `DRILLS: 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).
|
||||||
Loading…
Add table
Add a link
Reference in a new issue