Repository navigation
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Summary
Retire Electron safeStorage as an authority for OAuth / subscription tokens so desktop, TUI, headless, and other pure-Node surfaces share one credential path.
This is not part of the Electron major upgrade (#1118 / current desktop Electron 43 work). It is a follow-up to the credential-store RFC and the remaining dual-write seam.
Why
safeStorageis Electron-only. TUI (maka/maka-agent), headless / Harbor, and any pure-Node caller cannot use it as a store.- On macOS dev launches, keychain prompts show Electron asking for Maka Safe Storage whenever the Electron binary path or identity changes (e.g. major upgrades, worktree
node_modules). That is expected Keychain ACL behavior, but it is a product smell if the desktop copy is still treated as primary. SECURITY.mdalready treats the OS user account +0700/0600filesystem controls as the load-bearing credential-at-rest boundary. At-rest encryption viasafeStorageis a secondary desktop copy, not a cross-surface authority.
Current state (as of 2026-07)
| Surface | What exists today |
|---|---|
| Provider API keys | Pure-Node CredentialStore → workspace credentials.json (post-#32). Desktop keeps a one-time migration importer off legacy safeStorage encoding. |
| Claude / Codex OAuth | Dual-write: desktop still persists a safeStorage-encrypted token file under userData; also best-effort exports plaintext oauth_token into credentials.json for the pure-Node runtime. |
| Cursor / Antigravity | Preview integrations; still largely desktop + safeStorage token files. |
| TUI / headless | Consume credentials.json / CredentialStore. They do not decrypt desktop safeStorage blobs. |
So: using an already-exported OAuth token in TUI/headless can work; the login / refresh / desktop authority path still depends on Electron safeStorage for the desktop-side copy.
Goal
- Single source of truth for OAuth secrets:
@maka/storageCredentialStore(file store by default; optional futurecredential_providerfor keychain / 1Password / Vault). - Desktop OAuth services (Claude, Codex, and any remaining preview providers that become real) read/write that store for the runtime-visible secret; stop treating
safeStorage-encrypted userData files as authority. safeStoragerole → migration-only (or delete after a deprecation window): decrypt legacy desktop token files once intoCredentialStore, then stop writing them.- Login UX may still use Electron (system browser / loopback) on desktop; TUI/headless need documented paths: reuse exported tokens, device-code / CLI login where applicable, or env /
credential_provider— without requiring a running Electron app to decrypt secrets. - Update
SECURITY.md/ README credential sections so they describe one model, not dual-write.
Non-goals
- Changing the Electron major version (tracked separately).
- Making OS keychain the default store (rejected as default in RFC: unify credential storage for desktop + headless (pure-Node CredentialStore) #32; OK as optional provider later).
- Weakening IPC secret masking or putting cleartext secrets into the renderer.
Acceptance sketch
- No production OAuth path requires
safeStorage.isEncryptionAvailable()to save or load the runtime-usable token. - After a desktop OAuth login (or migration), TUI and headless can authenticate with the same account from
credentials.json/CredentialStorewithout touching Electron. - Legacy
safeStoragetoken files either migrate automatically on desktop start or are documented as dead with a one-shot importer. - Docs (
SECURITY.md, product README credential bullets) match the single-store model. - Contract tests cover: dual-write removed or reduced to explicit migrate-once; fail-closed behavior when the pure-Node store cannot write.
References
- RFC: unify credential storage for desktop + headless (pure-Node CredentialStore) #32 — RFC: unify credential storage (CredentialStore); safeStorage as one-time importer
- Merged implementation path for the file store / API-key migration (see history on RFC: unify credential storage for desktop + headless (pure-Node CredentialStore) #32)
SECURITY.md§ credential-at-rest boundaries (Claude/Codex dual-write note)- Desktop OAuth services under
apps/desktop/src/main/oauth/*andshared-credential-bridge.ts - Related product pain: macOS Keychain prompt for "Maka Safe Storage" when launching unsigned Electron during local dev / Electron upgrades
Proposal for sequencing
Keep this issue independent of Electron upgrades. Prefer a small PR series:
- Docs + inventory of remaining
safeStoragecall sites and what each secret is for - Make
CredentialStorethe write path for Claude/Codex runtime tokens; keep encrypted desktop file only if still needed for a short migrate window - Desktop startup: import-once from legacy encrypted files, then stop writing them
- Remove
safeStoragefrom OAuth hot paths; leave or delete the API-key migration helper as appropriate - Cursor/Antigravity when they leave preview: never introduce a new safeStorage authority
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
fix(desktop): seed visual-smoke fixtures before the window opens
feat(desktop): retire Electron safeStorage as OAuth credential author…