feat(vault): store API keys and insert text into agent and terminal panes - #840
Conversation
Implementation plan for #830/#831: encrypted per-key vault store with a touch-id once-per-run gate, renderer-owned session text delivery with bracket-paste-without-submit over any focused PTY, and named key references in prompt templates. First file on the branch per conventions. Refs #830, Refs #831
Per-key safeStorage blobs under STATE_DIR/key-vault with a non-secret metadata index, mirroring the dictation apiKeyStore failure discipline: a corrupt cipher blob costs one key, never the vault. Codec injection keeps the file discipline unit-testable outside the packaged app. Refs #831
Every secret-leaving path funnels through one once-per-run gate backed by an injected promptAuth (systemPreferences.promptTouchID in production), failing closed when the platform cannot prompt. Snapshot metadata never carries secrets; template references resolve by provider/key name. Refs #831
Thin ipcMain handlers delegating to VaultService, a flat preload surface, and production wiring of promptTouchID/clipboard in the composition root. The safeStorage codec lives in its own module so vaultStore stays unit-testable without the packaged electron module. Secrets only cross on gated reveal/copy/resolve-ref returns. Refs #831
One routing point for programmatic text insertion: composer draft edits for rendered agent panes, bracketed paste without Enter over sendInput for plain terminals and agent terminal views, with lazy-wake before PTY writes. Consumers: prompt templates and the api key vault. Refs #830
Terminal panes and agent terminal views become valid template targets; insertion bracket-pastes without submitting instead of silently doing nothing. Composer behavior is unchanged (insert modes, no submit), and composer-draft commands (save-as-template) stay agent-only. Refs #830
{{key:Provider/Key}} refs resolve against the gated vault before
variable fill; missing or locked refs abort insertion with a toast
naming every failure. Names over ids keep templates readable. Adds the
session-text-delivery wake caller to the lifecycle allowlist.
Refs #831
App-surface palette command opens the vault modal: provider/key CRUD, reveal/copy/insert actions, lock-now, and an explicit unavailable-keyring notice. Revealed plaintext stays in ephemeral component state only and is dropped on close. Refs #831
Resolve Claude/Codex review findings with cancellation-safe secret reads, serialized vault writes, damaged-index preservation, mounted-terminal paste ownership, and post-fill template resolution. Reuse the app workspace controller and clear plaintext caches on lock across windows. Document vault-only at-rest protection and downstream plaintext draft/transcript retention rather than claiming end-to-end prompt secrecy. Add regression coverage for races, failed writes, control bytes, source braces, and modal flows. Refs #830, #831
|
Final verification: both Agent Code MCP reviewers (one Claude, one Codex) gave APPROVE after the requested follow-up fixes. CI run 34180179423 is green: minimum-node-fixture-gate and quality-gate, including core/system/renderer tests, coverage and distributable verification. The local desktop/remote build also passed after rebasing onto the terminal-follow main. Local focused verification: 142 tests across 19 files, typecheck, test contract, keybindings and diff checks passed. The earlier full local Node 25 run remains recorded as incomplete; CI on the pinned toolchain is the authoritative passing suite. Manual real-password/Touch ID hardware checks remain a disclosed limitation. Proceeding under the explicit user instruction to review and then merge. |
Problem
Repeatedly copying low-stakes API keys from provider dashboards interrupts prompt authoring. Prompt templates also excluded raw terminals and could not serve unsupported agent harnesses.
Delivered Behavior
Review
One Claude and one Codex reviewer ran through the Agent Code MCP orchestration service. Both initially requested changes; all concrete blockers were fixed with regression tests, and both gave final APPROVE verdicts. Rebased onto current main; the terminal-follow integration conflict was only adjacent cleanup declarations, both retained. A final targeted run includes the newer terminal-follow tests.
Verification
Security Boundary and Limitations
Encryption protects stored vault values, not text deliberately inserted downstream. Composer drafts may autosave plaintext to workspace.json; terminal scrollback/provider transcripts and the system clipboard may retain it. The UI and design disclose this rather than claiming end-to-end prompt secrecy. Names and notes are plaintext metadata. No remote/MCP secret access or export/import is added.
macOS password/Touch ID dialogs on password-only and signed-release hardware still require manual verification. Live terminal smoke tests remain manual; unsupported multiline paste fails closed rather than guessing.
Fixes #830
Fixes #831