2.7 KiB
Storage
How sherlock persists secrets and runtime state.
Decisions
| Topic | Decision |
|---|---|
| Token storage | OS keyring via github.com/zalando/go-keyring. No on-disk credential files, no age blobs, no plaintext. |
| Pre-flight | Both sherlock and sherlock-broker call keyring.Probe() at startup. A missing/locked keyring fails fast with a platform-appropriate hint and exit code 3. |
| Service name | sherlock for real tokens; sherlock-preflight for the probe sentinel. |
| Account key | The Authentik sub claim once logged in, default before. |
| Runtime files | $XDG_RUNTIME_DIR/sherlock.sock, sherlock.pid, sherlock.log, sherlock/<agent>.mcp.json. All 0600 (files) / 0700 (dirs). |
| Config files | $XDG_CONFIG_HOME/sherlock/services.d/*.toml (operator-registered services, Phase 2+). Agent integrations are compiled in — see agents.md. |
TokenSet
What we store under the sherlock keyring service:
type TokenSet struct {
IDToken string
AccessToken string
RefreshToken string
IDExpiresAt time.Time
RefreshExpAt time.Time
Issuer string
Subject string
Email string
Name string
}
Serialized as a single JSON blob — the keyring exposes one secret per
(service, account) pair and we don't want to round-trip multiple
secrets.
Pre-flight semantics
keyring.Probe():
- Writes a fixed sentinel value under service
sherlock-preflight, accountprobe. - Reads it back, verifies the round-trip.
- Deletes it.
If any step fails the call returns keyring.ErrUnavailable wrapping
the underlying cause. keyring.IsUnavailable(err) is the test;
keyring.RemediationHint() returns a per-OS one-liner.
CLI behaviour: any failure prints the wrapped error and the hint, then
exits with code 3.
Platform notes
| OS | Backend | Common setup snag |
|---|---|---|
| Linux | Secret Service (D-Bus) | gnome-keyring-daemon, KWallet, or keepassxc with Secret Service enabled must be running for the session. Headless boxes need gnome-keyring-daemon --components=secrets started inside the session bus. |
| macOS | Keychain | Works out of the box. First write may prompt for unlock. |
| Windows | Credential Manager | Works out of the box. |
Why not files
We considered an age-encrypted token blob and dropped it: the keyring gives us OS-managed locking, session affinity, and consistent multi-user behaviour for free, and avoids inventing a new key management story. The trade-off — Linux headless setups need a deliberate session keyring — is the right one for a homelab operator tool where the operator already has a desktop session.