Commit Graph

11 Commits

Author SHA1 Message Date
kami 4793d77fa9 mavweb: gate /api/revert behind passkey step-up
RevertFact voids the latest fact for a key — a store mutation — but
/api/revert had no step-up gate, while POST /tools required L3. Close the
inconsistency: thread the same *webauthn.PasskeySession into handleRevert
and reject with 403 when a configured session isn't asserted. nil session
(WebAuthn unconfigured) keeps prior behavior — transport-level auth only.

Tests: un-asserted session → 403 and RevertFact not called; asserted → 200.
The RevertFact mock now records its key so the gate assertion is meaningful.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 12:04:11 +04:00
kami 9ffefd9e8c maven: gofmt handlers_test.go (fix stale alignment)
The Task-7 verification commit (d52f60c) added the CalendarEvents mock
method but left fakeCore's struct block misaligned, so `gofmt -l` still
flagged this file despite the "all gates green" claim. Realign it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:49:03 +04:00
kami d52f60c54e maven: fix test mocks for CalendarEvents interface (verification)
- Add CalendarEvents method to recordingAPI in auth_test.go
- Add CalendarEvents method to fakeCore in handlers_test.go

Co-Authored-By: opencode <opencode@anthropic.com>
2026-07-06 04:20:16 +04:00
kami 8d823000d1 fix: code-review findings on overnight-jul5
- digest queue no longer dropped on failed dispatch (retry next tick)
- collapsed reminders marked fired/rescheduled only after digest delivers
- /tools step-up gate skipped when WebAuthn is not configured (was 403 forever)
- passkey credential store rolls back memory on persist failure
- auth_test fake updated for TickTrace (branch build break)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ASstMtsZWLSRcD1Tq8T68Q
2026-07-05 17:50:21 +04:00
kami 5c34fb14f9 mavweb: add notifications history page at /notifications
RecentNudges IPC method, store adapter, dispatch, and client proxy.
Web UI at /notifications showing recent nudge history with color-coded
outcomes, nav links from /dash and /history.
2026-07-05 13:20:24 +04:00
kami 85013f7b8b mavweb: add rule trace page at /trace
New template showing the most recent tick's rule evaluation results
with color-coded table, expandable gate detail panels, nav links
to dash and history. Uses the TickTrace IPC method from #15.
2026-07-05 13:17:47 +04:00
kami 5afff001c3 mavweb: add in-process auth gate for POST /tools
Add a local PasskeySession that handleTools checks before processing
any POST action (enable/disable). If the session hasn't been asserted
within the 5-minute TTL, return 403 Forbidden.

Changes:
- webauthn/session.go: add IsStepUp() convenience method (nil-safe)
- webauthn.go: PasskeyHandle holds a *PasskeySession; AssertFinish
  calls session.Assert() after IPC step-up
- main.go: create stepUpSession, pass to handleTools and
  newPasskeyHandle; handleTools returns 403 if !session.IsStepUp()
- handlers_test.go: update TestEnableTool_NoInProcessAuthGate to
  expect 403; add TestEnableTool_WithAuthGate_RequiresStepUp for
  the happy path with asserted session; update all 10 call sites
2026-07-05 11:55:44 +04:00
kami 6b80fd0c0f tools: add scope column for capability model
Add a 'scope' TEXT column (default 'homelab') to the tools table so tools
can be namespaced by scope (e.g. "homelab:restart", "datacenter:reboot").
Backward-compat: bare name defaults to "homelab" scope.

Changes:
- Migration #1: ALTER TABLE tools ADD COLUMN scope
- store.Tool: add Scope field, update all SQL and scanTool()
- ipc.Tool DTO and request types: add Scope field
- CoreAPI interface: pass scope in ProposeTool/EnableTool
- storeAPI adapters: forward scope
- cmd/mavend/voice: pass scope (empty → homelab)
- cmd/mavweb/tools: show scope column in UI tables, hidden fields
- All tests updated for scope field
- Migration test made dynamic (startVer = len(migrations))
2026-07-05 11:40:15 +04:00
kami 185f4f578e mavweb: extend test coverage to credentials, signal, dash, history, revert handlers
- New credentials_test.go: 4 test functions covering credentialStore
  (new, save, lookup, update, persistence across restarts).
- Extended handlers_test.go: fakeCore now supports WriteFact, Presence,
  RecentFacts/Nudges/Notes, RevertFact. Added 7 new test functions:
  TestNoCache, TestHandleSignal (5 subtestcases covering method guard,
  nil core, unknown key, known key, write error), TestHandleDash (3),
  TestHandleHistory (3), TestHandleRevert (6), and ListToolsError 502.
- Fixed history.html: Go html/template requires conditional class
  rendered as separate <tr> branches, not inline attribute.
2026-07-05 02:31:05 +04:00
kami 44807b612c webauthn: persist credentials to JSON file instead of in-memory map
- New credentialStore type in credentials.go loads/saves
  map[id]localCred to a JSON file. Thread-safe with sync.RWMutex,
  writes to disk on every mutation.
- PasskeyHandle replaces sync.RWMutex+map with *credentialStore.
  Inline save/lookip/update closures delegate to store methods.
- newPasskeyHandle now takes a storePath parameter and returns an
  error; callers updated.
- New -passkey-file flag (default ./passkeys.json) configures the
  credential store path in main.go.
- Tests use os.CreateTemp in t.TempDir() so each test gets an
  isolated, auto-cleaned store file.
2026-07-05 02:09:56 +04:00
kami de2058c851 mavweb: handler tests + gate DisableTool at step-up
- handlers_test.go: first tests for cmd/mavweb (feature-ranking #2). Covers
  the /tools enable/disable surface (arg parsing, error mapping, html escaping)
  and the webauthn handler contracts (method guards, malformed input). 14 cases.
  Verified the enable path is genuinely gated: an un-asserted call fails at the
  mavend IPC boundary (Requirement(EnableTool)=AuthStepUp), so mavweb stays a
  trust-nothing pass-through and core mediates.

- policy.go: DisableTool now also requires AuthStepUp. It mutates the same tool
  allowlist as EnableTool and is a lever to silence a security-relevant tool;
  gating allowlist mutation uniformly beats a split rule. ProposeTool stays
  maven-callable (no passkey). Corrects the stale api.go comment that claimed
  all three gated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 21:22:10 +04:00