Documentation
¶
Index ¶
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 WorkspaceFinalizer = "workspace.llmsafespaces.dev/finalizer"
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
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 Cloudflare Worker URL for free-tier inference
// (Epic 26). When set, workspace pods route opencode provider requests
// through this URL for IP distribution. When empty, opencode uses its
// default gateway (opencode.ai/zen/v1) directly.
InferenceRelayURL string
// InferenceRelaySecret is the path-segment secret that authenticates
// requests to the CF Worker. When set, it is appended to InferenceRelayURL
// as the first path segment: https://relay.example.com/<secret>.
// The Worker strips and validates this segment before forwarding upstream.
// Set via --inference-relay-secret controller flag, sourced from a k8s Secret.
InferenceRelaySecret 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 /v1/reload-secrets push handles delivery).
APIServiceURL string
// contains filtered or unexported fields
}
func (*WorkspaceReconciler) SetupWithManager ¶
func (r *WorkspaceReconciler) SetupWithManager(mgr ctrl.Manager) error
Source Files
¶
- 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
- pod_builder.go
- pvc.go
- reconciler.go
- recovery.go
- recovery_policy.go
- runtime_resolver.go
- secrets.go
- suspend_request.go