@prmichaelsen/remember-mcp 3.18.1 → 3.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT.md +1 -1
- package/CHANGELOG.md +15 -0
- package/README.md +35 -1
- package/agent/commands/acp.clarification-address.md +417 -0
- package/agent/commands/acp.clarification-create.md +5 -0
- package/agent/commands/acp.clarifications-research.md +326 -0
- package/agent/commands/acp.handoff.md +270 -0
- package/agent/design/local.api-token-oauth-access.md +286 -0
- package/agent/milestones/milestone-21-api-token-oauth-access.md +53 -0
- package/agent/progress.yaml +73 -2
- package/agent/scripts/acp.install.sh +50 -27
- package/agent/scripts/acp.package-validate.sh +55 -27
- package/agent/tasks/milestone-21-api-token-oauth-access/task-515-add-auth-scheme-config.md +56 -0
- package/agent/tasks/milestone-21-api-token-oauth-access/task-516-implement-oauth-token-exchange.md +56 -0
- package/agent/tasks/milestone-21-api-token-oauth-access/task-517-implement-local-config-resolution.md +59 -0
- package/agent/tasks/milestone-21-api-token-oauth-access/task-518-wire-oauth-into-server-factory.md +56 -0
- package/agent/tasks/milestone-21-api-token-oauth-access/task-519-tests-and-documentation.md +54 -0
- package/agent/tasks/unassigned/task-514-remember-mcp-consume-core-space.md +71 -0
- package/dist/auth/config-resolver.d.ts +28 -0
- package/dist/auth/config-resolver.spec.d.ts +2 -0
- package/dist/auth/oauth-bootstrap.d.ts +22 -0
- package/dist/auth/oauth-bootstrap.spec.d.ts +2 -0
- package/dist/auth/oauth-exchange.d.ts +32 -0
- package/dist/auth/oauth-exchange.spec.d.ts +2 -0
- package/dist/config.d.ts +24 -0
- package/dist/server.js +1454 -78
- package/package.json +1 -1
- package/src/auth/config-resolver.spec.ts +101 -0
- package/src/auth/config-resolver.ts +127 -0
- package/src/auth/oauth-bootstrap.spec.ts +72 -0
- package/src/auth/oauth-bootstrap.ts +45 -0
- package/src/auth/oauth-exchange.spec.ts +126 -0
- package/src/auth/oauth-exchange.ts +128 -0
- package/src/config.ts +46 -0
- package/src/server.ts +17 -3
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# API Token & OAuth Access
|
|
2
|
+
|
|
3
|
+
**Concept**: Enable CLI and local access to remember data via API tokens exchanged through an OAuth flow
|
|
4
|
+
**Created**: 2026-03-14
|
|
5
|
+
**Status**: Design Specification
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Users currently access remember data through two paths: the agentbase.me web UI (Firebase Auth) and deployed MCP servers (JWT via mcp-auth). Neither supports local CLI access — there's no way to run remember-mcp locally in Claude Code or call remember-rest-service from a terminal without manually managing service credentials.
|
|
12
|
+
|
|
13
|
+
This design introduces API tokens as a first-class credential type. Users generate tokens on agentbase.me, configure them locally, and use them to authenticate via a standard OAuth token exchange. The entire downstream stack remains JWT-based.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Problem Statement
|
|
18
|
+
|
|
19
|
+
- **No CLI access path**: Users cannot connect Claude Code (local) to their cloud remember data without fragile manual secret management and raw curl commands.
|
|
20
|
+
- **Platform coupling**: The only auth path is through agentbase.me's Firebase Auth, which requires a browser and doesn't support headless/CLI workflows.
|
|
21
|
+
- **Multi-tenant inflexibility**: Self-hosted platforms can't use the same auth infrastructure because credentials are hardcoded to agentbase.me.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Solution
|
|
26
|
+
|
|
27
|
+
Introduce a three-layer auth architecture:
|
|
28
|
+
|
|
29
|
+
1. **API Token** (credential) — opaque, prefixed, short-lived (1 hour), stored as SHA-256 hash in Firestore
|
|
30
|
+
2. **OAuth Token Exchange** (flow) — API token is exchanged for a JWT via `REMEMBER_OAUTH_ENDPOINT`
|
|
31
|
+
3. **JWT** (access) — existing downstream code, unchanged
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
User generates token on agentbase.me
|
|
35
|
+
→ stored hashed in Firestore, raw shown once
|
|
36
|
+
→ user saves to .remember/config or REMEMBER_API_TOKEN env var
|
|
37
|
+
|
|
38
|
+
remember-mcp starts with REMEMBER_AUTH_SCHEME=oauth
|
|
39
|
+
→ reads REMEMBER_API_TOKEN + REMEMBER_OAUTH_ENDPOINT
|
|
40
|
+
→ exchanges API token for JWT via OAuth endpoint
|
|
41
|
+
→ proceeds with JWT as normal (userId extracted from claims)
|
|
42
|
+
|
|
43
|
+
All downstream code unchanged — same request.userId, same tool handlers
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Alternative Considered: Direct Token Validation in Auth Guard
|
|
47
|
+
|
|
48
|
+
Extending the remember-rest-service auth guard to validate API tokens directly (Firestore lookup per request). Rejected because:
|
|
49
|
+
- Mixes two auth strategies in one guard
|
|
50
|
+
- Doesn't work with mcp-auth's existing OAuth support
|
|
51
|
+
- Couples remember-rest-service to a specific token storage backend
|
|
52
|
+
- The OAuth exchange approach is standard and enables self-hosted platforms
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Implementation
|
|
57
|
+
|
|
58
|
+
### Token Format
|
|
59
|
+
|
|
60
|
+
Prefixed opaque tokens with secret/public key distinction:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
ab_live-sk_<32 bytes hex> # secret key (server-side, CLI)
|
|
64
|
+
ab_live-pk_<32 bytes hex> # public key (client-side, future)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- Opaque: leaked token reveals nothing (no embedded userId)
|
|
68
|
+
- Prefix enables secret scanning (GitHub, GitGuardian)
|
|
69
|
+
- 32 bytes of entropy (256 bits)
|
|
70
|
+
|
|
71
|
+
### Firestore Schema
|
|
72
|
+
|
|
73
|
+
Collection: `api_tokens` (top-level, keyed by SHA-256 hash of raw token)
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
interface ApiToken {
|
|
77
|
+
user_id: string;
|
|
78
|
+
name: string; // human-readable label, e.g. "MacBook Pro"
|
|
79
|
+
scopes: string[]; // ["*"] for full access, or specific scopes
|
|
80
|
+
created_at: Timestamp;
|
|
81
|
+
expires_at: Timestamp; // created_at + 1 hour
|
|
82
|
+
last_used_at: Timestamp;
|
|
83
|
+
disabled: boolean; // emergency kill switch
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Lookup: `hash(raw_token)` → document → `user_id`
|
|
88
|
+
|
|
89
|
+
### Auth Scheme Configuration
|
|
90
|
+
|
|
91
|
+
remember-mcp supports two auth schemes via `REMEMBER_AUTH_SCHEME`:
|
|
92
|
+
|
|
93
|
+
| Env Var | Value | Behavior |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| `REMEMBER_AUTH_SCHEME` | `service` (default) | Current behavior — JWT via mcp-auth, deployed behind remember-mcp-server |
|
|
96
|
+
| `REMEMBER_AUTH_SCHEME` | `oauth` | Local mode — exchanges API token for JWT via OAuth endpoint |
|
|
97
|
+
| `REMEMBER_OAUTH_ENDPOINT` | URL | OAuth token exchange endpoint (required when scheme=oauth) |
|
|
98
|
+
| `REMEMBER_API_TOKEN` | token | API token for OAuth exchange (or read from `.remember/config`) |
|
|
99
|
+
|
|
100
|
+
### Local Configuration Resolution
|
|
101
|
+
|
|
102
|
+
Token and endpoint are resolved in order (first wins):
|
|
103
|
+
|
|
104
|
+
1. `./.remember/config` (project-level)
|
|
105
|
+
2. `~/.remember/config` (global)
|
|
106
|
+
3. `REMEMBER_API_TOKEN` / `REMEMBER_OAUTH_ENDPOINT` env vars (override)
|
|
107
|
+
|
|
108
|
+
Config file format:
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
# .remember/config
|
|
112
|
+
oauth_endpoint: https://agentbase.me/api/oauth/token
|
|
113
|
+
api_token: ab_live-sk_...
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This enables per-project multi-tenant support (different projects → different platforms).
|
|
117
|
+
|
|
118
|
+
### OAuth Token Exchange
|
|
119
|
+
|
|
120
|
+
The OAuth endpoint accepts an API token and returns a JWT:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
POST {REMEMBER_OAUTH_ENDPOINT}
|
|
124
|
+
Content-Type: application/json
|
|
125
|
+
|
|
126
|
+
{
|
|
127
|
+
"grant_type": "api_token",
|
|
128
|
+
"api_token": "ab_live-sk_..."
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
→ 200 OK
|
|
132
|
+
{
|
|
133
|
+
"access_token": "<jwt>",
|
|
134
|
+
"token_type": "Bearer",
|
|
135
|
+
"expires_in": 3600
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The JWT contains the same claims as browser-issued tokens (`sub`, `iss`, `aud`), so downstream code is unaware of the auth method.
|
|
140
|
+
|
|
141
|
+
### Auth Method Observability
|
|
142
|
+
|
|
143
|
+
The auth guard sets `request.authMethod` alongside `request.userId`:
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
request.userId = payload.sub;
|
|
147
|
+
request.authMethod = 'jwt' | 'api_token';
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Downstream tool handlers ignore `authMethod`. Rate-limiting and logging can use it.
|
|
151
|
+
|
|
152
|
+
### Rate Limiting
|
|
153
|
+
|
|
154
|
+
| Tier | Rate | Purpose |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| Token hard limit | Higher than JWT default | API tokens get more headroom for programmatic access |
|
|
157
|
+
| Token emergency limit | Burst threshold | Auto-disable token on anomalous burst activity |
|
|
158
|
+
|
|
159
|
+
Rate limits are per-token (not per-user), enabling independent limits per credential.
|
|
160
|
+
|
|
161
|
+
### agentbase.me Endpoints
|
|
162
|
+
|
|
163
|
+
| Endpoint | Method | Description |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| `/api/tokens` | POST | Create token (returns raw token once) |
|
|
166
|
+
| `/api/tokens` | GET | List tokens (metadata only, no raw values) |
|
|
167
|
+
| `/api/tokens/:id` | DELETE | Revoke token |
|
|
168
|
+
| `/api/oauth/token` | POST | OAuth token exchange (API token → JWT) |
|
|
169
|
+
|
|
170
|
+
### CLI Login Flow
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
$ agentbase login
|
|
174
|
+
Opening browser for authentication...
|
|
175
|
+
→ Browser opens agentbase.me/cli-auth
|
|
176
|
+
→ User authenticates via Firebase Auth
|
|
177
|
+
→ agentbase.me generates API token
|
|
178
|
+
→ Token sent back to CLI via localhost callback
|
|
179
|
+
Authenticated! Token saved to ~/.remember/config
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### agentbase.me UI
|
|
183
|
+
|
|
184
|
+
Settings page: "API Tokens"
|
|
185
|
+
- Create token (name field, shown-once raw value)
|
|
186
|
+
- List tokens (name, created date, last used, revoke button)
|
|
187
|
+
- Token scopes display (v1: always "Full access")
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Benefits
|
|
192
|
+
|
|
193
|
+
- **CLI access**: Claude Code and terminal workflows can access cloud remember data
|
|
194
|
+
- **Platform agnostic**: `REMEMBER_OAUTH_ENDPOINT` can point to any compatible platform, not just agentbase.me
|
|
195
|
+
- **Zero downstream changes**: All existing tool handlers, services, and auth context work unchanged
|
|
196
|
+
- **Security**: Opaque tokens, SHA-256 hashing, 1-hour expiry, emergency disable
|
|
197
|
+
- **Multi-tenant**: Per-project `.remember/config` supports different accounts/platforms
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Trade-offs
|
|
202
|
+
|
|
203
|
+
- **Firestore read per exchange**: Each OAuth token exchange requires a Firestore lookup by token hash. Mitigated by 1-hour JWT TTL (one lookup per hour, not per request).
|
|
204
|
+
- **Token management complexity**: Users must manage tokens (generate, store, revoke). Mitigated by `agentbase login` CLI flow.
|
|
205
|
+
- **Cross-project coordination**: Changes span 4-5 codebases. Mitigated by breaking into per-project milestones.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Dependencies
|
|
210
|
+
|
|
211
|
+
- **agentbase.me**: Token CRUD API, OAuth endpoint, CLI auth page, settings UI
|
|
212
|
+
- **remember-core**: Firestore paths for `api_tokens` collection, optional token validation helpers
|
|
213
|
+
- **remember-rest-service**: Auth guard extension for `authMethod` observability
|
|
214
|
+
- **remember-mcp**: `REMEMBER_AUTH_SCHEME` config, OAuth token exchange at startup
|
|
215
|
+
- **agentbase-mcp-server** (new): Dedicated codebase wrapping remember-mcp with agentbase.me OAuth
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Testing Strategy
|
|
220
|
+
|
|
221
|
+
- **Unit**: Token generation (format, entropy), hashing, config resolution order, auth scheme switching
|
|
222
|
+
- **Integration**: Full OAuth flow (create token → exchange → JWT → tool call), token expiry, revocation
|
|
223
|
+
- **Security**: Verify raw tokens never stored, hash collisions, prefix scanning, disabled token rejection
|
|
224
|
+
- **E2E**: `agentbase login` flow, Claude Code local session with cloud data
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Migration Path
|
|
229
|
+
|
|
230
|
+
1. **agentbase.me**: Add `/api/tokens` CRUD + `/api/oauth/token` exchange endpoint + settings UI
|
|
231
|
+
2. **remember-core**: Add `api_tokens` Firestore paths, optional validation helpers
|
|
232
|
+
3. **remember-mcp**: Add `REMEMBER_AUTH_SCHEME=oauth` mode with token exchange
|
|
233
|
+
4. **remember-rest-service**: Add `request.authMethod` to auth guard
|
|
234
|
+
5. **CLI**: Build `agentbase login` command (or npm package)
|
|
235
|
+
|
|
236
|
+
No breaking changes — `REMEMBER_AUTH_SCHEME` defaults to `service` (current behavior).
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Key Design Decisions
|
|
241
|
+
|
|
242
|
+
### Token Format & Security
|
|
243
|
+
|
|
244
|
+
| Decision | Choice | Rationale |
|
|
245
|
+
|---|---|---|
|
|
246
|
+
| Token opacity | Opaque (random bytes) | Leaked token reveals nothing; userId requires API lookup which is rate-limitable and revocable |
|
|
247
|
+
| Token prefix | `ab_live-sk_` / `ab_live-pk_` | Enables secret scanning tools (GitHub, GitGuardian) |
|
|
248
|
+
| Storage | SHA-256 hash only | Raw token never persisted; shown once at creation |
|
|
249
|
+
| Expiry | 1 hour | Matches Google OAuth convention; limits blast radius of leaked tokens |
|
|
250
|
+
| Scopes | Supported but v1 = full access | Schema includes `scopes` array; v1 always `["*"]` |
|
|
251
|
+
|
|
252
|
+
### Architecture
|
|
253
|
+
|
|
254
|
+
| Decision | Choice | Rationale |
|
|
255
|
+
|---|---|---|
|
|
256
|
+
| Auth integration | OAuth token exchange (not direct guard validation) | Clean separation; works with mcp-auth; enables self-hosted platforms |
|
|
257
|
+
| Auth scheme env var | `REMEMBER_AUTH_SCHEME=service\|oauth` | remember-mcp stays platform-agnostic; no agentbase.me coupling in core code |
|
|
258
|
+
| Config naming | `REMEMBER_*` (not `AGENTBASE_*`) | Core code must be platform-agnostic; any OAuth endpoint should work |
|
|
259
|
+
| Config resolution | `./.remember/config` > `~/.remember/config` > env var | Per-project multi-tenancy; similar to `.npmrc` precedence |
|
|
260
|
+
|
|
261
|
+
### Observability
|
|
262
|
+
|
|
263
|
+
| Decision | Choice | Rationale |
|
|
264
|
+
|---|---|---|
|
|
265
|
+
| `request.authMethod` | `'jwt' \| 'api_token'` alongside `request.userId` | Zero downstream changes; rate-limiting and logging can differentiate |
|
|
266
|
+
| Rate limiting | Per-token with hard + emergency limits | Protects against abuse per credential; emergency auto-disable on burst |
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Future Considerations
|
|
271
|
+
|
|
272
|
+
- **Multiple tokens per user**: Schema supports array; v1 limited to single active token
|
|
273
|
+
- **Scoped tokens**: Read-only, per-tool, per-space scoping
|
|
274
|
+
- **Fully local mode**: Local Weaviate + Firestore emulator for offline/air-gapped use
|
|
275
|
+
- **Token rotation**: Automatic refresh before expiry
|
|
276
|
+
- **CLI package**: `@prmichaelsen/agentbase-cli` npm package with `agentbase login`, `agentbase status`, etc.
|
|
277
|
+
- **`remember_login` MCP tool**: In-session authentication for remember-mcp
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
**Status**: Design Specification
|
|
282
|
+
**Recommendation**: Break into per-project milestones and begin with agentbase.me token CRUD + OAuth endpoint
|
|
283
|
+
**Related Documents**:
|
|
284
|
+
- [Clarification 5: API Token & CLI Access](../clarifications/clarification-5-api-token-cli-access.md)
|
|
285
|
+
- [REST API Architecture](../../remember-rest-service/agent/design/local.rest-api-architecture.md)
|
|
286
|
+
- [Group ACL Integration](local.group-acl-integration.md)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Milestone 21: API Token & OAuth Access
|
|
2
|
+
|
|
3
|
+
**Status**: not_started
|
|
4
|
+
**Started**: —
|
|
5
|
+
**Estimated Weeks**: 1
|
|
6
|
+
**Tasks**: 5
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Goal
|
|
11
|
+
|
|
12
|
+
Enable remember-mcp to run locally (e.g. in Claude Code) by supporting an OAuth auth scheme where an API token is exchanged for a JWT via a configurable endpoint. This is the remember-mcp slice of the cross-project API Token feature.
|
|
13
|
+
|
|
14
|
+
## Scope
|
|
15
|
+
|
|
16
|
+
This milestone covers **remember-mcp changes only**. Other projects (agentbase.me, remember-core, remember-rest-service) have their own milestones for the remaining pieces.
|
|
17
|
+
|
|
18
|
+
Changes:
|
|
19
|
+
- `REMEMBER_AUTH_SCHEME` config (`service` | `oauth`)
|
|
20
|
+
- OAuth token exchange client
|
|
21
|
+
- Local config file resolution (`.remember/config`)
|
|
22
|
+
- Wiring into server-factory startup
|
|
23
|
+
- Tests and documentation
|
|
24
|
+
|
|
25
|
+
## Deliverables
|
|
26
|
+
|
|
27
|
+
- [ ] Config module supports `REMEMBER_AUTH_SCHEME`, `REMEMBER_OAUTH_ENDPOINT`, `REMEMBER_API_TOKEN`
|
|
28
|
+
- [ ] OAuth token exchange client exchanges API token for JWT
|
|
29
|
+
- [ ] `.remember/config` resolution (project > global > env var)
|
|
30
|
+
- [ ] server-factory uses OAuth flow when `REMEMBER_AUTH_SCHEME=oauth`
|
|
31
|
+
- [ ] Unit tests for config, exchange client, config resolution
|
|
32
|
+
- [ ] CHANGELOG and README updated
|
|
33
|
+
|
|
34
|
+
## Success Criteria
|
|
35
|
+
|
|
36
|
+
- `REMEMBER_AUTH_SCHEME=service` behaves exactly as today (no regression)
|
|
37
|
+
- `REMEMBER_AUTH_SCHEME=oauth` exchanges token and starts server with resolved userId
|
|
38
|
+
- Config resolution order: `./.remember/config` > `~/.remember/config` > env vars
|
|
39
|
+
- Build passes, all existing tests pass, new tests cover oauth flow
|
|
40
|
+
|
|
41
|
+
## Dependencies
|
|
42
|
+
|
|
43
|
+
- Design: [local.api-token-oauth-access.md](../design/local.api-token-oauth-access.md)
|
|
44
|
+
- Clarification: [clarification-5-api-token-cli-access.md](../clarifications/clarification-5-api-token-cli-access.md)
|
|
45
|
+
- External: agentbase.me must have `/api/oauth/token` endpoint for end-to-end testing (can be mocked for unit tests)
|
|
46
|
+
|
|
47
|
+
## Tasks
|
|
48
|
+
|
|
49
|
+
- [Task 515: Add auth scheme config](../tasks/milestone-21-api-token-oauth-access/task-515-add-auth-scheme-config.md)
|
|
50
|
+
- [Task 516: Implement OAuth token exchange client](../tasks/milestone-21-api-token-oauth-access/task-516-implement-oauth-token-exchange.md)
|
|
51
|
+
- [Task 517: Implement local config resolution](../tasks/milestone-21-api-token-oauth-access/task-517-implement-local-config-resolution.md)
|
|
52
|
+
- [Task 518: Wire OAuth into server-factory](../tasks/milestone-21-api-token-oauth-access/task-518-wire-oauth-into-server-factory.md)
|
|
53
|
+
- [Task 519: Tests and documentation](../tasks/milestone-21-api-token-oauth-access/task-519-tests-and-documentation.md)
|
package/agent/progress.yaml
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
project:
|
|
4
4
|
name: remember-mcp
|
|
5
|
-
version: 3.
|
|
5
|
+
version: 3.19.0
|
|
6
6
|
started: 2026-02-11
|
|
7
7
|
status: in_progress
|
|
8
|
-
current_milestone:
|
|
8
|
+
current_milestone: M21
|
|
9
9
|
last_updated: 2026-03-07
|
|
10
10
|
|
|
11
11
|
milestones:
|
|
@@ -381,6 +381,26 @@ milestones:
|
|
|
381
381
|
See: agent/milestones/milestone-20-unified-internal-memory-tools.md
|
|
382
382
|
Design: agent/design/local.unified-internal-memory-tools.md
|
|
383
383
|
|
|
384
|
+
- id: M21
|
|
385
|
+
name: API Token & OAuth Access
|
|
386
|
+
status: not_started
|
|
387
|
+
progress: 0%
|
|
388
|
+
estimated_weeks: 1
|
|
389
|
+
tasks_completed: 5
|
|
390
|
+
tasks_total: 5
|
|
391
|
+
completed: 2026-03-14
|
|
392
|
+
status: completed
|
|
393
|
+
progress: 100%
|
|
394
|
+
notes: |
|
|
395
|
+
🎉 MILESTONE COMPLETE! Local CLI access via OAuth token exchange.
|
|
396
|
+
✅ Task 515: Auth scheme config (discriminated union, no Zod)
|
|
397
|
+
✅ Task 516: OAuth token exchange client (native fetch, JWT decode)
|
|
398
|
+
✅ Task 517: .remember/config resolution (project > global > env)
|
|
399
|
+
✅ Task 518: Wire OAuth into server.ts startup
|
|
400
|
+
✅ Task 519: 20 new tests (450 total), CHANGELOG, README, v3.19.0
|
|
401
|
+
See: agent/milestones/milestone-21-api-token-oauth-access.md
|
|
402
|
+
Design: agent/design/local.api-token-oauth-access.md
|
|
403
|
+
|
|
384
404
|
tasks:
|
|
385
405
|
milestone_1:
|
|
386
406
|
- id: task-1
|
|
@@ -2408,3 +2428,54 @@ task_20_completion:
|
|
|
2408
2428
|
✅ Ghost source isolation verified (scope tags filter per ghost type)
|
|
2409
2429
|
✅ Agent exclusion from default search verified (task-216)
|
|
2410
2430
|
✅ 436 total tests passing
|
|
2431
|
+
|
|
2432
|
+
milestone_21:
|
|
2433
|
+
- id: task-515
|
|
2434
|
+
name: Add Auth Scheme Config
|
|
2435
|
+
status: completed
|
|
2436
|
+
completed_date: 2026-03-14
|
|
2437
|
+
file: agent/tasks/milestone-21-api-token-oauth-access/task-515-add-auth-scheme-config.md
|
|
2438
|
+
estimated_hours: 2
|
|
2439
|
+
dependencies: []
|
|
2440
|
+
notes: |
|
|
2441
|
+
📋 Add REMEMBER_AUTH_SCHEME, REMEMBER_OAUTH_ENDPOINT, REMEMBER_API_TOKEN to config module
|
|
2442
|
+
|
|
2443
|
+
- id: task-516
|
|
2444
|
+
name: Implement OAuth Token Exchange Client
|
|
2445
|
+
status: completed
|
|
2446
|
+
completed_date: 2026-03-14
|
|
2447
|
+
file: agent/tasks/milestone-21-api-token-oauth-access/task-516-implement-oauth-token-exchange.md
|
|
2448
|
+
estimated_hours: 3
|
|
2449
|
+
dependencies: [task-515]
|
|
2450
|
+
notes: |
|
|
2451
|
+
📋 Exchange API token for JWT via OAuth endpoint, extract userId from JWT
|
|
2452
|
+
|
|
2453
|
+
- id: task-517
|
|
2454
|
+
name: Implement Local Config Resolution
|
|
2455
|
+
status: completed
|
|
2456
|
+
completed_date: 2026-03-14
|
|
2457
|
+
file: agent/tasks/milestone-21-api-token-oauth-access/task-517-implement-local-config-resolution.md
|
|
2458
|
+
estimated_hours: 2-3
|
|
2459
|
+
dependencies: [task-515]
|
|
2460
|
+
notes: |
|
|
2461
|
+
📋 .remember/config resolution: project > global > env vars
|
|
2462
|
+
|
|
2463
|
+
- id: task-518
|
|
2464
|
+
name: Wire OAuth into Server Factory
|
|
2465
|
+
status: completed
|
|
2466
|
+
completed_date: 2026-03-14
|
|
2467
|
+
file: agent/tasks/milestone-21-api-token-oauth-access/task-518-wire-oauth-into-server-factory.md
|
|
2468
|
+
estimated_hours: 2-3
|
|
2469
|
+
dependencies: [task-515, task-516, task-517]
|
|
2470
|
+
notes: |
|
|
2471
|
+
📋 Bootstrap OAuth flow at startup when REMEMBER_AUTH_SCHEME=oauth
|
|
2472
|
+
|
|
2473
|
+
- id: task-519
|
|
2474
|
+
name: Tests and Documentation
|
|
2475
|
+
status: completed
|
|
2476
|
+
completed_date: 2026-03-14
|
|
2477
|
+
file: agent/tasks/milestone-21-api-token-oauth-access/task-519-tests-and-documentation.md
|
|
2478
|
+
estimated_hours: 2-3
|
|
2479
|
+
dependencies: [task-515, task-516, task-517, task-518]
|
|
2480
|
+
notes: |
|
|
2481
|
+
📋 Unit tests for all auth modules, CHANGELOG, README, version bump
|
|
@@ -112,6 +112,11 @@ if [ -d "$TEMP_DIR/agent/index" ]; then
|
|
|
112
112
|
find "$TEMP_DIR/agent/index" -maxdepth 1 -name "*.template.yaml" -exec cp {} "$TARGET_DIR/agent/index/" \;
|
|
113
113
|
fi
|
|
114
114
|
|
|
115
|
+
# Copy bundled index files (e.g. acp.core.yaml)
|
|
116
|
+
if [ -d "$TEMP_DIR/agent/index" ]; then
|
|
117
|
+
find "$TEMP_DIR/agent/index" -maxdepth 1 -name "*.yaml" ! -name "*.template.yaml" ! -name "local.*" -exec cp {} "$TARGET_DIR/agent/index/" \;
|
|
118
|
+
fi
|
|
119
|
+
|
|
115
120
|
# Copy command template
|
|
116
121
|
cp "$TEMP_DIR/agent/commands/command.template.md" "$TARGET_DIR/agent/commands/"
|
|
117
122
|
|
|
@@ -182,28 +187,30 @@ if [ -d "$TEMP_DIR/agent/scripts" ]; then
|
|
|
182
187
|
yaml_parse "$TEMP_DIR/package.yaml"
|
|
183
188
|
fi
|
|
184
189
|
|
|
185
|
-
# Find all NON-experimental commands
|
|
190
|
+
# Find all NON-experimental commands and collect their scripts
|
|
186
191
|
PACKAGE_COMMANDS=()
|
|
187
|
-
while IFS= read -r cmd; do
|
|
188
|
-
if [ -n "$cmd" ] && [ "$cmd" != "null" ]; then
|
|
189
|
-
# Check if command is experimental
|
|
190
|
-
is_exp=$(yaml_query ".contents.commands[] | select(.name == \"$cmd\") | .experimental?" 2>/dev/null || echo "false")
|
|
191
|
-
if [ "$is_exp" != "true" ]; then
|
|
192
|
-
PACKAGE_COMMANDS+=("$cmd")
|
|
193
|
-
fi
|
|
194
|
-
fi
|
|
195
|
-
done < <(yaml_query ".contents.commands[].name" 2>/dev/null || echo "")
|
|
196
|
-
|
|
197
|
-
# Collect required scripts from non-experimental commands
|
|
198
192
|
REQUIRED_SCRIPTS=()
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
193
|
+
cmd_index=0
|
|
194
|
+
while true; do
|
|
195
|
+
cmd_name=$(yaml_query ".contents.commands[$cmd_index].name" 2>/dev/null || echo "")
|
|
196
|
+
if [ -z "$cmd_name" ] || [ "$cmd_name" = "null" ]; then
|
|
197
|
+
break
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
# Check if command is experimental
|
|
201
|
+
is_exp=$(yaml_query ".contents.commands[$cmd_index].experimental" 2>/dev/null || echo "false")
|
|
202
|
+
if [ "$is_exp" != "true" ]; then
|
|
203
|
+
PACKAGE_COMMANDS+=("$cmd_name")
|
|
204
|
+
|
|
205
|
+
# Collect scripts for this command
|
|
206
|
+
script_index=0
|
|
207
|
+
while true; do
|
|
208
|
+
script=$(yaml_query ".contents.commands[$cmd_index].scripts[$script_index]" 2>/dev/null || echo "")
|
|
209
|
+
if [ -z "$script" ] || [ "$script" = "null" ]; then
|
|
210
|
+
break
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
# Add to required scripts (with deduplication)
|
|
207
214
|
already_added=false
|
|
208
215
|
for existing in "${REQUIRED_SCRIPTS[@]}"; do
|
|
209
216
|
if [ "$existing" = "$script" ]; then
|
|
@@ -211,12 +218,16 @@ if [ -d "$TEMP_DIR/agent/scripts" ]; then
|
|
|
211
218
|
break
|
|
212
219
|
fi
|
|
213
220
|
done
|
|
214
|
-
|
|
221
|
+
|
|
215
222
|
if [ "$already_added" = false ]; then
|
|
216
223
|
REQUIRED_SCRIPTS+=("$script")
|
|
217
224
|
fi
|
|
218
|
-
|
|
219
|
-
|
|
225
|
+
|
|
226
|
+
script_index=$((script_index + 1))
|
|
227
|
+
done
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
cmd_index=$((cmd_index + 1))
|
|
220
231
|
done
|
|
221
232
|
|
|
222
233
|
# Install required scripts (excluding common.sh and yaml-parser.sh already copied)
|
|
@@ -224,17 +235,29 @@ if [ -d "$TEMP_DIR/agent/scripts" ]; then
|
|
|
224
235
|
if [ "$script" = "acp.common.sh" ] || [ "$script" = "acp.yaml-parser.sh" ]; then
|
|
225
236
|
continue # Already copied
|
|
226
237
|
fi
|
|
227
|
-
|
|
238
|
+
|
|
228
239
|
if [ -f "$TEMP_DIR/agent/scripts/$script" ]; then
|
|
229
|
-
# Check if script is experimental
|
|
230
|
-
is_exp
|
|
240
|
+
# Check if script is experimental by finding it in contents.scripts
|
|
241
|
+
is_exp="false"
|
|
242
|
+
script_check_index=0
|
|
243
|
+
while true; do
|
|
244
|
+
s_name=$(yaml_query ".contents.scripts[$script_check_index].name" 2>/dev/null || echo "")
|
|
245
|
+
if [ -z "$s_name" ] || [ "$s_name" = "null" ]; then
|
|
246
|
+
break
|
|
247
|
+
fi
|
|
248
|
+
if [ "$s_name" = "$script" ]; then
|
|
249
|
+
is_exp=$(yaml_query ".contents.scripts[$script_check_index].experimental" 2>/dev/null || echo "false")
|
|
250
|
+
break
|
|
251
|
+
fi
|
|
252
|
+
script_check_index=$((script_check_index + 1))
|
|
253
|
+
done
|
|
231
254
|
if [ "$is_exp" != "true" ]; then
|
|
232
255
|
cp "$TEMP_DIR/agent/scripts/$script" "$TARGET_DIR/agent/scripts/"
|
|
233
256
|
chmod +x "$TARGET_DIR/agent/scripts/$script"
|
|
234
257
|
fi
|
|
235
258
|
fi
|
|
236
259
|
done
|
|
237
|
-
|
|
260
|
+
|
|
238
261
|
echo "${GREEN}✓${NC} Installed ${#REQUIRED_SCRIPTS[@]} required script(s)"
|
|
239
262
|
else
|
|
240
263
|
# Direct install mode (no package.yaml) - copy all scripts
|