agent

package
v0.9.5 Latest Latest
Warning

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

Go to latest
Published: Jul 1, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package agent implements a small ssh-agent-style background daemon that caches decrypted private keys in memory for a bounded TTL, so a headless process (like the MCP server Claude Code spawns) can unseal a vault secret without a passphrase prompt or ENVAULT_PASSPHRASE — as long as a human has unlocked that key from a real terminal within the TTL window.

Transport: a Unix domain socket, one JSON request/response pair per connection. Socket and containing directory are owner-only (0600/0700), keeping the same same-user threat model as ENVAULT_PASSPHRASE or a raw keychain blob — this is a convenience trade-off (wider exposure window: a decrypted key lives in memory up to TTL instead of being cleared right after use), never the default, and strictly opt-in via `envault agent unlock`.

Index

Constants

View Source
const DefaultTTL = 8 * time.Hour

DefaultTTL is used when the caller doesn't specify one.

Variables

This section is empty.

Functions

func EnsureRunning

func EnsureRunning() error

EnsureRunning starts a detached `envault agent serve-internal` process if none is already reachable, then waits (briefly) for it to start accepting connections. The spawned process is session-detached (no controlling terminal) so it outlives the caller and its terminal.

func IsRunning

func IsRunning() bool

IsRunning reports whether an agent is currently reachable at SocketPath.

func Listen

func Listen() (net.Listener, error)

Listen creates the Unix socket at SocketPath, ready for Serve. Returns an error if another agent is already listening there. A stale socket file left behind by a crashed agent (present on disk but nothing listening) is removed automatically before binding.

func Lock

func Lock() error

Lock clears every cached key. A no-op (not an error) if no agent is running.

func Serve

func Serve(ln net.Listener)

Serve accepts connections on ln until it is closed (by a "stop" request or by the caller), handling one request/response per connection. Blocks until the listener closes. All cached key bytes are cleared before returning.

func SocketPath

func SocketPath() (string, error)

SocketPath returns the fixed, per-user location of the agent socket: ~/.envault/agent.sock (or $ENVAULT_AGENT_SOCKET, if set). Not per-project — one agent serves every vault on the machine, the same way ssh-agent serves every repo.

func Stop

func Stop() error

Stop clears all cached keys and terminates the agent process. A no-op (not an error) if no agent is running.

func TryGet

func TryGet(id string) ([]byte, bool)

TryGet asks the agent for the cached plaintext private key for id. Returns (nil, false) whenever the key isn't available for any reason — agent not running, id not cached, expired, or a transport error — so callers can silently fall back to the passphrase-protected keychain path. It never spawns an agent: only Unlock does that, since Get is on the read path used by every command and must stay a no-op when the user never opted in.

func Unlock

func Unlock(id string, key []byte, ttl time.Duration) error

Unlock hands key (the decrypted private key for id) to the agent, caching it for ttl. Spawns a detached agent process first if none is reachable, so it keeps running after this command (and its terminal) exits.

Types

type StatusEntry

type StatusEntry struct {
	ID               string `json:"id"`
	ExpiresInSeconds int    `json:"expires_in_seconds"`
}

StatusEntry describes one cached identity.

func Status

func Status() ([]StatusEntry, error)

Status reports every currently-cached identity and its remaining TTL. A nil, non-error result means no agent is running — that is a normal state, not a failure.

Jump to

Keyboard shortcuts

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