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

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions