Documentation
¶
Overview ¶
Package keyring: device keychain storage for arbitrary key-value secrets. Uses macOS Keychain, Windows Credential Manager, or Linux Secret Service (via go-keyring). Callers use a logical service name and account (key) to store and retrieve values without writing token files to disk.
When SetKeyringScopeFromConfigPath is set (e.g. from config file path), all account keys are namespaced so multiple Genie instances (different configs) do not overwrite each other's keychain data (e.g. Google OAuth).
Package keyring provides a runtimevar implementation backed by the system keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service). Use OpenVariable or OpenVariableURL to construct a *runtimevar.Variable. Secrets stored via security.KeyringSet can be referenced in config as keyring://service/account (e.g. keyring://genie/TELEGRAM_BOT_TOKEN).
URLs ¶
For runtimevar.OpenVariable, keyringvar registers for the scheme "keyring". URL form: keyring://<service>/<account>. Example: keyring://genie/OPENAI_API_KEY. Query parameters:
- decoder: optional; defaults to "string". See runtimevar.DecoderByName.
Index ¶
- Constants
- func KeyringDelete(account string) error
- func KeyringDeleteAllGenie() (deleted int, err error)
- func KeyringGet(account string) ([]byte, error)
- func KeyringSet(account string, value []byte) error
- func OpenVariable(account string, decoder *runtimevar.Decoder) (*runtimevar.Variable, error)
- func SetKeyringScopeFromConfigPath(configPath string)
- type URLOpener
Constants ¶
const ( AccountGoogleOAuthToken = "google_oauth_token" AccountGoogleOAuthUser = "google_oauth_user" AccountGoogleOAuthCredentials = "google_oauth_credentials" // client ID/secret JSON stored after browser flow so Calendar/Gmail work without env at runtime AccountOpenAIAPIKey = "OPENAI_API_KEY" AccountGoogleAPIKey = "GOOGLE_API_KEY" AccountAnthropicAPIKey = "ANTHROPIC_API_KEY" AccountTelegramBotToken = "TELEGRAM_BOT_TOKEN" AccountSlackAppToken = "SLACK_APP_TOKEN" AccountSlackBotToken = "SLACK_BOT_TOKEN" AccountDiscordBotToken = "DISCORD_BOT_TOKEN" AccountTeamsAppID = "TEAMS_APP_ID" AccountTeamsAppPassword = "TEAMS_APP_PASSWORD" // AccountAGUIPassword is the password for the AG-UI web chat (one per agent, scoped by config path). AccountAGUIPassword = "agui_password" )
Account names Genie uses in the keyring (service "genie"). Use these constants instead of magic strings when calling KeyringGet/KeyringSet/KeyringDelete.
const Scheme = "keyring"
Scheme is the URL scheme keyringvar registers under on runtimevar.DefaultURLMux.
Variables ¶
This section is empty.
Functions ¶
func KeyringDelete ¶
KeyringDelete removes the stored value for the given service and account (e.g. on sign-out or key rotation). Also removes from the in-memory fallback. Account is namespaced by the current keyring scope when set.
func KeyringDeleteAllGenie ¶
KeyringDeleteAllGenie removes all known Genie keyring entries for the current scope (or unscoped legacy entries when scope is not set). It deletes each account in knownGenieAccounts and ignores "not found" errors. Also clears those accounts from the in-memory fallback. Returns the first non-not-found error from the keyring if any, and the number of keyring entries successfully deleted. Use for cleanup (e.g. back-to-bottle). Call SetKeyringScopeFromConfigPath before this to clear only one instance's data.
func KeyringGet ¶
KeyringGet returns the value stored in the system keychain for the given service and account (key). If the keyring is unavailable (e.g. headless Linux, Docker), returns the value from the in-memory fallback when present. Returns (nil, err) when the entry is not found in either. Account is namespaced by the current keyring scope when set.
func KeyringSet ¶
KeyringSet stores a value in the system keychain for the given service and account (key). If the keyring is unavailable (e.g. Docker, headless Linux), stores in an in-memory fallback so the app keeps working; no error is returned. Values in the fallback are process-only and lost on restart. A warning is logged when falling back to memory so operators know secrets are not persisted. Account is namespaced by the current keyring scope when set.
func OpenVariable ¶
func OpenVariable(account string, decoder *runtimevar.Decoder) (*runtimevar.Variable, error)
OpenVariable constructs a *runtimevar.Variable backed by the keyring entry for the given account. The value is read once and then treated as constant (keyring has no watch support).
func SetKeyringScopeFromConfigPath ¶
func SetKeyringScopeFromConfigPath(configPath string)
SetKeyringScopeFromConfigPath sets the keyring scope from the config file path so that multiple Genie instances (different config paths) use separate keychain entries and do not overwrite each other's Google OAuth (and other) data. Pass an empty path to use unscoped (legacy) keys. Should be called early (e.g. in root init or setup) before any keyring access.
Types ¶
type URLOpener ¶
type URLOpener struct {
// Decoder specifies the decoder to use if one is not specified in the URL.
// Defaults to string decoder.
Decoder *runtimevar.Decoder
}
URLOpener opens keyringvar URLs like "keyring://genie/TELEGRAM_BOT_TOKEN?decoder=string". The URL host is the keyring service name (e.g. "genie"); the path is the account (key) name (e.g. "/TELEGRAM_BOT_TOKEN"). Query parameter "decoder" defaults to "string".
func (*URLOpener) OpenVariableURL ¶
OpenVariableURL opens the variable at the given keyring URL. URL form: keyring:///account (path only) or keyring://service/account. The host (service name) is ignored; only the path, or host when path is empty, is used as the account. All keyring access uses the fixed service from the keyring package.