7.7 KiB
Background
Credential configuration still relies on process environment variables in important paths:
- provider API keys use
AuthRef::ApiKey { env, file }and provider-defaultINSOMNIA_API_KEY_*names; - WebSearch currently uses
web.search.api_key_env; - normal runtime intentionally does not load
.envfiles.
This should not be solved by implicit .env loading. .env files are easy to leak into projects, do not solve profile-specific credential selection cleanly, and still expose secrets through process environments.
The desired replacement is a local key-value secret store plus explicit references from manifest/profile/tool configuration.
The security target is intentionally modest. This is not a high-assurance password manager. The goal is to avoid casual plaintext exposure and generic environment-variable scraping, not to defend against a local attacker with the user's account or process memory access.
Intent
Implement a provider-independent local key-value secret store and use it as the normal credential path for provider and WebSearch credentials.
The logical store model is just:
{
"anthropic/default" = "sk-..."
"web/brave/default" = "..."
}
The store must not know that a key is Anthropic, Brave, OpenAI, or any other provider-specific kind. Provider/model/tool configuration chooses which key to reference.
Requirements
Store model
- Add a local secret/key store that maps a validated string id to a secret string value.
- Keep the user-visible logical schema provider-independent:
id -> value. - Do not add provider-specific slots, credential kinds, or required metadata to the store schema.
- Technical envelope fields needed for versioning/nonce/ciphertext/checksum are allowed, but they must not become user-facing semantic metadata.
- Store data outside the repository, under the user data directory, e.g.
<data_dir>/secrets/store.jsonor equivalent. - Use atomic writes.
- Validate ids:
- reject empty ids;
- reject path traversal / absolute-path-like ids;
- reject control characters;
- bound length;
- allow a conservative useful set such as ASCII alnum plus
._/-.
Obfuscation / encryption stance
- Apply lightweight encryption or obfuscation at rest so the file is not a casual plaintext key dump.
- Do not claim strong local security guarantees.
- Do not introduce OS keychain dependency or interactive passphrase UX in this ticket.
- Do not store plaintext values in logs, work items, session history, diagnostics, or normal command output.
- Decryption/decoding failures must fail closed and name only the key id, not the value.
insomnia keys TUI management
- Add
insomnia keysas an interactive TUI key manager. - The product CLI owner (
insomniacrate) routes the subcommand. - Use the TUI implementation crate for the terminal screen if practical.
- Minimum UI features:
- list key ids;
- add/set a key;
- delete a key with confirmation;
- quit.
- Do not display plaintext values in the list or normal screen output.
- During add/set, mask the value input or otherwise avoid echoing plaintext.
- Scriptable commands such as
insomnia keys set <id> --stdinmay be added if convenient, but the required user surface is the TUI manager.
Config references / consumers
- Use explicit secret references from configuration.
- Existing
AuthRef::SecretRef { ref_ }in manifest model should resolve through the new store for provider API keys. - WebSearch must gain an explicit secret reference path so Brave search can be configured without
BRAVE_SEARCH_API_KEY/api_key_env.- Prefer a generic auth/secret-ref shape if it stays small.
- A focused
api_key_secret = "web/brave/default"field is acceptable if it avoids a broad schema redesign.
- Secret refs are resolved at the consumer/runtime boundary only; resolved config/debug output must not contain plaintext.
- The store must not implicitly choose default keys based on provider name. No ambient lookup like "anthropic automatically reads anthropic/default" unless the profile/config explicitly references it.
Env credential removal
- Do not load
.envfiles. - Do not add new credential environment variables.
- Do not keep migration/backward-compatibility behavior for credential env config in the normal profile path.
- Remove credential env configuration from normal provider/WebSearch use as part of this ticket.
- Docs and diagnostics should point users to
insomnia keys+ secret refs as the credential path.
Codex OAuth relationship
- Codex OAuth is not part of this key-value secret store in this ticket.
- Current Codex OAuth intentionally interoperates with Codex CLI's
auth.jsonfile and refresh behavior; that file contains a structured token bundle, not a single provider API key string. - Do not store or refresh Codex OAuth token bundles through the key-value store as part of this ticket.
- Do not change
CODEX_HOME/$HOME/.codexlookup behavior in this ticket. - A future Insomnia-owned Codex login/token store could be designed separately if needed, but it should be a dedicated OAuth token-store design, not an implicit use of the simple key-value API-key store.
Phases within this ticket
- Core store
- key-value store API;
- id validation;
- lightweight encrypted/obfuscated file format;
- atomic load/save;
- focused tests.
insomnia keysTUI manager- list/add/delete;
- masked input;
- no plaintext display.
- Provider integration
- implement provider
AuthRef::SecretRefresolution through the store; - keep plaintext in memory only;
- fail closed on missing/invalid/decode failures.
- implement provider
- WebSearch integration
- add a secret-ref credential path;
- make Brave search usable without env credentials.
- Docs and env removal
- update
docs/environment.mdand manifest/profile docs; - document the modest security target honestly;
- point users to
insomnia keysand secret refs as the credential path; - remove credential env configuration from normal provider/WebSearch docs and code paths.
- update
Non-goals
- A high-assurance password manager.
- OS keychain integration.
- Passphrase prompt UX.
- Provider-specific secret-store schema.
- Automatic provider-name-to-secret-id lookup.
- Loading
.envfiles. - Changing Codex OAuth behavior. Codex OAuth remains an external structured token-source integration in this ticket.
- Reworking model/provider catalog ownership.
Acceptance criteria
- A user can run
insomnia keysand manage key ids interactively. - The store persists key-value entries under the user data directory without plaintext values in the on-disk file.
- Store id validation rejects unsafe ids.
- Provider
AuthRef::SecretRefresolves through the store and does not print/serialize plaintext. - WebSearch can use a configured secret ref without exporting an environment variable.
- Missing key, invalid id, unreadable store, and decode/decrypt failure produce clear fail-closed errors naming only the key id.
docs/environment.mdno longer presents credential env vars as the normal path, removes normal provider/WebSearch credential env configuration, and documents the limited protection goal.- Focused tests cover store round-trip, id validation, decode failure, provider secret-ref resolution, WebSearch secret-ref resolution, and no-plaintext debug/serialization paths where applicable.
cargo fmt --check, relevant crate tests/checks,./tickets.sh doctor, andgit diff --checkpass.