Documents
ADR-0007 - Operator Surface & Action Parity Commitment
ADR-0007 - Operator Surface & Action Parity Commitment
Type
External
Status
Published
Created
Apr 18, 2026
Updated
Apr 27, 2026
Updated by
Dosu Bot
Source
View

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 (per ENDI-1 Business+ 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-1 cross-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#

  1. 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.
  2. 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.
  3. 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)#

DomainOperator ActionStatus
Query & InvestigationRun 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 ManagementList 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
AlertingAcknowledge / mark FP / redeliver / delivery history🔵 Needs new tools
Health & OpsComponent health (procmond, agent)✅ Partial (stats only)
Prometheus metrics, collector schema catalog, rule execution stats⚠️ Spec'd
ConfigView / reload / toggle alert sinks🔵 Needs new tools
Audit / ForensicsVerify chain, Merkle inclusion proof, signed bundle export⚠️ Partial placeholder
Human-onlyGPG 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 showlineagequerytrace starttrace 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 json so the agent can generate valid SQL against processes.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-cli into 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 0600 perms; 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.md wasn'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.