Documentation
¶
Index ¶
- Constants
- Variables
- func ValidateAgentdDelivery(image, amd64, arm64 string) error
- func ValidateAgentdSidecar(sidecarEnabled bool, agentdImage string) error
- type AgentdBinaryPins
- type AgentdDeliveryConfig
- type CachedOrgStatusClient
- type FailureClass
- type HostResolver
- type OrgStatusClient
- type OrgStatusLogger
- type PodObservation
- type RecoveryPolicy
- type WorkspaceReconciler
Constants ¶
const ( LabelApp = "app" LabelComponent = "component" LabelWorkspace = "llmsafespaces.dev/workspace" LabelRuntime = "runtime" LabelTenant = "llmsafespaces.dev/tenant" AppName = "llmsafespaces" ComponentWorkspace = "workspace" )
Labels applied to workspace pods.
const ( // AgentdPinsConfigMapName caches the last successfully resolved pins // per digest so a controller restart during a registry outage does // not brick startup. AgentdPinsConfigMapName = "llmsafespaces-agentd-pins" )
const ( // SidecarRestartMarkerEnv wires LLMSAFESPACES_RESTART_MARKER_PATH on // both containers so the sidecar's and the supervisor's marker writes // land on one cross-uid-readable file (0640 + shared gid 1000). SidecarRestartMarkerEnv = agentd.SidecarRestartMarkerPath )
const WorkspaceFinalizer = "workspace.llmsafespaces.dev/finalizer"
Variables ¶
ErrAgentdPinsUnavailable wraps every resolution failure where the registry was unreachable AND no usable cache existed. Callers can errors.Is this to offer the manual-pin hint.
Functions ¶
func ValidateAgentdDelivery ¶ added in v0.15.8
ValidateAgentdDelivery is the exported startup guard used by controller main. Wraps validateAgentdDeliveryConfig.
func ValidateAgentdSidecar ¶ added in v0.18.0
ValidateAgentdSidecar is the exported startup guard used by controller main. Wraps validateAgentdSidecarConfig.
Types ¶
type AgentdBinaryPins ¶ added in v0.15.10
AgentdBinaryPins are the resolved per-arch binary sha256s.
func ResolvePinsWithCache ¶ added in v0.15.10
func ResolvePinsWithCache(ctx context.Context, image, flagAMD64, flagARM64 string) (AgentdBinaryPins, error)
ResolvePinsWithCache is the startup entrypoint used by controller main. validateAgentdDeliveryConfig has already run, guaranteeing both-or-neither hash flags: the both-set form returns them verbatim after hex validation (manual pin, no registry access); the neither form (the normal Renovate pin) resolves from the image index annotations via the ConfigMap-cached resolver. Runs before the manager starts so a broken pin fails fast.
type AgentdDeliveryConfig ¶ added in v0.15.8
AgentdDeliveryConfig is the #863 overlay-delivery configuration passed from controller main (flags) to the reconciler. Zero value = legacy baked-in mode.
type CachedOrgStatusClient ¶
type CachedOrgStatusClient struct {
// contains filtered or unexported fields
}
CachedOrgStatusClient is an OrgStatusClient backed by the API service's internal org-status endpoint with a per-org TTL cache.
Cache semantics (D20):
- On a fresh cache hit (< TTL): return the cached status, no fetch.
- On a stale entry (>= TTL) or cache miss: attempt a fetch.
- Fetch success: update the cache and return the new status.
- Fetch failure + prior entry: serve the STALE cached status so a transient API outage does not flip the controller into fail-open and leave suspended orgs running. This is the "30s cache absorbs transient failures" guarantee.
- Fetch failure + no entry: return ok=false (fail open — D20: an unwarranted suspension is more disruptive than leaving a pod running).
Concurrency: each orgID has its own entry guarded by a mutex, so concurrent refreshes for the SAME org are deduplicated (only one in-flight fetch per org) while different orgs refresh in parallel. The mutex is held for the duration of the fetch, bounding concurrent same-org fetches to one.
func NewCachedOrgStatusClient ¶
func NewCachedOrgStatusClient(baseURL, token string, ttl time.Duration, logger OrgStatusLogger) *CachedOrgStatusClient
NewCachedOrgStatusClient constructs the client. baseURL is the API service root (e.g. http://llmsafespaces-api.llmsafespaces.svc:8080); leave empty to disable org-suspension (the reconciler then never org-suspends). token, when non-empty, is sent as X-Internal-Token. ttl is the cache freshness window (production: 30s). logger may be nil.
func (*CachedOrgStatusClient) GetOrgStatus ¶
GetOrgStatus implements OrgStatusClient. See CachedOrgStatusClient docs for the cache + fail-open contract.
type FailureClass ¶
type FailureClass string
const ( FailureClassNone FailureClass = "" FailureClassInfrastructure FailureClass = "Infrastructure" FailureClassResource FailureClass = "Resource" FailureClassProcess FailureClass = "Process" FailureClassConfiguration FailureClass = "Configuration" )
type HostResolver ¶
HostResolver resolves a hostname to a list of IP strings. Tests inject a stub via WorkspaceReconciler.HostResolver to avoid hitting real DNS; production uses net.DefaultResolver via defaultHostResolver.
type OrgStatusClient ¶
type OrgStatusClient interface {
GetOrgStatus(ctx context.Context, orgID string) (status string, ok bool)
}
OrgStatusClient reports an org's operational status. ok is false when the status could not be determined (API unreachable and no cached value); callers MUST fail open in that case (D20). ok is true whenever a value — fresh or stale — is available.
The interface lets tests inject a fake without an HTTP server.
type OrgStatusLogger ¶
type OrgStatusLogger interface {
Info(msg string, keysAndValues ...any)
Error(err error, msg string, keysAndValues ...any)
}
OrgStatusLogger is the minimal logging surface CachedOrgStatusClient uses. controller-runtime's logr.Logger satisfies it; nil disables logging.
type PodObservation ¶
type RecoveryPolicy ¶
type WorkspaceReconciler ¶
type WorkspaceReconciler struct {
client.Client
Scheme *runtime.Scheme
// HostResolver is used by the per-workspace NetworkPolicy generator
// (network_policy.go) to resolve declared FQDNs to /32 ipBlocks at
// reconcile time. Tests inject a stub; production uses
// defaultHostResolver (net.DefaultResolver) when nil.
HostResolver HostResolver
// InferenceRelayURL is the self-hosted relay URL for free-tier inference
// (Epic 42 InferenceRelay fleet). When set, workspace pods route opencode
// free-tier provider requests through this URL for IP distribution. When
// empty (the chart default), opencode uses its default gateway
// (opencode.ai/zen/v1) directly with the built-in `public` key.
InferenceRelayURL string
// OrgStatusClient, when non-nil AND the workspace belongs to an org
// (Spec.Owner.OrgID != ""), is consulted on every Active reconcile to drive
// D20 org-level suspension: if the org is suspended, the workspace
// transitions Active → Suspending (pod killed, PVC retained). The client is
// nil when --api-service-url is unset, disabling the feature. Lookups are
// cached (30s TTL); a lookup failure fails open (workspace keeps running).
OrgStatusClient OrgStatusClient
// DefaultRuntimeClass is the container runtime class applied to all
// workspace pods (Epic 51 S51.1). Typically "gvisor" for production
// multi-tenant deployments to provide kernel-level isolation against
// container escape. Empty means use the default (runc). Set via
// --default-runtime-class controller flag, sourced from Helm
// .Values.gvisor.defaultRuntimeClass (only set when .Values.gvisor.enabled
// is true). Individual workspaces can override via spec.runtimeClass for
// compatibility opt-out (admin-gated).
DefaultRuntimeClass string
// APIServiceURL is the in-cluster URL of the API service, used by the
// workspace init container's bootstrap subcommand (Epic 35 US-35.4) to
// fetch decrypted credentials via POST /internal/v1/pod-bootstrap. Same
// value as --api-service-url (also used for OrgStatusClient). When empty,
// the bootstrap subcommand degrades gracefully (empty secrets, pod boots
// without credentials; live /reload-secrets push handles delivery).
APIServiceURL string
// PreviewOriginBaseDomain (Epic 66 Phase 1): when non-empty, workspace
// pods receive PREVIEW_ORIGIN_BASE_DOMAIN so agentd's dev_preview_url
// MCP tool emits the per-workspace-origin bootstrap URL instead of the
// path-based URL. Sourced from the same previewOrigin.baseDomain chart
// value the API consumes — one flag enables the deployment-wide mode.
// Empty = path-based dev preview (unchanged behavior).
PreviewOriginBaseDomain string
// #863 agentd overlay delivery. When AgentdImage is set, buildPod pins a
// digest-addressed image volume into every workspace pod and the
// entrypoint verifies the binary's sha256 against the per-arch pins
// before exec. All three fields must be set together (validated at
// startup by validateAgentdDeliveryConfig). Empty AgentdImage = legacy
// mode (binary baked into runtimes/base; no volume, mount, or env).
AgentdImage string
AgentdBinarySHA256AMD64 string
AgentdBinarySHA256ARM64 string
// AgentdSidecarEnabled (design 0051 US-2, chart-gated, default
// false): when true, buildPod appends the native agentd sidecar and
// switches the main container to supervise-opencode mode. Requires
// AgentdImage (validated at startup) — the sidecar runs the same
// digest-pinned delivery artifact.
AgentdSidecarEnabled bool
// Recorder emits Kubernetes events on the Workspace (agentd verify
// failures). Injected from mgr.GetEventRecorderFor() in production;
// a FakeRecorder in tests.
Recorder record.EventRecorder
// contains filtered or unexported fields
}
func (*WorkspaceReconciler) SetupWithManager ¶
func (r *WorkspaceReconciler) SetupWithManager(mgr ctrl.Manager) error
Source Files
¶
- agentd_overlay.go
- agentd_pins.go
- agentd_sidecar.go
- boot_failure.go
- classification.go
- constants.go
- health.go
- helpers.go
- metrics_wiring.go
- network_policy.go
- org_status_client.go
- org_suspend.go
- phase_active.go
- phase_creating.go
- phase_pending.go
- phase_suspend.go
- phase_terminating.go
- platform_init.go
- pod_builder.go
- pvc.go
- reconciler.go
- recovery.go
- recovery_policy.go
- runtime_resolver.go
- secrets.go
- suspend_request.go