Files
Void-Homelab/docs/yerin-security-agent.md

98 lines
5.4 KiB
Markdown

# Yerin — the Void 2.0 Security Agent
> Cradle note: Yerin is the sword artist — fast, vigilant, the one who *notices the
> threat first and calls it*. In Void 1.x she already owns the 5-minute alert
> cron. In Void 2.0 she becomes a first-class **read-only security/observability
> agent**: she watches, reports, and proposes — she never silently acts.
## Design principles
1. **Read-only by capability.** Yerin's agent record gets `{ read: true }` and
**no** `write`/`suggest`. Anything she wants changed she raises to you; she
cannot mutate state. (If you later want her to be able to *propose* a
remediation, add `suggest: true` and the existing pending-change flow gives
you an approval gate for free.)
2. **Own toolset, own registry.** Security tools live in
`lib/ai/agent/tools/security/` behind `securityRegistry` — separate from
Dross's `companionRegistry`, so she gets investigative tools, not
`propose_change`.
3. **No secret material, ever.** Tools project explicit columns and rely on the
audit layer's write-time redaction. `agent_inventory` deliberately never does
`SELECT *`.
## Built (TDD, on `main`, not deployed) — 5 tools
`lib/ai/agent/tools/security/` + `securityRegistry`, tests in
`tests/ai/security_tools.test.js`:
| Tool | What it answers |
|------|-----------------|
| `audit_log` | "Who did what, newest first?" Filter by `actor_kind` / `actor_id`. Reads the redacted audit trail. Capped at 200. |
| `agent_inventory` | "Which agents exist and what is each allowed to do?" id/slug/name/kind/model + capabilities + scopes. No token material. |
| `pending_review` | The queue of agent-proposed (suggest-tier) changes awaiting approval — where injected/misbehaving intent surfaces. |
| `resource_exposure` | Attack-surface inventory: every resource's host/url/status across spaces. No `monitoring`/`metadata` blobs, no credentials. |
| `token_audit` | Agent tokens with label/last_used/revoked_at (never the hash) — spot stale/unused credentials. |
## Roadmap — tools to add next (designed, not yet built)
- **`recent_captures`** — newly ingested refs/source_docs (untrusted external
content entering the system), so Yerin can flag suspicious inbound material.
Stretch (needs new plumbing, your call):
- **`tls_expiry` / `service_health`** — port Void 1.x's `lib/security.js` cert
checks + the Yerin alert cron into a tool she can call on demand.
- **Active probes** (e.g. "is this CT's admin port exposed?") would require
network egress — must go through `safeFetch` and be owner-gated. Defer.
## Wiring Yerin up
1.**Seed the agent.** Migration `011_yerin.sql` inserts a `yerin` agent —
`capabilities {"read":true,"suggest":false,"write":false}`, `kind:'claude'`,
`model:NULL` (server default; flip to a local Ollama model anytime by setting
`agents.model`). Read-only by design.
2.**Expose `securityRegistry` over MCP.** `lib/mcp/companion-stdio.js` now
selects the registry from `VOID_TOOL_REGISTRY` (`security` → Yerin's tools;
default → companion). Test: `tests/mcp/registry_select.test.js`.
3.**A Yerin entry point — LEFT FOR YOU** (it's a new API/UX surface; deserves
your attention, not an unsupervised guess). Two shapes:
- A route (`POST /api/security/ask`) reusing the `claude_cli` driver with
Yerin's persona + an MCP config that sets `VOID_TOOL_REGISTRY=security`.
Mirror `lib/api/routes/companion.js` (SSE, conversation persistence).
- Or a scheduled cron: a standing "anything suspicious in the last 24h?" pass
that files its result as a Sacred Valley card (ties into Plan 6).
- Either way she'll need a **persona prompt** (the Cradle Yerin voice +
security-analyst framing) — worth writing together.
## Adjacent agent roles (so the roster stays coherent)
- **Dross** — companion/chat (Lindon's own spirit-AI; the right-rail assistant).
Read + suggest. Already live.
- **Yerin** — security/vigilance (this doc). Read-only.
- **Orthos** — see the role proposal below.
### Proposed role: Orthos — the local-model Advisor / Council
Orthos in Cradle is the ancient dragon-turtle: a **powerful ally with long
experience and a deep spiritual (Path of Black Flame) connection** — exactly your
framing. That maps cleanly onto a specific, useful Void 2.0 role:
**Orthos = the reflective Advisor, running on the local Ollama model (free,
always-on), not Claude.** He plays to a local model's strengths (summarisation &
synthesis, not precise tool-use):
- **The long view / "council briefing."** A scheduled pass that fuses recent
captures, open tasks, and audit highlights into a short reflective digest —
the Void 1.x "Orthos council briefing" reborn as a Sacred Valley widget.
- **"Spiritual connection" = the knowledge graph.** Let Orthos traverse the
embedding/RRF links to surface *non-obvious connections* across Spaces
("these three captures in two different Spaces are converging on X"). That's
the literal mechanisation of his deep-sight: semantic connection-finding over
the vector store.
- **Why local:** it's high-frequency, low-stakes, cost-sensitive reflection —
perfect for `llama3.1:8b` on `192.168.1.185`, keeping Claude budget for Dross.
Capability: `{ read: true }`, `kind: 'ollama'`, `model: 'llama3.1:8b'`.
So the trio reads naturally: **Dross** converses, **Yerin** guards, **Orthos**
reflects — and two of the three (Yerin alerts, Orthos council) become Plan 6
Sacred Valley widgets. See `docs/plan-6-brainstorm-brief.md`.