Resource Model
This page is rebuilt from the current CRD types and runtime code in api/..., controllers/..., internal/materializer, internal/render, internal/resolver, internal/routingprovider, and internal/sbclient. It describes what the current code does, including fields that are accepted but not yet acted on by the in-cluster controllers.
SandboxMesh currently ships four CRDs:
| CRD | API version | What it does |
|---|---|---|
Sandbox | control.sandbox.mesh.dev/v1alpha1 | Local runtime intent CR. In SaaS deployments, the agent writes it from hosted assignments and the operator materializes it into SandboxGroup and optionally SandboxRoute. |
SandboxGroup | sandbox.mesh.dev/v1alpha1 | Freezes source workload snapshots and renders sandbox Deployment and Service objects. |
SandboxRoute | routing.mesh.dev/v1alpha1 | Attaches traffic selection using Gateway API, Istio, or the built-in proxy provider. |
DevSession | control.sandbox.mesh.dev/v1alpha1 | Creates a PVC-backed development pod for one sandbox workload and gives the sb CLI a stable target for sync and port-forwarding. |
How the resources fit together
- In SaaS deployments, the agent usually writes a local
Sandboxfrom a hosted assignment. In low-level runtime workflows, you can also author one yourself for testing. - The
Sandboxcontroller validates it, defaultsspec.visibilitytoprivate, and materializes a same-nameSandboxGroup. - If
spec.routingis present, theSandboxcontroller also materializes a same-nameSandboxRoute. - The
SandboxGroupcontroller resolves source workloads, freezes a snapshot, and renders sandboxDeploymentandServiceobjects. - The
SandboxRoutecontroller resolves component backends and attaches a provider-specific child resource such asHTTPRoute,VirtualService, or a proxyDeployment. - When you start local development with
sb up, the CLI creates aDevSessionfor the target sandbox workload. The operator scales the normal sandbox deployment to0, brings up a PVC-backed dev deployment, and retargets the sandbox service at it.
Shared Runtime Behavior
- Supported source kinds are
Deployment,StatefulSet, and ArgoRollout. - Rendered sandbox workloads are always Kubernetes
Deploymentobjects in the current implementation, even when the source is aStatefulSetorRollout. - A
SandboxGroupfreezes the first successful source snapshot. After that, the controller reusesstatus.components[].snapshotuntil thesourceRefchanges or the resource is recreated. - Each sandbox group gets a generated sandbox ID with the form
sbx-xxxxxxxx. That value is also used as the default routing key. - Rendered component names follow fixed conventions:
- deployment:
<sandbox-group>-<component>-sbx - service:
<sandbox-group>-<component>-svc
- deployment:
- Routing defaults to the
baggageheader when no selector header is specified. - When the selector header is
baggage, providers look for asandbox=<id>entry inside the header value. For any other header name, providers expect an exact header value match.
Sandbox
Complete Example
apiVersion: control.sandbox.mesh.dev/v1alpha1
kind: Sandbox
metadata:
name: storefront-preview
namespace: storefront
spec:
projectRef:
id: storefront
clusterRef:
name: dev-cluster-usw2
displayName: Storefront Preview
owner:
type: user
id: user_123
displayName: Jane Developer
visibility: private
workloads:
- name: frontend
type: inherit
inherit:
sourceRef:
apiVersion: apps/v1
kind: Deployment
name: storefront
overrides:
replicas: 2
deploymentLabels:
preview: "true"
deploymentAnnotations:
reloader.stakater.com/auto: "true"
templateLabels:
tier: web
templateAnnotations:
sidecar.istio.io/inject: "false"
containers:
- name: app
image: ghcr.io/acme/storefront:pr-421
command: ["npm", "run", "start:preview"]
args: ["--port", "8080"]
env:
- name: API_BASE_URL
value: http://storefront-preview-api-svc:8080
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
podTemplatePatch:
- op: add
path: /spec/nodeSelector
value:
workload-tier: preview
service:
type: ClusterIP
labels:
expose: "true"
annotations:
cloud.google.com/neg: '{"ingress": true}'
ports:
- name: http
port: 8080
targetPort: 8080
- name: api
type: inherit
inherit:
sourceRef:
apiVersion: apps/v1
kind: StatefulSet
name: api
service:
ports:
- name: http
port: 8080
targetPort: 8080
routing:
provider: gateway
key:
headerName: x-sandbox-id
gateway:
parentRefs:
- name: edge
namespace: infra
hostnames:
- preview.example.com
interceptions:
- name: frontend
targetService:
name: storefront
matches:
- path:
type: PathPrefix
value: /
routeTo:
workload: frontend
port: 8080
- name: api
targetService:
name: storefront-api
matches:
- path:
type: PathPrefix
value: /api
routeTo:
workload: api
port: http
delivery:
provider: argocd
environment: shared-dev
lifecycle:
sleepAfterUnused: 30m
deleteAfterUnused: 24h
minReplicas: 1
metadata:
tags:
team: checkout
ticket: ENG-421
Top-Level Fields
| Field | Required | What the code does |
|---|---|---|
metadata.name | Yes | Becomes the materialized SandboxGroup name and SandboxRoute name. Also becomes part of rendered deployment and service names. |
metadata.namespace | Yes | Namespace for the Sandbox, its materialized resources, and any defaulted source or route references. |
spec.projectRef.id | Yes | Required by validation. Copied onto materialized SandboxGroup and SandboxRoute labels as control.sandbox.mesh.dev/project. Also used by Argo CD companion-application templates. |
spec.clusterRef | No | Stored on the CRD, usually written by the hosted agent to record cluster intent. The local Sandbox reconciler does not use it when materializing resources. |
spec.displayName | No | User-facing label only. The in-cluster renderers do not read it. |
spec.owner | No | Copied into status.createdBy. Not used for rendering or routing decisions in the in-cluster controller. |
spec.visibility | No | Defaults to private when empty. No current in-cluster behavior difference between private and project. |
spec.workloads[] | Yes | Required and must be non-empty. Materializes into SandboxGroup.spec.components[]. Workload names must be unique. |
spec.routing | No | When present, materializes a SandboxRoute. When absent, no route resource is created. |
spec.delivery | No | Controls optional GitOps/Argo CD integration. Empty provider means direct, which skips companion Argo application management. |
spec.lifecycle | No | Accepted and stored, but not currently enforced by the in-cluster controllers. |
spec.metadata.tags | No | Accepted and stored, but not currently used by the in-cluster controllers. |
spec.clusterRef, spec.visibility, spec.lifecycle, and spec.metadata are part of the public shape, but the local Sandbox, SandboxGroup, and SandboxRoute reconcilers do not currently change runtime behavior based on them. They are primarily useful to the hosted control plane, the agent-written runtime contract, or future lifecycle logic.
spec.workloads[]
Only one workload type is currently supported: type: inherit.
| Field | Required | What the code does |
|---|---|---|
name | Yes | Required, unique per sandbox, and used as the SandboxGroup component name. Routing references this name from routeTo.workload. |
type | Yes | Must be inherit. Any other value is rejected by validation. |
inherit | When type=inherit | Required for the current implementation. Defines how to clone the source workload. |
spec.workloads[].inherit
| Field | Required | What the code does |
|---|---|---|
sourceRef.apiVersion | Yes | Required. Parsed into a GVK and resolved against the supported source kinds. |
sourceRef.kind | Yes | Required. Must currently be Deployment, StatefulSet, or Argo Rollout. |
sourceRef.name | Yes | Required. Name of the source workload to clone. |
sourceRef.namespace | No | Defaults to the sandbox namespace during source resolution. |
overrides.replicas | No | Overrides the source replica count for the rendered sandbox deployment. |
overrides.deploymentLabels | No | Merged onto the rendered Deployment labels. |
overrides.deploymentAnnotations | No | Replaces and manages the rendered Deployment annotations. |
overrides.templateLabels | No | Merged onto the rendered pod template labels. |
overrides.templateAnnotations | No | Merged onto the rendered pod template annotations. |
overrides.containers[] | No | Applied by container name after the source template is resolved. A missing source container name causes rendering to fail. |
overrides.containers[].image | No | Replaces the source container image. |
overrides.containers[].command | No | Replaces the source container command when provided. |
overrides.containers[].args | No | Replaces the source container args when provided. |
overrides.containers[].env[] | No | Merged by env var name onto the source container env list. |
overrides.containers[].resources | No | Replaces the source container resource requirements. |
podTemplatePatch[] | No | RFC 6902 JSON patch operations applied after container overrides. Invalid patches fail rendering. |
service | No | Overrides the service rendered for this component. If omitted, the controller infers ports from the source pod template. |
spec.workloads[].inherit.service
service.ports[] is a native Kubernetes ServicePort list.
| Field | Required | What the code does |
|---|---|---|
type | No | Defaults to ClusterIP when empty. |
labels | No | Merged onto the rendered service labels. |
annotations | No | Copied to the rendered service annotations. |
ports[] | No | If provided, these ports replace inferred source ports. If omitted, the controller uses the frozen snapshot ports from the source workload. |
Service port handling has a few runtime defaults:
- if a rendered port omits
targetPort, SandboxMesh sets it to the same numeric value asport - if a rendered port omits
protocol, SandboxMesh defaults it toTCP - if a rendered port omits
name, SandboxMesh usesport-<number> - if no ports can be inferred and none are provided, the component fails to render
spec.routing
The Sandbox CRD exposes a simpler routing model than authoring SandboxRoute directly. Each interception becomes exactly one route rule with exactly one component backend.
| Field | Required | What the code does |
|---|---|---|
provider | Yes, when routing is set | Must be gateway, istio, or proxy. Empty is rejected. |
key.headerName | No | Defaults to baggage. Controls which header the materialized route provider matches on. |
gateway | When provider=gateway | Required for the gateway provider. Copied through to SandboxRoute.spec.gateway. |
istio | When provider=istio | Required for the Istio provider. Copied through to SandboxRoute.spec.istio. |
interceptions[] | Yes, when routing is set | Required and materialized into SandboxRoute.spec.rules[]. |
Provider validation enforced by the controller:
provider: gatewayrequiresgateway.parentRefsand forbidsistioprovider: istiorequiresistio.gatewaysandistio.hosts, and forbidsgatewayprovider: proxyforbids bothgatewayandistio
spec.routing.interceptions[]
| Field | Required | What the code does |
|---|---|---|
name | No | Copied to the generated route rule name. |
targetService.name | Yes | Required. The live service being intercepted. |
targetService.namespace | No | Defaults to the sandbox namespace when materialized. |
matches[] | No | HTTP match list. Empty means catch-all. Each match entry is ORed; fields inside a single match are ANDed. |
matches[].path.type | No | Passed through to the routing provider. Prefix behavior is the practical default when omitted. |
matches[].path.value | No | The matched path or regex. Also used to derive status.endpoints[].path on the parent Sandbox. |
matches[].method | No | Exact HTTP method match. |
matches[].headers[] | No | Header matches. Header match type defaults to exact unless the provider applies its own baggage regex behavior for the selector header. |
matches[].queryParams[] | No | Query parameter matches. Type defaults to exact. |
routeTo.workload | Yes | Required. Must name an existing sandbox workload. |
routeTo.port | Yes | Required. Can be a number or a named component service port. |
spec.delivery
| Field | Required | What the code does |
|---|---|---|
provider | No | Empty or direct means the operator only materializes SandboxGroup and SandboxRoute. argocd additionally creates or updates a companion Argo Application for the Sandbox itself. |
environment | No | Selects an Argo CD environment overlay from operator config when provider=argocd. Ignored for direct delivery. |
Important Argo delivery behavior:
provider=argocdrequires the operator to have Argo companion applications enabled inSANDBOX_MESH_DELIVERY_CONFIG- Argo mode still materializes
SandboxGroupandSandboxRoutedirectly from the liveSandbox - the companion
Applicationpoints at the configured Git source for theSandboxmanifest, not at rendered child resources - when using direct delivery, any previously managed Argo applications for the sandbox are deleted
status
These fields are controller-owned.
| Field | What the code does |
|---|---|
status.phase | The local controller currently sets Materializing, Ready, Degraded, Failed, and Deleting. The enum also includes Pending, PendingCapacity, Sleeping, and Waking for shared/hosted flows, but the local controller does not emit those today. |
status.observedGeneration | Last generation processed by the Sandbox controller. |
status.assignedClusterRef | Part of the CRD shape for higher-level control-plane flows. The local Sandbox controller does not currently populate it. |
status.leaseRef | Part of the CRD shape for higher-level control-plane flows. The local Sandbox controller does not currently populate it. |
status.routingKey.headerName | Set when the materialized SandboxGroup publishes a sandbox ID. Mirrors the effective selector header name. |
status.routingKey.value | The effective sandbox ID used for routing. |
status.activity.lastActiveTime | Present in the API shape, but not set by the local Sandbox controller today. |
status.endpoints[] | Derived from routing hostnames plus each interception path. Only populated for gateway and Istio routes. Proxy routes do not produce endpoint URLs. |
status.underlyingRefs.sandboxGroupName | Name of the materialized SandboxGroup. |
status.underlyingRefs.sandboxRouteName | Name of the materialized SandboxRoute, if routing is enabled. |
status.createdBy | Copy of spec.owner when owner data is present. |
status.conditions[] | Uses Applied, Rendered, Attached, and Ready with reasons like InvalidSpec, ResourcesPending, ApplySucceeded, and RouteAttached. |
SandboxGroup
Complete Example
apiVersion: sandbox.mesh.dev/v1alpha1
kind: SandboxGroup
metadata:
name: storefront-preview
namespace: storefront
spec:
components:
- name: frontend
sourceRef:
apiVersion: apps/v1
kind: Deployment
name: storefront
overrides:
replicas: 2
deploymentLabels:
preview: "true"
deploymentAnnotations:
reloader.stakater.com/auto: "true"
templateLabels:
tier: web
templateAnnotations:
sidecar.istio.io/inject: "false"
containers:
- name: app
image: ghcr.io/acme/storefront:pr-421
command: ["npm", "run", "start:preview"]
args: ["--port", "8080"]
env:
- name: API_BASE_URL
value: http://storefront-preview-api-svc:8080
podTemplatePatch:
- op: add
path: /spec/nodeSelector
value:
workload-tier: preview
service:
type: ClusterIP
labels:
expose: "true"
annotations:
cloud.google.com/neg: '{"ingress": true}'
ports:
- name: http
port: 8080
targetPort: 8080
- name: api
sourceRef:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
name: api
service:
ports:
- name: http
port: 8080
targetPort: 8080
spec.components[]
SandboxGroup is the lower-level form of a materialized sandbox workload. Its fields map almost one-for-one to the materialized output of Sandbox.spec.workloads[].
| Field | Required | What the code does |
|---|---|---|
name | Yes | Required component key. Used in rendered deployment and service names. |
sourceRef | Yes | Defines the workload to clone. Supports Deployment, StatefulSet, and Argo Rollout. Namespace defaults to the group namespace if omitted. |
overrides | No | Same semantics as Sandbox.spec.workloads[].inherit.overrides. Applied before JSON patching. |
podTemplatePatch[] | No | JSON patch list applied to the resolved pod template after container overrides. |
service | No | Controls the rendered service. If omitted, ports come from the frozen source snapshot. |
status
| Field | What the code does |
|---|---|
status.sandboxID | Generated once, then reused. Also becomes the routing key value and the sandbox.mesh.dev/id label on rendered resources. |
status.observedGeneration | Last generation processed by the SandboxGroup controller. |
status.components[].name | Component name this status row belongs to. |
status.components[].sourceRefDigest | Hash of the source reference plus namespace context. Used to decide whether an existing frozen snapshot can be reused. |
status.components[].deploymentName | Actual rendered deployment name, usually <group>-<component>-sbx. |
status.components[].serviceName | Actual rendered service name, usually <group>-<component>-svc. |
status.components[].servicePorts[] | Numeric service ports from the rendered service. |
status.components[].ready | True when the rendered deployment is readable and all replicas are ready. |
status.components[].snapshot.replicas | Frozen source replica count captured at first successful resolution. |
status.components[].snapshot.template | Full frozen PodTemplateSpec captured from the source workload. This is why later source workload edits do not automatically change an existing sandbox. |
status.components[].snapshot.servicePorts[] | Frozen inferred service ports from the source template. |
status.components[].conditions[] | Uses SourceResolved, Rendered, Applied, and Ready. |
status.conditions[] | Group-wide rollup of component conditions. |
Direct-Authoring Notes
- If you edit the source workload after the first successful reconcile, the sandbox stays pinned to the saved snapshot.
- To resnapshot from source, change the component
sourceRefor recreate theSandboxGroup. - If a source template has no container ports and you do not provide
service.ports, the component fails to render.
SandboxRoute
Complete Gateway Example
apiVersion: routing.mesh.dev/v1alpha1
kind: SandboxRoute
metadata:
name: storefront-preview
namespace: storefront
spec:
sandboxGroupRef:
name: storefront-preview
provider: gateway
gateway:
parentRefs:
- name: edge
namespace: infra
hostnames:
- preview.example.com
rules:
- name: storefront
matches:
- path:
type: PathPrefix
value: /
backends:
- component:
name: frontend
port: http
weight: 90
- service:
name: canary-frontend
namespace: storefront
port: 8080
weight: 10
Complete Istio Example
apiVersion: routing.mesh.dev/v1alpha1
kind: SandboxRoute
metadata:
name: storefront-preview-istio
namespace: storefront
spec:
sandboxGroupRef:
name: storefront-preview
provider: istio
selectorHeaderName: x-sandbox-id
istio:
gateways:
- istio-system/public
hosts:
- preview.example.com
rules:
- name: api
matches:
- path:
type: PathPrefix
value: /api
method: GET
backends:
- component:
name: api
port: http
Complete Proxy Example
apiVersion: routing.mesh.dev/v1alpha1
kind: SandboxRoute
metadata:
name: storefront-preview-proxy
namespace: storefront
spec:
sandboxGroupRef:
name: storefront-preview
provider: proxy
selectorHeaderName: baggage
rules:
- name: storefront
targetServiceRef:
name: storefront
matches:
- path:
type: PathPrefix
value: /
backends:
- component:
name: frontend
port: http
Top-Level Fields
| Field | Required | What the code does |
|---|---|---|
metadata.name | Yes | Name of the route and, for gateway or Istio, usually the name of the provider-owned child resource too. |
metadata.namespace | Yes | Namespace used for defaulting component refs, explicit service refs, and provider-owned resources. |
spec.sandboxGroupRef | No | Needed when you route to component backends. The controller reads component status from the referenced SandboxGroup to resolve service names and named ports. |
spec.provider | Yes | Must be gateway, istio, or proxy. Empty is rejected. Unsupported providers also fail status. |
spec.selectorHeaderName | No | Defaults to baggage. baggage uses regex matching for sandbox=<id> entries. Any other header name uses exact value matching. |
spec.gateway | When provider=gateway | Required for the gateway provider. Converted into a Kubernetes HTTPRoute. |
spec.istio | When provider=istio | Required for the Istio provider. Converted into an Istio VirtualService. |
spec.rules[] | Yes | Required. Each rule must define at least one backend. |
spec.rules[]
| Field | Required | What the code does |
|---|---|---|
name | No | Optional rule label. Used directly as the Istio HTTP route name and in error messages. |
targetServiceRef | Required for provider=proxy | Required only for proxy routing. Identifies the live service whose selector will be redirected through the proxy deployment. |
matches[] | No | Match list. Empty means catch-all. Entries are ORed. Within a single entry, path, method, headers, and query params are ANDed. |
matches[].path.type | No | Exact, PathPrefix, or RegularExpression. Gateway and Istio default to prefix semantics when omitted. |
matches[].path.value | No | Path prefix, exact path, or regex depending on type. |
matches[].method | No | Exact HTTP method match. |
matches[].headers[].name | Yes | HTTP header name to test. |
matches[].headers[].value | Yes | Exact or regex value depending on type. |
matches[].headers[].type | No | Defaults to exact. |
matches[].queryParams[].name | Yes | Query parameter name to test. |
matches[].queryParams[].value | Yes | Exact or regex value depending on type. |
matches[].queryParams[].type | No | Defaults to exact. |
backends[] | Yes | Required. Each backend must set exactly one of component or service. |
backends[].weight | No | Defaults to 1. Used by all providers when more than one backend is present. |
backends[].component.name | Yes, for component backends | Must name a component in the referenced SandboxGroup. |
backends[].component.port | Yes, for component backends | Can be numeric or named. Named ports resolve from the component snapshot service ports. |
backends[].service.name | Yes, for service backends | Explicit service backend without consulting a sandbox group. |
backends[].service.namespace | No | Defaults to the route namespace. |
backends[].service.port | Yes, for service backends | Must currently be numeric. Named service backend ports are not supported by the controller. |
Provider-Specific Behavior
gateway- validates that
spec.gateway.parentRefsis present - creates a Gateway API
HTTPRoute - injects the selector header match into every rule before writing the route
- validates that
istio- validates that
spec.istio.gatewaysandspec.istio.hostsare present - creates an Istio
VirtualService - lowercases matched header names when generating Istio header matches
- validates that
proxy- requires every rule to set
targetServiceRef - requires
targetServiceRef.namespaceto match the route namespace - creates a shadow baseline service plus a proxy deployment and service
- rewrites the live target service selector so matching traffic flows through the proxy
- requires every rule to set
status
| Field | What the code does |
|---|---|
status.sandboxID | Copied from the referenced SandboxGroup when one is present. If no group is referenced, the controller generates a new sandbox ID for the route. |
status.observedGeneration | Last generation processed by the SandboxRoute controller. |
status.provider | The provider that actually reconciled the route. |
status.attachedResource | Reference to the provider-owned child resource such as HTTPRoute, VirtualService, or proxy Deployment. |
status.conditions[] | Uses Attached with reasons like InvalidSpec, ProviderUnavailable, ResolveFailed, AttachFailed, OwnershipConflict, and RouteAttached. |
DevSession
Complete Example
apiVersion: control.sandbox.mesh.dev/v1alpha1
kind: DevSession
metadata:
name: storefront-preview-frontend-dev
namespace: storefront
spec:
sandboxRef:
name: storefront-preview
workload: frontend
targetPath: /app
containerName: app
image: ghcr.io/acme/storefront:dev
storage:
size: 10Gi
storageClassName: fast-ssd
accessModes:
- ReadWriteOnce
Top-Level Fields
| Field | Required | What the code does |
|---|---|---|
metadata.name | Yes | Session name used by the CLI and by the operator-owned PVC and development deployment. |
metadata.namespace | Yes | Namespace used for defaulting sandboxRef.namespace and for creating the dev deployment and PVC. |
spec.sandboxRef.name | Yes | Required. Names the parent Sandbox. |
spec.sandboxRef.namespace | No | Defaults to the DevSession namespace. |
spec.workload | Yes | Required. Must match a workload name in the target sandbox. |
spec.targetPath | Yes | Absolute path inside the selected container where the PVC-backed workspace is mounted. |
spec.containerName | No | If set, selects which app container receives the workspace mount and any optional image override. Defaults to the first container. |
spec.image | No | Optional image override for the target container in the dev deployment. |
spec.storage | No | Optional PVC settings for the workspace volume. |
Runtime Behavior
- The controller resolves the sandbox and its materialized
SandboxGroup. - The normal sandbox deployment for the selected workload is still the source of truth for the pod template.
- A dedicated PVC-backed development deployment named
<devsession>-devis created. - A copy-up init container seeds the PVC from the image's existing
targetPathcontents when the volume is empty. - While a
DevSessionexists for a workload, theSandboxGroupcontroller scales the normal sandbox deployment to0and retargets the sandbox service at the dev deployment. - The
sb upCLI creates or updates this resource, waits for it to become ready, then syncs a local directory intospec.targetPath.
status
| Field | What the code does |
|---|---|
status.observedGeneration | Last generation processed by the DevSession controller. |
status.phase | Pending, Ready, Failed, or Deleting. |
status.deploymentName | Name of the operator-managed dev deployment, usually <session>-dev. |
status.pvcName | Name of the operator-managed workspace PVC, usually <session>-workspace. |
status.serviceName | Sandbox service that now points at the dev deployment while the session is active. |
status.containerName | Effective container selected for the workspace mount. |
status.ports[] | Service ports exposed by the workload for CLI port-forwarding. |
status.conditions[] | Uses Resolved and Ready. Ready=True means the dev deployment is serving traffic. |
What To Author Directly
- Use
Sandboxwhen you want the higher-level API and are happy with one-backend-per-interception routing. - Use
SandboxGroupdirectly when you want fixed frozen workload clones without the higher-levelSandboxAPI. - Use
SandboxRoutedirectly when you need routing features theSandboxCRD does not expose, such as multiple weighted backends in a single rule. - Use
DevSessionwhen you want a PVC-backed development pod for a specific sandbox workload and you need the sandbox service to shift over to that dev pod while you iterate locally.