summaryrefslogtreecommitdiff
path: root/docs/adr/005-agent-api-authentication.md
blob: e64a5a8f286b18d7f36ba4f96ad7423664d8360a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# ADR 005: Agent API Authentication Architecture

## Status
Accepted

## Context
External agents (CLI tools, automation scripts, AI assistants) need secure access to dashboard context without exposing user credentials. Traditional approaches have weaknesses:

- **API Keys**: Long-lived, often stored insecurely, difficult to revoke
- **OAuth2**: Complex setup, overkill for personal dashboard
- **SSH Keys**: Key management burden on user

Requirements:
- User awareness of agent access (no hidden API keys)
- Easy revocation (deny re-auth requests)
- Time-limited sessions to reduce exposure
- Support for both CLI and browser-based agents

## Decision
Implement **notification-based approval flow** with ephemeral sessions.

### Technical Details:

**Identity Model:**
- Agents identified by `name` + `agent_id` (UUID) pair
- Binding persisted on first approval
- Impersonation detected if name/agent_id mismatch

**Trust Levels:**
- `TRUSTED`: Previously approved, auto-approve on re-auth
- `UNKNOWN`: New agent, requires user approval
- `BLOCKED`: Denied agent, reject immediately

**Session Model:**
- 1-hour TTL tokens
- One active session per agent_id
- Session token in Authorization header

**Approval Flow:**
```
Agent                    Dashboard                 Browser
  |                          |                        |
  |-- POST /auth/request --> |                        |
  |                          |-- WebSocket push ----> |
  |                          |                        | (user sees modal)
  |                          |                        |
  |<-- request_token --------|                        |
  |                          |                        |
  |-- GET /auth/poll ------> |                        |
  |   (polling)              |                        |
  |                          | <-- POST /approve ---- |
  |                          |                        |
  |<-- session_token --------|                        |
  |                          |                        |
  |-- GET /context --------> |                        |
  |   (with session_token)   |                        |
```

**Implementation:**
- `internal/handlers/agent.go` - Auth flow handlers (615 LOC)
- `internal/handlers/websocket.go` - Real-time notifications (216 LOC)
- `migrations/010_agent_tables.sql` - Storage schema
- `web/static/js/app.js` - Browser UI for approval modal

**Rate Limiting:**
- 10 requests/minute per IP on auth endpoints
- Prevents brute-force token guessing

## Consequences

**Pros:**
- User-visible agent access (approval modal shows agent name)
- Easy revocation by denying re-auth or blocking agent
- Trust level caching reduces approval fatigue for known agents
- Time-limited sessions reduce credential exposure
- Works for both CLI agents (polling) and browser agents (web endpoints)

**Cons:**
- Requires browser window open for first-time approval
- Poll loop adds latency to auth flow (~1-5 seconds)
- Session expiry interrupts long-running agent tasks (must re-auth)

## Alternatives Considered

**Option A: Traditional API Keys**
- Rejected: Long-lived credentials, no user awareness of access

**Option B: OAuth2 Device Flow**
- Rejected: Complex implementation, requires external auth server setup

**Option C: SSH-style Key Pairs**
- Rejected: Key management burden, harder to revoke

**Option D: Magic Links (email-based)**
- Rejected: Adds email dependency, slower approval flow