Documentation
¶
Overview ¶
Package daemon implements the proxy daemon's management API.
Backwards Compatibility ¶
The daemon is a long-lived process that may run a different binary version than the CLI or the moat-run process. This happens during development (rebuilding moat while runs are active) and during upgrades.
To keep old and new versions interoperable, the daemon API follows these rules:
- Additive only: new fields in request/response structs are fine (encoding/json ignores unknown fields). Never remove or rename fields.
- New endpoints are fine: old clients won't call them. New clients must handle 404 gracefully when talking to an older daemon.
- Never change the semantics of existing fields.
When adding new API surface, consider: "will a CLI built today still work if the daemon is an older binary?" and vice versa.
Package daemon implements the proxy daemon for multi-run credential injection.
Index ¶
- Variables
- func RemoveLockFile(dir string)
- func StartTokenRefresh(ctx context.Context, rc *RunContext, grants []string)
- func WriteLockFile(dir string, info LockInfo) error
- type AWSConfig
- type Client
- func (c *Client) Health(ctx context.Context) (*HealthResponse, error)
- func (c *Client) ListRuns(ctx context.Context) ([]RunInfo, error)
- func (c *Client) RegisterRoutes(ctx context.Context, agent string, services map[string]string) error
- func (c *Client) RegisterRun(ctx context.Context, regReq RegisterRequest) (*RegisterResponse, error)
- func (c *Client) Shutdown(ctx context.Context) error
- func (c *Client) UnregisterRoutes(ctx context.Context, agent string) error
- func (c *Client) UnregisterRun(ctx context.Context, token string) error
- func (c *Client) UpdateRun(ctx context.Context, token, containerID string) error
- type CommandContainerChecker
- type ContainerChecker
- type CredentialEntry
- type CredentialSpec
- type ExtraHeaderEntry
- type ExtraHeaderSpec
- type HealthResponse
- type IdleTimer
- type LivenessChecker
- type LockInfo
- type RegisterRequest
- type RegisterResponse
- type Registry
- func (r *Registry) Count() int
- func (r *Registry) List() []*RunContext
- func (r *Registry) Lookup(token string) (*RunContext, bool)
- func (r *Registry) Register(rc *RunContext) string
- func (r *Registry) RegisterWithToken(rc *RunContext, token string)
- func (r *Registry) Unregister(token string)
- func (r *Registry) UpdateContainerID(token, containerID string) bool
- type RemoveHeaderSpec
- type RouteRegistration
- type RunContext
- func (rc *RunContext) AddExtraHeader(host, headerName, headerValue string)
- func (rc *RunContext) AddResponseTransformer(host string, transformer credential.ResponseTransformer)
- func (rc *RunContext) CancelRefresh()
- func (rc *RunContext) GetContainerID() string
- func (rc *RunContext) GetCredential(host string) (CredentialEntry, bool)
- func (rc *RunContext) GetExtraHeaders(host string) []ExtraHeaderEntry
- func (rc *RunContext) GetRemoveHeaders(host string) []string
- func (rc *RunContext) GetResponseTransformers(host string) []credential.ResponseTransformer
- func (rc *RunContext) GetTokenSubstitution(host string) (TokenSubstitutionEntry, bool)
- func (rc *RunContext) RemoveRequestHeader(host, headerName string)
- func (rc *RunContext) SetAWSHandler(h http.Handler)
- func (rc *RunContext) SetCredential(host, value string)
- func (rc *RunContext) SetCredentialHeader(host, headerName, headerValue string)
- func (rc *RunContext) SetCredentialWithGrant(host, headerName, headerValue, grant string)
- func (rc *RunContext) SetRefreshCancel(cancel context.CancelFunc)
- func (rc *RunContext) SetTokenSubstitution(host, placeholder, realToken string)
- func (rc *RunContext) ToProxyContextData() *proxy.RunContextData
- type RunInfo
- type Server
- func (s *Server) Registry() *Registry
- func (s *Server) SetOnEmpty(fn func())
- func (s *Server) SetOnRegister(fn func())
- func (s *Server) SetOnShutdown(fn func())
- func (s *Server) SetOnUnregister(fn func(runID string))
- func (s *Server) SetProxyPort(port int)
- func (s *Server) SetRoutes(rt *routing.RouteTable)
- func (s *Server) Start() error
- func (s *Server) Stop(ctx context.Context) error
- type TokenSubstitutionEntry
- type TokenSubstitutionSpec
- type TransformerSpec
- type UpdateRunRequest
Constants ¶
This section is empty.
Variables ¶
var BuildCommit string
BuildCommit is the git commit hash of the running binary. Set by the CLI at startup so the health endpoint can report the daemon's version. This allows diagnosing version skew between daemon and CLI.
var ErrRunNotFound = errors.New("run not found")
ErrRunNotFound is returned when a run is not registered with the daemon.
Functions ¶
func StartTokenRefresh ¶
func StartTokenRefresh(ctx context.Context, rc *RunContext, grants []string)
StartTokenRefresh begins a background goroutine that periodically refreshes credentials for the given run context.
func WriteLockFile ¶
WriteLockFile writes the daemon lock file.
Types ¶
type AWSConfig ¶
type AWSConfig struct {
RoleARN string `json:"role_arn"`
Region string `json:"region"`
SessionDuration time.Duration `json:"session_duration"`
ExternalID string `json:"external_id,omitempty"`
}
AWSConfig holds AWS credential provider configuration.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client communicates with the daemon over a Unix socket.
func EnsureRunning ¶
EnsureRunning checks if the daemon is already running and returns a client. If not running, it starts the daemon via self-exec and waits for it to be ready.
An advisory file lock serializes the check-and-spawn sequence so concurrent callers don't each spawn a separate daemon process.
func (*Client) Health ¶
func (c *Client) Health(ctx context.Context) (*HealthResponse, error)
Health returns the daemon's health status.
func (*Client) RegisterRoutes ¶
func (c *Client) RegisterRoutes(ctx context.Context, agent string, services map[string]string) error
RegisterRoutes registers service routes for an agent.
func (*Client) RegisterRun ¶
func (c *Client) RegisterRun(ctx context.Context, regReq RegisterRequest) (*RegisterResponse, error)
RegisterRun registers a new run with the daemon.
func (*Client) UnregisterRoutes ¶
UnregisterRoutes removes service routes for an agent.
func (*Client) UnregisterRun ¶
UnregisterRun removes a run from the daemon.
type CommandContainerChecker ¶
type CommandContainerChecker struct {
// contains filtered or unexported fields
}
CommandContainerChecker checks container liveness by shelling out to the container runtime CLI. It tries Docker first, then Apple containers.
func NewCommandContainerChecker ¶
func NewCommandContainerChecker() *CommandContainerChecker
NewCommandContainerChecker creates a new container checker that uses CLI commands.
func (*CommandContainerChecker) IsContainerRunning ¶
IsContainerRunning checks if a container is still running. Returns (true, nil) when the container is confirmed alive, (false, nil) when confirmed dead, and (false, err) when the check itself failed (e.g. transient CLI error).
type ContainerChecker ¶
type ContainerChecker interface {
IsContainerRunning(ctx context.Context, id string) (alive bool, err error)
}
ContainerChecker checks if a container is still running. Returns (true, nil) when confirmed alive, (false, nil) when confirmed dead, and (false, err) when the check failed (transient error).
type CredentialEntry ¶
type CredentialEntry struct {
Name string `json:"name"` // Header name (e.g., "Authorization", "x-api-key")
Value string `json:"value"` // Header value
Grant string `json:"grant"` // Grant name for logging
}
CredentialEntry holds a credential header for proxy injection.
type CredentialSpec ¶
type CredentialSpec struct {
Host string `json:"host"`
Header string `json:"header"`
Value string `json:"value"`
Grant string `json:"grant,omitempty"`
}
CredentialSpec describes a credential to inject for a host.
type ExtraHeaderEntry ¶
ExtraHeaderEntry holds an additional header to inject.
type ExtraHeaderSpec ¶
type ExtraHeaderSpec struct {
Host string `json:"host"`
HeaderName string `json:"header_name"`
Value string `json:"value"`
}
ExtraHeaderSpec describes an additional header to inject.
type HealthResponse ¶
type HealthResponse struct {
PID int `json:"pid"`
ProxyPort int `json:"proxy_port"`
RunCount int `json:"run_count"`
StartedAt string `json:"started_at"`
Commit string `json:"commit,omitempty"` // Git commit hash of the daemon binary
}
HealthResponse is returned from GET /v1/health.
type IdleTimer ¶
type IdleTimer struct {
// contains filtered or unexported fields
}
IdleTimer triggers a callback after a period of inactivity.
func NewIdleTimer ¶
NewIdleTimer creates an idle timer (does not start automatically).
type LivenessChecker ¶
type LivenessChecker struct {
// contains filtered or unexported fields
}
LivenessChecker periodically checks container liveness and cleans up dead runs.
func NewLivenessChecker ¶
func NewLivenessChecker(registry *Registry, checker ContainerChecker) *LivenessChecker
NewLivenessChecker creates a new liveness checker with 30-second default interval.
func (*LivenessChecker) CheckOnce ¶
func (lc *LivenessChecker) CheckOnce(ctx context.Context)
CheckOnce performs a single liveness check for all registered runs.
func (*LivenessChecker) Run ¶
func (lc *LivenessChecker) Run(ctx context.Context)
Run starts the periodic liveness check loop. Blocks until ctx is canceled.
func (*LivenessChecker) SetOnCleanup ¶
func (lc *LivenessChecker) SetOnCleanup(fn func(token, runID string))
SetOnCleanup sets a callback invoked when a run is cleaned up. The callback receives both the auth token and run ID.
func (*LivenessChecker) SetOnEmpty ¶
func (lc *LivenessChecker) SetOnEmpty(fn func())
SetOnEmpty sets a callback invoked when the registry becomes empty after cleanup.
type LockInfo ¶
type LockInfo struct {
PID int `json:"pid"`
ProxyPort int `json:"proxy_port"`
SockPath string `json:"sock_path"`
StartedAt time.Time `json:"started_at"`
Commit string `json:"commit,omitempty"` // Git commit hash of the daemon binary
}
LockInfo holds information about a running daemon.
func ReadLockFile ¶
ReadLockFile reads the daemon lock file. Returns nil, nil if not found.
type RegisterRequest ¶
type RegisterRequest struct {
RunID string `json:"run_id"`
AuthToken string `json:"auth_token,omitempty"` // Re-registration: use existing token
Credentials []CredentialSpec `json:"credentials,omitempty"`
ExtraHeaders []ExtraHeaderSpec `json:"extra_headers,omitempty"`
RemoveHeaders []RemoveHeaderSpec `json:"remove_headers,omitempty"`
TokenSubstitutions []TokenSubstitutionSpec `json:"token_substitutions,omitempty"`
MCPServers []config.MCPServerConfig `json:"mcp_servers,omitempty"`
NetworkPolicy string `json:"network_policy,omitempty"`
NetworkAllow []string `json:"network_allow,omitempty"`
Grants []string `json:"grants,omitempty"`
AWSConfig *AWSConfig `json:"aws_config,omitempty"`
ResponseTransformers []TransformerSpec `json:"response_transformers,omitempty"`
}
RegisterRequest is sent to POST /v1/runs.
func (*RegisterRequest) ToRunContext ¶
func (req *RegisterRequest) ToRunContext() *RunContext
ToRunContext converts a RegisterRequest into a RunContext.
type RegisterResponse ¶
type RegisterResponse struct {
AuthToken string `json:"auth_token"`
ProxyPort int `json:"proxy_port"`
}
RegisterResponse is returned from POST /v1/runs.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is a thread-safe mapping of auth tokens to RunContexts. It provides the central lookup mechanism for the daemon proxy to resolve incoming requests to their per-run configuration and credentials.
func (*Registry) List ¶
func (r *Registry) List() []*RunContext
List returns all registered RunContexts.
func (*Registry) Lookup ¶
func (r *Registry) Lookup(token string) (*RunContext, bool)
Lookup finds a RunContext by auth token.
func (*Registry) Register ¶
func (r *Registry) Register(rc *RunContext) string
Register adds a RunContext and returns a generated auth token. The token is a 32-byte cryptographically random hex string.
func (*Registry) RegisterWithToken ¶
func (r *Registry) RegisterWithToken(rc *RunContext, token string)
RegisterWithToken adds a RunContext with a specific auth token. This is used for re-registration after a daemon restart so the container can keep using the same proxy auth token it was configured with.
func (*Registry) Unregister ¶
Unregister removes a RunContext by its auth token.
func (*Registry) UpdateContainerID ¶
UpdateContainerID sets the container ID for a registered run. Returns false if the token is not found.
type RemoveHeaderSpec ¶
RemoveHeaderSpec describes a header to remove from requests.
type RouteRegistration ¶
RouteRegistration is sent to POST /v1/routes/{agent}.
type RunContext ¶
type RunContext struct {
RunID string `json:"run_id"`
ContainerID string `json:"container_id,omitempty"`
AuthToken string `json:"auth_token"`
Credentials map[string]CredentialEntry `json:"credentials"`
ExtraHeaders map[string][]ExtraHeaderEntry `json:"extra_headers"`
RemoveHeaders map[string][]string `json:"remove_headers"`
TokenSubstitutions map[string]TokenSubstitutionEntry `json:"token_substitutions"`
ResponseTransformers map[string][]credential.ResponseTransformer `json:"-"` // not serialized
MCPServers []config.MCPServerConfig `json:"mcp_servers,omitempty"`
NetworkPolicy string `json:"network_policy,omitempty"`
NetworkAllow []string `json:"network_allow,omitempty"`
AWSConfig *AWSConfig `json:"aws_config,omitempty"`
TransformerSpecs []TransformerSpec `json:"transformer_specs,omitempty"`
RegisteredAt time.Time `json:"registered_at"`
// contains filtered or unexported fields
}
RunContext holds per-run proxy state. It implements credential.ProxyConfigurer so providers can configure it identically to how they configure proxy.Proxy.
func NewRunContext ¶
func NewRunContext(runID string) *RunContext
NewRunContext creates a new RunContext for a run.
func (*RunContext) AddExtraHeader ¶
func (rc *RunContext) AddExtraHeader(host, headerName, headerValue string)
AddExtraHeader implements credential.ProxyConfigurer.
func (*RunContext) AddResponseTransformer ¶
func (rc *RunContext) AddResponseTransformer(host string, transformer credential.ResponseTransformer)
AddResponseTransformer implements credential.ProxyConfigurer.
func (*RunContext) CancelRefresh ¶
func (rc *RunContext) CancelRefresh()
CancelRefresh cancels the token refresh goroutine, if any. Safe to call concurrently and multiple times.
func (*RunContext) GetContainerID ¶
func (rc *RunContext) GetContainerID() string
GetContainerID returns the container ID safely.
func (*RunContext) GetCredential ¶
func (rc *RunContext) GetCredential(host string) (CredentialEntry, bool)
GetCredential returns the credential for a host, checking host:port fallback.
func (*RunContext) GetExtraHeaders ¶
func (rc *RunContext) GetExtraHeaders(host string) []ExtraHeaderEntry
GetExtraHeaders returns extra headers for a host, checking host:port fallback.
func (*RunContext) GetRemoveHeaders ¶
func (rc *RunContext) GetRemoveHeaders(host string) []string
GetRemoveHeaders returns headers to remove for a host, checking host:port fallback.
func (*RunContext) GetResponseTransformers ¶
func (rc *RunContext) GetResponseTransformers(host string) []credential.ResponseTransformer
GetResponseTransformers returns response transformers for a host, checking host:port fallback.
func (*RunContext) GetTokenSubstitution ¶
func (rc *RunContext) GetTokenSubstitution(host string) (TokenSubstitutionEntry, bool)
GetTokenSubstitution returns the token substitution for a host, checking host:port fallback.
func (*RunContext) RemoveRequestHeader ¶
func (rc *RunContext) RemoveRequestHeader(host, headerName string)
RemoveRequestHeader implements credential.ProxyConfigurer.
func (*RunContext) SetAWSHandler ¶
func (rc *RunContext) SetAWSHandler(h http.Handler)
SetAWSHandler stores the AWS credential endpoint handler for this run.
func (*RunContext) SetCredential ¶
func (rc *RunContext) SetCredential(host, value string)
SetCredential implements credential.ProxyConfigurer.
func (*RunContext) SetCredentialHeader ¶
func (rc *RunContext) SetCredentialHeader(host, headerName, headerValue string)
SetCredentialHeader implements credential.ProxyConfigurer.
func (*RunContext) SetCredentialWithGrant ¶
func (rc *RunContext) SetCredentialWithGrant(host, headerName, headerValue, grant string)
SetCredentialWithGrant implements credential.ProxyConfigurer.
func (*RunContext) SetRefreshCancel ¶
func (rc *RunContext) SetRefreshCancel(cancel context.CancelFunc)
SetRefreshCancel stores the cancel function for the token refresh goroutine.
func (*RunContext) SetTokenSubstitution ¶
func (rc *RunContext) SetTokenSubstitution(host, placeholder, realToken string)
SetTokenSubstitution implements credential.ProxyConfigurer.
func (*RunContext) ToProxyContextData ¶
func (rc *RunContext) ToProxyContextData() *proxy.RunContextData
ToProxyContextData converts this RunContext into a proxy.RunContextData for use in per-request credential resolution.
type RunInfo ¶
type RunInfo struct {
RunID string `json:"run_id"`
ContainerID string `json:"container_id,omitempty"`
RegisteredAt string `json:"registered_at"`
}
RunInfo is an element of the list returned by GET /v1/runs.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the daemon's HTTP API server over a Unix socket.
func NewServer ¶
NewServer creates a daemon API server that will listen on the given Unix socket path.
func (*Server) SetOnEmpty ¶
func (s *Server) SetOnEmpty(fn func())
SetOnEmpty sets a callback that is invoked when the last run is unregistered.
func (*Server) SetOnRegister ¶
func (s *Server) SetOnRegister(fn func())
SetOnRegister sets a callback invoked when a new run is registered.
func (*Server) SetOnShutdown ¶
func (s *Server) SetOnShutdown(fn func())
SetOnShutdown sets a callback that is invoked when shutdown is requested via the API. This should signal the main daemon loop to exit (e.g., by sending SIGTERM to self).
func (*Server) SetOnUnregister ¶
SetOnUnregister sets a callback that is invoked when a run is unregistered. The callback receives the run ID for per-run resource cleanup.
func (*Server) SetProxyPort ¶
SetProxyPort updates the proxy port reported in API responses. Call after the credential proxy starts to set the actual port.
func (*Server) SetRoutes ¶
func (s *Server) SetRoutes(rt *routing.RouteTable)
SetRoutes sets the route table used for route registration handlers.
type TokenSubstitutionEntry ¶
type TokenSubstitutionEntry struct {
Placeholder string `json:"placeholder"`
RealToken string `json:"real_token"`
}
TokenSubstitutionEntry holds a placeholder-to-real-token mapping.
type TokenSubstitutionSpec ¶
type TokenSubstitutionSpec struct {
Host string `json:"host"`
Placeholder string `json:"placeholder"`
RealToken string `json:"real_token"`
}
TokenSubstitutionSpec describes a token substitution.
type TransformerSpec ¶
type TransformerSpec struct {
Host string `json:"host"`
Kind string `json:"kind"` // "oauth-endpoint-workaround" or "response-scrub"
}
TransformerSpec describes a response transformer to apply for a host. Since transformers are Go functions (not serializable), this spec allows the daemon to reconstruct them from well-known kinds.
type UpdateRunRequest ¶
type UpdateRunRequest struct {
ContainerID string `json:"container_id"`
}
UpdateRunRequest is sent to PATCH /v1/runs/{token}.