summaryrefslogtreecommitdiff
path: root/issues
diff options
context:
space:
mode:
Diffstat (limited to 'issues')
-rw-r--r--issues/feature_agent_context_api.md287
1 files changed, 287 insertions, 0 deletions
diff --git a/issues/feature_agent_context_api.md b/issues/feature_agent_context_api.md
new file mode 100644
index 0000000..7be5f50
--- /dev/null
+++ b/issues/feature_agent_context_api.md
@@ -0,0 +1,287 @@
+# Feature: Agent Context API
+
+**Status:** [IN_PROGRESS] Phase 1 Complete
+**Created:** 2026-01-27
+**Author:** Architect
+
+---
+
+## Overview
+
+Expose a JSON API that allows external chat agents (e.g., Claude Code) to query dashboard context and manipulate items. Authentication uses a notification-based approval flow with agent identity binding.
+
+---
+
+## User Stories
+
+1. **As a user**, I can approve/deny agent access requests from the dashboard UI
+2. **As a user**, I can see which agents have been granted access and revoke them
+3. **As an agent**, I can request access by providing my name and unique ID
+4. **As an agent**, once approved, I can query the 7-day context (tasks, meals, timeline)
+5. **As an agent**, I can complete/uncomplete tasks, update due dates, modify details, and create items
+
+---
+
+## Authentication Flow
+
+```
+Agent Dashboard API Browser Tab
+ │ │ │
+ │ POST /agent/auth/request │ │
+ │ {name, agent_id} │ │
+ │ ──────────────────────────────>│ │
+ │ │ │
+ │ {request_token, status: │ WebSocket push: │
+ │ "pending"} │ "Agent X wants access" │
+ │ <──────────────────────────────│ ────────────────────────────>│
+ │ │ │
+ │ │ User approves
+ │ │ │
+ │ │ POST /agent/auth/approve │
+ │ │ <────────────────────────────│
+ │ │ │
+ │ GET /agent/auth/poll │ │
+ │ ?token=X │ │
+ │ ──────────────────────────────>│ │
+ │ │ │
+ │ {status: "approved", │ │
+ │ session_token, expiry} │ │
+ │ <──────────────────────────────│ │
+ │ │ │
+ │ GET /agent/context │ │
+ │ Authorization: Bearer X │ │
+ │ ──────────────────────────────>│ │
+ │ │ │
+ │ {timeline, tasks, ...} │ │
+ │ <──────────────────────────────│ │
+```
+
+---
+
+## Agent Identity Binding
+
+| Scenario | Behavior |
+|----------|----------|
+| New agent (name + ID never seen) | Show approval prompt, store pairing on approve |
+| Known agent (name + ID match stored) | Show approval prompt with "Recognized" indicator |
+| Suspicious (known name, different ID) | Show warning: "Agent 'X' with different ID" — require explicit re-trust |
+
+---
+
+## Design Decisions
+
+| Decision | Choice | Rationale |
+|----------|--------|-----------|
+| Session refresh | None — re-authenticate after expiry | Keep it simple |
+| Concurrent sessions | One per agent — new approval invalidates previous | Predictable state |
+| Deny behavior | Single-request denial, no blocking | Simple first pass |
+
+---
+
+## Database Schema
+
+### New Tables
+
+```sql
+-- Registered/approved agents
+CREATE TABLE agents (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL,
+ agent_id TEXT NOT NULL UNIQUE, -- UUID from agent
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ last_seen DATETIME,
+ trusted BOOLEAN DEFAULT 1 -- can be revoked
+);
+
+-- Pending access requests and sessions
+CREATE TABLE agent_sessions (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ request_token TEXT NOT NULL UNIQUE,
+ agent_name TEXT NOT NULL,
+ agent_id TEXT NOT NULL,
+ status TEXT DEFAULT 'pending', -- pending, approved, denied, expired
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ expires_at DATETIME NOT NULL, -- request expires after 5 min
+ session_token TEXT, -- populated on approval
+ session_expires_at DATETIME -- session TTL (1 hour)
+);
+
+CREATE INDEX idx_agent_sessions_request ON agent_sessions(request_token);
+CREATE INDEX idx_agent_sessions_session ON agent_sessions(session_token);
+```
+
+---
+
+## API Endpoints
+
+### Authentication (no auth required)
+
+| Method | Path | Purpose |
+|--------|------|---------|
+| POST | `/agent/auth/request` | Request access (returns request_token) |
+| GET | `/agent/auth/poll?token=X` | Poll for approval status |
+
+### Authentication (browser session required)
+
+| Method | Path | Purpose |
+|--------|------|---------|
+| POST | `/agent/auth/approve` | User approves request |
+| POST | `/agent/auth/deny` | User denies request |
+
+### Context (agent session required)
+
+| Method | Path | Purpose |
+|--------|------|---------|
+| GET | `/agent/context` | Full 7-day context |
+
+### Write Operations (agent session required)
+
+| Method | Path | Purpose | Priority |
+|--------|------|---------|----------|
+| PATCH | `/agent/tasks/{id}/due` | Update due date | P1 |
+| POST | `/agent/tasks/{id}/complete` | Complete task | P1 |
+| POST | `/agent/tasks/{id}/uncomplete` | Reopen task | P1 |
+| PATCH | `/agent/tasks/{id}` | Update details (title, desc) | P2 |
+| POST | `/agent/tasks` | Create task | P3 |
+| POST | `/agent/shopping/add` | Add shopping item | P3 |
+
+---
+
+## Context Response Format
+
+```json
+{
+ "generated_at": "2026-01-27T10:30:00-10:00",
+ "range": {
+ "start": "2026-01-27",
+ "end": "2026-02-03"
+ },
+ "timeline": [
+ {
+ "id": "task_123",
+ "source": "todoist",
+ "type": "task",
+ "title": "Buy groceries",
+ "description": "Milk, eggs, bread",
+ "due": "2026-01-27T17:00:00-10:00",
+ "priority": 2,
+ "completable": true,
+ "url": "https://todoist.com/..."
+ }
+ ],
+ "summary": {
+ "total_items": 42,
+ "by_source": {"todoist": 15, "trello": 20, "plantoeat": 7},
+ "overdue": 3,
+ "today": 8
+ }
+}
+```
+
+---
+
+## Browser Components
+
+### WebSocket Endpoint
+- Path: `/ws/notifications`
+- Purpose: Push agent request alerts to open browser tabs
+- Must handle: reconnect on disconnect, authentication check
+
+### Approval UI
+- Trigger: WebSocket message of type `agent_request`
+- Display: Modal or toast notification
+- Content:
+ - Agent name
+ - Agent ID (truncated to 8 chars)
+ - Trust indicator: "New Agent" / "Recognized" / "Warning: Different ID"
+- Actions: Approve / Deny buttons
+
+### Agent Management (Phase 3)
+- List of trusted agents with last-seen timestamp
+- Revoke access button per agent
+
+---
+
+## Session Configuration
+
+| Parameter | Value |
+|-----------|-------|
+| Request expiry | 5 minutes |
+| Session TTL | 1 hour |
+| Poll interval (agent-side) | 2 seconds |
+
+---
+
+## Security Considerations
+
+1. **Rate limiting** on `/agent/auth/request` — 10 requests/minute per IP
+2. **Tokens** are cryptographically random (32 bytes, base64url)
+3. **HTTPS required** — tokens in Authorization header
+4. **No CSRF** for agent endpoints — token-based auth, not cookies
+5. **One session per agent** — new approval invalidates previous session
+
+---
+
+## Implementation Phases
+
+### Phase 1: Auth Flow + Read Context
+Files to create/modify:
+- `migrations/010_agent_tables.sql` — new tables
+- `internal/store/sqlite.go` — agent/session CRUD methods
+- `internal/handlers/agent.go` — new handler file for agent endpoints
+- `internal/handlers/websocket.go` — WebSocket notification hub
+- `cmd/dashboard/main.go` — register new routes
+- `web/templates/partials/agent-approval.html` — approval modal
+- `web/static/js/app.js` — WebSocket connection + approval UI logic
+
+Endpoints:
+- POST `/agent/auth/request`
+- GET `/agent/auth/poll`
+- POST `/agent/auth/approve`
+- POST `/agent/auth/deny`
+- GET `/agent/context`
+- WS `/ws/notifications`
+
+### Phase 2: Write Operations (P1 + P2)
+- POST `/agent/tasks/{id}/complete`
+- POST `/agent/tasks/{id}/uncomplete`
+- PATCH `/agent/tasks/{id}/due`
+- PATCH `/agent/tasks/{id}`
+
+### Phase 3: Create + Management
+- POST `/agent/tasks`
+- POST `/agent/shopping/add`
+- Agent management UI (list, revoke)
+
+---
+
+## Testing Strategy
+
+### Unit Tests
+- `internal/store/sqlite_test.go` — agent/session CRUD
+- `internal/handlers/agent_test.go` — endpoint logic
+
+### Integration Tests
+- Full auth flow: request → approve → poll → context
+- Identity binding: same name different ID triggers warning
+- Session expiry: requests fail after TTL
+
+### Manual Testing
+- Open dashboard in browser
+- Run agent simulation script to request access
+- Verify notification appears
+- Approve and verify context returned
+
+---
+
+## Files Reference
+
+| Purpose | File |
+|---------|------|
+| Migration | `migrations/010_agent_tables.sql` |
+| Store methods | `internal/store/sqlite.go` |
+| Agent handlers | `internal/handlers/agent.go` (new) |
+| WebSocket hub | `internal/handlers/websocket.go` (new) |
+| Route registration | `cmd/dashboard/main.go` |
+| Approval modal | `web/templates/partials/agent-approval.html` (new) |
+| Client JS | `web/static/js/app.js` |