Problem
Admin/CMS commands (me, media, knowledge, tag, org, …) authenticate with a bearer JWT only. Today users must copy that JWT by hand out of the admin UI's browser session into config set token. The JWT expires in ~7 days, so this repeats constantly. Painful and error-prone.
There is no auth command in the CLI — it's a UX gap, not a backend limitation.
Building blocks already exist (builder-auth)
The admin web never copies JWTs by hand — it calls the separate builder-auth service. Endpoints observed in admin-react/deploy/runtime-proxy.mjs:
| Endpoint |
Body |
Returns |
POST /v1/auth/login/email (or /login/username) |
{ email/username, password } |
{ data: { accessToken, refreshToken } } |
POST /v1/auth/refresh |
{ refreshToken } |
new { accessToken, refreshToken } (rotating) |
POST /v1/auth/logout |
Bearer accessToken |
revokes |
accessToken = the 7-day CMS JWT; refreshToken ~30-day.
- No MFA in this flow (email + password).
- Base URL is separate from the CMS API. Staging:
https://auth-worker.core-f0d.workers.dev (BUILDER_AUTH_BASE_URL, per admin-react/wrangler.jsonc).
Proposed scope (interactive users; no backend change)
agentbrain auth login — prompt email + password at the terminal (never store the password), POST /v1/auth/login/email, store accessToken + refreshToken in ~/.agentbrain/config.json (already chmod 600).
- Silent refresh: on a CMS
401, POST /v1/auth/refresh, persist the rotated pair, retry the request once. Falls back to a clear "run auth login" message when refresh fails.
agentbrain auth logout — POST /v1/auth/logout + clear stored tokens.
- New config key
authUrl (default the builder-auth base; overridable via AGENTBRAIN_AUTH_URL / --auth-url), plus refreshToken storage (secret, masked in config list).
auth status / whoami convenience (reuse GET /v1/me).
Out of scope (separate issue)
- Headless/CI auth. Refresh tokens rotate (unusable as a static CI secret) and
sk_ API keys can't reach CMS (verified: X-API-Key/Bearer sk_ → 401 on /cms/*). Needs a backend decision — builder-auth machine-token / api-key→accessToken exchange (preferred), or scoped API-key auth on admin routes. File as a backend question.
Acceptance criteria
auth login → subsequent me get / knowledge list succeed with no manual config set token.
- Expired access token auto-refreshes transparently on the next command.
- Password never written to disk; tokens stored 0600 and masked in
config list.
- Unit tests for login/refresh/logout + the 401→refresh→retry path.
Context
Surfaced during the live-backend smoke test (see PR #4). Auth-model evidence: agent-brain/backend-go CMS uses JWT session (mw.Auth); /mcp uses APIKeyWithOrg; builder-auth verifies api-keys at /v1/api-keys/verify but that path does not grant CMS access.
Open questions
- Does builder-auth support a non-rotating / long-lived token for automation? (drives the CI issue)
- Username vs email identifier mode — expose both
login/email and login/username?
Problem
Admin/CMS commands (
me,media,knowledge,tag,org, …) authenticate with a bearer JWT only. Today users must copy that JWT by hand out of the admin UI's browser session intoconfig set token. The JWT expires in ~7 days, so this repeats constantly. Painful and error-prone.There is no auth command in the CLI — it's a UX gap, not a backend limitation.
Building blocks already exist (builder-auth)
The admin web never copies JWTs by hand — it calls the separate builder-auth service. Endpoints observed in
admin-react/deploy/runtime-proxy.mjs:POST /v1/auth/login/email(or/login/username){ email/username, password }{ data: { accessToken, refreshToken } }POST /v1/auth/refresh{ refreshToken }{ accessToken, refreshToken }(rotating)POST /v1/auth/logoutaccessToken= the 7-day CMS JWT;refreshToken~30-day.https://auth-worker.core-f0d.workers.dev(BUILDER_AUTH_BASE_URL, peradmin-react/wrangler.jsonc).Proposed scope (interactive users; no backend change)
agentbrain auth login— prompt email + password at the terminal (never store the password),POST /v1/auth/login/email, storeaccessToken+refreshTokenin~/.agentbrain/config.json(already chmod 600).401,POST /v1/auth/refresh, persist the rotated pair, retry the request once. Falls back to a clear "runauth login" message when refresh fails.agentbrain auth logout—POST /v1/auth/logout+ clear stored tokens.authUrl(default the builder-auth base; overridable viaAGENTBRAIN_AUTH_URL/--auth-url), plusrefreshTokenstorage (secret, masked inconfig list).auth status/whoamiconvenience (reuseGET /v1/me).Out of scope (separate issue)
sk_API keys can't reach CMS (verified:X-API-Key/Bearer sk_→ 401 on/cms/*). Needs a backend decision — builder-auth machine-token / api-key→accessToken exchange (preferred), or scoped API-key auth on admin routes. File as a backend question.Acceptance criteria
auth login→ subsequentme get/knowledge listsucceed with no manualconfig set token.config list.Context
Surfaced during the live-backend smoke test (see PR #4). Auth-model evidence:
agent-brain/backend-goCMS uses JWT session (mw.Auth);/mcpusesAPIKeyWithOrg; builder-auth verifies api-keys at/v1/api-keys/verifybut that path does not grant CMS access.Open questions
login/emailandlogin/username?