Skip to content

Implement CredentialStore for Windows (DPAPI) and Linux (libsecret) #180

Description

@ChrisonSimtian

Context

CredentialStore (src/Fallout.Build/Utilities/CredentialStore.cs) is the OS-keychain backing for step 5 of the ADR-0002 secret resolution chain — but it's macOS-only today. SavePassword / TryGetPassword short-circuit on PlatformFamily.OSX; Windows and Linux users fall back to prompt-every-run.

This gets painful as the v12 plugin SDK lands — Windows plugin authors are the first cohort to routinely hit dotnet fallout :secrets, and prompt-fallback becomes a day-one stumbling block.

Why now (v11, not v12)

Flagged in ADR-0002 as a v12 entry, but pulling into v11 because:

  • v11 is where the plugin foundation lands. Better to have Windows credential storage working before the SDK ships.
  • Both impls are well-trodden — DPAPI on Windows is a one-file ProtectedData wrapper; libsecret on Linux is a P/Invoke or secret-tool shell wrap.
  • Unlike most ADR-0002 follow-ups, this has a concrete, scoped surface — no design ambiguity.

If load suggests it's too big for v11, move to v12 (the original ADR placement).

Scope

  • Windows: SavePassword / TryGetPassword for PlatformFamily.Windows via System.Security.Cryptography.ProtectedData (DPAPI, user scope). Storage: a small file under %LOCALAPPDATA%\Fallout\credentials\ or registry under HKCU\Software\Fallout\Credentials\ — pick one and document.
  • Linux: same surface via libsecret. P/Invoke libsecret-1, shell-out to secret-tool (simpler, needs a binary), or a freedesktop.org Secret Service D-Bus call. Pick the simplest that handles the GNOME Keyring / KWallet duopoly.
  • Tests: at minimum round-trip save+retrieve+delete on each platform behind [OSPlatformFact] (or whatever per-platform xUnit gating already exists).
  • Docs: docs/secrets.md updated to drop the "macOS-only" caveat.

Out of scope

  • Cross-platform key import/export. Each platform stores under its native primitive; values don't roam.
  • Headless Linux fallback. If neither GNOME Keyring nor KWallet is present (e.g. CI runners without a session), the prompt fallback stays as last resort.
  • keyring-style consolidation libraries — keep the surface minimal and stdlib-first.

Acceptance

  • CredentialStore.SavePassword("test", "value") round-trips on Windows (DPAPI) and Linux (Secret Service or libsecret).
  • CredentialStore.TryGetPassword("missing", out _) returns false without throwing on both.
  • macOS path unchanged.
  • ADR-0002's "Open Questions" entry struck through with a link back here, then to the implementing PR.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions