keyring

package
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

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

View Source
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.

View Source
const Scheme = "keyring"

Scheme is the URL scheme keyringvar registers under on runtimevar.DefaultURLMux.

Variables

This section is empty.

Functions

func KeyringDelete

func KeyringDelete(account string) error

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

func KeyringDeleteAllGenie() (deleted int, err error)

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

func KeyringGet(account string) ([]byte, error)

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

func KeyringSet(account string, value []byte) error

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

func (o *URLOpener) OpenVariableURL(ctx context.Context, u *url.URL) (*runtimevar.Variable, error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL