Context
Raised in #nixmac on 2026-05-29 by Cooper:
"I don't think we should store every API key as an individual keychain item… sometimes crypto wallets will Face ID you 3 times to send 1 tx, this is why. We should just store an encrypted blob somewhere with all the sensitive data encrypted by a single data key, and then that key should be in the keychain. The security is equivalent in either implementation. If you type 'safe storage' in keychain you can see this is what pretty much every app does."
ENG-438 (Done) migrated from plaintext settings.json to the OS keychain. However the current implementation stores each API key as a separate keychain item, causing multiple OS-level password/biometric prompts per session — especially painful in dev builds.
The correct pattern is:
- Generate a single symmetric data key and store it in keychain (one prompt, once)
- Encrypt all sensitive fields (API keys, tokens, etc.) into a single encrypted blob stored in the app's data directory
- On launch, unlock the blob with the single keychain key
Acceptance Criteria / Gherkin Specs
Scenario: App requests keychain access only once per session
Given the user launches nixmac for the first time after this change
When the app initialises and loads secrets
Then the OS keychain prompt appears exactly once
And all API keys are accessible without further keychain prompts in that session
Scenario: Encrypted blob stores all sensitive fields
Given the user has configured an Anthropic key, an OpenRouter key, and a vLLM API key
When the secrets are persisted
Then all three keys are stored in a single encrypted blob on disk
And the encryption key for that blob is the only item stored in the OS keychain
Scenario: Blob is regenerated when the data key rotates
Given a data key rotation is triggered (e.g., on first migration)
When the rotation completes
Then the old per-key keychain items are removed
And the new single-key + blob layout is in place
And the user can still access all their previously configured secrets
Scenario: Dev build does not prompt repeatedly
Given the app is running as an unsigned or dev build
When secrets are read multiple times in one session (e.g., Analyze button clicked repeatedly)
Then the OS prompt appears at most once per session
And subsequent reads use the in-memory decrypted secrets
Context
Raised in #nixmac on 2026-05-29 by Cooper:
ENG-438 (Done) migrated from plaintext
settings.jsonto the OS keychain. However the current implementation stores each API key as a separate keychain item, causing multiple OS-level password/biometric prompts per session — especially painful in dev builds.The correct pattern is:
Acceptance Criteria / Gherkin Specs