254 lines
7.4 KiB
Markdown
254 lines
7.4 KiB
Markdown
# Credential System v2 (API + OAuth/token) — Implementation Checklist
|
|
|
|
**Date:** 2026-02-15
|
|
|
|
**Parent roadmap:** `docs/plans/2026-02-15-openclaw-gap-roadmap.md`
|
|
|
|
**Goal:** Close the gap item "OAuth subscription auth" by supporting **both** API-key credentials and OAuth/token-based credentials (provider-specific) with consistent UX, per-tier control, and deterministic resolution.
|
|
|
|
## Scope Summary
|
|
|
|
- Add `auth_mode` **per tier** (default/fast/complex/local and any `local_providers` entries).
|
|
- Keep backward compatibility with existing `use_oauth` behavior.
|
|
- Add stored credential support where it currently doesn't exist:
|
|
- OpenAI: stored API key (OAuth already exists)
|
|
- Anthropic: stored auth token (API key already exists)
|
|
- Improve doctor output to surface which auth sources are present (without revealing secrets).
|
|
|
|
Non-goals (explicitly out of scope for this checklist):
|
|
|
|
- Inventing an Anthropic OAuth device flow.
|
|
- Building new provider integrations (Vercel/MiniMax/etc.).
|
|
|
|
## Current Baseline (important constraints)
|
|
|
|
- OpenAI OAuth uses the ChatGPT/Codex backend endpoint (SSE) and currently **does not support tools** on that path.
|
|
- Source: `src/models/openai.ts`
|
|
- Anthropic supports `apiKey` and `authToken` in `AnthropicClientConfig`.
|
|
- Source: `src/models/anthropic.ts`
|
|
- Stored credentials live at `~/.config/flynn/auth.json`.
|
|
- Source: `src/auth/openai.ts`, `src/auth/anthropic.ts`
|
|
|
|
## Design Decisions
|
|
|
|
### 1) New config field: `auth_mode`
|
|
|
|
Add `auth_mode` to the per-tier model config:
|
|
|
|
- `auto` (default)
|
|
- `api_key`
|
|
- `oauth`
|
|
|
|
`oauth` is interpreted as "OAuth/token mode" (provider-specific). For Anthropic, that means `auth_token`.
|
|
|
|
### 2) Backward compatibility: `use_oauth`
|
|
|
|
Preserve `use_oauth` as a compatibility alias.
|
|
|
|
Recommended rule:
|
|
|
|
- If `auth_mode` is set: it wins.
|
|
- Else if `use_oauth: true`: treat as `auth_mode: oauth`.
|
|
|
|
### 3) Credential resolution order
|
|
|
|
For each provider, resolve the required credential type by trying:
|
|
|
|
1) config (`api_key` / `auth_token`)
|
|
2) env var
|
|
3) auth store (`~/.config/flynn/auth.json`)
|
|
|
|
`auth_mode` controls which credential type is required.
|
|
|
|
## PR Breakdown (atomic, test-backed)
|
|
|
|
### PR 1 — Schema + docs: per-tier `auth_mode`
|
|
|
|
Checklist:
|
|
|
|
- [ ] Add `auth_mode` to `modelConfigBaseSchema` in `src/config/schema.ts`.
|
|
- [ ] Update `src/config/schema.test.ts` to cover defaults + validation.
|
|
- [ ] Update `README.md` config examples (brief mention).
|
|
- [ ] Update `config/default.yaml` comment/help text (brief mention).
|
|
|
|
Acceptance:
|
|
|
|
- Config parses with no changes (defaults preserved).
|
|
- Setting `auth_mode: oauth` or `auth_mode: api_key` validates.
|
|
|
|
Tests:
|
|
|
|
- `pnpm test:run src/config/schema.test.ts`
|
|
|
|
---
|
|
|
|
### PR 2 — OpenAI auth store: add API-key storage
|
|
|
|
Goal: allow OpenAI to run without `api_key` in YAML.
|
|
|
|
Checklist:
|
|
|
|
- [ ] Extend `src/auth/openai.ts` `AuthStore` shape to allow `openai.api_key` alongside existing OAuth info.
|
|
- [ ] Add functions:
|
|
- [ ] `loadStoredOpenAIApiKey()`
|
|
- [ ] `storeOpenAIApiKey(key)`
|
|
- [ ] `clearOpenAIApiKey()`
|
|
- [ ] `getOpenAIApiKey()` (env override + store)
|
|
- [ ] Keep existing OAuth store code working unchanged.
|
|
- [ ] Add/extend tests for new store functions.
|
|
|
|
Files:
|
|
|
|
- `src/auth/openai.ts`
|
|
- `src/auth/openai.test.ts` (or add if missing)
|
|
|
|
Acceptance:
|
|
|
|
- Stored OpenAI API key is written to `~/.config/flynn/auth.json` with `0600` permissions.
|
|
- OAuth entry remains backward compatible.
|
|
|
|
Tests:
|
|
|
|
- `pnpm test:run src/auth/openai.test.ts`
|
|
|
|
---
|
|
|
|
### PR 3 — Anthropic auth store: add auth-token storage
|
|
|
|
Goal: allow `auth_token` to be stored and selected with `auth_mode: oauth`.
|
|
|
|
Checklist:
|
|
|
|
- [ ] Extend `src/auth/anthropic.ts` auth store shape to include `auth_token`.
|
|
- [ ] Add functions:
|
|
- [ ] `loadStoredAnthropicAuthToken()`
|
|
- [ ] `storeAnthropicAuthToken(token)`
|
|
- [ ] `clearAnthropicAuthToken()`
|
|
- [ ] `getAnthropicAuthToken()`
|
|
- [ ] Extend `src/auth/anthropic.test.ts`.
|
|
|
|
Files:
|
|
|
|
- `src/auth/anthropic.ts`
|
|
- `src/auth/anthropic.test.ts`
|
|
|
|
Acceptance:
|
|
|
|
- `auth_token` can be stored and resolved without being present in YAML.
|
|
|
|
Tests:
|
|
|
|
- `pnpm test:run src/auth/anthropic.test.ts`
|
|
|
|
---
|
|
|
|
### PR 4 — CLI commands for managing new stored credentials
|
|
|
|
Checklist:
|
|
|
|
- [ ] Add `flynn openai-key` command (store API key in auth.json).
|
|
- [ ] Extend `flynn anthropic-auth` to support storing either API key or auth token:
|
|
- [ ] recommended: `flynn anthropic-auth --token` OR `flynn anthropic-token`
|
|
- [ ] Update `src/cli/index.ts` registration.
|
|
|
|
Files:
|
|
|
|
- `src/cli/openai-key.ts` (new)
|
|
- `src/cli/anthropic-auth.ts` (modify)
|
|
- `src/cli/index.ts`
|
|
|
|
Acceptance:
|
|
|
|
- CLI can store credentials without printing them.
|
|
- Re-running commands detects existing stored credentials and exits cleanly.
|
|
|
|
Tests:
|
|
|
|
- Add targeted unit tests if the CLI layer has existing patterns; otherwise validate via integration tests where feasible.
|
|
|
|
---
|
|
|
|
### PR 5 — TUI `/login` UX: OpenAI choice (OAuth vs API key) + Anthropic token
|
|
|
|
Checklist:
|
|
|
|
- [ ] Update `/login openai` in `src/frontends/tui/minimal.ts`:
|
|
- [ ] Present a simple prompt: "1) OAuth device flow 2) Paste API key"
|
|
- [ ] Store selected credential via auth store
|
|
- [ ] Add `/login anthropic` in `src/frontends/tui/minimal.ts`:
|
|
- [ ] "1) Paste API key 2) Paste auth token"
|
|
- [ ] Keep existing `/login github` and `/login zai` behavior intact.
|
|
|
|
Files:
|
|
|
|
- `src/frontends/tui/minimal.ts`
|
|
- `src/frontends/tui/commands.ts` (if command parsing needs to accept new provider)
|
|
|
|
Acceptance:
|
|
|
|
- TUI can store OpenAI API key or OAuth token.
|
|
- TUI can store Anthropic API key or auth token.
|
|
|
|
Tests:
|
|
|
|
- Add or extend minimal TUI tests as needed (existing suite patterns exist for model switching).
|
|
|
|
---
|
|
|
|
### PR 6 — Model factory: enforce `auth_mode` per tier
|
|
|
|
This is the core runtime change.
|
|
|
|
Checklist:
|
|
|
|
- [ ] Update `src/daemon/models.ts`:
|
|
- [ ] Read `cfg.auth_mode` (or inferred from `use_oauth`) per tier.
|
|
- [ ] For OpenAI:
|
|
- [ ] `auth_mode=oauth`: configure `OpenAIClient({ useOAuth: true })` and verify OAuth tokens exist.
|
|
- [ ] `auth_mode=api_key`: configure `OpenAIClient({ apiKey: resolvedKey })`.
|
|
- [ ] For Anthropic:
|
|
- [ ] `auth_mode=oauth`: require auth token (config/env/store).
|
|
- [ ] `auth_mode=api_key`: require API key (config/env/store).
|
|
- [ ] For other providers:
|
|
- [ ] define behavior explicitly (likely `api_key` only unless provider already supports token-style auth).
|
|
- [ ] Ensure error messages name the expected auth type and remediation.
|
|
|
|
Files:
|
|
|
|
- `src/daemon/models.ts`
|
|
- potentially `src/models/openai.ts` (if you decide to unify API key vs OAuth selection naming)
|
|
|
|
Tests:
|
|
|
|
- `src/daemon/clientFactory.test.ts`
|
|
- [ ] auth_mode precedence over use_oauth
|
|
- [ ] auto -> api key path
|
|
- [ ] oauth -> token path
|
|
- [ ] correct failures when missing
|
|
|
|
Acceptance:
|
|
|
|
- Selecting `auth_mode` changes runtime behavior deterministically.
|
|
|
|
---
|
|
|
|
### PR 7 — Doctor: report auth source availability
|
|
|
|
Checklist:
|
|
|
|
- [ ] Extend `checkModelConnectivity` in `src/cli/doctor.ts` to reflect `auth_mode`:
|
|
- [ ] If `auth_mode=api_key`, warn/fail when API key is absent from config/env/store.
|
|
- [ ] If `auth_mode=oauth`, warn/fail when OAuth/token is absent.
|
|
- [ ] If `auth_mode=auto`, keep current behavior but improve messaging.
|
|
- [ ] Add tests in `src/cli/doctor.test.ts`.
|
|
|
|
Acceptance:
|
|
|
|
- Doctor output tells user what to do next (command name + env var) without exposing secrets.
|
|
|
|
## Final Integration Checks
|
|
|
|
- [ ] `pnpm typecheck`
|
|
- [ ] `pnpm test:run`
|
|
- [ ] Update `docs/plans/state.json` entry for this checklist once implemented (status, summary, test status).
|