Originally created by: Maqbool61
Closes [#236]
First slice of the ambient monitor: the data plane other agent surfaces
will report through.
ActivityEvent in models.py
Frozen, extra="forbid", wraps a SecurityObject plus a collector id,
HMAC entity/session fingerprints, and string-valued class metadata
(target_class, action_class). Redaction is enforced by construction —
there is no field a raw command, argument, or secret could ride in.
Local SQLite bus — storage/db.py + storage/activity.py
Two additive CREATE TABLE IF NOT EXISTS tables (schema v14, no
migration needed on existing DBs):
activity_events — append-only bus log, one row per ActivityEventmonitor_state — per-reader cursor so consumers resume withoutThree operations in storage/activity.py:
emit_activity_event — best-effort, never raises into the caller;_oversized_countread_activity_events — cursor-based page read keyed on the integerpurge_activity_events — bounded retention; refuses naive datetimessave_cursor / load_cursor persist each reader's position in
monitor_state.
Plugin seam — engine/registry.py
COLLECTOR_GROUP = "doberman.collectors" and discover_collectors():
loaded defensively via the same entry-point pattern as every other
plugin group. Each collector must expose collect() ->
Iterable[ActivityEvent]; a raising collector is isolated — its events
are dropped for that tick, but the bus and every other collector
continue unaffected. Returns [] on a core-only install.
Import boundary — pyproject.toml
doberman.monitor joins the import-linter forbidden list alongside
doberman.proxy, doberman.hosthooks, doberman.dash, and
doberman.turngate. The bus is off the decision path at the import
level as well as the runtime level.
extra="forbid" rejects any unknown field (including an accidentalraw_secret kwarg) at construction timeemit never raiseslint-imports: 5/5 contracts kept26 passed in 1.58s # activity bus suite
3420 passed, 3 skipped # full suite
91.51% coverage # above the 80% threshold
ruff check . ✓
ruff format --check . ✓
lint-imports: 5 kept, 0 broken ✓
Nothing on this bus can suppress, lower, or alter an inline decision.
There is no code path from it into combine(). The import-linter
contract makes this a CI-enforced invariant, not a review-only
convention.
Ticket changed by: Maqbool61
Ticket changed by: Maqbool61
Originally posted by: Maqbool61
The Windows job was cancelled by the runner at 40m — no test failures in the log, just a timeout. All three Ubuntu matrix runs (3.11, 3.12, 3.13) passed cleanly. Happy to re-run if needed.