diff --git a/PROGRESS.md b/PROGRESS.md index 728854d..bce2dc5 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -1,11 +1,13 @@ -## Maven — current state (2026-07-03) +## Maven — current state (2026-07-05) Consolidated status. The reactive↔proactive core is closed and testable through -the web PWA. The SPEC's open items 1–7 are now landed (protocol doc, away-channel +the web PWA. The SPEC's open items 1–7 are landed (protocol doc, away-channel fallthrough, CalDAV poller, quiet-hours schedule, tools enable/disable, note RAG, passkey step-up); item 8 (multi-user) is deliberately deferred — see the tail. -Big untouched infra remaining: **at-rest security** (sqlcipher) and **systemd/ -container deployment** (still scripts + tmux). ~13.1k LOC + ~5.3k test, 202 tests. +The two big infra gaps from the last revision are now closed on `overnight-jul5`: +**at-rest encryption** (AES-256-GCM, tmpfs working copy — not sqlcipher, see +`internal/store/crypt.go`) and **Docker deployment** (one image, six daemon +containers). ~14.6k LOC + ~8.1k test, 284 tests, `-race` in `make test`. ### Access model @@ -91,24 +93,62 @@ Caveats / gotchas: by flipping the sign; as a presence-*here* signal it's inverted. desk_active + page_heartbeat cover home presence. +### Done since last revision (overnight-jul5, 2026-07-05) + +The overnight session (`SESSION-05-07-2026.md`, 25 tasks) closed the previous +"not built yet" items 1–3 and added feature depth: + +- **At-rest encryption** — the on-disk db is AES-256-GCM ciphertext; the daemon + works on a tmpfs (RAM) plaintext copy, sealed back atomically on close. Wrong + key / tamper ⇒ fail closed, never a plaintext fallback. Legacy plaintext dbs + upgrade on first clean shutdown. Key via config/env (`db_key_env`); no KDF — + raw 32-byte key, base64. The passkey cold-start unlock plugs into the same + `store.OpenEncrypted` seam later. +- **Docker deployment** — single image, one container per daemon + (`docker-compose.yml`); only mavend mounts the key + db volume; IPC over a + shared socket volume. `ipc.DialWait` (boot-order tolerance) + redial-on-drop + (core restarts don't kill modules). `deploy/README.md` has the runbook. +- **Tests** — mavcaldav, mavttsd, voicesink, mavweb main/handlers covered; + `make test` runs `-race -coverprofile`. +- **Recurring reminders** — `cron` + `next_fire_ts` on reminders; recurring ones + reschedule (instead of mark-fired) after successful delivery. +- **Notification digest/batching** — low-severity nudges queue and flush as one + digest per window/max-items (`digest` config block); stale-reminder bursts on + boot collapse into a single digest reminder, completed only after delivery. +- **Rule trace engine** — `ExplainTick`/`ExplainGate` record per-rule + predicate/gate/selection results each tick; served over IPC (`tick_trace`) + and rendered at mavweb `/trace` ("why didn't she nudge me"). +- **Web UI** — new `/history` (facts + revert buttons), `/notifications` (nudge + history), `/trace` pages; nav links on `/dash`; RU/EN cheatsheet toggle in the + PWA; manifest icons (`icon.svg`). POST `/tools` now requires an in-process + passkey step-up when WebAuthn is configured. +- **Revert/undo** — `RevertFact` voids the latest fact for a key (append-only + void-marker, audit trail intact); exposed at `/api/revert` from `/history`. +- **Tool scopes** — `scope` column on tools, threaded through propose/enable/UI. + `DisableTool` raised to AuthStepUp alongside Enable. +- **Passkey persistence** — mavweb credentials in a JSON file (`-passkey-file`), + surviving restarts; rollback-on-persist-failure keeps memory and disk in sync. +- **STT silence gate** — min-duration + RMS floor drop non-speech before whisper + hallucinates on it (`-min-ms`, `-silence-rms` flags on mavsttd). +- **Housekeeping** — `db_key.env` gitignored (+`.env.example`), `build-caldav` + target, zero-timestamp "never" fix on /dash. + ### Not built yet (ranked by ROI) -1. **At-rest encryption** — sqlcipher + cold-start unlock. Today the store is - plain sqlite: disk access = full read. Passkey step-up now gates *actions*, - but not the data at rest. -2. **`cmd/mavweb` / `cmd/mavcaldav` tests** — both are untested (0 test files). - mavweb now carries the passkey + tools HTTP flow (the webauthn *crypto* is - tested; the handlers and browser JS are not). Highest-value test gap. -3. **Deployment** — still `start-maven.sh` + tmux. systemd user units (one per - binary, socket-activated, `After=mavend.socket`, `Restart=on-failure`) are - specced, not written. Docker/Podman is a later phase. +1. **Purge + rotate the leaked db key** — a live AES key was committed at + `deploy/db_key.env` before it was gitignored. It must be scrubbed from git + history and rotated. Operator action, highest urgency. +2. **Step-up gate on `/api/revert`** — it mutates the store (voids facts) but + has no passkey gate, unlike POST `/tools`. Inconsistent with the auth model. +3. **Cold-start unlock** — the at-rest key still comes from env/config; the + passkey→key L3 dance is a documented seam, not a feature. Until then the key + sits in the container env. 4. **Multi-user (SPEC item 8)** — deliberately deferred, see the tail. -Housekeeping: `go.mod` isn't tidied — `onnxruntime_go` and `coder/websocket` -are used but marked `// indirect`. Passkey credentials are mavweb in-memory -(re-enroll after a mavweb restart — acceptable for single-user, by design). +Housekeeping: `go.mod` isn't tidied — `onnxruntime_go`, `coder/websocket`, and +`robfig/cron` are used directly but marked `// indirect`. -Done since last revision: **act tool executor, store-backed, full flow** +Done earlier (2026-07-03): **act tool executor, store-backed, full flow** (`internal/tool` + `internal/store/tools.go` + `tools` CoreAPI methods). - **Execution:** IntentAct runs the matched fn against the store's ENABLED allowlist. argv, no shell → STT text can't inject. Live store read, so a