Skip to content

v1.7.0 — per-user areas, email, calendar & webhooks

Choose a tag to compare

@IkarusMK IkarusMK released this 02 Jul 15:16
· 41 commits to main since this release

Added

  • Per-user service/skill areas + per-user cron (act-as). Tenancy extends from private data to shared capabilities and scheduled jobs. policy.json users gain services/skills = all | none | allow-list of names/categories — default-deny and fail-closed under enforcement. A cron job can run as an owner: a non-admin schedules only as themselves, an admin as anyone. cron_due mints a short-lived per-job capability token (HMAC, HKDF-derived from STORAGE_ENCRYPTION_KEY, 5-min TTL, single-use); the runner presents it via act_as_begin/act_as_end, so it holds no standing authority and a job is scoped to its owner at the owner's own privilege. See docs/per-user-areas.md.
  • IMAP — read incoming email. imap_add / imap_list / imap_search / imap_fetch — the read-side counterpart to SMTP. Read-only (BODY.PEEK) so nothing is marked seen; attachments optionally saved to /data/work. SSRF-guarded connect, vault password.
  • CalDAV — calendars as data. caldav_add / caldav_list_calendars / caldav_list_events / caldav_add_event — discover calendars, list events in a range, create an event (over PROPFIND / REPORT / PUT, no extra dependency). SSRF-guarded, TLS verified by default, vault password.
  • Webhooks — inbound + outbound. Inbound: a public POST /hooks/<name> route (via FastMCP custom_route, outside the MCP OAuth) lets external services push events into the inbox — making the brain event-driven. Each hook authenticates with a per-hook shared secret token and/or HMAC signature (constant-time), rejects unknown/unsigned requests, caps body size, and only deposits into the inbox — never the tool surface. Outbound: webhook_send(url, json_body) — a thin SSRF-guarded POST. Operator note: expose only /hooks/* past the reverse proxy's auth, never /mcp.
  • Running version is observable — logged at startup, returned by ping, and shown in the bootstrap catalog header.

Changed (breaking)

  • Isolation now rides on AUTH_ENFORCE. The separate TENANCY_ISOLATE switch is retired — one switch, "enforce means enforce". With AUTH_ENFORCE=1 (the default), non-admins are confined (own memory scope + private vault) and default-denied services/skills until an admin grants them; homelab mode (AUTH_ENFORCE=0) is unchanged. A leftover TENANCY_ISOLATE=1 in .env becomes a harmless no-op. Admins are unaffected.

Upgrade

cd <deploy-dir> && git pull && docker compose pull && docker compose up -d --force-recreate

Then ping reports AICortex v1.7.0. For inbound webhooks, pass only /hooks/* past the reverse proxy's auth (never /mcp). To run per-user cron jobs, the NAS runner wraps each job in act_as_begin / act_as_end. You can drop a leftover TENANCY_ISOLATE=1 from .env.

Full diff: v1.6.3...v1.7.0