filecoin-project / filecoin-project/filecoin-pin
feat(auth): OS keychain storage via @napi-rs/keyring
- Dominant language
- TypeScript
- Stars
- 26
- Forks
- 21
- Avg merge
- 5d 18h
- Merged PRs (30d)
- 27
Description
Part of #457.
### Description
Store the keystore passphrase (not the raw key) in the OS-native vault: macOS Keychain, Windows Credential Manager, libsecret on Linux, via [`@napi-rs/keyring`](https://github.com/Brooooooklyn/keyring-node) (maintained napi-rs binding to the Rust `keyring` crate). After a one-time `wallet import`, the CLI unlocks the keystore without prompting, with access control enforced by the OS.
Depends on the keystore v3 child of #457; this tier sits on top of it, not beside it. Two wins: convenience for CLI users (no passphrase prompt, no passphrase env var), and headless unlock for local MCP servers spawned by AI assistants, which have no terminal to prompt on; for that shape keychain is the difference between working and not. It is not a security boundary against same-user local compromise, since an attacker with keychain access typically has the keystore file too.
### Scope
- `--keychain` opt-in flag on `keystore create|import` to save the passphrase; automatic lookup on use.
- Generated passphrases, so the user never knows or keeps a password: `keystore create --keychain` generates a random passphrase, stores it only in the OS vault, and never displays it. This requires a recovery path (`keystore export` re-encrypts to a user-supplied passphrase) and a plain warning that losing the keychain entry without an export makes the keystore unrecoverable.
- Session keys in the vault for agent callers: an agent that invokes filecoin-pin should be able to use a stored session key without the key ever entering the agent's environment, prompt context, or logs; filecoin-pin reads it from the vault itself. Document the honest boundary: OS keychains are same-user readable, so this prevents accidental exposure (transcripts, env dumps, error reports), not exfiltration by a compromised agent process. Containment for that case stays with the upload-only permission profile, expiry, and revocation (#682).
- Credential naming convention: service `filecoin-pin`, account `keystore:`, so multiple keystores and multiple OS users coexist.
- Skip keychain lookup entirely when `CI` is set: macOS runners can raise an invisible blocking keychain prompt that hangs the job instead of failing fast.
- Headless unlock is scoped to session-key material only. A headless process must never silently decrypt the owner keystore: an assistant-spawned MCP tool that can unlock the owner key without a TTY hands wallet-draining authority to anything that prompt-injects the agent. Owner-key decryption always requires an interactive confirmation; agents get session keys.
- Graceful fallback to the passphrase prompt when the platform vault is unavailable (headless Linux without libsecret, containers).
- Keep it out of browser exports; Node CLI only.
- Before adopting, review `@napi-rs/keyring`'s maintenance health (bus factor, release cadence, security contact); it is another native dependency near key material, and #457 documents why an unmaintained one is disqualifying.
Contributor guide
Assessment
This issue has not been assessed yet.