Originally created by: fu351
First slice of the ambient monitor: the data plane other agent surfaces will report through.
Build
ActivityEvent in models.py: frozen, extra="forbid", wrapping a SecurityObject plus a collector id, HMAC entity/session fingerprints, and string-valued class metadata. Redaction is inherited by construction; there is no field a raw command or secret could ride in.activity_events + monitor_state tables (additive CREATE TABLE IF NOT EXISTS in storage/db.py), and storage/activity.py with emit_activity_event, cursor-based read_activity_events, and purge_activity_events. Emitters never block or crash their host process; oversize events are rejected and counted; retention is bounded.doberman.collectors entry-point group in engine/registry.py (collect() -> Iterable[ActivityEvent], called per daemon tick, failures isolated like every other plugin group).doberman.monitor joins the adapters the policy core must not import (the import-linter contract in pyproject.toml).Tests must prove: a synthetic secret placed in raw input never appears in a stored event; malformed and oversize events are rejected and counted; cursor resume loses nothing and replays nothing; retention purge works; a stub collector is discovered and a raising one is isolated; lint-imports stays green.
Nothing on this bus can suppress, lower, or alter an inline decision. There is no code path from it into combine().
Originally posted by: Maqbool61
Working on this issue.