Status#
Accepted (2026-04-27) — with scope-reduction escape hatch. Adopted as the v0.5.0 (CLI & Management, aspirational target 2027-02-28) target scope. Implementation lives across END-301 (CLI surface) and END-299 (daemon/service mode).
Scope-reduction escape hatch#
If v0.5.0 timing is at risk, the discipline (action parity as procedural commitment, atomic tools, schema-versioned JSON, admin IPC architecture) is non-negotiable, but the implementation surface may be reduced as follows:
- v1.0-blocking minimum (must ship for OSS GA): the four MVP tools (
alerts list,alerts show,query,lineage) plus rule management (rules list,rules load,rules enable,rules disable) and audit verification (audit verify,audit prove). - Deferable to post-v1.0: trace initiation tools (
trace start,trace stop,trace export) and signed forensic export from CLI. These can land in a v1.x epic alongside cross-host ShadowHunt work (perENDI-1Business+ scoping).
Status history#
- 2026-04-18 — Proposed (during open-core hygiene pass; backfilled to Nygard-style template)
- 2026-04-27 — Accepted with escape hatch. v0.5.0 needs a target scope and this ADR provides it. The action-parity discipline is the load-bearing piece (every operator action reachable by an agent through the CLI); the specific tool set can be reduced if velocity demands it. ShadowHunt-related tools (trace init, signed export) naturally pair with
ENDI-1cross-host work and can defer to v1.x without harming OSS Community v1.0 utility.
Context#
DaemonEye's operator surface (primarily daemoneye-cli) is a 78-line stub today that prints database statistics and exits. Requirement 8, the ShadowHunt use case (AGENTS.md mission), and the reactive orchestration model (spec §4.9–4.10) all describe a much broader surface: SQL queries, rule management, trace initiation, alert triage, audit verification, and signed export bundles.
Why action parity now#
- AI-driven security operations is no longer speculative. Operators are already embedding Claude Code, SOC copilots, and similar agents into their workflows. If DaemonEye is agent-reachable, it amplifies the operator; if it is not, the agent routes around it.
- DaemonEye's core use case (ShadowHunt) is inherently multi-step. Passive baseline → heuristic trigger → silent trace → focused capture → analyst review → manual action is exactly the shape of work an agent accelerates. An agent that cannot initiate a trace, walk lineage, or export a signed bundle cannot help with ShadowHunt.
- The CLI is effectively greenfield. There is no legacy subcommand surface to preserve. This is the cheapest moment in the project's life to adopt parity as a discipline.
Failure mode to prevent#
Operator (via agent): "I see alert 4821 — show me the process lineage and start a trace on the root PID."
Agent: "I don't have a way to do that. You'll need to open daemoneye-cli manually."
Without parity, the agent degrades to a chat interface wrapped around documentation — the operator does the real work.
Capability map (current state)#
| Domain | Operator Action | Status |
|---|---|---|
| Query & Investigation | Run SQL query over event store | ⚠️ Spec'd (Req 8.1) |
| List alerts by rule/time/severity | ⚠️ Spec'd | |
| Fetch alert detail + source-row refs | ⚠️ Spec'd | |
| Get process history by PID / time range | ⚠️ Spec'd | |
| Walk process lineage (parent/child via MRC) | ⚠️ Spec'd (§11.5) | |
| Stream/paginate large result sets | ⚠️ Spec'd (Req 8.5) | |
| Rule Management | List installed rules | ⚠️ Spec'd (Req 8.3) |
| Load rule (AST-validate) | ⚠️ Spec'd | |
| Enable/disable rule | ⚠️ Spec'd (§4.3) | |
| Test rule against recent events (dry run) | ⚠️ Spec'd | |
| Import/export rule pack bundle | ⚠️ Spec'd (Req 9.4) | |
| Rollback rule to prior version | ⚠️ Spec'd (§4.3) | |
| Tracing (ShadowHunt) | Initiate TraceCommand for PID + descendants | 🔵 Core use case, not wired |
| List / stop / export signed trace bundle | 🔵 Needs new tools | |
| Alerting | Acknowledge / mark FP / redeliver / delivery history | 🔵 Needs new tools |
| Health & Ops | Component health (procmond, agent) | ✅ Partial (stats only) |
| Prometheus metrics, collector schema catalog, rule execution stats | ⚠️ Spec'd | |
| Config | View / reload / toggle alert sinks | 🔵 Needs new tools |
| Audit / Forensics | Verify chain, Merkle inclusion proof, signed bundle export | ⚠️ Partial placeholder |
| Human-only | GPG hardware key sign, biometric approve | 🚫 User-only |
| Tally: 1 done (partial), ~15 spec'd but not implemented, ~10 new, 2 user-only. |
Decision#
This ADR commits to action parity as an ongoing discipline — every operator action must be reachable by an external agent (Claude Code, SOC copilot, future MCP server) through a stable, machine-readable interface. The commitment is procedural and architectural, not a single feature.
1. Action parity as a named discipline#
Every new operator-facing feature PR must:
- Identify the operator action it introduces
- Expose it through
daemoneye-cli(or a documented admin IPC) with machine-readable output - Update the capability map in
docs/src/technical/action-parity.md(new file, to be created as part of the first MVP PR) - Include a test that invokes the action through the CLI, not just the library
This is a PR-checklist-level commitment, enforced in review.
2. Minimum Viable Parity Set (four tools)#
Build these four subcommands before any other operator-facing features. Together they enable an external agent to drive a complete ShadowHunt triage (alert → investigate → lineage → decision).
daemoneye-cli alerts list [--since, --rule, --severity, --limit, --format]
daemoneye-cli alerts show <alert-id> [--format]
daemoneye-cli query <sql-or-rule-name> [--format]
daemoneye-cli lineage <pid> [--format]
All four are read-only and talk only to redb. They do not require the admin IPC (item 4 below) and can ship independently.
3. Stable, schema-versioned JSON output#
Requirement 8.2 already commits to JSON/human/CSV formats. This ADR adds: JSON output must carry a schema_version field (e.g., "schema_version": "1.0") at the root. Schema changes follow semver; breaking changes bump the major version and are gated by a --schema-version flag with a deprecation grace period. Agents compose tools over time; a silently-changing JSON shape breaks scripts and agent prompts alike.
4. Admin IPC socket on daemoneye-agent for mutating actions#
Read-only operator actions can go directly from daemoneye-cli to redb. Mutating actions (rule enable/disable, trace initiation, sink toggles, config reload) need to reach the running agent. Adopt a local Unix-socket / named-pipe admin IPC on daemoneye-agent, protobuf-framed (consistent with existing ipc.proto patterns per ADR-0001). daemoneye-cli becomes the canonical client; future MCP servers or GUI tools can use the same surface. No new dependencies — reuses the existing interprocess + protobuf stack.
5. Atomic tools, composed by the agent#
Tools represent operator primitives, not workflows. The temptation to build investigate_alert or triage_incident as a single subcommand is rejected. The agent composes: alerts show → lineage → query → trace start → trace export. Workflow logic lives in the agent's prompt or the operator's head, not in the CLI. Atomic tools survive emergent use cases.
6. Context parity#
When the agent uses DaemonEye, it needs the same context the operator has. Specifically:
- The collector schema catalog (§4.1) must be exposed via
daemoneye-cli catalog show --format jsonso the agent can generate valid SQL againstprocesses.snapshots,network.connections,fs.events, etc. - Rule metadata (spec §4.3) — rule_id, tables used, capabilities — must be queryable so the agent can reason about what rules exist and what they depend on.
- Health output must include enough detail that the agent knows which collectors are live (not just "green/red"), because detection coverage depends on it.
Consequences#
Positive#
- ShadowHunt becomes agent-drivable. The core product use case survives contact with AI-assisted operators.
- CLI stabilizes as an API. Versioned JSON output turns
daemoneye-cliinto a durable integration point for GUI (commercial tiers), MCP servers, custom tooling, and ad-hoc operator scripts. - Capability map surfaces gaps early. Reviewers catch parity violations at PR time, not after customer complaints.
- Atomic tools survive emergent use cases. The discipline of building primitives rather than workflows is the same pattern the collector-core SDK (ADR-0003) applies at the collector layer.
- Audit trail completeness. Every mutating action goes through the admin IPC, which means every admin action is audit-loggable in the same ledger as detection events.
Negative#
- Four tools is still four tools of work before any direct user value beyond today's stub. Mitigation: the four-tool MVP is bounded (each tool is small — read-only, redb-only, no new IPC).
- Schema-versioned JSON has maintenance cost. Every breaking output change needs a major-version bump and migration doc. Mitigation: bias toward additive changes; reserve breaking changes for annual release boundaries.
- Admin IPC expands the attack surface. Mitigation: local-only (Unix socket with
0600perms; named pipe with restricted DACL); per-caller identity check; rate limiting; audit ledger entry for every mutating call. - Discipline cost. PR reviewers must actually check the capability map. Mitigation: add the capability-map update to the PR template; CI lint that fails if
docs/src/technical/action-parity.mdwasn't touched when a new CLI subcommand is added.
Neutral#
- Library-level API unchanged. This ADR is about the operator surface, not
daemoneye-lib. - Collector-core (ADR-0003) unchanged. Collector authors keep their current contract; action parity is about the agent-to-operator-to-system direction.
Alternatives Considered#
Ship a dedicated MCP server first#
MCP is the emerging standard for agent-tool interfaces; richer tool descriptions and type-aware schemas. Adds a dependency and another process to audit. Shelling out to a CLI is the universal fallback — every agent framework already supports it. An MCP server is a natural v2 layered over the same actions once the CLI surface stabilizes. Deferred — build the CLI surface first; MCP server can wrap it later without re-architecting.
Direct REST / gRPC API on daemoneye-agent#
Modern, tooling-friendly. Violates the "no inbound network" principle (AGENTS.md security model: daemoneye-agent is outbound-only). A local admin IPC on a Unix socket / named pipe is inbound-within-host only and keeps the zero-network posture intact. Rejected — admin IPC socket preserves the security model.
Build every spec'd capability at once#
Complete surface, no phased rollout. ~25 tools, significant infrastructure (JSON schemas, admin IPC, rule lifecycle state machine), and no way to validate the design end-to-end until the last one lands. High risk of spec'd features that don't serve actual agent workflows. Rejected — phase via the four-tool MVP; extend after measuring agent-driven usage.
Two surfaces: CLI for humans, something else for agents#
Keeps the CLI's prose-friendly output stable. Two surfaces to maintain, two capability maps, two sets of tests. Every new feature requires double-implementation. Divergence is inevitable. Rejected — one surface, two output modes (--format human and --format json), enforced via snapshot tests.