Skip to content

Phase 2.5: extract SecretStore protocol seam - #44

Merged
initcore0 merged 1 commit into
mainfrom
feat/core-secretstore
Jun 23, 2026
Merged

Phase 2.5: extract SecretStore protocol seam#44
initcore0 merged 1 commit into
mainfrom
feat/core-secretstore

Conversation

@initcore0

Copy link
Copy Markdown
Owner

First step of the platform-agnostic core extraction (WINDOWS_PORT.md). AppState referenced the concrete KeychainStore at three sites with no seam — this introduces a SecretStore protocol and dependency-injects it.

Changes

  • SecretStore protocol (read/save; empty-string save = delete) + InMemorySecretStore — both Foundation-only, added to the OpenWhispCore SwiftPM target so the contract is unit-tested.
  • KeychainStore: enum of statics → final class conforming to SecretStore. The Apple-only Security (SecItem*) calls stay isolated here.
  • AppState gains let secretStore: SecretStore, injected via init(secretStore:) = KeychainStore(). The API-key didSet and the legacy-key migration now route through it. No behavior change on macOS — the default is still the Keychain.
  • Tests: +6 SecretStoreTests (round-trip, overwrite, empty-delete, key independence, seeding). 92 → 98.
  • ROADMAP: SecretStore marked done under Phase 2.5.

A Windows/Linux port now supplies its own backend (Credential Manager / DPAPI / libsecret) without touching call sites.

swift test 98/98 · ./build.sh clean.

🤖 Generated with Claude Code

First step of the platform-agnostic core extraction (per WINDOWS_PORT.md). The
secret-handling logic in AppState referenced the concrete KeychainStore at three
sites with no seam; this introduces a SecretStore protocol and injects it.

- SecretStore protocol (read/save; empty-string save = delete) + InMemorySecretStore,
  both Foundation-only and added to the OpenWhispCore SwiftPM target so the contract
  is exercised by `swift test`.
- KeychainStore: enum of statics -> final class conforming to SecretStore. The
  Apple-only Security (SecItem*) calls stay isolated here; AppState no longer names
  it except as the default injected value.
- AppState gains `let secretStore: SecretStore`, injected via
  `init(secretStore:) = KeychainStore()`. The API-key didSet and the one-time
  legacy-key migration now go through it. Behavior unchanged on macOS.
- Tests: 6 SecretStoreTests covering round-trip, overwrite, empty-delete, key
  independence, seeding. 92 -> 98 tests.
- ROADMAP: mark SecretStore done under Phase 2.5.

A Windows/Linux port now supplies its own SecretStore (Credential Manager /
DPAPI / libsecret) without touching call sites.

swift test 98/98; ./build.sh clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant