Documentation
¶
Overview ¶
Package keychainauth is the client-side integration with the keychain-auth daemon.
keychain-auth is a standalone security daemon that mediates all secret reads between AgentSecrets and the OS keychain. It verifies process identity (binary hash + PID) before granting access, and enforces namespace isolation so only secrets in the {project_id}:{environment}:{key} format are readable.
This package owns:
- The Unix socket session lifecycle (init, request, close)
- Auto-setup of keychain-auth (install, register, start)
- User-facing error messages for rejection/denial
This package does NOT own:
- Writing secrets to the OS keychain (pkg/keyring handles that)
- keychain-auth's internal verification logic
- The daemon process itself
Index ¶
- func AutoSetup() error
- func Close()
- func EnsureDaemonRunning(keychainAuthPath string) error
- func EnsureInstalled() (string, error)
- func EnsureRegistered(keychainAuthPath string) error
- func GetSecret(projectID, environment, key string) (string, error)
- func Init() error
- func IsAvailable() bool
- func IsInitialized() bool
- func RestartDaemon() error
- func SocketPath() string
- func UserMessage(err error) string
- type DaemonNotRunningError
- type SecretDeniedError
- type SessionRejectedError
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AutoSetup ¶
func AutoSetup() error
AutoSetup performs the full keychain-auth setup sequence:
- Ensures keychain-auth is installed (installs if missing)
- Registers the AgentSecrets binary hash with keychain-auth
- Ensures the daemon is running (starts if not)
This is designed to be invisible to the user during normal operation. When called during an upgrade (first secret read after update), the caller should display a spinner and explanatory message.
Returns nil if everything is ready, or an error describing what failed.
func Close ¶
func Close()
Close tears down the Unix socket connection to keychain-auth. Safe to call multiple times. Should be deferred from main or called in a signal handler.
func EnsureDaemonRunning ¶
EnsureDaemonRunning checks if the keychain-auth daemon is running by probing the socket. If the socket doesn't exist, it attempts to start the daemon using the platform's service manager.
func EnsureInstalled ¶
EnsureInstalled checks if keychain-auth is in PATH. If not found, attempts to install it via the platform's package manager. Returns the absolute path to the keychain-auth binary.
func EnsureRegistered ¶
EnsureRegistered registers the current AgentSecrets binary with keychain-auth. This tells keychain-auth "this binary is trusted" by recording its SHA-256 hash.
On upgrade, the new hash must be registered before the first secret read. This function is idempotent — re-registering the same hash is a no-op.
func GetSecret ¶
GetSecret sends a SECRET_REQUEST to keychain-auth and returns the plaintext value.
The key is the bare secret name (e.g., "OPENAI_API_KEY"). The projectID and environment are sent alongside it — keychain-auth constructs the full {projectID}:{environment}:{key} keychain key internally.
The returned value should be used immediately and not stored in any persistent variable, struct field, log, or error message.
func Init ¶
func Init() error
Init connects to the keychain-auth daemon and performs the SESSION_INIT handshake.
This must be called once per process lifetime before any GetSecret() call. The session token is stored in memory only. The binary hash is computed fresh on every call — it is never cached between invocations.
If the daemon is not running, Init returns a *DaemonNotRunningError with a user-facing message explaining how to fix it.
func IsAvailable ¶
func IsAvailable() bool
IsAvailable checks whether the keychain-auth socket file exists on disk. This is a quick probe — it does not attempt a connection.
func IsInitialized ¶
func IsInitialized() bool
IsInitialized returns true if a session has been successfully established.
func RestartDaemon ¶
func RestartDaemon() error
RestartDaemon kills any running keychain-auth daemon and starts a fresh one. This is needed after re-registering a binary so the daemon picks up the new hash.
func SocketPath ¶
func SocketPath() string
SocketPath returns the keychain-auth Unix socket path. It uses platform-specific, user-writable directories to avoid permission issues.
func UserMessage ¶
UserMessage returns the full user-facing error text for a rejection reason. These messages are specified in the integration spec and should not be changed without updating the spec.
Types ¶
type DaemonNotRunningError ¶
DaemonNotRunningError is returned when the keychain-auth socket does not exist or the connection is refused.
func (*DaemonNotRunningError) Error ¶
func (e *DaemonNotRunningError) Error() string
func (*DaemonNotRunningError) Unwrap ¶
func (e *DaemonNotRunningError) Unwrap() error
type SecretDeniedError ¶
type SecretDeniedError struct {
Key string
Reason rejectReason
}
SecretDeniedError is returned when keychain-auth denies a SECRET_REQUEST.
func (*SecretDeniedError) Error ¶
func (e *SecretDeniedError) Error() string
type SessionRejectedError ¶
type SessionRejectedError struct {
Reason rejectReason
}
SessionRejectedError is returned when keychain-auth rejects a SESSION_INIT request. The Reason field matches the protocol's RejectReason constants.
func (*SessionRejectedError) Error ¶
func (e *SessionRejectedError) Error() string
func (*SessionRejectedError) IsHashMismatch ¶
func (e *SessionRejectedError) IsHashMismatch() bool
IsHashMismatch returns true if the rejection was due to a binary hash mismatch.
func (*SessionRejectedError) IsPathMismatch ¶ added in v1.2.0
func (e *SessionRejectedError) IsPathMismatch() bool
IsPathMismatch returns true if the rejection was due to a binary path mismatch (e.g. Homebrew upgrade).