-
feat(cli): migrate API key storage from plaintext to OS keyring (#3202)
发布于
2026-04-14 07:13:41 +00:00 Summary
- Wire
@composio/cli-keyringintoComposioUserContextso the API key
lives in the macOS Keychain / Linux Secret Service instead of plaintext
~/.composio/user_data.json - Read precedence: env var (
COMPOSIO_USER_API_KEY) > OS keyring >
legacy plaintext - One-shot migration: on first run after upgrade, if the keyring is
empty butuser_data.jsonhas anapi_key, copy it to the keyring and
strip it from JSON - In-process memoization: keyring read happens once at layer build
(~1.4ms), held in closure for the rest of the process dangerouslySaveApiKeyInUserConfig: opt-in escape hatch in
~/.composio/config.jsonfor headless Linux / containers / CI where the
keyring is unavailablectx.datais now a getter: fixes a pre-existing bug where
mutations vialogin()/update()were invisible through the stale
snapshot- In-memory mock keyring for test isolation — tests never touch the
real keychain
Files changed
file what ts/packages/cli/package.jsonAdd @composio/cli-keyringworkspacedep ts/packages/cli/src/models/cli-user-config.tsdangerously_save_api_key_in_user_configschema fieldts/packages/cli/src/services/cli-user-config.tsSurface new field on CliUserConfigResolvedts/packages/cli/src/services/user-context.tsKeyring-first read/write/migrate/fallback chain ts/packages/cli/src/cli-main.tsWire KeyringLiveinto layercomposition ts/packages/cli-keyring/src/stores/macos-security-ffi.tsFix: writes via subprocess -A, cleanup dead ACL builder code, add base64encoding ts/packages/cli/test/__utils__/services/test-layer.tsIn-memory mock keyring for test isolation ts/packages/cli/test/src/commands/login.cmd.test.tsUpdate assertion: api_key no longer in JSON after login Verified end-to-end
$ ./dist/composio version INFO: Composio API key migrated from user_data.json to the OS keyring 0.2.22 $ cat ~/.composio/user_data.json # no api_key {"base_url":"...","web_url":"...","org_id":"...","test_user_id":"..."} $ # Rebuild binary (new hash) → read from keychain → no dialog $ ./dist/composio whoami {"email":"rahul@composio.dev",...}Test plan
- 676 CLI tests passing (676 passed, 1 skipped)
- Login test updated: asserts
api_keyabsent from JSON + present
viactx.data.apiKey - In-memory mock keyring — no real keychain access in tests
- Binary build + FFI roundtrip verified
- Rebuild with new hash → no keychain dialog (allow-any ACL via
-A)
🤖 Generated with Claude Code
Stack: 2/2 — base PR:
cli/keyring-package(#3201)Co-authored-by: Claude Opus 4.6 (1M context) noreply@anthropic.com
下载附件
- Wire