daemon

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2026 License: Apache-2.0 Imports: 44 Imported by: 0

Documentation

Overview

Package daemon provides the local symbrowse daemon's Unix-socket protocol.

Index

Constants

View Source
const (
	DefaultIdleTimeout      = 30 * 60 * 1e9
	DefaultOperationTimeout = 25 * 1e9
	DefaultReadTimeout      = 30 * 1e9
)
View Source
const (
	ErrorMalformedRequest   = "malformed_request"
	ErrorUnknownCommand     = "unknown_command"
	ErrorOperationTimeout   = "operation_timeout"
	ErrorOperationFailed    = "operation_failed"
	ErrorPeerDenied         = "peer_denied"
	ErrorDaemonUnavailable  = "daemon_unavailable"
	ErrorInvalidSession     = "invalid_session"
	ErrorSessionNotFound    = "session_not_found"
	ErrorSessionUserControl = "session_user_control"
	ErrorSessionInactive    = "session_inactive"
	ErrorHandoffTimeout     = "handoff_timeout"
)
View Source
const SessionSchemaVersion = 1

Variables

View Source
var (
	ErrSessionNotFound = errors.New("session not found")
	ErrInvalidSession  = errors.New("invalid session name")
)
View Source
var ErrIdleTimeout = errors.New("daemon idle timeout")
View Source
var ErrVaultUnavailable = errors.New("symvault is not installed")

ErrVaultUnavailable is returned when symvault is not installed. The CLI maps it to a clear error with setup instructions and never offers a plaintext fallback.

Functions

func SocketPath

func SocketPath(session string) (string, error)

SocketPath resolves the platform-specific default socket path for a session.

func SocketPathIn

func SocketPathIn(base, session string) (string, error)

SocketPathIn returns a socket path under base. It is intended for tests and callers that explicitly own a runtime directory.

func StartDaemonProcess

func StartDaemonProcess(ctx context.Context, executable, session string) error

StartDaemonProcess launches an independent daemon process using executable.

func StartDaemonProcessArgs

func StartDaemonProcessArgs(ctx context.Context, executable string, args ...string) error

StartDaemonProcessArgs launches an independent daemon process with an explicit argument list (e.g. "daemon", "--session", "default", "--ssrf"). Callers that need policy flags beyond the session use this form.

Types

type AuthRuntime

type AuthRuntime struct {
	// contains filtered or unexported fields
}

AuthRuntime implements credential login through symvault. Credentials are resolved in memory, typed into the detected fields via CDP and never returned, logged or persisted (issue B-39).

func NewAuthRuntime

func NewAuthRuntime(nav *NavigationRuntime, vault *VaultResolver) *AuthRuntime

NewAuthRuntime creates an auth bridge for one navigation runtime.

func (*AuthRuntime) Handle

func (r *AuthRuntime) Handle(ctx context.Context, frame Frame) (any, []Warning, error)

Handle executes auth frames.

func (*AuthRuntime) Login

func (r *AuthRuntime) Login(ctx context.Context, session, entry, url string) (LoginResult, error)

Login resolves the vault entry, navigates to the target URL when given, detects the login form and types the credentials. Errors are redacted so the password never reaches the caller, the journal or the log.

type AutosaveConfig

type AutosaveConfig struct {
	Policy   AutosavePolicy
	Interval time.Duration
	Key      string // named state to write; empty disables autosave
}

AutosaveConfig wires the daemon's autosave behaviour.

func (*AutosaveConfig) Validate

func (c *AutosaveConfig) Validate() error

Validate normalizes the policy and interval.

type AutosavePolicy

type AutosavePolicy string

AutosavePolicy controls when session state is persisted automatically.

const (
	AutosaveAuto   AutosavePolicy = "auto"   // save at most once per interval
	AutosaveAlways AutosavePolicy = "always" // save after every change
	AutosaveNever  AutosavePolicy = "never"  // never save automatically
)

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client sends requests to a daemon, optionally autostarting it when the socket is unavailable.

func NewClient

func NewClient(options ClientOptions) *Client

NewClient constructs a client. The default starter launches the current executable with the daemon subcommand. Setting SYMBROWSE_NO_AUTOSTART=1 disables autostart entirely (useful for scripts and tests that manage the daemon lifecycle themselves). SYMBROWSE_READ_TIMEOUT overrides the per-request socket deadline (default 30s) for slow first commands such as a cold Chrome launch.

func (*Client) Request

func (c *Client) Request(ctx context.Context, frame Frame) (Response, error)

Request sends one request and waits for one response. A failed initial dial triggers the configured autostart hook and bounded startup retries.

func (*Client) RequestWithoutAutostart

func (c *Client) RequestWithoutAutostart(ctx context.Context, frame Frame) (Response, error)

RequestWithoutAutostart sends one request and never starts a process. It is used by status and stop so those lifecycle commands do not create a daemon.

type ClientOptions

type ClientOptions struct {
	SocketPath     string
	Session        string
	StartupTimeout time.Duration
	ReadTimeout    time.Duration
	StartDaemon    StartDaemonFunc
}

ClientOptions configures a daemon client.

type Error

type Error struct {
	Code                     string         `json:"code"`
	Message                  string         `json:"message"`
	Hint                     string         `json:"hint,omitempty"`
	Details                  map[string]any `json:"details,omitempty"`
	Retryable                *bool          `json:"retryable,omitempty"`
	RequiresUserConfirmation *bool          `json:"requires_user_confirmation,omitempty"`
	ResumeHint               string         `json:"resume_hint,omitempty"`
}

Error is the stable structured error payload returned by the daemon.

func NewError

func NewError(code, message string) *Error

NewError constructs a response error with a stable code and message.

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface for handler-level protocol failures.

func (*Error) ErrorCode

func (e *Error) ErrorCode() string

ErrorCode exposes the stable protocol error code for the unified output schema (internal/output). Codes are members of the documented enum.

func (*Error) ErrorDetails added in v0.2.0

func (e *Error) ErrorDetails() map[string]any

ErrorDetails exposes the protocol error details for the output schema.

func (*Error) ErrorHint added in v0.2.0

func (e *Error) ErrorHint() string

ErrorHint exposes the protocol error hint for the output schema.

type FetchRuntime added in v0.3.0

type FetchRuntime struct {
	// contains filtered or unexported fields
}

FetchRuntime exposes the absorbed SymFetch fetch pipeline through the daemon protocol without requiring a browser session. It serves the fetch.url, fetch.batch and wayback.snapshots compatibility frames (issue #258): the three SymFetch MCP contracts that Hermes relied on before the archived symfetch runtime was retired. All three work on plain HTTP and never launch a browser.

func NewFetchRuntime added in v0.3.0

func NewFetchRuntime(options FetchRuntimeOptions) (*FetchRuntime, error)

NewFetchRuntime creates the runtime with an honest (CGO-free) fetch client. The honest profile keeps the binary free of the browser-impersonation dependency tree while preserving the stable response semantics clients rely on.

func (*FetchRuntime) Close added in v0.3.0

func (r *FetchRuntime) Close() error

Close releases the underlying fetch client.

func (*FetchRuntime) Handle added in v0.3.0

func (r *FetchRuntime) Handle(ctx context.Context, frame Frame) (any, []Warning, error)

Handle executes one fetch frame.

type FetchRuntimeOptions added in v0.3.0

type FetchRuntimeOptions struct {
	// AllowPrivate relaxes the SSRF guard for plain HTTP fetches
	// (mirrors the daemon --allow-private opt-in).
	AllowPrivate bool
	// Robots enables robots.txt compliance checks before fetching.
	Robots bool
	// UserAgent is used for the robots check and honest fetches.
	UserAgent string
	// CacheDir and CacheTTL configure the response cache (empty disables
	// the shared cache instance; the pipeline falls back to its default).
	CacheDir string
	CacheTTL time.Duration
}

FetchRuntimeOptions configures the fetch runtime.

type Frame

type Frame struct {
	Cmd       string          `json:"cmd"`
	Args      json.RawMessage `json:"args,omitempty"`
	Session   string          `json:"session,omitempty"`
	RequestID string          `json:"request_id,omitempty"`
	// MaxTokens caps the response payload (issue #23, B-19): when the
	// serialized data exceeds the budget the daemon returns head+foot plus
	// a cache handle instead of the full payload.
	MaxTokens *int `json:"max_tokens,omitempty"`
}

Frame is one newline-delimited request sent to the daemon.

func DecodeFrame

func DecodeFrame(raw []byte) (Frame, error)

DecodeFrame validates and decodes a single JSON frame.

type Handler

type Handler func(context.Context, Frame) (any, []Warning, error)

Handler executes one application command. It must honor ctx so cancellation after an operation timeout can stop expensive work.

type JournalRuntime

type JournalRuntime struct {
	// contains filtered or unexported fields
}

JournalRuntime wraps the navigation runtime and appends one journal entry per action frame (issue B-41). Entry payloads are redacted by the journal itself before hitting the disk.

func NewJournalRuntime

func NewJournalRuntime(j *journal.Journal, nav *NavigationRuntime) *JournalRuntime

NewJournalRuntime creates a journaling wrapper. When journal is nil the wrapper passes through without logging (tests, disabled config).

func (*JournalRuntime) Handle

func (r *JournalRuntime) Handle(ctx context.Context, frame Frame) (any, []Warning, error)

Handle runs the frame and journals it. The journal entry is written after the action completes so the result is accurate; a failed frame still gets an entry with result "error:<kind>".

func (*JournalRuntime) HandleJournal

func (r *JournalRuntime) HandleJournal(ctx context.Context, frame Frame) (any, []Warning, error)

HandleJournal executes journal inspection frames: tail and show.

func (*JournalRuntime) HandleOOB

func (r *JournalRuntime) HandleOOB(ctx context.Context, frame Frame, handler func(context.Context, Frame) (any, []Warning, error)) (any, []Warning, error)

HandleOOB runs an OOB frame through the given handler and journals it, so granted/denied approvals and handoffs land in the journal with their scope and outcome (issue B-46).

func (*JournalRuntime) HandleWithDecider

func (r *JournalRuntime) HandleWithDecider(ctx context.Context, frame Frame, decider string) (any, []Warning, error)

HandleWithDecider is Handle with an explicit decider for the journal entry ("policy", "guard" or "human" — issue #52).

type LoginResult

type LoginResult struct {
	Status      string `json:"status"` // logged_in | no_form | failed
	URL         string `json:"url"`
	UsernameSet bool   `json:"username_set"`
	PasswordSet bool   `json:"password_set"`
	Hint        string `json:"hint,omitempty"`
}

LoginResult is the stable outcome of auth login. It deliberately contains no credential material.

type NavigationRuntime struct {
	// contains filtered or unexported fields
}

NavigationRuntime lazily owns one protocol-neutral navigation service and Chrome engine per session. CDP details remain confined to engine/chrome.

func NewNavigationRuntime

func NewNavigationRuntime(registry *SessionRegistry, executable string, options NavigationRuntimeOptions) *NavigationRuntime

NewNavigationRuntime creates a runtime. Chrome is not started until the first navigation or wait operation for a session.

func (r *NavigationRuntime) AutosaveConfig() *AutosaveConfig

AutosaveConfig returns the active autosave configuration.

func (r *NavigationRuntime) Close() error

Close releases all per-session browser engines.

func (r *NavigationRuntime) Handle(ctx context.Context, frame Frame) (any, []Warning, error)

Handle executes one navigation frame and returns JSON-serializable data together with network-policy warnings collected from the session engine. When autosave is active and the frame changed session state, a save is scheduled asynchronously so interactive commands never pay for I/O.

func (r *NavigationRuntime) SetAutosave(config *AutosaveConfig, store *state.Store)

SetAutosave updates the autosave configuration at runtime (used by `symbrowse daemon --restore` wiring and tests).

type NavigationRuntimeOptions struct {
	// Autosave enables automatic state persistence (issue B-36).
	Autosave *AutosaveConfig
	// StateStore is the store used by autosave and restore-on-start.
	StateStore *state.Store
	// RestoreOnStart maps a session name to the state to restore when the
	// session's browser is first launched.
	RestoreOnStart map[string]string
	// Profile is an existing Chrome profile directory to reuse instead of a
	// private session profile (issue B-38). The daemon emits a warning when
	// set, because a running Chrome locks the profile and the domain
	// allowlist cannot be enforced for a human-owned profile.
	Profile string
	// AllowedDomains activates the domain allowlist network policy for every
	// session engine (see chrome.Options.AllowedDomains).
	AllowedDomains []string
	// SSRFEnabled activates the SSRF guard for every session engine (see
	// chrome.Options.SSRFEnabled). It is the MCP-mode default.
	SSRFEnabled bool
	// AllowPrivate relaxes the SSRF guard (--allow-private).
	AllowPrivate bool
	// Headless launches Chrome headless (no GUI session); used in CI and
	// agent contexts.
	Headless bool
	// UploadDirs are the allowed roots for file uploads (issue #63);
	// paths outside are rejected by the path guard.
	UploadDirs []string
	// ScreenshotDirs are the allowed roots for screenshot files (issue #16);
	// without an explicit directory the first root (cache out dir) is used.
	ScreenshotDirs []string
	// Engine selects the engine implementation: "chrome" (default), "static"
	// (JS-free HTML reader, issue #64), or "safari-attach" (live Safari session
	// via Apple Events, issue #297).
	Engine string
	// Mode is the runtime mode (TTY or MCP). The safari-attach engine only
	// enables its interaction path in TTY mode; in MCP mode it is read-only
	// because no network layer means the SSRF guard cannot be enforced.
	Mode policy.Mode
	// CDPEndpoint attaches session engines to an existing DevTools endpoint
	// instead of launching Chrome (issue #296; flag, SYMBROWSE_CDP_ENDPOINT,
	// or config.toml). Attached engines do not own the browser lifetime.
	CDPEndpoint string
	// RequestTimeout is the per-command CDP budget for session engines
	// (chrome.Options.RequestTimeout; default 10s). E2E tests use a
	// generous budget because Chrome round-trips can stall for seconds on
	// loaded machines right after a sibling tab is created.
	RequestTimeout time.Duration
	// StaticGuard provides explicit guard options for the static engine.
	// When nil, hardened defaults (SSRFEnabled: true, RobotsEnabled: true)
	// with AllowPrivate propagated from options are used.
	StaticGuard *static.GuardOptions
}

NavigationRuntimeOptions configures the browser engines created per session.

type OOBRuntime

type OOBRuntime struct {
	// contains filtered or unexported fields
}

OOBRuntime wires the out-of-band channel (overlay + notification + blocking wait) into the daemon: handoff, approvals and watch all share it.

func NewOOBRuntime

func NewOOBRuntime(manager *oob.Manager, notifier *oob.Notifier, nav *NavigationRuntime, p *policy.Policy, mode policy.Mode) *OOBRuntime

NewOOBRuntime creates the OOB channel for one daemon.

func (*OOBRuntime) DecideAndConfirm

func (r *OOBRuntime) DecideAndConfirm(ctx context.Context, session, command, url string, timeout time.Duration) (bool, policy.Decision, string, error)

DecideAndConfirm is the policy gate used before executing a frame: when the effective decision is deny, the frame is refused; when it is confirm, the human is asked via the OOB channel. Returns (allowed, decision, decider, error); the decider is "guard" when the guard decided and "policy" otherwise (issue #52).

func (*OOBRuntime) Handle

func (r *OOBRuntime) Handle(ctx context.Context, frame Frame) (any, []Warning, error)

Handle executes OOB frames.

func (*OOBRuntime) RequestApproval

func (r *OOBRuntime) RequestApproval(ctx context.Context, session, command, url string, class policy.RiskClass, warnings []string, timeout time.Duration) (bool, *oob.Prompt, error)

RequestApproval runs the B-46 approval flow: the policy says "confirm", so the human is asked over the OOB channel. Timeout and cancellation both deny; only an explicit completion allows. The outcome is journaled by the caller.

func (*OOBRuntime) SetDecider

func (r *OOBRuntime) SetDecider(decide func(ctx context.Context, command, url string, mode policy.Mode, warnings []string) (policy.Decision, string, string, error))

SetDecider installs the guard-aware decision hook used by the approval gate (see PolicyRuntime.Decide).

func (*OOBRuntime) StartHandoff

func (r *OOBRuntime) StartHandoff(ctx context.Context, session, reason string, timeout time.Duration) (map[string]any, error)

StartHandoff runs the B-45 handoff: show the overlay with the reason, notify the human and block until completion, cancellation or timeout. Headless sessions fall back to notification + oob status.

type Options

type Options struct {
	SocketPath       string
	Session          string
	Handler          Handler
	Registry         *SessionRegistry
	IdleTimeout      time.Duration
	OperationTimeout time.Duration
	ReadTimeout      time.Duration
	PeerValidator    func(net.Conn) error
	Policy           PolicyStatus
	// CacheDir is the truncate-and-store output cache root (issue #23).
	// Frame max_tokens budgets are enforced against it; empty disables
	// budgets (the daemon fails closed when a budget is requested).
	CacheDir string
	// CacheTTL is the output cache entry lifetime (issue #23; default 24h).
	CacheTTL time.Duration
}

Options configures a Server. Zero durations use the production defaults.

type PolicyRuntime

type PolicyRuntime struct {
	// contains filtered or unexported fields
}

PolicyRuntime exposes the local policy engine and the optional guard delegation over the daemon protocol (issue #52).

func NewPolicyRuntime

func NewPolicyRuntime(stateDir string, mode policy.Mode) *PolicyRuntime

NewPolicyRuntime loads the policy from <state-dir>/policy.toml (missing file = built-in defaults) and detects the guard binary. The mode distinguishes MCP and TTY defaults.

func NewPolicyRuntimeWithGuard

func NewPolicyRuntimeWithGuard(stateDir string, mode policy.Mode, guard *policy.Guard) *PolicyRuntime

NewPolicyRuntimeWithGuard is NewPolicyRuntime with an explicit guard (nil disables delegation). Tests use it to inject a fake guard.

func (*PolicyRuntime) Decide

func (r *PolicyRuntime) Decide(ctx context.Context, command, url string, mode policy.Mode, warnings []string) (policy.Decision, string, string, error)

Decide resolves the effective decision for one command. When the guard is present and configured the verdict is delegated to it (command, class, domain and warnings as input); the guard's decision wins. A guard failure denies with a clear reason — never a silent allow. The returned decider is "guard" when the guard decided and "policy" otherwise; the returned reason explains the origin (rule:domain, default, guard:<reason>).

func (*PolicyRuntime) DeciderFor

func (r *PolicyRuntime) DeciderFor(command string) string

DeciderFor reports who would decide a command ("guard" or "policy") without invoking the guard (used by the journal for its decider field).

func (*PolicyRuntime) Guard

func (r *PolicyRuntime) Guard() *policy.Guard

Guard returns the configured guard delegation (nil when absent).

func (*PolicyRuntime) Handle

func (r *PolicyRuntime) Handle(ctx context.Context, frame Frame) (any, []Warning, error)

Handle executes policy frames.

func (*PolicyRuntime) Policy

func (r *PolicyRuntime) Policy() *policy.Policy

Policy returns the loaded policy (for the OOB approval gate).

func (*PolicyRuntime) PolicyFilePath

func (r *PolicyRuntime) PolicyFilePath() string

PolicyFilePath returns where the policy file is expected.

type PolicyStatus

type PolicyStatus struct {
	AllowedDomains []string `json:"allowed_domains,omitempty"`
	SSRFEnabled    bool     `json:"ssrf_enabled"`
	AllowPrivate   bool     `json:"allow_private"`
}

PolicyStatus reports the network-policy configuration of a running daemon. It is part of the daemon.status payload so clients (notably the MCP server) can verify that a pre-existing daemon enforces the policy they require.

type RecordedAction

type RecordedAction struct {
	Index        int    `json:"index"`
	Command      string `json:"command"`
	Selector     string `json:"selector,omitempty"`
	Value        string `json:"value,omitempty"`
	Role         string `json:"role,omitempty"`
	Name         string `json:"name,omitempty"`
	InputType    string `json:"input_type,omitempty"`
	Autocomplete string `json:"autocomplete,omitempty"`
}

RecordedAction is one captured session action during flow recording. The recorder resolves session-bound @eN refs to semantic selectors immediately, so the draft generation (in cmd/symbrowse) never needs engine access.

type Response

type Response struct {
	Success  bool      `json:"success"`
	Data     any       `json:"data,omitempty"`
	Error    *Error    `json:"error,omitempty"`
	Warnings []Warning `json:"warnings,omitempty"`
}

Response is one newline-delimited response returned by the daemon.

func ErrorResponse

func ErrorResponse(code, message string) Response

ErrorResponse creates a failed protocol response.

func SuccessResponse

func SuccessResponse(data any, warnings []Warning) Response

SuccessResponse creates a successful protocol response.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server serves newline-delimited JSON frames over a protected Unix socket.

func NewServer

func NewServer(options Options) *Server

NewServer constructs a daemon server without binding its socket.

func (*Server) Close

func (s *Server) Close() error

Close stops accepting new connections. Existing handlers are allowed to finish their current frame and connections close naturally.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe(ctx context.Context) error

ListenAndServe binds the socket and serves until ctx is canceled, Close is called, or the configured idle timeout expires.

func (*Server) Registry

func (s *Server) Registry() *SessionRegistry

Registry returns the daemon-local session registry.

func (*Server) SocketPath

func (s *Server) SocketPath() string

SocketPath returns the configured socket path.

type Session

type Session struct {
	Name             string
	PID              int
	UserDataDir      string
	BrowserContextID string
	// contains filtered or unexported fields
}

Session is a daemon-owned browser context. Its ref table is deliberately private: callers can only mutate it through the registry, which keeps each session's references isolated.

type SessionInfo

type SessionInfo struct {
	Name             string `json:"name"`
	PID              int    `json:"pid"`
	StartedAt        string `json:"started_at"`
	ActiveTabs       int    `json:"active_tabs"`
	LastActivity     string `json:"last_activity"`
	UserDataDir      string `json:"user_data_dir"`
	BrowserContextID string `json:"browser_context_id"`
	RefCount         int    `json:"ref_count"`
	Scope            string `json:"scope,omitempty"`
	OriginPath       string `json:"origin_path,omitempty"`
}

SessionInfo is the stable machine-readable shape used by session list/info.

type SessionListData

type SessionListData struct {
	SchemaVersion int           `json:"schema_version"`
	Sessions      []SessionInfo `json:"sessions"`
}

SessionListData is the stable payload returned by session.list.

type SessionRegistry

type SessionRegistry struct {
	// contains filtered or unexported fields
}

SessionRegistry owns all session state for one daemon instance. The current B-06 architecture uses one socket per session, so a production daemon normally contains one entry; keeping the registry daemon-local makes the boundary protocol-neutral and allows future shared-socket listing without a second state store.

func NewSessionRegistry

func NewSessionRegistry(options SessionRegistryOptions) *SessionRegistry

NewSessionRegistry constructs an empty registry. Session directories are created lazily by Ensure, so construction itself has no filesystem effects.

func (*SessionRegistry) Clear

func (r *SessionRegistry) Clear()

Clear drops all live session state while leaving profile directories intact. It is called when a daemon exits, including idle shutdown; a subsequent daemon has a fresh registry and must explicitly re-open a session.

func (*SessionRegistry) Ensure

func (r *SessionRegistry) Ensure(name string) (*Session, error)

Ensure returns the named session, creating its private profile and ref table if needed. Names are validated before being used as filesystem paths.

func (*SessionRegistry) Get

func (r *SessionRegistry) Get(name string) (SessionInfo, error)

Get returns a snapshot of one session's stable metadata.

func (*SessionRegistry) List

func (r *SessionRegistry) List() []SessionInfo

List returns session metadata in name order for deterministic JSON output.

func (*SessionRegistry) ListData

func (r *SessionRegistry) ListData() SessionListData

ListData is the protocol payload for session.list.

func (*SessionRegistry) Ref

func (r *SessionRegistry) Ref(name, key string) (string, error)

Ref resolves a session-local ref key.

func (*SessionRegistry) RefTable

func (r *SessionRegistry) RefTable(name string) (map[string]string, error)

RefTable returns a copy of the session's ref table.

func (*SessionRegistry) SetActiveTabs

func (r *SessionRegistry) SetActiveTabs(name string, count int) error

SetActiveTabs records the number of active tabs owned by a session.

func (*SessionRegistry) SetRef

func (r *SessionRegistry) SetRef(name, key, ref string) error

SetRef associates a stable ref key with a session-local reference.

func (*SessionRegistry) Touch

func (r *SessionRegistry) Touch(name string) error

Touch updates the last activity timestamp without changing session start time. It is safe to call for an unknown session; request handling uses Ensure first when a command creates or uses a session.

func (*SessionRegistry) UserDataRoot

func (r *SessionRegistry) UserDataRoot() string

UserDataRoot returns the root under which session-specific profiles live.

type SessionRegistryOptions

type SessionRegistryOptions struct {
	UserDataRoot string
	PID          int
	Now          func() time.Time
	Scope        string
	OriginPath   string
}

SessionRegistryOptions configures the in-memory registry and its private browser-profile root. UserDataRoot is injectable so tests never need to touch a real browser profile. Scope and OriginPath record where the session was created (issue B-37: worktree-scoped session ids).

type StartDaemonFunc

type StartDaemonFunc func(context.Context) error

StartDaemonFunc starts a daemon process and returns once it has been launched. Tests can inject an in-process starter or a deterministic hook.

type StateRuntime

type StateRuntime struct {
	// contains filtered or unexported fields
}

StateRuntime bridges the state store and the per-session navigation services: it captures and restores cookies/storage and reports store metadata. It owns no browser state itself.

func NewStateRuntime

func NewStateRuntime(store *state.Store, nav *NavigationRuntime) *StateRuntime

NewStateRuntime creates a state bridge for one store.

func (*StateRuntime) Handle

func (r *StateRuntime) Handle(ctx context.Context, frame Frame) (any, []Warning, error)

Handle executes state frames. Metadata-only commands never touch the browser; save/load require a session service.

func (*StateRuntime) Load

func (r *StateRuntime) Load(ctx context.Context, session, name string) (state.Metadata, []string, error)

Load restores a named state into the session browser.

func (*StateRuntime) ReportExpired

func (r *StateRuntime) ReportExpired()

ReportExpired logs expired states at daemon startup without touching them.

func (*StateRuntime) Save

func (r *StateRuntime) Save(ctx context.Context, session, name string) (state.Metadata, error)

Save captures the session's cookies and storage into a named state.

func (*StateRuntime) Store

func (r *StateRuntime) Store() *state.Store

Store exposes the underlying store (for metadata commands).

type TransportError added in v0.2.0

type TransportError struct {
	Code    string         `json:"code"`
	Message string         `json:"message"`
	Hint    string         `json:"hint,omitempty"`
	Details map[string]any `json:"details,omitempty"`
	Err     error          `json:"-"`
}

TransportError represents a client-side daemon transport, dial, or lifecycle failure.

func (*TransportError) Error added in v0.2.0

func (e *TransportError) Error() string

Error implements the error interface.

func (*TransportError) ErrorCode added in v0.2.0

func (e *TransportError) ErrorCode() string

ErrorCode exposes the stable error code for the unified output schema.

func (*TransportError) ErrorDetails added in v0.2.0

func (e *TransportError) ErrorDetails() map[string]any

ErrorDetails exposes diagnostic context.

func (*TransportError) ErrorHint added in v0.2.0

func (e *TransportError) ErrorHint() string

ErrorHint exposes the remediation hint.

func (*TransportError) Unwrap added in v0.2.0

func (e *TransportError) Unwrap() error

Unwrap returns the underlying error if any.

type VaultCredentials

type VaultCredentials struct {
	Username string
	Password string
}

VaultCredentials are the resolved username/password pair. The values live only in memory and must never be logged, journaled or returned.

type VaultResolver

type VaultResolver struct {
	LookPath func(string) (string, error)
	Run      func(context.Context, string, ...string) ([]byte, error)
}

VaultResolver resolves credential entries through the symvault CLI. It is a field-based struct so tests can inject fakes; production uses the real binary discovered on PATH.

func NewVaultResolver

func NewVaultResolver() *VaultResolver

NewVaultResolver creates a resolver backed by the symvault binary.

func (*VaultResolver) Resolve

func (r *VaultResolver) Resolve(ctx context.Context, entry string) (VaultCredentials, error)

Resolve fetches one vault entry and extracts username/password. Supported entry shapes: {"username": ..., "password": ...} JSON, "key: value" lines and "key=value" lines. The raw output is never returned to callers.

type Warning

type Warning struct {
	Kind     string `json:"kind"`
	Severity string `json:"severity,omitempty"`
	Message  string `json:"message"`
	Ref      string `json:"ref,omitempty"`
	Excerpt  string `json:"excerpt,omitempty"`
}

Warning is a non-fatal diagnostic attached to a response. Ref and Excerpt carry the optional element locator and evidence excerpt of prompt-injection detections (issue #28).

Jump to

Keyboard shortcuts

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