docs: accept adr 0006 api and agent architecture
This commit is contained in:
@@ -1,16 +1,77 @@
|
|||||||
# 0006 — API auth and LLM agent architecture
|
# 0006 — API auth and LLM agent architecture
|
||||||
|
|
||||||
Date: 2026-07-03
|
Date: 2026-07-03
|
||||||
Status: proposed
|
Status: accepted (2026-07-04)
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
P1 needs a documented API with token auth coexisting with OIDC session auth, plus a provider-agnostic OpenAI-compatible agent that tool-calls the API. Decide MCP vs direct tools. Gitea: [#14](https://gitea.ginnoir.com/ginnoir/famapp/issues/14) (epic [#13](https://gitea.ginnoir.com/ginnoir/famapp/issues/13)). Tasks 87 then 88.
|
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](https://gitea.ginnoir.com/ginnoir/famapp/issues/14) (epic [#13](https://gitea.ginnoir.com/ginnoir/famapp/issues/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
|
## Decision
|
||||||
|
|
||||||
To be filled when research completes.
|
### Token auth (coexists with OIDC session)
|
||||||
|
|
||||||
|
- Add a single **household-scoped API token** stored hashed in the database (`household_api_tokens` or 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 `actorId` from session when present; bearer-token calls use `actorId = 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.yaml` or 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
|
## Consequences
|
||||||
|
|
||||||
To be filled when research completes.
|
### 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 `actorId` in 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_tokens` with `household_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`
|
||||||
|
|||||||
@@ -28,5 +28,5 @@ What this costs us, what it buys us.
|
|||||||
- [0003 — Release workflow (commitlint + release-it)](0003-release-workflow.md)
|
- [0003 — Release workflow (commitlint + release-it)](0003-release-workflow.md)
|
||||||
- [0004 — Rich-text editor library and storage format](0004-rich-text-editor.md) (proposed)
|
- [0004 — Rich-text editor library and storage format](0004-rich-text-editor.md) (proposed)
|
||||||
- [0005 — Journal / mood tracking research](0005-journal-research.md) (proposed)
|
- [0005 — Journal / mood tracking research](0005-journal-research.md) (proposed)
|
||||||
- [0006 — API auth and LLM agent architecture](0006-api-llm-agent.md) (proposed)
|
- [0006 — API auth and LLM agent architecture](0006-api-llm-agent.md) (accepted 2026-07-04)
|
||||||
<!-- END AUTO-GENERATED -->
|
<!-- END AUTO-GENERATED -->
|
||||||
|
|||||||
Reference in New Issue
Block a user