4.9 KiB
4.9 KiB
0006 — API auth and LLM agent architecture
Date: 2026-07-03 Status: accepted (2026-07-04)
Context
P1 needs a documented HTTP API with token auth coexisting with OIDC session auth, plus a provider-agnostic OpenAI-compatible agent that tool-calls the API. Tasks 87 (API surface) and 88 (agent chat) depend on these choices. Gitea: #14 (epic #13).
Existing auth: Authentik OIDC via Auth.js, database sessions, household-scoped data via getCurrentSession(). Mutations today are server actions; a handful of route handlers exist under /api/ for uploads, SSE, and auth.
What we decided (2026-07-04)
| # | Topic | Choice |
|---|---|---|
| 1 | API token model | One shared household token (not per-user) |
| 1b | Token management | Household owner only — create, revoke, view last-used |
| 2 | API shape | REST JSON under /api/v1/ — additive versioning |
| 3 | LLM provider | Env-configured OpenAI-compatible endpoint (LLM_BASE_URL, optional LLM_API_KEY, LLM_MODEL) |
| 4 | Agent → API wiring | Direct tools (JSON-schema tools → HTTP calls). No MCP server in v1 |
Decision
Token auth (coexists with OIDC session)
- Add a single household-scoped API token stored hashed in the database (
household_api_tokensor equivalent). - Non-browser clients send
Authorization: Bearer <token>. /api/v1/*route handlers accept either a valid Auth.js session cookie or a valid household bearer token. Both resolve to the same household scope and permission checks.- OIDC / browser login is unchanged. Middleware continues to guard pages; API routes perform their own auth (session or bearer).
- Token lifecycle UI on
/settings(owner only): create (show raw token once), revoke, last-used timestamp. - Activity log for API mutations may attribute
actorIdfrom session when present; bearer-token calls useactorId = null(same pattern as share-link anonymous mutations).
API shape
- REST resources under
/api/v1/with JSON request/response bodies. - Additive versioning: new modules (journal, etc.) add routes under
/api/v1/without breaking existing clients. No v2 until a breaking change is unavoidable. - Task 87 covers: calendars, events, lists, list items, notes, garden (plants + containers), bangs. Dashboards deferred unless needed.
- OpenAPI spec committed as living docs (
docs/api/openapi.yamlor generated from route definitions). - Handlers call the same module server queries/actions as the web app — no parallel business logic.
LLM provider (task 88)
- Famapp does not host a model. The agent client points at an external OpenAI-compatible HTTP API configured via environment variables.
- Compatible with Ollama, vLLM, LiteLLM proxy, or any
/v1/chat/completions-style endpoint on the homelab. - CI uses a mock/stub provider — no live LLM calls in tests.
Agent tool-calling (task 88)
- Direct tools: the in-app agent defines tool schemas (name, description, parameters) that map to
/api/v1/HTTP methods. The agent loop calls the API with the household bearer token. - No MCP server in v1. Revisit if famapp needs to be a tool provider for Cursor or other MCP clients later.
Consequences
Positive
- One token to configure for scripts, wife's automations, and the agent — simple for a two-user household.
- REST + OpenAPI gives predictable integration and straightforward tool schema generation.
- Session and bearer auth share household scope; web app behavior unchanged.
- Direct tools avoid MCP transport, extra processes, and protocol overhead.
Trade-offs
- Shared token: revoking it disables all non-browser clients at once; no per-person revocation.
- Bearer calls lack a user
actorIdin activity log unless we add optional token metadata later. - Direct tools couple agent definitions to famapp's HTTP API; external MCP consumers would need a separate effort.
Implementation notes (task 87)
- Schema:
household_api_tokenswithhousehold_id,token_hash,name(e.g. "default"),last_used_at,created_by(owner),revoked_at. - Middleware: exempt
/api/v1/from session redirect; handlers enforce auth. - Settings: owner-only card for token create/revoke.
- Tests: Vitest for bearer auth resolution, 401/403 paths, and representative CRUD handlers.
References
- Task briefs:
docs/tasks/87-api-surface.md,docs/tasks/88-llm-agent-chat.md - Design:
docs/superpowers/specs/2026-07-03-backlog-triage-design.md