# Native credential storage

`pkg/keyring` stores the sudo password used by background Linux package-manager jobs. It uses [`github.com/zalando/go-keyring`](https://github.com/zalando/go-keyring) and keeps the existing MPV Manager package API (`Open`, `StorePassword`, `GetPassword`, `HasPassword`, and `DeletePassword`). Context-aware variants are available to internal callers.

## Platform backends

| Platform | Backend | Entry identity |
|---|---|---|
| Linux | freedesktop.org Secret Service, default/login collection | service `mpv-manager`, account `sudo-password` |
| macOS | Keychain | service `mpv-manager`, account `sudo-password` |
| Windows | Credential Manager | service `mpv-manager`, account `sudo-password` |

On Linux, Secret Service is the desktop-native interoperability protocol. GNOME Keyring implements it, as do current KDE installations through KDE's Secret Service/KWallet integration. MPV Manager talks to `org.freedesktop.secrets` on the user's session bus; it does not require a GNOME desktop and it does not select a separate KWallet-specific API.

There is intentionally no `pass` or application-managed file fallback. In particular, a machine ID is not an encryption key: any process that can read the old encrypted file could normally read the same machine ID. If the native store is absent, locked, or unavailable, password storage is reported as unavailable and package operations must use an existing sudo credential or obtain authorization interactively.

## When the keyring is accessed

Normal startup and package update discovery do not touch the keyring and never display an unconditional terminal prompt. A native-store lookup occurs only when:

- the Settings/password modal requests `/api/keyring/status`;
- the user stores or clears a password through `/api/keyring/auth`; or
- an installation/removal job is about to run a privileged command.

The status endpoint reuses one bounded lookup result for backend availability and `hasPassword`; it does not run repeated probes.

The web authentication endpoint first validates the supplied password with bounded `sudo -S -v`, then writes it to the native store. The password is passed on standard input, is never placed in command arguments, and is not logged.

## Timeouts and cancellation

All native credential operations have a three-second application deadline and accept caller cancellation through the context-aware methods:

```go
password, err := kr.GetPasswordContext(ctx)
err = kr.StorePasswordContext(ctx, password)
err = kr.DeletePasswordContext(ctx)
```

The underlying Zalando API and Linux D-Bus prompt flow are synchronous and do not accept a Go context. A timed-out native call can therefore remain blocked inside the platform library. MPV Manager limits this residual risk with a global one-operation gate: at most one such call may remain outstanding, and later callers time out while waiting for the gate rather than creating more stuck goroutines. This bounds application resource use, but cannot cancel a prompt or D-Bus method already owned by the desktop service.

## Linux setup

The credential service must run in the same graphical login session as MPV Manager.

- GNOME, Cinnamon, and many display-manager sessions normally start and unlock GNOME Keyring through PAM.
- Current KDE systems can provide Secret Service through KDE Wallet integration. Enable the wallet and Secret Service integration in System Settings if it is disabled.
- Minimal window-manager sessions can start GNOME Keyring's secrets component, for example `gnome-keyring-daemon --start --components=secrets`, as part of session initialization.
- Headless sessions without a user D-Bus Secret Service do not support stored sudo passwords. MPV Manager does not weaken storage by silently falling back to a local file.

`DetectStatus` verifies the service with a bounded read instead of guessing from installed binaries or process names. An unlocked service with no MPV Manager entry is considered available; a locked, missing, or unresponsive service is not.

## Migration from versions using 99designs/keyring

Older versions could store credentials in a dedicated Secret Service collection, a direct KWallet folder, `pass`, or an encrypted file below the MPV Manager configuration directory. Those locations are not automatically read by this implementation because doing so would preserve the insecure fallback paths and could trigger multiple unlock prompts.

After upgrading, enter the sudo password once in Settings so it is written to the operating system's default native store. Legacy entries are left untouched to avoid destructive migration. After confirming the new entry works, users may remove the old `mpv-manager` collection/item or legacy `keyring` directory with their desktop credential manager or filesystem tools.

## Security boundary

Native credential storage protects secrets at rest and integrates with desktop locking. It does not protect an unlocked user's secrets from every other process running as that same user. Retaining a reusable sudo password has inherent risk; users who do not want that tradeoff should clear it in Settings and rely on an already-authorized or interactive sudo session.
