Xeonr Developer Docs

Concepts

Namespaces, the three axes of a workload, the isolation model, and how failures are classified.

Namespaces

A namespace is the tenancy scope. Every resource — environment, job, sandbox, app, workspace, egress policy, pool — belongs to exactly one, and a namespace-scoped credential cannot name another namespace's resources. Cross-namespace visibility exists only for the admin scope.

The logical boundary is backed by a real one: creating a namespace provisions a dedicated Kubernetes runner namespace (cp-rn-<namespace>) with its own service account, NetworkPolicies, LimitRange, ResourceQuota and gVisor runtime class. Deleting the namespace tears it down. There is no shared runner pool.

FieldMeaning
groupsOIDC group → role bindings; how humans get access
default_limitsPer-workload resource defaults
quota_cpu_millis / quota_memory_mb / quota_max_podsSeeds the Kubernetes ResourceQuota
internal_targetsIn-cluster hosts this namespace's policies may reach (Egress)
image_pull_secretsNames of platform-held pull secrets copied into this namespace's runner namespace

Three separate axes

A workload is composed from three independent things. Keeping them apart is what makes caching, forking and rollback cheap.

AxisWhat it isMutability
EnvironmentDeps and toolchain, as a digest-pinned OCI imageImmutable, content-addressed, shared
WorkspaceThe user's files, via a full file API over object storageMutable, durable, outlives any pod
Egress policyWhich hosts the workload may reachSet at create; widened or narrowed live on a sandbox

A sandbox is environment + workspace + agent. A job is environment + argv (+ optional workspace). An app version is environment + port (+ optional read-only workspace snapshot).

The pod

Every workload pod is built to the same hardened shape.

  • gVisor (runsc) by default. The kernel boundary is a userspace kernel, not the host's. RUNC and KATA are per-environment knobs; running as root is only accepted under gVisor or Kata, never runc.
  • Hardened by default: non-root uid 1000, read-only root filesystem, all capabilities dropped, allowPrivilegeEscalation: false, seccomp RuntimeDefault, no service-account token, emptyDir scratch with size limits, requests == limits, and an activeDeadlineSeconds kill switch. ContainerSecurity relaxes only uid and rootfs writability.
  • An agent sidecar holds the pod's only credentials, materialises the workspace, brokers exec and file IO, seeds inputs, and collects outputs. The workload container itself holds nothing.
  • An egress gate init container blocks the workload from starting until the network policy is provably active. A CNI programs per-pod rules shortly after the pod gets its IP; the gate polls direct external egress and only exits once it is sealed. If egress never seals within 40s the pod fails closed and the workload never runs.
  • Filesystem layout: /work is scratch — where job inputs are staged and outputs collected. /workspace is the attached workspace, when there is one.

Network

There is no partial network. The L3 policy is default-deny with exactly one additive rule: TCP to the egress proxy. There is no DNS route (the pod's resolver is 127.0.0.1), no CIDR rule to the internet, no UDP and no QUIC.

Which names resolve and which hosts connect is decided by the egress policy the proxy enforces, per job, per moment. HTTP_PROXY is set for compliant clients, but it is not the boundary — the topology is.

Failure taxonomy

Termination is always derived from pod and cgroup status, never self-reported by the workload.

ValueMeans
TERMINATION_EXITEDClean exit; read exit_code
TERMINATION_OOM_KILLEDMemory limit hit
TERMINATION_TIMEOUTtimeout_sec / deadline fired
TERMINATION_SANDBOX_VIOLATIONgVisor killed it (SIGSYS / exit 159), or the egress gate never sealed
TERMINATION_CANCELLEDCancelJob, or the sandbox went away
TERMINATION_IMAGE_PULL_FAILEDImage unreachable or not pullable with the namespace's secrets
TERMINATION_INFRA_ERRORPlatform-side failure

Identifiers and labels

Ids (job_id, sandbox_id, environment_id, workspace_id, app_id) are the reference and are stable. label is a display name — required by the console, optional on the wire, never interpreted by the platform.

Streaming

The API is unary except where streaming is genuinely needed: RunJob, TailLogs, BuildEnvironment, WatchSandbox, WatchApp, StreamEgressEvents (server streams), and Exec / AttachConsole (bidi). Browsers can't do bidi over connect-web, so the console reaches the bidi calls through WebSocket bridges on the api; native clients use them directly.

On this page