# Agent brief — DAEMON (`veloxd`) **Starts with CORE. You are the only process that owns state.** ## You own ``` daemon/** cli/** nmhost/** packaging/nativehost/** ``` Read `contracts/`, `core/include/`, `docs/`. Never write in `core/`, `gui/`, or `extension/`. ## Read first `docs/01-architecture.md` §2–§5, `contracts/README.md`, `docs/05-extension-spec.md` §4 (you implement the daemon half of pairing). ## Build order 1. **RPC server** — `rpc/uds_server` (NDJSON over `$XDG_RUNTIME_DIR/velox/velox.sock`, 0600, `SO_PEERCRED` same-UID check) and `rpc/ws_server` (bind `127.0.0.1` only, first free port in 52000–52016, write the chosen port to `ws.port`). One dispatcher, generated from `contracts/`. Never block the RPC loop — disk and network work goes to CORE's pools. 2. **Auth & pairing** — `session.pair` triggers a user prompt (GUI dialog if connected, else a desktop notification with actions). Tokens: 256-bit, stored **hashed**, per-install, revocable. Failed-auth rate limit 5/min then 60 s lockout. Enforce `x-transports` and `x-privileged` from the schema: privileged methods are refused over WS with `-32003`. 3. **Store** — SQLite WAL. Tables: `tasks`, `segments`, `categories`, `queues`, `rules`, `settings`, `history`, `pairings`. Numbered migrations in `store/migrations/`, applied at startup, with a forward-only test from every released schema version. **Credentials never go in SQLite** — Secret Service via libsecret. 4. **Scheduler & queues** — concurrency governor (global max active, per-queue max, per-host caps), time windows, days-of-week, one-shot vs periodic, "when queue completes" actions. 5. **Event fan-out** — per-subscription filtering, and **`event.task.progress` batched at ≤ 4 Hz into a single array message**. Do not emit one message per task per tick; that is how you turn 20 downloads into a GUI that burns a core. 6. **Capture endpoint** — `capture.offer` must answer within **750 ms**, always. Apply the rules table, resolve the category folder, dedupe against active tasks, return `take`/`ignore`. If anything internally is slow, answer `ignore` and let Firefox have it. Never make the browser wait. 7. **Integration** — systemd user units (`velox.service` + `velox.socket` for socket activation), single-instance lock, XDG autostart, `org.freedesktop.Notifications`, graceful shutdown that flushes buffers and meta files. 8. **`velox` CLI** — `add`, `ls`, `pause`, `resume`, `rm`, `queue`, `settings`, `--json` output. Build this early: it is how you test the daemon before the GUI exists. 9. **`velox-nmhost`** — 4-byte-length-prefixed stdio ⇄ Unix socket pump. **Under 300 lines, zero business logic**, and it must exit cleanly when Firefox closes the pipe. Install manifests to the three real locations in `docs/05` §4 / `docs/adr/0003` — not four: spike S1 found `~/snap/firefox/common/.mozilla/native-messaging-hosts/` (the intuitive "inside the snap" path) is not actually read by snap Firefox, and corrected `docs/05` §4 down from its original four-location list. `packaging/nativehost/README.md` has the current table. ## Definition of done (M1) - Passes the full conformance suite as a server, over **both** transports. - Kill and restart the daemon mid-download: all tasks reload with correct state and resume. - 1 000 tasks in the DB: `download.list` with paging under 50 ms. - Pairing flow works from a real Firefox extension; unpair revokes immediately. - `systemctl --user status velox` clean; socket activation verified from cold. - Security review passed: no bind beyond loopback, no path traversal in `saveDir` (canonicalize and check against allowed roots → `-32011`), no plaintext secrets. ## Do not - Do not put download logic here — that's CORE. You schedule and persist; CORE transfers. - Do not invent protocol fields. File a request with PROTO.