modelprofiles

package
v0.0.0-...-5272a8a Latest Latest
Warning

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

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

Documentation

Overview

Package modelprofiles owns the daemon Model Profiles catalog, per-Session RouteBinding state, the pure launch compiler, the thin same-protocol loopback routing runtime, and the durable route-state codec. It never stores or returns API-key values.

First-slice executors are Codex (Responses) and Claude Code (Anthropic Messages). OpenCode is not part of the public capability/compiler/router surface. ClientModelContract (immutable CLI catalog model + envelope) is separate from UpstreamModel (mutable route target).

Index

Constants

View Source
const (
	ClientCodex  = "codex"
	ClientClaude = "claude"
)

Product client ids (App-visible). Map 1:1 to internal executors today but are named as clients on the public wire.

View Source
const (
	HistoryStateEmpty            = "empty"
	HistoryStateMayContainOpaque = "may_contain_opaque"
)

History opacity tracking for Activate domain switching.

View Source
const (
	ReasoningClassNone     = "none"
	ReasoningClassStandard = "standard"
	ReasoningClassExtended = "extended"

	ThinkingClassNone     = "none"
	ThinkingClassStandard = "standard"
	ThinkingClassExtended = "extended"

	ToolClassNone     = "none"
	ToolClassFunction = "function"

	ModalityText  = "text"
	ModalityImage = "image"
)

Capability class / modality vocabulary (daemon-authorized envelopes only).

View Source
const (
	LoopbackAuthPlaceholder = "zen-loopback-placeholder-not-a-secret"
	EnvOpenAIAPIKey         = "OPENAI_API_KEY"
	EnvAnthropicAuthToken   = "ANTHROPIC_AUTH_TOKEN"
)

Fixed non-secret local placeholders injected into CLI env for clean-machine routed launches. Never stored in Profile/store/wire/history/logs as secrets. Router strips inbound auth and injects real upstream credentials.

View Source
const (
	CodeProfilesUnavailable        = "model_profiles_unavailable"
	CodeProfileNotFound            = "model_profile_not_found"
	CodeProfileConflict            = "model_profile_conflict"
	CodeProfileInvalid             = "model_profile_invalid"
	CodeProfileInUse               = "model_profile_in_use"
	CodeProfileUnsupported         = "model_profile_unsupported"
	CodeCredentialNotReady         = "model_profile_credential_not_ready"
	CodeCredentialStoreUnavailable = "credential_store_unavailable"
	CodeCredentialStoreFailed      = "credential_store_failed"
	CodeBindingNotFound            = "route_binding_not_found"
	CodeBindingConflict            = "route_binding_conflict"
	CodeBindingBusy                = "route_binding_busy"
	CodeBindingIncompatible        = "route_binding_incompatible"
	CodeBindingNotRouted           = "route_binding_not_routed"
	CodeContractUnverified         = "model_profile_contract_unverified"
	CodeUpstreamModelRequired      = "upstream_model_required"
	CodeModelUnsupported           = "model_unsupported"
	CodeReasoningEffortUnsupported = "reasoning_effort_unsupported"
	CodeDiscoveryCacheInvalid      = "provider_discovery_cache_invalid"
	CodeRouteListenerFailed        = "route_listener_failed"
	CodeRouteSnapshotInvalid       = "route_snapshot_invalid"
	CodeLaunchBypass               = "model_profile_bypass"
)

Typed control / wire error codes for App and CLI consumers.

View Source
const (
	// HistoryPortabilityStripOpaque means the Session has explicitly switched
	// HistoryDomain after opaque traffic and the router must strip provider-
	// specific opaque blocks on every later request (CLIs may resent them).
	HistoryPortabilityStripOpaque = "strip_opaque_provider_state"
	// HistoryDegradationStripOpaque is the honest activation fact recorded when
	// a cross-domain activate relies on that strip boundary.
	HistoryDegradationStripOpaque = "strip_opaque_provider_state"
)

History portability / degradation vocabulary (daemon + wire).

View Source
const (
	ProviderPresetOpenAI     = "openai"
	ProviderPresetOpenRouter = "openrouter"
	ProviderPresetAnthropic  = "anthropic"
	ProviderPresetDeepSeek   = "deepseek"
	ProviderPresetCustom     = "custom"
)

ProviderPresetID identifies a curated Provider template.

View Source
const (
	ModelSourceBundled    = "bundled"
	ModelSourceDiscovered = "discovered"
	ModelSourceLKG        = "lkg"
	ModelSourceManual     = "manual"
	ModelSourceCodexCache = "codex_cache"
)
View Source
const (
	RoutePathPrefix = "/r/"
	RouteAPIPrefix  = "/v1"
)
View Source
const (
	TakeoverStateActive   = "active"
	TakeoverStateInactive = "inactive"
	TakeoverStateDrifted  = "drifted"
	TakeoverStateBroken   = "broken"
)
View Source
const (
	ProtocolOpenAINative      = "openai_native"
	ProtocolOpenAIResponses   = "openai_responses"
	ProtocolAnthropicMessages = "anthropic_messages"
)

Profile protocols (catalog / capability matrix).

View Source
const (
	RouteProtocolResponses         = "responses"
	RouteProtocolAnthropicMessages = "anthropic_messages"
)

Route protocols spoken by the Zen-owned loopback (same-protocol pass-through).

View Source
const (
	ExecutorCodex  = "codex"
	ExecutorClaude = "claude"
)
View Source
const (
	AuthModeNone              = "none"
	AuthModeBearerEnv         = "bearer_env"
	AuthModeXAPIKeyEnv        = "x_api_key_env"
	AuthModeNativePassthrough = "native_passthrough"
)

Upstream auth injection modes (secret-free; values resolved at request time).

View Source
const (
	ActivationDefaultSelection = "default_selection"
	ActivationLaunch           = "launch"
	ActivationActiveSession    = "active_session"
)
View Source
const (
	ProjectionNativeArgs = "native_args"
	ProjectionEnvBaseURL = "env_base_url"
)
View Source
const (
	ContractProvenanceBuiltinCatalog = "builtin_catalog"
	ContractProvenanceVerifiedAlias  = "verified_alias"
	// ContractProvenanceConfiguredCompatibility means UpstreamEnvelope is the
	// daemon-owned ClientModelContract envelope applied as a configured
	// compatibility mapping — not a claim that upstream capabilities were probed.
	ContractProvenanceConfiguredCompatibility = "configured_compatibility"
	// ContractProvenanceOpaquePassthrough admits an exact, syntactically valid
	// model slug without claiming daemon-owned capability metadata for it.
	ContractProvenanceOpaquePassthrough = "opaque_passthrough"
)

ClientModelContract provenance. Strings never prove catalog metadata; an explicit verified source is required. Unverified / empty provenance fails closed.

View Source
const (
	// ReasoningEffortNone is the native Codex wire value for "no explicit
	// effort" (the model's documented default applies). Codex 0.147 models the
	// default as ReasoningEffort::None ("none" on the wire, "default" in the
	// TUI footer) and it is the ONLY native value that resets an explicit
	// thread effort. Zen's empty-effort (model default) semantic maps to this
	// value at every native boundary and is normalized back to "" at every
	// Zen boundary.
	ReasoningEffortNone    = "none"
	ReasoningEffortMinimal = "minimal"
	ReasoningEffortLow     = "low"
	ReasoningEffortMedium  = "medium"
	ReasoningEffortHigh    = "high"
	ReasoningEffortXHigh   = "xhigh"
	ReasoningEffortMax     = "max"
)

Codex Reasoning Effort values (OpenAI Responses API `reasoning.effort`, mirrored by Codex `model_reasoning_effort`). `none`/`max`/`ultra` are ChatGPT-tier presets and are never Zen-admitted Session efforts.

View Source
const ActiveSwitchRouteBinding = "route_binding"

ActiveSwitchRouteBinding is advertised only for routed profile protocols.

View Source
const ConnectionScopeAccount = "account"

ConnectionScopeAccount marks a durable Provider account connection. Protocol, client model, auth mode, and executor are compiled per client at launch/activate — never stored as the public connection identity.

View Source
const ContractProvenanceCodexCatalog = "codex_catalog"

ContractProvenanceCodexCatalog marks model metadata pinned from the Codex CLI / OpenAI model catalog contract (versioned, evidence-based).

View Source
const DefaultGatewayListenAddr = "127.0.0.1:38777"

DefaultGatewayListenAddr is the stable machine-level Codex gateway endpoint. The takeover projection bakes this address into ~/.codex/config.toml exactly once; every daemon restart must bind the same address (or repair the projection) before takeover can claim active.

View Source
const DiscoveryTTL = 5 * time.Minute

DiscoveryTTL is the bounded live-model refresh window.

View Source
const DurableRouteSchemaVersion = 4
View Source
const EnvAnthropicBaseURL = "ANTHROPIC_BASE_URL"

EnvAnthropicBaseURL is the Claude Code gateway override.

View Source
const GatewayProviderName = "zen-gateway"

GatewayProviderName is the Codex model_provider identity projected into the CLI's native config by takeover. It is also the provider table key.

View Source
const HistoryDomainNone = "none"

Opaque-history domains are provider/model-specific strings from a trusted verifier (see DeriveOpaqueHistoryDomain). There is no protocol-wide default compatibility domain.

View Source
const MaxModelIDLength = 256

MaxModelIDLength caps opaque model identifiers (including org/model forms).

View Source
const MaxProviderNameLength = 64

MaxProviderNameLength caps the user-facing Provider display name. Names are the primary user-facing identity and are unique case-insensitively across the Provider list.

View Source
const MaxRouteHistoryEvents = 64

MaxRouteHistoryEvents bounds in-memory / durable activation history growth.

View Source
const MaxRouteRequestBodyBytes = 8 << 20

Variables

View Source
var (
	ErrNotFound            = errors.New("model profile not found")
	ErrConflict            = errors.New("model profile revision conflict")
	ErrInvalid             = errors.New("invalid model profile")
	ErrUnsupportedExecutor = errors.New("executor does not support model profiles")
	ErrUnsupportedProtocol = errors.New("protocol is not supported for executor")
	ErrDuplicateID         = errors.New("model profile id already exists")
	// ErrDuplicateName means another Provider already uses the same display
	// name (case-insensitive). Names are the user-facing identity.
	ErrDuplicateName              = errors.New("provider name already exists")
	ErrRouteRequired              = errors.New("zen loopback route url is required")
	ErrBindingNotFound            = errors.New("session route binding not found")
	ErrBindingConflict            = errors.New("session route binding generation conflict")
	ErrBindingExecutorMismatch    = errors.New("route binding cannot change executor")
	ErrBindingSessionRequired     = errors.New("session id is required for route binding")
	ErrBindingNotRouted           = errors.New("session is not routed; active switch unsupported")
	ErrBindingProtocolChange      = errors.New("route protocol class cannot change on active switch")
	ErrBindingContractChange      = errors.New("client model contract cannot change on active switch")
	ErrBindingHistoryDomain       = errors.New("opaque-history compatibility domain mismatch")
	ErrBindingHistoryState        = errors.New("opaque-history state prevents domain change")
	ErrRequestBodyNotPortable     = errors.New("request history is not portable across providers")
	ErrBindingBusy                = errors.New("route has in-flight requests; cross-domain activate denied")
	ErrContractUnverified         = errors.New("profile contract provenance is unverified")
	ErrEnvelopeIncompatible       = errors.New("upstream capability envelope cannot support client envelope")
	ErrCredentialNotReady         = errors.New("credential environment variable is not ready")
	ErrCredentialStoreUnavailable = errors.New("credential store unavailable")
	ErrCredentialStoreFailed      = errors.New("credential store operation failed")
	ErrDiscoveryCacheInvalid      = errors.New("provider discovery cache invalid")
	ErrDiscoveryPersistFailed     = errors.New("provider discovery cache persist failed")
	ErrInternalNotWire            = errors.New("modelprofiles: internal type cannot be JSON-marshaled; use ToWire")
	ErrPersistDirSync             = errors.New("model profile file renamed but directory sync failed")

	ErrRouteNotFound               = errors.New("route not found")
	ErrRouteAdmissionDenied        = errors.New("route admission denied")
	ErrRoutePathMismatch           = errors.New("route path mismatch")
	ErrRouteProtocolMismatch       = errors.New("route protocol mismatch")
	ErrRouteMethodMismatch         = errors.New("route method mismatch")
	ErrRouteWebSocket              = errors.New("websocket upgrade rejected")
	ErrRequestBodyTooLarge         = errors.New("request body too large")
	ErrRequestBodyMalformed        = errors.New("request body malformed")
	ErrResponsesFeatureUnsupported = errors.New("responses feature unsupported by upstream capability envelope")
	ErrUpstreamInvalid             = errors.New("upstream invalid")
	// ErrUpstreamModelRequired means a connection has no explicit upstream model:
	// compile produced only a probe placeholder (client contract id), which must
	// never enter a RouteBinding. Run discovery and select a model first.
	ErrUpstreamModelRequired = errors.New("connection has no upstream model; run discovery and select a model")
	// ErrModelUnsupported means the selected model has no daemon-owned metadata
	// (not in the versioned Codex model catalog). Managed Codex fails closed:
	// an unknown model is never launched, activated, or routed under a hidden
	// compatibility identity.
	ErrModelUnsupported = errors.New("model is not supported for managed Codex")
	// ErrReasoningEffortUnsupported means the requested Reasoning Effort is not
	// admitted by the target Codex client model's daemon-owned effort contract.
	// Activation fails inline and the old route is kept — an invalid effort is
	// never sent upstream.
	ErrReasoningEffortUnsupported = errors.New("reasoning effort is not supported by the client model")
	ErrUpstreamSSRF               = errors.New("upstream address blocked")
	ErrUpstreamRedirect           = errors.New("upstream redirect rejected")
	ErrRouteSnapshotInvalid       = errors.New("route snapshot invalid")
	ErrProfileInUse               = errors.New("model profile is in use by a session")
	ErrListenerFailed             = errors.New("route listener failed")
	ErrLaunchCleanupIncomplete    = errors.New("launch cleanup incomplete")
	// ErrSessionStillLive means KillSession failed and the Session is still
	// confirmed present — route ownership must be preserved.
	ErrSessionStillLive = errors.New("session still live after kill failure")
	// ErrSessionLivenessUnknown means a post-kill liveness probe failed or was
	// ambiguous — not proof of absence, so the route must be preserved.
	ErrSessionLivenessUnknown = errors.New("session liveness probe ambiguous")
)

Functions

func AuthReady

func AuthReady(authMode, envName string, lookup func(string) (string, bool)) bool

AuthReady reports whether the auth mode can be satisfied from process env. Launch/bind/compile must use connectionAuthReady so a stored secret counts.

func CleanupCodexControlArtifacts

func CleanupCodexControlArtifacts(socketPath string) error

CleanupCodexControlArtifacts terminates a Session's Codex app-server (via the recorded pid, verified against the process cmdline to guard against pid reuse) and removes the daemon-owned socket, pid, and log files. Idempotent and safe to call after the Session is confirmed dead.

func CodexControlLogPath

func CodexControlLogPath(socketPath string) string

CodexControlLogPath returns the per-session app-server log path.

func CodexControlPidPath

func CodexControlPidPath(socketPath string) string

CodexControlPidPath returns the daemon-owned pid file for a Session's Codex app-server control socket. The launch wrapper writes the app-server PID here so Session teardown can kill an orphaned app server and startup can sweep stale artifacts.

func ControlErrorCode

func ControlErrorCode(err error) string

ControlErrorCode maps typed package errors to stable wire codes.

func CredentialReady

func CredentialReady(envName string, lookup func(string) (string, bool)) bool

CredentialReady reports whether a named credential environment variable is present and non-empty. The value is never returned.

func CredentialRefFor

func CredentialRefFor(connectionID string) string

CredentialRefFor returns the opaque credential key for a connection. It is secret-free and safe to persist on routes/bindings.

func DefaultCodexConfigPath

func DefaultCodexConfigPath() string

DefaultCodexConfigPath resolves the CLI's native Codex config path, honoring CODEX_HOME.

func DeriveOpaqueHistoryDomain

func DeriveOpaqueHistoryDomain(protocol, providerID, upstreamBaseURL, upstreamModel, clientContractID string) string

DeriveOpaqueHistoryDomain builds a provider/model/contract-specific opaque domain. Not a protocol-wide default; used by trusted verifiers / tests. clientContractID is the daemon-known ClientModel / compatibility contract id.

func EncodeDurableSnapshot

func EncodeDurableSnapshot(states []SessionRouteState) ([]byte, error)

EncodeDurableSnapshot encodes SessionRouteState records for daemon-owned 0600 persistence. Credential values and readiness bools are never included.

func EndpointAllowedForProtocol

func EndpointAllowedForProtocol(routeProtocol string, endpoint RouteEndpoint) bool

EndpointForRouteProtocol returns admitted endpoints for a route protocol. GET /v1/models is the local catalog surface and is admitted for every protocol; all other endpoints are POST-only request paths.

func LoadGatewayState

func LoadGatewayState(path string) (listenAddr, upstreamProfileID string, err error)

LoadGatewayState reads the durable gateway state.

func LoopbackClaudeRootURL

func LoopbackClaudeRootURL(listenAddr, routeID string) (string, error)

LoopbackClaudeRootURL builds http://127.0.0.1:<port>/r/<routeID> for ANTHROPIC_BASE_URL (CLI requests /v1/messages, optionally ?beta=true).

func LoopbackCodexBaseURL

func LoopbackCodexBaseURL(listenAddr, routeID string) (string, error)

LoopbackCodexBaseURL builds http://127.0.0.1:<port>/r/<routeID>/v1 for Codex openai_base_url (CLI appends /responses under /v1).

func LoopbackRouteBaseURL

func LoopbackRouteBaseURL(listenAddr, routeID string) (string, error)

LoopbackRouteBaseURL is an alias for Codex base (tests / legacy callers).

func NewSafeHTTPClient

func NewSafeHTTPClient(timeout time.Duration) *http.Client

NewSafeHTTPClient builds an upstream client that never uses ambient HTTP proxy environment variables, never follows redirects, and dials through a resolver that permits explicit public/private model endpoints while blocking metadata, link-local, multicast, and implicit DNS-to-loopback targets.

func ProfileHotSwitchable

func ProfileHotSwitchable(profileProtocol string) bool

ProfileHotSwitchable reports whether a profile class supports route activation.

func RequireAuth

func RequireAuth(authMode, envName string, lookup func(string) (string, bool)) error

RequireAuth fails closed when the auth mode needs an env that is missing/empty.

func RequireContractProvenance

func RequireContractProvenance(provenance string) error

RequireContractProvenance fails closed unless provenance is an allowed authorized source label. This checks vocabulary for daemon-admitted identities; it does not trust TOML self-claims.

func RouteProtocolFor

func RouteProtocolFor(profileProtocol string) (routeProtocol string, ok bool)

RouteProtocolFor returns the Zen loopback protocol for a profile protocol.

func SetDeepSeekSanitizeRejectHook

func SetDeepSeekSanitizeRejectHook(hook func(path string, structure map[string]any))

SetDeepSeekSanitizeRejectHook installs a test-only capture for rejected DeepSeek Responses requests. structure is secret-free JSON shape only (keys/types/enum-ish scalars); never request text or secrets.

func SupportedProtocols

func SupportedProtocols(executorID string) []string

SupportedProtocols returns profile protocols valid for an executor.

func SupportsExecutor

func SupportsExecutor(executorID string) bool

SupportsExecutor reports whether the executor participates in Model Profiles.

func SweepCodexControlArtifacts

func SweepCodexControlArtifacts(socketPath string)

SweepCodexControlArtifacts removes stale daemon-owned app-server artifacts for a restored Session binding: when the recorded app-server pid is dead or no longer matches this socket, the socket/pid/log files are daemon-owned leftovers and are removed. A live matching app server is left untouched so the restored Session keeps its native control surface after a daemon restart.

func UpstreamRequestURL

func UpstreamRequestURL(upstreamBase, apiPath string) (string, error)

UpstreamRequestURL joins an upstream base URL with the API path under /v1/... RawQuery from the inbound request must be attached by the caller.

func ValidateAuthMode

func ValidateAuthMode(authMode, credentialEnv, baseURL, protocol string) error

ValidateAuthMode checks auth_mode + credential_env pairing.

func ValidateCredentialEnv

func ValidateCredentialEnv(name string) error

ValidateCredentialEnv accepts only POSIX-like environment variable names.

func ValidateLoopbackRouteURL

func ValidateLoopbackRouteURL(raw string) error

ValidateLoopbackRouteURL requires an HTTP(S) loopback URL with no userinfo, query, or fragment. Secrets must never appear in the route URL.

func ValidateModelID

func ValidateModelID(model string) error

ValidateModelID accepts opaque model identifiers including org/model forms.

func ValidateProfile

func ValidateProfile(profile Profile) error

ValidateProfile checks durable profile fields without reading secret values.

func ValidateProviderName

func ValidateProviderName(name string) error

ValidateProviderName checks the user-facing Provider display name: trimmed, non-empty, length-bounded, and free of control characters. Uniqueness (case-insensitive) is enforced by the Store against the live catalog.

func ValidateUpstreamBaseURL

func ValidateUpstreamBaseURL(raw string) error

ValidateUpstreamBaseURL accepts explicitly configured HTTP(S) gateways while rejecting malformed URLs and infrastructure metadata targets.

func WirePersistFields

func WirePersistFields(p PersistResult) (outcome string, durable *bool)

WirePersistFields projects PersistResult onto control PersistenceOutcome fields.

Types

type BuiltinEnvelopeVerifier

type BuiltinEnvelopeVerifier struct{}

BuiltinEnvelopeVerifier is the Stage 2B daemon contract authority. It admits profiles whose ClientModel matches a daemon-known Codex/Claude client compatibility contract. Provider ID/label, Gateway URL, and upstream model ID may be any ValidateProfile-legal values; UpstreamEnvelope is the selected daemon-owned client contract envelope (configured compatibility mapping), not a claim that upstream capabilities were discovered. Profile TOML provenance/capability/history claims are never trusted.

func (BuiltinEnvelopeVerifier) VerifyProfileContract

func (BuiltinEnvelopeVerifier) VerifyProfileContract(profile Profile) (VerifiedProfileContract, error)

VerifyProfileContract admits every syntactically valid model identity when the executor/protocol pairing is supported. The daemon-owned catalog adds metadata for known models; it is never an identity allowlist.

Unified identity: for managed Codex the selected model slug is BOTH the Codex session model (ClientModelID) and the routed upstream model (UpstreamModelID) — the daemon never admits a hidden compatibility model.

type CapabilityEnvelope

type CapabilityEnvelope struct {
	ContextWindowTokens int64
	ReasoningClass      string
	ThinkingClass       string
	ToolClass           string
	Modalities          []string
}

CapabilityEnvelope is the daemon-authorized capability surface for a model identity.

func DefaultTestEnvelope

func DefaultTestEnvelope() CapabilityEnvelope

DefaultTestEnvelope is a minimal text+function envelope for package tests.

type Catalog

type Catalog struct {
	Revision int64             `json:"revision"`
	Profiles []Profile         `json:"profiles"`
	Defaults map[string]string `json:"defaults"`
}

Catalog is the secret-free view of the durable profile store (settings CRUD).

type CatalogProjection

type CatalogProjection struct {
	Catalog Catalog
	Views   []ProfileView
}

CatalogProjection is an atomic catalog + views snapshot for control-plane list/mutation replies (same Store read lock / Owner transaction boundary).

type ClientContractDescriptor

type ClientContractDescriptor struct {
	ExecutorID  string             `json:"executor_id"`
	ClientModel string             `json:"client_model"`
	Provenance  string             `json:"provenance"`
	Envelope    CapabilityEnvelope `json:"envelope"`
}

ClientContractDescriptor is the secret-free App-facing description of one daemon-known Codex/Claude client compatibility contract.

func BuiltinClientContractDescriptors

func BuiltinClientContractDescriptors() []ClientContractDescriptor

BuiltinClientContractDescriptors returns the daemon-owned client contract vocabulary for App editors (secret-free). Codex descriptors come from the versioned model catalog; Claude descriptors from the Claude contracts.

type CodexEffortContractSnapshot

type CodexEffortContractSnapshot struct {
	ClientModel string   `json:"client_model"`
	Default     string   `json:"default"`
	Supported   []string `json:"supported"`
}

CodexEffortContractSnapshot is the secret-free App-facing projection of one model's Reasoning Effort contract.

func CodexEffortContractSnapshots

func CodexEffortContractSnapshots() []CodexEffortContractSnapshot

CodexEffortContractSnapshots returns the daemon-owned effort vocabulary for every known Codex model with an effort contract (secret-free).

type CodexModelCatalogWireEntry

type CodexModelCatalogWireEntry struct {
	Slug                       string                       `json:"slug"`
	DisplayName                string                       `json:"display_name,omitempty"`
	DefaultReasoningLevel      string                       `json:"default_reasoning_level,omitempty"`
	SupportedReasoningLevels   []CodexReasoningEffortPreset `json:"supported_reasoning_levels"`
	ContextWindow              int64                        `json:"context_window,omitempty"` // 0 = unknown, omitted (native fallback)
	ShellType                  string                       `json:"shell_type,omitempty"`
	Visibility                 string                       `json:"visibility,omitempty"`
	SupportedInAPI             bool                         `json:"supported_in_api"`
	Priority                   int                          `json:"priority"`
	BaseInstructions           string                       `json:"base_instructions"`
	SupportVerbosity           bool                         `json:"support_verbosity"`
	TruncationPolicy           CodexTruncationPolicyConfig  `json:"truncation_policy"`
	SupportsParallelToolCalls  bool                         `json:"supports_parallel_tool_calls"`
	ExperimentalSupportedTools []string                     `json:"experimental_supported_tools"`
}

CodexModelCatalogWireEntry is the Codex ModelsResponse model entry shape (codex model_catalog_json / GET /v1/models contract). Unknown models are never projected here.

The Codex CLI >= 0.147 ModelInfo serde contract requires every field below that has no serde default: supported_in_api, priority, base_instructions, support_verbosity, truncation_policy, supports_parallel_tool_calls, experimental_supported_tools, and supported_reasoning_levels. Omitting any of them makes codex exit at config load ("missing field ..."), which kills the host tmux session and drives the brain host replacement loop. context_window is the one capability claim resolved evidence-based (installed Codex catalog cache, then daemon-owned pinned catalog) and omitted for unknown models so the native CLI applies its own fallback — it is never fabricated.

type CodexModelMetadata

type CodexModelMetadata struct {
	// Slug is the exact model identity — the Codex session model, the routed
	// upstream model, and the UI-visible model are this one slug.
	Slug string
	// DisplayName is the catalog display label (evidence-based when known).
	DisplayName string
	Envelope    CapabilityEnvelope
	// Effort contract (nil = no configurable Reasoning Effort).
	Effort *codexEffortContract
	// Provenance is the daemon-owned evidence label for this entry.
	Provenance string
}

CodexModelMetadata is the daemon-owned, versioned, evidence-based metadata for one known Codex model identity. Entries are pinned from the Codex CLI model catalog / OpenAI Responses model contract; unknown models resolve nowhere and fail closed for managed Codex (never masquerade under another identity).

func CodexModelCatalogEntries

func CodexModelCatalogEntries() []CodexModelMetadata

CodexModelCatalogEntries returns a clone of the daemon-owned catalog (secret-free; deterministic order).

type CodexModelsResponse

type CodexModelsResponse struct {
	Models []CodexModelCatalogWireEntry `json:"models"`
}

CodexModelsResponse is the Codex-expected /v1/models + model_catalog_json envelope (`models` array — NOT the OpenAI list `data` shape).

func CodexModelsResponseForEntries

func CodexModelsResponseForEntries(entries []ProviderModelEntry) CodexModelsResponse

func CodexModelsResponseForModels

func CodexModelsResponseForModels(models []string) CodexModelsResponse

CodexModelsResponseForModels projects the exact known-model subset.

type CodexReasoningEffortPreset

type CodexReasoningEffortPreset struct {
	Effort      string `json:"effort"`
	Description string `json:"description,omitempty"`
}

CodexReasoningEffortPreset mirrors the Codex model catalog entry shape (`supported_reasoning_levels` items: effort + description).

type CodexTruncationPolicyConfig

type CodexTruncationPolicyConfig struct {
	Mode  string `json:"mode"`
	Limit int64  `json:"limit"`
}

CodexTruncationPolicyConfig is the Codex ModelInfo truncation_policy wire shape: the tool-output truncation contract of the running model (mode is "bytes" or "tokens"). Required by the Codex CLI >= 0.147 deserializer.

type CompileOptions

type CompileOptions struct {
	LoopbackRouteURL        string
	CatalogRevision         int64
	CodexModelCatalogPath   string // per-connection Codex ModelsResponse JSON (responses protocol)
	Lookup                  func(string) (string, bool)
	Credentials             CredentialStore
	Verifier                ProfileContractVerifier
	VerifiedProfileContract VerifiedProfileContract
	// CodexControlSocket, when set, launches the Codex session in app-server
	// live-control mode: a headless `codex app-server` owns the thread and the
	// TUI attaches via `--remote`, exposing the native thread/settings/update
	// mutation surface to the daemon. Only meaningful for ExecutorCodex with
	// the responses route protocol.
	CodexControlSocket string
}

CompileOptions configures Compile, including required contract authorization. Supply Verifier or VerifiedProfileContract; Profile TOML claims are never sufficient. Credentials is consulted for readiness only; secret values never enter launch env.

type ContractAuth

type ContractAuth struct {
	Verifier ProfileContractVerifier
	Verified VerifiedProfileContract
}

ContractAuth authorizes contract establishment for Bind/Compile/Activate/Restore.

type CredentialStore

type CredentialStore interface {
	// Available reports whether the backend can accept writes.
	Available() bool
	Set(ref, secret string) error
	Get(ref string) (string, bool, error)
	Delete(ref string) error
	// Refs returns the opaque refs currently stored (never secret values).
	Refs() ([]string, error)
}

CredentialStore is the daemon secret vault for Provider API keys. Implementations must never log, serialize, or return secrets through public projections — only Set/Get/Delete/Refs of opaque refs.

type DiscoverProviderModelsResult

type DiscoverProviderModelsResult struct {
	Entries            []ProviderModelEntry
	PersistenceDurable bool
	PersistenceWarning string
}

DiscoverProviderModelsResult is live discovery plus honest LKG persistence.

type ExecutorCapabilities

type ExecutorCapabilities struct {
	ExecutorID     string               `json:"executor_id"`
	Supported      bool                 `json:"supported"`
	Protocols      []ProtocolCapability `json:"protocols,omitempty"`
	RouteProtocols []string             `json:"route_protocols,omitempty"`
	Projection     string               `json:"projection,omitempty"`
}

ExecutorCapabilities advertises launch projection and per-protocol switch support.

func CapabilitiesFor

func CapabilitiesFor(executorID string) ExecutorCapabilities

CapabilitiesFor returns honest launch/route/switch capabilities.

type FileCredentialStore

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

FileCredentialStore is the production secret store for the headless Zen daemon. The parent directory is private and every committed file is 0600, so Provider credentials do not depend on a desktop Secret Service being active.

func NewFileCredentialStore

func NewFileCredentialStore(path string) (*FileCredentialStore, error)

func (*FileCredentialStore) Available

func (s *FileCredentialStore) Available() bool

func (*FileCredentialStore) Delete

func (s *FileCredentialStore) Delete(ref string) error

func (*FileCredentialStore) Get

func (s *FileCredentialStore) Get(ref string) (string, bool, error)

func (*FileCredentialStore) Refs

func (s *FileCredentialStore) Refs() ([]string, error)

Refs returns the stored refs sorted (never secret values).

func (*FileCredentialStore) Set

func (s *FileCredentialStore) Set(ref, secret string) error

type Gateway

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

Gateway is Zen's stable loopback Codex endpoint. It proxies requests to the currently selected upstream connection, preserving the request bytes and client model exactly. Provider switching swaps the upstream atomically; the next request from every routed Codex process uses the new connection without CLI restart, Session kill/resume, or model substitution.

func NewGateway

func NewGateway(addr string, creds CredentialStore, opts ...GatewayOption) *Gateway

NewGateway constructs the machine-level Codex gateway. addr is the stable loopback listen address (DefaultGatewayListenAddr in production).

func (*Gateway) ActualAddr

func (g *Gateway) ActualAddr() string

ActualAddr returns the bound listener address (useful when listening on :0 in tests). Empty when not listening.

func (*Gateway) Addr

func (g *Gateway) Addr() string

Addr returns the configured listen address.

func (*Gateway) ClearUpstream

func (g *Gateway) ClearUpstream()

ClearUpstream removes the upstream; routed requests fail honestly until a Provider is selected.

func (*Gateway) Close

func (g *Gateway) Close() error

Close stops the gateway listener.

func (*Gateway) Listen

func (g *Gateway) Listen() error

Listen binds the stable loopback address and serves the gateway. It fails closed when the address is taken (another daemon, or a stale takeover).

func (*Gateway) Listening

func (g *Gateway) Listening() bool

Listening reports whether the gateway listener is bound.

func (*Gateway) ServeHTTP

func (g *Gateway) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP implements the loopback gateway handler. Every /v1/* request is proxied to the selected upstream with the request body preserved exactly; nothing is rewritten (model, effort, and client payload stay byte-identical).

func (*Gateway) SetGatewayStatePath

func (g *Gateway) SetGatewayStatePath(path string)

SetGatewayStatePath binds the durable gateway state file (listen address and upstream profile id) so restart restores the same endpoint.

func (*Gateway) SetUpstream

func (g *Gateway) SetUpstream(upstream GatewayUpstream)

SetUpstream atomically swaps the gateway's upstream connection. The next request uses the new connection; the running Codex processes are untouched.

func (*Gateway) Upstream

func (g *Gateway) Upstream() (GatewayUpstream, bool)

Upstream returns the current upstream connection.

type GatewayOption

type GatewayOption func(*Gateway)

GatewayOption configures Gateway construction (tests).

func WithGatewayClient

func WithGatewayClient(client *http.Client) GatewayOption

WithGatewayClient overrides the upstream HTTP client (tests).

func WithGatewayLookup

func WithGatewayLookup(lookup func(string) (string, bool)) GatewayOption

WithGatewayLookup overrides credential env resolution (tests).

func WithGatewayMaxBody

func WithGatewayMaxBody(n int64) GatewayOption

WithGatewayMaxBody overrides the bounded request body size (tests).

type GatewayUpstream

type GatewayUpstream struct {
	ProfileID     string
	BaseURL       string
	Protocol      string
	AuthMode      string
	CredentialEnv string
	CredentialRef string
}

GatewayUpstream is the atomic upstream connection state of the machine-level gateway. It is derived from one Zen Provider connection (profile) and never carries secrets.

func GatewayUpstreamFromProfile

func GatewayUpstreamFromProfile(profile Profile) GatewayUpstream

GatewayUpstreamFromProfile derives the gateway upstream connection from a Zen Provider profile. Secret-free.

type LaunchCleanupResult

type LaunchCleanupResult struct {
	Persist PersistResult
	Err     error
}

LaunchCleanupResult is the typed compensation outcome after a failed watcher create or not-applied CommitLaunch.

func CleanupFailedLaunch

func CleanupFailedLaunch(
	owner LaunchRouteOwner,
	provisionalID, agentID string,
	kill func(string) error,
	probe func(string) (SessionLiveness, error),
) LaunchCleanupResult

CleanupFailedLaunch compensates a failed create/commit/attach path. It kills the Session (or requires KillSession to report idempotent missing) before AbortLaunch/ReleaseSession. A non-missing kill error, delegated resource cleanup failure, or ambiguous liveness probe preserves the exact provisional and/or committed route and surfaces retryable cleanup state.

type LaunchRouteOwner

type LaunchRouteOwner interface {
	AbortLaunch(provisionalID string) (PersistResult, error)
	ReleaseSession(sessionID string) (PersistResult, error)
}

LaunchRouteOwner is the Abort/Release surface used by failed-launch compensation. *Owner implements it; callers may pass any route lifecycle that owns those ops.

type ListenerFile

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

ListenerFile persists the loopback Router listen address (host:port only).

func NewListenerFile

func NewListenerFile(path string) (*ListenerFile, error)

NewListenerFile constructs a listener-state owner at path.

func (*ListenerFile) Load

func (f *ListenerFile) Load() (string, error)

Load returns the persisted listen address, or "" when missing.

func (*ListenerFile) Path

func (f *ListenerFile) Path() string

Path returns the durable file path.

func (*ListenerFile) RemoveDurable

func (f *ListenerFile) RemoveDurable() error

RemoveDurable removes the listener file and dirsyncs the parent when present.

func (*ListenerFile) RestoreBytes

func (f *ListenerFile) RestoreBytes(raw []byte) error

RestoreBytes writes exact prior metadata bytes via temp+fsync+rename+dirsync.

func (*ListenerFile) Save

func (f *ListenerFile) Save(listenAddr string) error

Save persists listenAddr at 0600.

func (*ListenerFile) SetDirSync

func (f *ListenerFile) SetDirSync(fn func(dir string) error)

SetDirSync installs a test seam for directory fsync after rename/remove.

func (*ListenerFile) SetPersistHook

func (f *ListenerFile) SetPersistHook(hook func(phase string) error)

SetPersistHook installs a test failpoint. Phases: before_write, after_write, before_rename, after_rename, before_dirsync, after_dirsync, before_remove, after_remove.

func (*ListenerFile) SetReadFile

func (f *ListenerFile) SetReadFile(fn func(path string) ([]byte, error))

SetReadFile installs a test seam for listener metadata reads.

type MemoryCredentialStore

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

MemoryCredentialStore is a test fake. It never persists to disk.

func NewMemoryCredentialStore

func NewMemoryCredentialStore() *MemoryCredentialStore

NewMemoryCredentialStore returns an available in-memory fake.

func (*MemoryCredentialStore) Available

func (m *MemoryCredentialStore) Available() bool

func (*MemoryCredentialStore) Delete

func (m *MemoryCredentialStore) Delete(ref string) error

func (*MemoryCredentialStore) Get

func (m *MemoryCredentialStore) Get(ref string) (string, bool, error)

func (*MemoryCredentialStore) Refs

func (m *MemoryCredentialStore) Refs() ([]string, error)

Refs returns the stored refs sorted (never secret values).

func (*MemoryCredentialStore) Set

func (m *MemoryCredentialStore) Set(ref, secret string) error

func (*MemoryCredentialStore) SetAvailable

func (m *MemoryCredentialStore) SetAvailable(ok bool)

func (*MemoryCredentialStore) SetFail

func (m *MemoryCredentialStore) SetFail(set, get, del error)

func (*MemoryCredentialStore) SnapshotRefs

func (m *MemoryCredentialStore) SnapshotRefs() []string

SnapshotRefs returns stored refs only (never secret values) for tests.

type Owner

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

Owner is the production lifecycle owner for catalog + RouteTable + loopback Router. All RouteTable mutations that touch durable state run under Owner.mu as mutate+persist transactions with snapshot rollback on save failure.

The loopback listener is started only when live routes are restored or on the first managed launch. Cold installs with an empty catalog and no routes stay inert: no listen socket and no listener-state file write.

func StartOwner

func StartOwner(cfg OwnerConfig) (*Owner, error)

StartOwner loads catalog + durable routes. Missing profile/route files are OK (empty). Malformed route snapshots fail closed. Routes whose contract no longer verifies under the current daemon authority are still restored and kept serving — drift is advisory (reported via RestoreContractNotices for startup logging), never destructive, so a snapshot written under an older daemon contract can never brick startup nor drop a live Session. The restored binding remains authoritative at the Router boundary: stale request payloads are normalized to it, while only an explicit Codex model-switch signal may mutate the Session runtime.

Listener semantics:

  • Live (committed) routes: bind the persisted (or PreferAddr) port or fail closed, then serve the Router and refresh listener-state.
  • No live routes: remain inert — no loopback listener and no listener-state write. Stale/malformed listener metadata is ignored, not rewritten. Catalog CRUD works; the listener starts atomically on first managed launch.

pending:* provisional bindings are cleanup records, never live Sessions. On start they are quarantined and removed (and listener metadata cleared when no live routes remain) before hasRoutes / sticky listen. Failure to persist that sweep fails StartOwner closed.

func (*Owner) AbortLaunch

func (o *Owner) AbortLaunch(provisionalID string) (PersistResult, error)

AbortLaunch releases a provisional binding after create failure.

func (*Owner) ActivateSession

func (o *Owner) ActivateSession(sessionID, profileID string, expectedGeneration int64) (SessionRouteState, WireSessionSnapshot, PersistResult, error)

ActivateSession atomically activates a profile on an existing routed Session. WireSessionSnapshot is projected from the mutated state under the same Owner.mu transaction; callers must not unlock then re-read for the mutation reply.

func (*Owner) ApplyTerminalModelSwitch

func (o *Owner) ApplyTerminalModelSwitch(routeID, modelID, effort string, effortPresent bool) error

ApplyTerminalModelSwitch applies only Codex's explicit reserved model-switch signal through the same route mutation and durable projection used by the Interface picker. A bare request-body mismatch never calls this operation.

func (*Owner) Catalog

func (o *Owner) Catalog() Catalog

Catalog returns the secret-free catalog snapshot.

func (*Owner) ClearProviderCredential

func (o *Owner) ClearProviderCredential(connectionID string) (ProviderCredentialResult, error)

ClearProviderCredential removes the private secret for a connection. Serialized under Owner.mu with DeleteProviderConnection / SetCredentialStore.

func (*Owner) Close

func (o *Owner) Close() error

Close stops the loopback listener and HTTP server.

func (*Owner) CodexControlSocket

func (o *Owner) CodexControlSocket(sessionID string) string

CodexControlSocket returns the durable app-server control socket for a Session (empty when the Session has no live native control surface).

func (*Owner) CodexModelCatalogPath

func (o *Owner) CodexModelCatalogPath(connectionID string) string

CodexModelCatalogPath returns the stable per-connection Codex ModelsResponse catalog file path (empty when the owner has no routes path).

func (*Owner) CodexRoutedDefault

func (o *Owner) CodexRoutedDefault() bool

CodexRoutedDefault reports whether the effective Codex connection is a routed Provider/API-key connection rather than the direct official ChatGPT/Codex login. Official Codex subscription usage is meaningful only for the direct login, so Stats suppression keys off this authoritative fact.

func (*Owner) CommitLaunch

func (o *Owner) CommitLaunch(provisionalID, sessionID string) (SessionRouteState, WireSessionSnapshot, PersistResult, error)

CommitLaunch rebinds a provisional launch to the real Zen Session id. When Persist.Applied is true the binding is live even if Durable is false. The returned WireSessionSnapshot is built under the same Owner.mu transaction.

func (*Owner) CommitThreadRuntime

CommitThreadRuntime publishes a prepared mutation atomically (generation CAS inside the same Owner transaction). On failure the table is unchanged; a caller that already applied the native side must revert it.

func (*Owner) DeleteProfile

func (o *Owner) DeleteProfile(id string, expectedRevision int64) (CatalogProjection, error)

DeleteProfile removes a profile. Rejects defaults and in-use Session bindings. The in-use check and Store.Delete run under Owner.mu so PrepareLaunch / ActivateSession / Commit / Transfer / Release cannot bind a deleted Profile.

func (*Owner) DeleteProviderConnection

func (o *Owner) DeleteProviderConnection(id string, revision int64) (ProviderCatalogProjection, error)

DeleteProviderConnection removes a connection after non-orphaning credential cleanup. Under Owner.mu: preflight revision/existence/defaults/in-use (no mutation) → delete private credential entry → commit catalog delete. Credential-delete failure leaves catalog/revision/defaults/key unchanged (not-applied). Catalog persistence failure after successful key deletion leaves the connection present but credential-not-ready (or env-ready). Dir-sync warnings remain applied-with-warning.

func (*Owner) DisableCodexGateway

func (o *Owner) DisableCodexGateway() (TakeoverStatus, error)

DisableCodexGateway removes the Zen-owned projection and restores the pre-takeover config; the gateway listener stays up (harmless, and re-enable is instant).

func (*Owner) DiscoverProviderModels

func (o *Owner) DiscoverProviderModels(connectionID string, force bool) ([]ProviderModelEntry, error)

DiscoverProviderModels performs SSRF-safe live /v1/models (or /models) lookup and returns availability entries intersected with the trusted/bundled set. On refresh failure, last-known-good ids are retained. Live availability may be returned with a persistence warning; durable LKG is never claimed on write failure.

func (*Owner) DiscoverProviderModelsDetailed

func (o *Owner) DiscoverProviderModelsDetailed(connectionID string, force bool) (DiscoverProviderModelsResult, error)

DiscoverProviderModelsDetailed returns entries plus LKG persistence honesty.

func (*Owner) EnableCodexGateway

func (o *Owner) EnableCodexGateway(listenAddr string) (TakeoverStatus, error)

EnableCodexGateway activates the machine-level takeover and points the gateway at the currently selected Codex Provider connection.

func (*Owner) Gateway

func (o *Owner) Gateway() *Gateway

Gateway returns the machine-level gateway runtime (nil when not configured).

func (*Owner) GatewayStatus

func (o *Owner) GatewayStatus() TakeoverStatus

GatewayStatus returns the truthful takeover + gateway status.

func (*Owner) GetProfile

func (o *Owner) GetProfile(id string) (Profile, error)

GetProfile returns one profile.

func (*Owner) ListenAddr

func (o *Owner) ListenAddr() string

ListenAddr returns the bound loopback host:port.

func (*Owner) PrepareLaunch

func (o *Owner) PrepareLaunch(executorID, profileID, baseCommand string) (SessionLaunchPlan, error)

PrepareLaunch resolves profile override/default, binds a provisional route, and compiles a secret-free command/env plan. Raw/custom/unsupported commands bypass.

func (*Owner) PrepareLaunchModel

func (o *Owner) PrepareLaunchModel(executorID, profileID, modelOverride, baseCommand string) (SessionLaunchPlan, error)

PrepareLaunchModel is PrepareLaunch with an explicit client model override (create_session's connection_id + model_id). The gateway never owns a model: the launch model is the explicit override or the exact client-selected default. Discovery and local catalogs never replace or reject that identity.

func (*Owner) PrepareThreadRuntime

func (o *Owner) PrepareThreadRuntime(sessionID string, choice ThreadRuntimeChoice) (PreparedThreadRuntime, error)

PrepareThreadRuntime validates and resolves one runtime mutation without committing it. The Owner lock is not held across the returned handle, so callers may perform native (network) work between Prepare and Commit.

func (*Owner) ProjectCatalog

func (o *Owner) ProjectCatalog() CatalogProjection

ProjectCatalog captures catalog + views under Owner.mu and one Store read lock so list/CRUD replies cannot mix revisions under concurrent mutation.

func (*Owner) ProjectProviders

func (o *Owner) ProjectProviders() (ProviderCatalogProjection, error)

ProjectProviders returns the Provider-first Settings projection.

func (*Owner) ReleaseSession

func (o *Owner) ReleaseSession(sessionID string) (PersistResult, error)

ReleaseSession drops route ownership on Session teardown.

func (*Owner) RestoreCodexGatewayBackup

func (o *Owner) RestoreCodexGatewayBackup() (TakeoverStatus, error)

RestoreCodexGatewayBackup rolls the exact pre-takeover config backup back.

func (*Owner) RestoreContractNotices

func (o *Owner) RestoreContractNotices() []RestoreContractNotice

RestoreContractNotices returns the durable routes restored at StartOwner whose persisted contract drifted from the current daemon authority (secret-free; immutable after start). The routes are kept live — notices are advisory, for startup logging and diagnostics. Empty when nothing drifted.

func (*Owner) ResumeEnv

func (o *Owner) ResumeEnv(sessionID string) (map[string]string, bool, error)

ResumeEnv returns secret-free loopback env for an existing binding.

func (*Owner) ResumeLaunch

func (o *Owner) ResumeLaunch(sessionID, baseCommand string) (command string, env map[string]string, found bool, err error)

ResumeLaunch recompiles a secret-free command/env from the immutable RouteBinding snapshot only — never from a later-edited catalog profile.

func (*Owner) RouteIDForSession

func (o *Owner) RouteIDForSession(sessionID string) string

RouteIDForSession returns the route id for a Session (empty when unbounded).

func (*Owner) RouterHandler

func (o *Owner) RouterHandler() http.Handler

RouterHandler returns the loopback routing handler (nil when the owner is not started or has no router).

func (*Owner) RoutesFile

func (o *Owner) RoutesFile() *RouteStateFile

RoutesFile returns the durable route-state owner (tests/failpoints).

func (*Owner) SessionRouteCapabilities

func (o *Owner) SessionRouteCapabilities(sessionID string) SessionRouteCapabilities

SessionRouteCapabilities reports whether sessionID currently has a managed Model Profile binding and whether that binding supports active switching. Provisional pending:* IDs are never App-visible managed Sessions.

func (*Owner) SessionSnapshot

func (o *Owner) SessionSnapshot(sessionID string) (WireSessionSnapshot, bool)

SessionSnapshot returns the App-safe launched/current binding view.

func (*Owner) SetCredentialStore

func (o *Owner) SetCredentialStore(store CredentialStore)

SetCredentialStore installs Zen's private credential store (or a test fake). Serialized with Set/Clear/Delete under Owner.mu so the store pointer cannot race a mid-flight credential mutation.

func (*Owner) SetDefault

func (o *Owner) SetDefault(executorID, profileID string, expectedRevision int64) (CatalogProjection, error)

SetDefault sets or clears the default profile for an executor under Owner.mu so PrepareLaunch cannot observe a torn catalog revision.

func (*Owner) SetEditHook

func (o *Owner) SetEditHook(hook func(phase string) error)

SetEditHook installs a test failpoint seam for Provider edit transactions. Phases: before_stage, after_stage, before_commit, after_commit, before_cleanup, after_cleanup. Returning an error aborts the transaction at that point exactly as a process crash would: every durable write before the phase stays on disk and recovery is exercised by the next StartOwner.

func (*Owner) SetGatewayBypass

func (o *Owner) SetGatewayBypass(bypass func() bool)

SetGatewayBypass installs the takeover-readiness callback consulted by PrepareLaunchModel: when it reports true, new managed Codex launches use the plain base command and rely on the machine-level config projection (the canonical gateway route) instead of per-Session loopback injection.

func (*Owner) SetNativeSettingsLookup

func (o *Owner) SetNativeSettingsLookup(lookup func(routeID string) (codexctl.NativeSettings, bool))

SetNativeSettingsLookup replaces the authoritative native settings source (test seam; nil restores the monitor-backed implementation).

func (*Owner) SetProviderCredential

func (o *Owner) SetProviderCredential(connectionID, secret string) (ProviderCredentialResult, error)

SetProviderCredential writes a secret to the credential store for a connection. Public replies expose readiness only — never the secret. Connection validation and credential persistence run under Owner.mu with DeleteProviderConnection / SetCredentialStore so a concurrent delete cannot leave an orphan key for a removed connection.

func (*Owner) SetProviderDefault

func (o *Owner) SetProviderDefault(clientOrExecutor, connectionID, modelID string, revision int64) (ProviderCatalogProjection, error)

SetProviderDefault sets the future-launch default connection for a client in one catalog mutation and one atomic durable write. The gateway never owns a model: modelID is the client's explicit selection (chosen from the synced support allowlist) and is never fabricated from a preset or catalog. An empty modelID preserves the existing client-selected model when the same connection stays default. A different connection must provide its model atomically.

func (*Owner) SetProviderModelSupport

func (o *Owner) SetProviderModelSupport(connectionID string, enabledIDs []string) (ProviderCatalogProjection, PersistResult, error)

SetProviderModelSupport persists the client-side model support allowlist of one connection: every discovered model is supported unless the client explicitly disabled it. enabledIDs is the full set of models the client wants to expose; the durable representation is the complement (disabled ids) so a refresh never re-enables an explicitly disabled model while genuinely new discovered models default enabled. The catalog revision is untouched; durability comes from the discovery-cache file.

func (*Owner) SetThreadRuntime

func (o *Owner) SetThreadRuntime(sessionID string, choice ThreadRuntimeChoice) (SessionRouteState, WireSessionSnapshot, PersistResult, error)

SetThreadRuntime validates and commits one runtime without process staging, process replacement, or resume input. It is the route-only path; live native synchronization is orchestrated by the server layer through PrepareThreadRuntime + CommitThreadRuntime.

func (*Owner) Store

func (o *Owner) Store() *Store

Store returns the catalog owner (tests / advanced callers).

func (*Owner) SwitchProvider

func (o *Owner) SwitchProvider(clientOrExecutor, connectionID string, revision int64) (ProviderCatalogProjection, error)

SwitchProvider atomically updates the future-launch default Provider and retargets every currently running routed Session for the same client without changing each Session's selected model or effect.

func (*Owner) Table

func (o *Owner) Table() *RouteTable

Table returns the RouteTable (tests).

func (*Owner) Takeover

func (o *Owner) Takeover() *Takeover

Takeover returns the Codex config takeover manager (nil when not configured).

func (*Owner) TeardownSession

func (o *Owner) TeardownSession(sessionID string, kill func(string) error, probe func(string) (SessionLiveness, error)) SessionTeardownResult

TeardownSession releases via Owner.ReleaseSession after the kill rule.

func (*Owner) TestProviderConnection

func (o *Owner) TestProviderConnection(in ProviderConnectionTestInput) (ProviderConnectionTestResult, error)

TestProviderConnection validates credentials and protocol compatibility by issuing a bounded, SSRF-safe model-list request. It does not create a connection, touch the credential store, mutate discovery cache, or alter defaults.

func (*Owner) TestSavedProviderConnection

func (o *Owner) TestSavedProviderConnection(connectionID string) (ProviderConnectionTestResult, error)

TestSavedProviderConnection probes the exact saved connection by stable Provider ID: the persisted Base URL, the compiled per-client protocol, and the active stored credential ref are all resolved daemon-side, so the App never supplies or receives the secret. Read-only: no catalog/default/session mutation, no discovery-cache write, and no secret in the result or logs.

func (*Owner) ThreadRuntime

func (o *Owner) ThreadRuntime(sessionID string) (ThreadRuntimeSelection, bool)

ThreadRuntime returns the Plus-menu projection for a Session.

func (*Owner) TransferSession

func (o *Owner) TransferSession(fromID, toID string) (PersistResult, error)

TransferSession remaps route ownership when a Zen Session id changes.

func (*Owner) UpsertProfile

func (o *Owner) UpsertProfile(profile Profile, expectedRevision int64, create bool) (CatalogProjection, error)

UpsertProfile creates or updates a profile under CAS revision after full AuthorizeProfileContract admission. Serialized under Owner.mu against PrepareLaunch/ActivateSession profile resolution. Returns an atomic catalog+views projection from the same transaction.

func (*Owner) UpsertProviderConnection

func (o *Owner) UpsertProviderConnection(in ProviderConnectionInput, apiKey string, revision int64, create bool) (ProviderCatalogProjection, error)

UpsertProviderConnection creates/updates a connection via public input and optionally rotates its API key as part of the same crash-recoverable edit. An empty apiKey preserves the existing stored secret; a non-empty value replaces it atomically with the whole Provider edit.

Durability design (versioned credential reference):

  1. VALIDATE first — any validation failure applies zero writes.
  2. STAGE — when the edit carries a new key, write it privately under a fresh staged ref (provider:<id>:<token>) that no catalog row references yet. The old secret stays active and routing still resolves the old ref.
  3. COMMIT — the single atomic catalog write flips Name/Base URL AND the active credential ref together. Before it, router/launch observe the complete old version; after it, the complete new version. A crash can never expose a mixed Name/Base URL/API key state.
  4. CLEANUP — delete the old ref once nothing references it (a crash here leaves an inactive secret only; the deterministic StartOwner orphan sweep removes every provider:* ref no catalog row or route binding references). Secrets never enter the catalog, journal, logs, or telemetry — the catalog stores only the opaque secret-free ref.

func (*Owner) Views

func (o *Owner) Views() []ProfileView

Views returns profiles with credential readiness.

type OwnerConfig

type OwnerConfig struct {
	ProfilesPath  string
	RoutesPath    string
	ListenerPath  string
	DiscoveryPath string // secret-free TTL/LKG model id cache
	Lookup        func(string) (string, bool)
	Credentials   CredentialStore // Zen private store (or test fake); optional
	Verifier      ProfileContractVerifier
	ListenNetwork string // default "tcp"
	// PreferAddr overrides ListenerFile for tests when the listener is started
	// (live-route restore or first managed launch).
	PreferAddr string
	// RoutesPersistHook is a test seam installed on the route-state file before
	// StartOwner sweeps provisionals / starts the listener.
	RoutesPersistHook func(phase string) error
	// ListenerPersistHook is a test seam installed on the listener file before
	// StartOwner converges inert metadata or restores a sticky listener.
	ListenerPersistHook func(phase string) error
	// CodexControlDir, when set, is the daemon-owned root for per-session
	// Codex app-server control sockets. Managed Codex launches with a Zen
	// route then run in live-control mode (headless app server + `--remote`
	// TUI), exposing the native thread/settings/update mutation surface to
	// the daemon. Empty keeps the legacy embedded-TUI launch.
	CodexControlDir string
	// GatewayAddr, when set, enables the machine-level Codex gateway on the
	// stable loopback address baked into the takeover projection.
	GatewayAddr string
	// GatewayStateDir is the daemon-owned state dir for the gateway and the
	// Codex config takeover (state + exact backups).
	GatewayStateDir string
	// CodexConfigPath is the CLI's native Codex config file for the takeover
	// projection (CODEX_HOME-aware; empty disables takeover management).
	CodexConfigPath string
}

OwnerConfig configures production Owner paths and seams.

type ParsedRouteRequest

type ParsedRouteRequest struct {
	RouteID  string
	APIPath  string // e.g. /v1/responses or /v1/messages
	Endpoint RouteEndpoint
}

ParsedRouteRequest is the opaque-route admission parse of an inbound path.

func ParseRouteRequestPath

func ParseRouteRequestPath(rawPath string) (ParsedRouteRequest, error)

ParseRouteRequestPath extracts the opaque RouteID and API path from an inbound request path shaped like /r/{routeID}/v1/...

type PersistResult

type PersistResult struct {
	Applied bool
	Durable bool
}

PersistResult mirrors auth.PersistenceResult / control PersistenceOutcome: Applied means the durable named file reflects the mutation; Durable means directory sync confirmed. Applied && !Durable is success-with-warning.

func CombinePersistResults

func CombinePersistResults(a, b PersistResult) PersistResult

CombinePersistResults merges independent applied mutations. If either side is applied with uncertain durability, the result is applied+!durable.

func PersistResultFromError

func PersistResultFromError(err error) PersistResult

PersistResultFromError maps Store/Route persist errors onto PersistResult. nil => applied+durable; ErrPersistDirSync => applied+!durable; else not-applied.

type PreparedThreadRuntime

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

PreparedThreadRuntime is a validated, not-yet-committed runtime mutation. The native-first transaction in the server layer applies the native Codex thread/settings/update between PrepareThreadRuntime and CommitThreadRuntime; Commit re-validates the generation CAS so a concurrent mutation fails closed.

func (PreparedThreadRuntime) Previous

Previous is the pre-mutation native identity for rollback.

func (PreparedThreadRuntime) Target

Target is the exact resolved native identity (client model + effort) the mutation will apply.

type Profile

type Profile struct {
	ID    string `toml:"id" json:"id"`
	Name  string `toml:"name" json:"name"`
	Scope string `toml:"scope,omitempty" json:"scope,omitempty"`
	// Client scopes an account connection to exactly one product client.
	Client        string `toml:"client,omitempty" json:"client,omitempty"`
	ExecutorID    string `toml:"executor_id,omitempty" json:"executor_id,omitempty"`
	ProviderID    string `toml:"provider_id" json:"provider_id"`
	ProviderLabel string `toml:"provider_label" json:"provider_label"`
	Protocol      string `toml:"protocol,omitempty" json:"protocol,omitempty"`
	// ClientModel is the CLI-visible model id string from durable catalog input.
	// Establishing a ClientModelContract requires daemon ContractAuth — TOML alone
	// never authorizes this field.
	ClientModel string `toml:"client_model,omitempty" json:"client_model,omitempty"`
	// ClientModelProvenance is optional durable description only (builtin_catalog /
	// verified_alias). User-editable TOML may claim either label; that claim is
	// never treated as authorization by ValidateProfile or contract establishment.
	ClientModelProvenance string `toml:"client_model_provenance,omitempty" json:"client_model_provenance,omitempty"`
	// Model is Advanced/Custom manual upstream model only on durable account
	// connections. Curated account connections leave it empty; defaults and
	// Session activation own model selection. Legacy executor-scoped profiles
	// may still store a catalog model.
	Model string `toml:"model,omitempty" json:"model,omitempty"`
	// ReasoningEffort is an ephemeral compile-only carrier for Session effort
	// activation (same pattern as ModelPlaceholder). It is never durable and
	// never a connection setting: the Session route owns the override and
	// Settings stays Provider/Model-only. Empty means no override.
	ReasoningEffort string `toml:"-" json:"-"`
	// ModelPlaceholder is an internal compile-only marker set when a Custom/
	// Advanced connection had no explicit upstream model and compilation fell
	// back to the ClientModel contract id (probe validation only). It is never
	// durable (toml/json excluded) and binding creation fails closed on it so a
	// fabricated model can never reach a RouteBinding's UpstreamModel.
	ModelPlaceholder bool   `toml:"-" json:"-"`
	BaseURL          string `toml:"base_url,omitempty" json:"base_url,omitempty"`
	AuthMode         string `toml:"auth_mode,omitempty" json:"auth_mode,omitempty"`
	CredentialEnv    string `toml:"credential_env,omitempty" json:"credential_env,omitempty"`
	// CredentialRef is the opaque active credential-slot reference (never a
	// secret). Legacy rows leave it empty and resolve the canonical
	// provider:<id> ref; unified edits stage a fresh provider:<id>:<token> ref
	// and flip this field in the same atomic catalog commit that changes
	// Name/Base URL, so routing observes either the complete old version or
	// the complete new version.
	CredentialRef string `toml:"credential_ref,omitempty" json:"credential_ref,omitempty"`
	// HistoryDomain is optional durable description only — never authorization.
	HistoryDomain string `toml:"history_domain,omitempty" json:"history_domain,omitempty"`
}

Profile is durable catalog upstream metadata (secret-free values only). Account-scoped Provider connections (Scope=account) belong to exactly one product client and omit executor/protocol/client_model/auth_mode; those are compiled for that client at launch/activate.

func CompileConnectionTarget

func CompileConnectionTarget(conn Profile, clientOrExecutor, modelOverride, effortOverride string) (Profile, error)

CompileConnectionTarget builds an ephemeral internal Profile for one client from a durable account connection or internal executor profile. modelOverride and effortOverride are session-only and never written back to the catalog. A non-empty effortOverride must be in the daemon-owned Codex vocabulary; the target client model's support is admitted by the runtime transaction caller.

func CompileProviderConnection

func CompileProviderConnection(in ProviderConnectionInput) (Profile, error)

CompileProviderConnection builds a durable account-scoped connection from a public input. Per-client Profile targets are compiled via CompileConnectionTarget.

The mutation contract requires an explicit non-empty trimmed display name: a blank Name fails before any catalog or credential write. Only load-time migration of legacy persisted records may synthesize names; the App may prefill a preset label in the form, but the submitted mutation must carry it.

type ProfileContractVerifier

type ProfileContractVerifier interface {
	VerifyProfileContract(profile Profile) (VerifiedProfileContract, error)
}

ProfileContractVerifier is a daemon-owned authority that admits a full profile contract. TOML capability/provenance/history claims are descriptive input only.

type ProfileEditorSchema

type ProfileEditorSchema struct {
	SupportedClientContracts []ClientContractDescriptor `json:"supported_client_contracts"`
	FreelyConfigurable       []string                   `json:"freely_configurable"`
}

ProfileEditorSchema is the App-facing vocabulary for the profile editor. Provider ID/label, Gateway URL, and model remain freely configurable; the catalog is suggestions and metadata, not an identity allowlist.

func ProfileEditorSchemaSnapshot

func ProfileEditorSchemaSnapshot() ProfileEditorSchema

ProfileEditorSchemaSnapshot returns the App-facing editor vocabulary.

type ProfileView

type ProfileView struct {
	Profile
	CredentialReady bool `json:"credential_ready"`
}

ProfileView is catalog profile plus readiness for settings (never secret values).

type ProtocolCapability

type ProtocolCapability struct {
	Protocol      string `json:"protocol"`
	Routed        bool   `json:"routed"`
	RouteProtocol string `json:"route_protocol,omitempty"`
	ActiveSwitch  string `json:"active_switch,omitempty"`
}

ProtocolCapability is profile/routing-specific capability advertisement.

type ProviderCatalogProjection

type ProviderCatalogProjection struct {
	Revision    int64                           `json:"revision"`
	Connections []ProviderConnection            `json:"connections"`
	Defaults    map[string]ProviderDefault      `json:"defaults"`
	Presets     []ProviderPreset                `json:"presets"`
	Models      map[string][]ProviderModelEntry `json:"models"`
}

ProviderCatalogProjection is the Settings list payload.

type ProviderConnection

type ProviderConnection struct {
	ID              string   `json:"id"`
	Name            string   `json:"name"`
	PresetID        string   `json:"preset_id,omitempty"`
	Clients         []string `json:"clients,omitempty"`
	BaseURL         string   `json:"base_url,omitempty"`
	ManualModelID   string   `json:"manual_model_id,omitempty"`
	CredentialReady bool     `json:"credential_ready"`
	CredentialHint  string   `json:"credential_hint,omitempty"`
	Advanced        bool     `json:"advanced,omitempty"`
}

ProviderConnection is one Settings-managed Provider account connection. Curated public shape: {id,name,preset_id,clients?,credential_ready}. BaseURL and ManualModelID appear only for Custom/Advanced.

id is the stable internal identity (never derived from name/URL/key); name is the primary user-facing identity and is unique case-insensitively across the Provider list. Multiple connections may share the same Base URL with different API keys; they are distinguished by id and name, never by URL.

CredentialHint is a conservative masked preview of the active stored secret (small bounded prefix/suffix, fixed bullet center); the full key never leaves the private credential store and no hint is emitted in logs or telemetry. The editable API-key input stays logically empty — the hint is presentation only and must never be submitted as a credential.

type ProviderConnectionInput

type ProviderConnectionInput struct {
	ID       string `json:"id"`
	Name     string `json:"name"`
	PresetID string `json:"preset_id"`
	Client   string `json:"client"`
	BaseURL  string `json:"base_url,omitempty"`
	ModelID  string `json:"model_id,omitempty"`
	Advanced bool   `json:"advanced,omitempty"`
}

ProviderConnectionInput is the public mutation shape for create/update. Every create is scoped to one client. Advanced/Custom may set base_url and model_id; protocol and auth details remain internal.

type ProviderConnectionTestInput

type ProviderConnectionTestInput struct {
	Client     string `json:"client"`
	BaseURL    string `json:"base_url"`
	Credential string `json:"credential"`
}

ProviderConnectionTestInput is a transient, write-free connectivity probe. Credential is inbound-only and must never be projected or persisted.

type ProviderConnectionTestResult

type ProviderConnectionTestResult struct {
	Client     string `json:"client"`
	ModelCount int    `json:"model_count"`
	LatencyMS  int64  `json:"latency_ms"`
}

ProviderConnectionTestResult contains only secret-free probe facts.

type ProviderCredentialResult

type ProviderCredentialResult struct {
	ConnectionID       string `json:"connection_id"`
	CredentialReady    bool   `json:"credential_ready"`
	PersistenceOutcome string `json:"persistence_outcome"`
	PersistenceDurable bool   `json:"persistence_durable"`
	PersistenceWarning string `json:"persistence_warning,omitempty"`
}

ProviderCredentialResult is the write-only credential mutation reply.

type ProviderDefault

type ProviderDefault struct {
	ConnectionID string `json:"connection_id"`
	ModelID      string `json:"model_id"`
}

ProviderDefault is the future-launch default for one product client.

type ProviderModelEntry

type ProviderModelEntry struct {
	ID                     string   `json:"id"`
	DisplayName            string   `json:"display_name,omitempty"`
	Available              bool     `json:"available"`
	Source                 string   `json:"source"` // codex_cache | discovered | lkg | manual
	ReasoningEffortDefault string   `json:"reasoning_effort_default,omitempty"`
	ReasoningEfforts       []string `json:"reasoning_efforts,omitempty"`
	// Known marks daemon-owned display/effect metadata for managed Codex.
	// Unknown gateway-only models remain valid opaque identities.
	Known bool `json:"known,omitempty"`
}

ProviderModelEntry is a catalog/discovery model id with availability only.

type ProviderPreset

type ProviderPreset struct {
	ID       string   `json:"id"`
	Label    string   `json:"label"`
	Clients  []string `json:"clients"`
	Advanced bool     `json:"advanced,omitempty"`
}

ProviderPreset is the App-facing curated Provider template (secret-free). Base URLs, auth, protocol, and internal provider_id stay daemon-internal.

func ListProviderPresets

func ListProviderPresets() []ProviderPreset

ListProviderPresets returns curated public presets (no Base URL / auth / protocol).

type ResolvedLaunch

type ResolvedLaunch struct {
	Command       string
	Env           map[string]string
	NeedsRoute    bool
	RouteProtocol string
	Draft         RouteBinding
	Wire          WireBinding
	// CodexWebSocketNote records empirical WS→POST fallback behavior for the
	// installed Codex under test (not a permanent product version lock).
	CodexWebSocketNote string
	// CodexControlSocket is the app-server control socket when the launch runs
	// in live-control mode (see CompileOptions.CodexControlSocket).
	CodexControlSocket string
}

ResolvedLaunch is a secret-free compiled launch plan for daemon use.

func Compile

func Compile(baseCommand string, profile Profile, opts CompileOptions) (ResolvedLaunch, error)

Compile builds a secret-free launch plan that targets opts.LoopbackRouteURL when the profile uses a Zen route. Upstream base URL/credential stay on Draft for RouteTable — never in command/env values beyond the loopback URL and model id.

Client/upstream contract requires opts.VerifiedProfileContract or opts.Verifier. Profile TOML provenance/capability/history claims are never sufficient.

func (ResolvedLaunch) MarshalJSON

func (ResolvedLaunch) MarshalJSON() ([]byte, error)

func (*ResolvedLaunch) UnmarshalJSON

func (*ResolvedLaunch) UnmarshalJSON([]byte) error

type RestoreContractNotice

type RestoreContractNotice struct {
	SessionID string
	RouteID   string
	Reason    string
}

RestoreContractNotice records one durable route whose persisted contract no longer matches what the current daemon authority would admit (for example after a daemon upgrade tightened the client contract). The route is still restored and keeps serving — notices are advisory only, for startup logging. The restored binding stays authoritative at the router boundary; a stale CLI request is normalized to that binding. Secret-free.

type RouteActivationEvent

type RouteActivationEvent struct {
	Generation         int64
	Activation         string
	HistoryDegradation string
	From               RouteBinding
	To                 RouteBinding
}

RouteActivationEvent is daemon-internal append-only history (bounded).

func (RouteActivationEvent) MarshalJSON

func (RouteActivationEvent) MarshalJSON() ([]byte, error)

func (*RouteActivationEvent) UnmarshalJSON

func (*RouteActivationEvent) UnmarshalJSON([]byte) error

type RouteBinding

type RouteBinding struct {
	RouteID               string
	SessionID             string
	ExecutorID            string
	ProfileID             string
	ProfileName           string
	RouteProtocol         string
	ProviderID            string
	ProviderLabel         string
	Protocol              string
	ClientModel           string
	ClientModelProvenance string
	UpstreamBaseURL       string
	UpstreamModel         string
	HistoryDomain         string
	HistoryState          string // empty | may_contain_opaque
	// HistoryPortability is sticky once set (CLI may resent old opaque blocks).
	HistoryPortability string
	ClientEnvelope     CapabilityEnvelope
	UpstreamEnvelope   CapabilityEnvelope
	AuthMode           string
	CredentialEnv      string
	// CredentialRef is an opaque private-store reference (never a secret).
	CredentialRef   string
	CredentialReady bool
	// ReasoningEffort is the Session's daemon-owned Codex effort override
	// (empty = no override; the CLI/model default applies). Set only by Session
	// activation against the client model's daemon-owned effort contract; it is
	// snapshotted per request flight (in-flight immutability) and persisted with
	// the route state (restart restoration). Never a connection setting.
	ReasoningEffort string
	// CodexControlSocket is the daemon-owned Codex app-server control socket
	// for this Session's live native thread (empty when the Session runs in
	// embedded mode or is not Codex). Durable so live control survives daemon
	// restarts; the native thread id is re-resolved from the app server.
	CodexControlSocket string
	Generation         int64
	CatalogRevision    int64
	Activation         string
}

RouteBinding is daemon-internal per-Session route state.

func BindingDraftFromProfile

func BindingDraftFromProfile(profile Profile, catalogRevision int64, activation string, ready bool, admitted VerifiedProfileContract) (RouteBinding, error)

BindingDraftFromProfile builds internal RouteBinding fields from a profile using a daemon-admitted VerifiedProfileContract (never raw TOML claims alone).

func (RouteBinding) MarshalJSON

func (RouteBinding) MarshalJSON() ([]byte, error)

func (RouteBinding) ToWire

func (b RouteBinding) ToWire() WireBinding

ToWire projects an internal binding to the App/control Provider-first DTO. Reasoning Effort projects the daemon-owned override plus the client model's effort contract (absent for unsupported clients/models).

func (*RouteBinding) UnmarshalJSON

func (*RouteBinding) UnmarshalJSON([]byte) error

type RouteEndpoint

type RouteEndpoint string

RouteEndpoint is a proven CLI path/method pair the router admits.

const (
	EndpointResponses            RouteEndpoint = "responses"
	EndpointAnthropicMessages    RouteEndpoint = "anthropic_messages"
	EndpointAnthropicCountTokens RouteEndpoint = "anthropic_count_tokens"
	// EndpointModels is the standard GET /v1/models catalog surface Codex's
	// native /model switch reads. Served locally from the synced discovery
	// cache — never forwarded upstream.
	EndpointModels RouteEndpoint = "models"
)

type RouteStateFile

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

RouteStateFile is the daemon-owned durable owner for route snapshots.

Stage 2B integration seam: Session lifecycle Save/Load through this type.

func NewRouteStateFile

func NewRouteStateFile(path string) (*RouteStateFile, error)

NewRouteStateFile constructs a route-state persistence owner at path.

func (*RouteStateFile) Load

Load decodes the durable file and Restores into an empty table using the table's installed contract verifier. Every structurally valid route is kept live; the returned report lists contract drift for logging only — callers must NOT rewrite the file (nothing was dropped).

func (*RouteStateFile) Path

func (f *RouteStateFile) Path() string

Path returns the durable file path.

func (*RouteStateFile) Save

func (f *RouteStateFile) Save(table *RouteTable) error

Save encodes table.Snapshot() to the durable 0600 file.

func (*RouteStateFile) SaveStates

func (f *RouteStateFile) SaveStates(states []SessionRouteState) error

SaveStates persists an already-cloned snapshot. Callers that mutate under a global Owner lock should snapshot once and pass that clone here so a slow write cannot race a newer in-memory generation.

func (*RouteStateFile) SetDirSync

func (f *RouteStateFile) SetDirSync(fn func(dir string) error)

SetDirSync installs a test seam for directory fsync after rename. A failure here means the named file already reflects the mutation (ErrPersistDirSync).

func (*RouteStateFile) SetPersistHook

func (f *RouteStateFile) SetPersistHook(hook func(phase string) error)

SetPersistHook installs a test failpoint/serialization seam. Phases: before_encode, after_encode, before_write, after_write, before_sync, after_sync, before_rename, after_rename, before_dirsync, after_dirsync.

type RouteTable

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

RouteTable is the process-local atomic owner of per-Session RouteBindings.

func NewRouteTable

func NewRouteTable() *RouteTable

NewRouteTable constructs an empty in-memory route binding owner.

func (*RouteTable) Activate

func (t *RouteTable) Activate(sessionID string, profile Profile, catalogRevision, expectedGeneration int64, auth ContractAuth) (SessionRouteState, error)

Activate atomically updates upstream fields on an existing routed Session. Client model + client envelope are immutable. History domain may change only while HistoryState is empty; once may_contain_opaque, domain must match exactly.

func (*RouteTable) BeginRouteFlight

func (t *RouteTable) BeginRouteFlight(routeID string) (RouteBinding, string, error)

BeginRouteFlight atomically snapshots the binding and registers an in-flight lease. Callers must Release(false) on local/network failure, or Complete(true) after a successful 2xx upstream response (before forwarding to the client).

func (*RouteTable) BindLaunch

func (t *RouteTable) BindLaunch(sessionID string, profile Profile, catalogRevision int64, auth ContractAuth) (SessionRouteState, error)

BindLaunch creates the initial RouteBinding for a Session from a profile.

func (*RouteTable) EndRouteFlight

func (t *RouteTable) EndRouteFlight(routeID, token string, markOpaque bool) error

EndRouteFlight releases a lease. markOpaque=true atomically sets HistoryStateMayContainOpaque after a successful 2xx upstream response.

func (*RouteTable) Get

func (t *RouteTable) Get(sessionID string) (SessionRouteState, bool)

Get returns a copy of the Session route state with CredentialReady rechecked.

func (*RouteTable) GetByRouteID

func (t *RouteTable) GetByRouteID(routeID string) (RouteBinding, bool)

GetByRouteID resolves a route id to its Session binding (router lookup only).

func (*RouteTable) InFlightCount

func (t *RouteTable) InFlightCount(routeID string) int

InFlightCount returns the number of in-flight leases for a route (tests).

func (*RouteTable) Len

func (t *RouteTable) Len() int

Len returns the number of bound Sessions (tests/diagnostics).

func (*RouteTable) MarkHistoryMayContainOpaque

func (t *RouteTable) MarkHistoryMayContainOpaque(routeID string) error

MarkHistoryMayContainOpaque is retained for tests that force opaque state without a flight.

func (*RouteTable) RebindSession

func (t *RouteTable) RebindSession(fromID, toID string) error

RebindSession moves an existing binding from fromID to toID while preserving RouteID, generation, history, and upstream fields. Used when a Zen Session identity is remapped (e.g. missing-tmux native resume) without allocating a new opaque route or native conversation.

func (*RouteTable) Release

func (t *RouteTable) Release(sessionID string) error

Release removes a Session binding and its route id index entry.

func (*RouteTable) ReplaceSnapshot

func (t *RouteTable) ReplaceSnapshot(states []SessionRouteState)

ReplaceSnapshot replaces all Session route state with a prior Snapshot() clone. Used to roll back Owner mutate+persist transactions. In-flight leases for routes that no longer exist are dropped; surviving route IDs keep leases.

func (*RouteTable) Restore

Restore replaces an empty RouteTable from durable SessionRouteState records. Requires a daemon verifier (argument or table-owned) and re-verifies each binding's client/upstream IDs, envelopes, and history domain for the advisory drift report. CredentialReady is recalculated; persisted readiness is ignored.

Every structurally valid route is restored and kept serving — contract drift never drops a live Session. The report lists drifted bindings for logging; request admission keeps using the restored binding. Structural failures (validateRestorableState) remain fatal — corrupt or foreign data is never silently discarded.

func (*RouteTable) SessionsUsingProfile

func (t *RouteTable) SessionsUsingProfile(profileID string) []string

SessionsUsingProfile returns Session IDs currently bound to profileID.

func (*RouteTable) SetCodexControlSocket

func (t *RouteTable) SetCodexControlSocket(sessionID, socketPath string) error

SetCodexControlSocket records the durable app-server control socket on a Session binding (launch-time only; empty clears it).

func (*RouteTable) SetContractVerifier

func (t *RouteTable) SetContractVerifier(v ProfileContractVerifier)

SetContractVerifier installs the daemon-owned verifier used by Restore.

func (*RouteTable) SetCredentials

func (t *RouteTable) SetCredentials(store CredentialStore)

SetCredentials installs the private store used for launch/bind readiness. Secret values are never copied onto bindings or launch env.

func (*RouteTable) SetLookup

func (t *RouteTable) SetLookup(lookup func(string) (string, bool))

SetLookup overrides credential probing (deterministic tests).

func (*RouteTable) Snapshot

func (t *RouteTable) Snapshot() []SessionRouteState

Snapshot returns a clone of all Session route states for persistence.

type Router

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

Router is the Zen-owned same-protocol loopback routing runtime.

func NewRouter

func NewRouter(table *RouteTable, opts ...RouterOption) *Router

NewRouter constructs a loopback routing runtime over table.

func (*Router) CloseWebSocketConnections

func (r *Router) CloseWebSocketConnections()

CloseWebSocketConnections drops every hijacked Responses WebSocket connection. Called by Owner.Close after the HTTP server shutdown so no long-lived socket survives the daemon process teardown; hijacked connections are not covered by http.Server.Shutdown.

func (*Router) Handler

func (r *Router) Handler() http.Handler

Handler returns the HTTP handler for loopback admission.

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP implements http.Handler.

type RouterOption

type RouterOption func(*Router)

RouterOption configures Router construction.

func WithRouterClient

func WithRouterClient(client *http.Client) RouterOption

WithRouterClient overrides the upstream HTTP client (tests).

func WithRouterCredentials

func WithRouterCredentials(store CredentialStore) RouterOption

WithRouterCredentials installs the Provider credential store for route auth.

func WithRouterLookup

func WithRouterLookup(lookup func(string) (string, bool)) RouterOption

WithRouterLookup overrides credential resolution (tests).

func WithRouterMaxBody

func WithRouterMaxBody(n int64) RouterOption

WithRouterMaxBody overrides the bounded request body size (tests).

func WithRouterModelCatalog

func WithRouterModelCatalog(models func(profileID string) ([]ProviderModelEntry, error)) RouterOption

WithRouterModelCatalog installs the resolver for the local GET /v1/models surface. It receives the route binding's connection id and must return the synced (discovery-cache) model entries for that connection.

func WithRouterModelSwitch

func WithRouterModelSwitch(apply func(routeID, modelID, effort string, effortPresent bool) error) RouterOption

WithRouterModelSwitch installs the explicit Terminal /model mutation path.

func WithRouterNativeSettings

func WithRouterNativeSettings(lookup func(routeID string) (codexctl.NativeSettings, bool)) RouterOption

WithRouterNativeSettings installs the authoritative native thread-settings source (the live-control app-server subscription snapshot). With it, a fragment-less request whose model/effort differs from the binding is checked against the native thread before deciding converge vs normalize.

type SessionLaunchPlan

type SessionLaunchPlan struct {
	Applied       bool
	Bypass        bool
	Command       string
	Env           map[string]string
	ProvisionalID string
	State         SessionRouteState
	Wire          WireBinding
	Launch        ResolvedLaunch
	Persist       PersistResult
	// CodexControlSocket is the app-server control socket when the launch runs
	// in live-control mode (empty otherwise).
	CodexControlSocket string
}

SessionLaunchPlan is the secret-free result of resolving a profile for create.

type SessionLiveness

type SessionLiveness int

SessionLiveness is the tri-state probe result used after a non-nil KillSession error. It never authorizes route release.

const (
	SessionLivenessUnknown SessionLiveness = iota
	SessionLivenessPresent
	SessionLivenessAbsent
)

type SessionRouteCapabilities

type SessionRouteCapabilities struct {
	Managed      bool // Session has a managed Model Profile binding
	ActiveSwitch bool // current binding admits ActivateSession (hot switch)
}

SessionRouteCapabilities is the secret-free authorization fact for App Model Profile presentation and active-Session actions. Derived only from the route table — never from agent command/name heuristics. Does not expose gateway URL, credential env/value, route id, or history.

type SessionRouteState

type SessionRouteState struct {
	Binding    RouteBinding
	Launched   RouteBinding
	Generation int64
	History    []RouteActivationEvent
}

SessionRouteState is daemon-internal Session route ownership. Launched is the immutable original launch binding and is never trimmed with activation history (MaxRouteHistoryEvents only bounds History).

func DecodeDurableSnapshot

func DecodeDurableSnapshot(raw []byte) ([]SessionRouteState, error)

DecodeDurableSnapshot validates and reconstructs SessionRouteState records.

func (SessionRouteState) MarshalJSON

func (SessionRouteState) MarshalJSON() ([]byte, error)

func (SessionRouteState) ToWire

ToWire projects SessionRouteState to App/control DTO.

func (*SessionRouteState) UnmarshalJSON

func (*SessionRouteState) UnmarshalJSON([]byte) error

type SessionTeardownResult

type SessionTeardownResult struct {
	Persist PersistResult
	Err     error
}

SessionTeardownResult is the coherent kill+release outcome for a Session.

func TeardownSession

func TeardownSession(
	sessionID string,
	kill func(string) error,
	probe func(string) (SessionLiveness, error),
	release func(string) (PersistResult, error),
) SessionTeardownResult

TeardownSession kills a Session then releases its Model Profile route only when KillSession returns nil (window gone and any delegated resource cleanup completed). A non-nil kill error — including resource-release failure after a successful window kill, or ambiguous probe failures — preserves the route and is surfaced. probe is consulted only to annotate kill failures; it never authorizes release. Applied but non-durable release/listener cleanup is surfaced (not silent success).

type Store

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

Store is the process-local owner of ~/.zen/model-profiles.toml.

func NewStore

func NewStore(path string) (*Store, error)

NewStore loads path or returns an empty revision-0 catalog when missing. Tests must pass an owned temp path; production uses DefaultModelProfilesPath.

func (*Store) Catalog

func (s *Store) Catalog() Catalog

Catalog returns a sorted secret-free snapshot of profiles and defaults.

func (*Store) ClientDefault

func (s *Store) ClientDefault(client string) (connectionID, modelID string)

ClientDefault returns the recorded default connection and client-selected model for one client (empty when none). The model is explicit client choice only — the store never fabricates one.

func (*Store) Create

func (s *Store) Create(profile Profile, expectedRevision int64) (Catalog, error)

Create inserts a profile. expectedRevision must match the current revision.

func (*Store) DefaultModelID

func (s *Store) DefaultModelID(client string) string

DefaultModelID returns the Settings default model override for a client.

func (*Store) DefaultProfileID

func (s *Store) DefaultProfileID(executorID string) string

DefaultProfileID returns the default profile for an executor, if any.

func (*Store) Delete

func (s *Store) Delete(id string, expectedRevision int64) (Catalog, error)

Delete removes a profile. Fails if the profile is currently a default.

func (*Store) Get

func (s *Store) Get(id string) (Profile, error)

Get returns one profile by id.

func (*Store) Path

func (s *Store) Path() string

Path returns the durable file path.

func (*Store) PreflightDelete

func (s *Store) PreflightDelete(id string, expectedRevision int64) error

PreflightDelete reports whether Delete would succeed without mutating state.

func (*Store) Projection

func (s *Store) Projection() (Catalog, []ProfileView)

Projection returns catalog and views under one Store read lock.

func (*Store) ResolveProfile

func (s *Store) ResolveProfile(executorID, profileID string) (Profile, error)

ResolveProfile returns an explicit profile or the executor default. Account-scoped connections are compiled into an ephemeral client Profile. Empty profileID with no default yields ErrNotFound.

func (*Store) ResolveProfileWithModel

func (s *Store) ResolveProfileWithModel(executorID, profileID, modelOverride string) (Profile, error)

ResolveProfileWithModel is ResolveProfile with an explicit client model override for the launch: a non-empty modelOverride wins over the recorded client-selected model, which wins over the connection's durable model. The gateway itself never owns a model — an empty result means no client selection exists yet.

func (*Store) Revision

func (s *Store) Revision() int64

Revision returns the current catalog revision.

func (*Store) SetClientDefault

func (s *Store) SetClientDefault(client, connectionID, modelID string, expectedRevision int64) (Catalog, error)

SetClientDefault atomically sets or clears the future-launch default connection and model for one client in a single revisioned durable write. Empty connectionID clears both fields. Persistence failure leaves memory and revision unchanged.

func (*Store) SetDefault

func (s *Store) SetDefault(executorID, profileID string, expectedRevision int64) (Catalog, error)

SetDefault sets or clears the default profile for an executor/client. Empty profileID clears the default. Account connections may be defaults for any client the preset supports.

func (*Store) SetDefaultModel

func (s *Store) SetDefaultModel(client, modelID string, expectedRevision int64) (Catalog, error)

SetDefaultModel sets or clears the Settings default model for a client without mutating the connection row. Prefer SetClientDefault for Provider+model pairs.

func (*Store) SetDirSync

func (s *Store) SetDirSync(fn func(dir string) error)

SetDirSync installs a test seam for parent-directory sync after rename. A failure returns ErrPersistDirSync with memory already aligned to the new catalog.

func (*Store) SetLookup

func (s *Store) SetLookup(lookup func(string) (string, bool))

SetLookup overrides credential readiness probing for Views (tests).

func (*Store) SetPersistHook

func (s *Store) SetPersistHook(hook func(phase string) error)

SetPersistHook installs a test failpoint/serialization seam. Phases: before_write, after_write, before_rename, after_rename, before_dirsync, after_dirsync.

func (*Store) Update

func (s *Store) Update(profile Profile, expectedRevision int64) (Catalog, error)

Update replaces an existing profile. expectedRevision must match.

func (*Store) Views

func (s *Store) Views() []ProfileView

Views returns profiles with credential readiness metadata (never values).

type Takeover

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

Takeover manages the machine-level Codex gateway projection into the CLI's native config (~/.codex/config.toml by default, CODEX_HOME-aware). It never touches the user's model, effort, or unrelated config; it preserves the exact pre-takeover bytes in a durable backup and only ever writes the marked Zen-owned projection.

func NewTakeover

func NewTakeover(configPath, stateDir string, gateway *Gateway) *Takeover

NewTakeover constructs the takeover manager. configPath is the Codex config file (honor CODEX_HOME); stateDir is the daemon-owned gateway state dir.

func (*Takeover) ConfigPath

func (t *Takeover) ConfigPath() string

ConfigPath returns the managed Codex config path.

func (*Takeover) Disable

func (t *Takeover) Disable() (TakeoverStatus, error)

Disable removes only the Zen-owned projection: the marked block and the projected model_provider line (restoring the pre-takeover value when it was recorded). Unrelated user changes are preserved. A user-edited projected line is a conflict and is left in place, reported as drifted.

func (*Takeover) Enable

func (t *Takeover) Enable(listenAddr string) (TakeoverStatus, error)

Enable activates the machine-level takeover: exact backup, then an atomic surgical projection that preserves every unrelated byte of the user's config. Idempotent: re-enabling an already-matching projection is a no-op. Missing config is created; malformed config fails safe.

func (*Takeover) LoadState

func (t *Takeover) LoadState() (TakeoverState, error)

LoadState reads the durable takeover state; missing state means inactive.

func (*Takeover) Projection

func (t *Takeover) Projection(listenAddr string) string

Projection returns the exact Zen-owned config block for the gateway.

func (*Takeover) Repair

func (t *Takeover) Repair(listenAddr string) (TakeoverStatus, error)

Repair re-applies the Zen-owned projection over the current config while preserving unrelated user changes. It is used at daemon restart when the durable state claims takeover but the live config drifted (or the daemon crashed mid-write). Never creates a second backup.

func (*Takeover) RestoreBackup

func (t *Takeover) RestoreBackup() (TakeoverStatus, error)

RestoreBackup rolls the exact pre-takeover backup over the current config. This is the recorded rollback procedure; it discards any changes made to the config while takeover was enabled.

func (*Takeover) StatePath

func (t *Takeover) StatePath() string

StatePath returns the durable takeover state path.

func (*Takeover) Status

func (t *Takeover) Status() TakeoverStatus

Status computes the truthful takeover status.

type TakeoverState

type TakeoverState struct {
	Enabled               bool   `json:"enabled"`
	ConfigPath            string `json:"config_path"`
	BackupPath            string `json:"backup_path"`
	ListenAddr            string `json:"listen_addr"`
	ProviderName          string `json:"provider_name"`
	OriginalProviderValue string `json:"original_provider_value,omitempty"`
	EnabledAt             string `json:"enabled_at,omitempty"`
}

TakeoverState is the durable takeover record (never secrets).

type TakeoverStatus

type TakeoverStatus struct {
	State             string `json:"state"` // active | inactive | drifted | broken
	Detail            string `json:"detail,omitempty"`
	ConfigPath        string `json:"config_path,omitempty"`
	BackupPath        string `json:"backup_path,omitempty"`
	ListenAddr        string `json:"listen_addr,omitempty"`
	ProviderName      string `json:"provider_name,omitempty"`
	UpstreamProfileID string `json:"upstream_profile_id,omitempty"`
	GatewayListening  bool   `json:"gateway_listening"`
	Enabled           bool   `json:"enabled"`
	RestoreAvailable  bool   `json:"restore_available"`
}

TakeoverStatus is the truthful control-plane view of takeover state.

type ThreadRuntimeChoice

type ThreadRuntimeChoice struct {
	ConnectionID     string `json:"connection_id"`
	ModelID          string `json:"model_id"`
	Effect           string `json:"effect,omitempty"`
	UseDefaultEffect bool   `json:"use_default_effect,omitempty"`
}

ThreadRuntimeChoice is the complete atomic runtime requested for one existing Zen thread lane. Connection, model, and optional effect are validated together; callers cannot mutate any component independently.

type ThreadRuntimeSelection

type ThreadRuntimeSelection struct {
	SessionID              string   `json:"session_id"`
	Client                 string   `json:"client"`
	ConnectionID           string   `json:"connection_id"`
	ConnectionName         string   `json:"connection_name"`
	ProviderLabel          string   `json:"provider_label,omitempty"`
	ModelID                string   `json:"model_id"`
	ReasoningEffort        string   `json:"reasoning_effort,omitempty"`
	ReasoningEffortDefault string   `json:"reasoning_effort_default,omitempty"`
	ReasoningEfforts       []string `json:"reasoning_efforts,omitempty"`
	CredentialReady        bool     `json:"credential_ready"`
	HotSwitchable          bool     `json:"hot_switchable"`
}

ThreadRuntimeSelection is the Plus-menu current-Session projection. Ordinary public wire omits provider_id. Reasoning Effort fields mirror WireBinding: the current override plus the client model's daemon-owned effort contract (absent for unsupported clients/models).

type VerifiedProfileContract

type VerifiedProfileContract struct {
	Provenance       string
	ClientModelID    string
	UpstreamModelID  string
	ExecutorID       string
	Protocol         string
	RouteProtocol    string
	ProviderID       string
	ClientEnvelope   CapabilityEnvelope
	UpstreamEnvelope CapabilityEnvelope
	// HistoryDomain is provider/model-specific opaque-history compatibility identity.
	HistoryDomain string
}

VerifiedProfileContract is the daemon-authorized Session contract. ClientModelID and UpstreamModelID must exactly equal Profile fields — no drift.

func AuthorizeProfileContract

func AuthorizeProfileContract(profile Profile, auth ContractAuth) (VerifiedProfileContract, error)

AuthorizeProfileContract admits a VerifiedProfileContract. Profile TOML self-claims are never sufficient. Verifier-returned model IDs must exactly match Profile.

func ContractFromProfile

func ContractFromProfile(profile Profile, auth ContractAuth) (VerifiedProfileContract, error)

ContractFromProfile builds the authorized contract view. Self-declared TOML provenance/history/capabilities are not authorization.

type WireActivationEvent

type WireActivationEvent struct {
	Activation string       `json:"activation"`
	From       *WireBinding `json:"from,omitempty"`
	To         WireBinding  `json:"to"`
}

WireActivationEvent is retained for internal audit helpers only. Ordinary Session projections omit activation history (no generation/degradation).

func WireHistory

func WireHistory(history []RouteActivationEvent) []WireActivationEvent

WireHistory projects internal activation history without generation/degradation.

type WireBinding

type WireBinding struct {
	SessionID              string   `json:"session_id"`
	Client                 string   `json:"client"`
	ConnectionID           string   `json:"connection_id"`
	ConnectionName         string   `json:"connection_name"`
	ProviderLabel          string   `json:"provider_label,omitempty"`
	ModelID                string   `json:"model_id"`
	ReasoningEffort        string   `json:"reasoning_effort,omitempty"`
	ReasoningEffortDefault string   `json:"reasoning_effort_default,omitempty"`
	ReasoningEfforts       []string `json:"reasoning_efforts,omitempty"`
	CredentialReady        bool     `json:"credential_ready"`
	HotSwitchable          bool     `json:"hot_switchable"`
}

WireBinding is the App/control-safe Provider-first projection of a RouteBinding. Protocol, client_model, envelopes, auth_mode, credential_env, generation, history portability/degradation, provider_id, and route internals are never exposed here.

Reasoning Effort projection: reasoning_effort is the Session's current daemon-owned override (empty = no override, the CLI/model default applies). reasoning_effort_default and reasoning_efforts are the client model's daemon-owned effort contract (absent for unsupported clients/models).

type WireSessionSnapshot

type WireSessionSnapshot struct {
	Launched *WireBinding `json:"launched,omitempty"`
	Current  *WireBinding `json:"current,omitempty"`
	Ready    bool         `json:"credential_ready"`
}

WireSessionSnapshot is the control-plane Session Provider selection projection. Generation, activation history, and degradation facts are not ordinary public.

type WireSessionState

type WireSessionState struct {
	Binding WireBinding `json:"binding"`
}

WireSessionState is the App-safe Session route projection.

Jump to

Keyboard shortcuts

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