Files
wehub-resource-sync e0e362d700
SDK Tests / changes (push) Successful in 2m29s
Real E2E Tests / changes (push) Successful in 2m29s
Deploy Docs Pages / build (push) Has been cancelled
Deploy Docs Pages / deploy (push) Has been cancelled
Real E2E Tests / JavaScript E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Python E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Java E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / C# E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Go E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Real E2E CI (push) Has been cancelled
SDK Tests / SDK CI (push) Has been cancelled
SDK Tests / CLI Tests (push) Has been cancelled
SDK Tests / Python SDK Quality (code-interpreter) (push) Has been cancelled
SDK Tests / Python SDK Quality (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (sandbox) (push) Has been cancelled
SDK Tests / CLI Quality (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Go SDK Quality And Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:39:33 +08:00

1636 lines
58 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
openapi: 3.1.0
info:
title: OpenSandbox Lifecycle API
version: 0.1.0
description: |
The Sandbox Lifecycle API coordinates how untrusted workloads are created,
executed, paused, resumed, and finally disposed. This specification focuses on
the primary lifecycle flows for the `sandbox` domain concept. Sandboxes can
be provisioned directly from container images or restored from snapshots.
## Sandbox Lifecycle
A sandbox follows this lifecycle:
1. **Creation** → Sandbox is provisioned and enters `Running` state
2. **Execution** → Sandbox is running and ready to accept requests
3. **Pause** (optional) → `Pausing` → `Paused` (asynchronous process)
4. **Resume** (optional) → `Resuming` → `Running` (asynchronous process)
5. **Termination** → `Stopping` → `Terminated` (can be triggered by kill action, TTL expiry, or error)
6. **Error** → Any state can transition to `Failed` on critical errors
The `status` field provides fine-grained details through `state`, `reason`, and `message`.
## Authentication
API Key authentication is required for all operations:
1. **HTTP Header**
```
OPEN-SANDBOX-API-KEY: your-api-key
```
2. **Environment Variable** (for SDK clients)
```
OPEN_SANDBOX_API_KEY=your-api-key
```
SDK clients will automatically pick up this environment variable.
servers:
- url: http://localhost:8080/v1
description: Local development
security:
- apiKeyAuth: []
tags:
- name: Sandboxes
description: Provision and transition sandboxes through their lifecycle
- name: Snapshots
description: Create, list, and delete persistent sandbox snapshots
paths:
/sandboxes:
get:
tags: [ Sandboxes ]
summary: List sandboxes
description: |
List all sandboxes with optional filtering and pagination using query parameters.
All filter conditions use AND logic. Multiple `state` parameters use OR logic within states.
parameters:
- name: state
in: query
description: |
Filter by lifecycle state. Pass multiple times for OR logic.
Example: `?state=Running&state=Paused`
schema:
type: array
items:
type: string
style: form
explode: true
- name: metadata
in: query
description: |
Arbitrary metadata key-value pairs for filteringkeys and values must be url encoded
Example: To filter by `project=Apollo` and `note=Demo Test`: `?metadata=project%3DApollo%26note%3DDemo%252520Test`
schema:
type: string
style: form
- name: page
in: query
description: Page number for pagination
schema:
type: integer
minimum: 1
default: 1
- name: pageSize
in: query
description: Number of items per page
schema:
type: integer
minimum: 1
default: 20
responses:
'200':
description: Paginated collection of sandboxes
content:
application/json:
schema:
$ref: '#/components/schemas/ListSandboxesResponse'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
post:
tags: [Sandboxes]
summary: Create a sandbox
description: |
Creates a new sandbox from a container image or restores one from a
persistent sandbox snapshot with optional resource limits, environment
variables, and metadata.
Exactly one startup source must be provided:
- `image` to provision directly from a container image.
- `snapshotId` to restore from a previously created snapshot.
When `image` is provided, `entrypoint` is required. When `snapshotId` is
provided, `entrypoint` is optional. If omitted, the server defaults the
sandbox entrypoint to `["tail", "-f", "/dev/null"]`.
## Authentication
API Key authentication is required via:
- `OPEN-SANDBOX-API-KEY: <api-key>` header
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateSandboxRequest'
examples:
deny-with-allowlist:
summary: Deny by default with allowed domains
value:
image:
uri: python:3.11
timeout: 3600
resourceLimits:
cpu: "500m"
memory: "512Mi"
entrypoint: ["python", "/app/main.py"]
networkPolicy:
defaultAction: deny
egress:
- action: allow
target: "pypi.org"
allow-with-denylist:
summary: Allow by default with a deny rule
value:
image:
uri: python:3.11
timeout: 3600
resourceLimits:
cpu: "500m"
memory: "512Mi"
entrypoint: ["python", "/app/main.py"]
networkPolicy:
defaultAction: allow
egress:
- action: deny
target: "bad.example.com"
manual-cleanup:
summary: Manual cleanup without automatic expiration
value:
image:
uri: python:3.11
platform:
os: linux
arch: amd64
resourceLimits:
cpu: "500m"
memory: "512Mi"
entrypoint: ["python", "/app/main.py"]
secure-access:
summary: Enable secured access for sandbox endpoints in Kubernetes gateway mode
value:
image:
uri: python:3.11
timeout: 3600
resourceLimits:
cpu: "500m"
memory: "512Mi"
entrypoint: ["python", "/app/main.py"]
secureAccess: true
restore-snapshot:
summary: Restore from a snapshot
value:
snapshotId: snap_123
timeout: 3600
resourceLimits:
cpu: "500m"
memory: "512Mi"
restore-snapshot-with-entrypoint:
summary: Restore from a snapshot with a custom entrypoint
value:
snapshotId: snap_123
timeout: 3600
resourceLimits:
cpu: "500m"
memory: "512Mi"
entrypoint: ["python", "/workspace/app.py"]
responses:
'202':
description: |
Sandbox created and provisioned successfully.
The returned sandbox includes:
- `id`: Unique sandbox identifier
- `status.state: "Running"` (provisioning completed synchronously)
- `status.reason` and `status.message` indicating current state
- `metadata`, `expiresAt`, `createdAt`: Core sandbox information
Note: startup source details and `updatedAt` are not included in the create response.
Use GET /sandboxes/{sandboxId} to retrieve the complete sandbox information.
content:
application/json:
schema:
$ref: '#/components/schemas/CreateSandboxResponse'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
Location:
$ref: '#/components/headers/Location'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
/snapshots:
get:
tags: [Snapshots]
summary: List snapshots
description: |
List all snapshots with optional filtering and pagination using query parameters.
Snapshots are persistent captures of sandbox state and may outlive the source sandbox.
parameters:
- name: sandboxId
in: query
description: Filter snapshots by source sandbox identifier
schema:
type: string
- name: state
in: query
description: |
Filter by snapshot lifecycle state. Pass multiple times for OR logic.
Example: `?state=Ready&state=Failed`
schema:
type: array
items:
$ref: '#/components/schemas/SnapshotState'
style: form
explode: true
- name: page
in: query
description: Page number for pagination
schema:
type: integer
minimum: 1
default: 1
- name: pageSize
in: query
description: Number of items per page
schema:
type: integer
minimum: 1
default: 20
responses:
'200':
description: Paginated collection of snapshots
content:
application/json:
schema:
$ref: '#/components/schemas/ListSnapshotsResponse'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/snapshots/{snapshotId}:
parameters:
- $ref: '#/components/parameters/SnapshotId'
get:
tags: [Snapshots]
summary: Fetch a snapshot by id
description: Returns snapshot state and metadata.
responses:
'200':
description: Snapshot current state and metadata
content:
application/json:
schema:
$ref: '#/components/schemas/Snapshot'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
tags: [Snapshots]
summary: Delete a snapshot
description: |
Delete a persistent sandbox snapshot by id. Snapshots that are still
being created cannot be deleted.
For Kubernetes-backed snapshots, deletion removes OpenSandbox metadata
and Kubernetes coordination resources, but does not guarantee removal
of pushed OCI images from the configured registry. Use registry
retention or garbage collection policies for image lifecycle cleanup.
responses:
'204':
description: Snapshot successfully deleted
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
/sandboxes/{sandboxId}:
parameters:
- $ref: '#/components/parameters/SandboxId'
get:
tags: [Sandboxes]
summary: Fetch a sandbox by id
description: |
Returns the complete sandbox information including:
- `id`, `status`, `metadata`, `expiresAt`, `createdAt`: Core information
- `image` or `snapshotId`: Startup source information (not included in create response)
- `entrypoint`: Entry process specification
This is the complete representation of the sandbox resource.
responses:
'200':
description: Sandbox current state and metadata
content:
application/json:
schema:
$ref: '#/components/schemas/Sandbox'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
tags: [Sandboxes]
summary: Delete a sandbox
description: Delete a sandbox, terminating its execution. The sandbox will transition through Stopping state to Terminated.
responses:
'204':
description: |
Sandbox successfully deleted.
Sandbox has been scheduled for termination and will transition to Stopping state, then Terminated.
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
/sandboxes/{sandboxId}/metadata:
parameters:
- $ref: '#/components/parameters/SandboxId'
patch:
tags: [Sandboxes]
summary: Patch sandbox metadata
description: |
Update sandbox metadata using JSON Merge Patch semantics (RFC 7396).
**Merge Patch rules:**
| Request body key/value | Behavior |
|---|---|
| `"key": "value"` | Add or replace the key |
| `"key": null` | Delete the key (silently ignored if key does not exist) |
| key absent | Keep current value (no change) |
| Empty `{}` | No-op, returns current metadata |
Metadata keys and values must comply with Kubernetes label rules:
- Keys must be valid DNS label names or prefixed DNS subdomains
- Keys with the `opensandbox.io/` prefix are reserved and rejected
- Values must be 63 characters or less, matching `[A-Za-z0-9]([-A-Za-z0-9_.]*[A-Za-z0-9])?`
This operation does not restart or recreate the sandbox container/pod.
**Concurrency:** This endpoint uses read-modify-write without optimistic
locking (no `resourceVersion` check). Concurrent PATCH requests may
interleave and silently drop updates. Use a single writer or coordinate
out-of-band when concurrent modifications to the same key are expected.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PatchSandboxMetadataRequest'
examples:
add-and-replace:
summary: Add new keys and replace existing values
value:
team: "platform"
version: "2.0"
delete-key:
summary: Delete a metadata key
value:
deprecated-key: null
mixed-operations:
summary: Add, replace, and delete in a single request
value:
project: "new-project"
team: null
environment: "production"
empty-body:
summary: No-op (returns current metadata)
value: {}
responses:
'200':
description: |
Metadata patched successfully. Returns the complete sandbox resource
with updated metadata.
content:
application/json:
schema:
$ref: '#/components/schemas/Sandbox'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
/sandboxes/{sandboxId}/snapshots:
post:
tags: [Snapshots]
summary: Create a snapshot from a sandbox
description: |
Create a persistent point-in-time snapshot from the sandbox's current state.
The source sandbox must be `Running`. The returned snapshot id identifies
the created artifact. Snapshot creation may temporarily pause the sandbox
while the runtime captures provider-supported state, then the source
sandbox continues running.
parameters:
- $ref: '#/components/parameters/SandboxId'
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/CreateSnapshotRequest'
examples:
default:
summary: Create an unnamed snapshot
value: {}
named:
summary: Create a named snapshot
value:
name: checkpoint-before-import
responses:
'202':
description: |
Snapshot creation accepted.
The returned snapshot includes `status.state: "Creating"`.
Poll GET /snapshots/{snapshotId} to track progress until the snapshot
transitions to `Ready` or `Failed`.
content:
application/json:
schema:
$ref: '#/components/schemas/Snapshot'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
Location:
$ref: '#/components/headers/Location'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
/sandboxes/{sandboxId}/pause:
post:
tags: [Sandboxes]
summary: Pause execution while retaining state
description: Pause a running sandbox while preserving its state. Poll GET /sandboxes/{sandboxId} to track state transition through Pausing and eventually Paused.
parameters:
- $ref: '#/components/parameters/SandboxId'
responses:
'202':
description: |
Pause operation accepted.
Sandbox will transition to Pausing state and eventually Paused.
Poll GET /sandboxes/{sandboxId} to track progress.
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
/sandboxes/{sandboxId}/resume:
post:
tags: [Sandboxes]
summary: Resume a paused sandbox
description: Resume execution of a paused sandbox. Poll GET /sandboxes/{sandboxId} to track state transition through Resuming and eventually Running.
parameters:
- $ref: '#/components/parameters/SandboxId'
responses:
'202':
description: |
Resume operation accepted.
Sandbox will transition from Paused → Resuming → Running.
Poll GET /sandboxes/{sandboxId} to track progress.
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
/sandboxes/{sandboxId}/renew-expiration:
post:
tags: [Sandboxes]
summary: Renew sandbox expiration
description: Renew the absolute expiration time of a sandbox.
parameters:
- $ref: '#/components/parameters/SandboxId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RenewSandboxExpirationRequest'
responses:
'200':
description: |
Sandbox expiration updated successfully.
Returns only the updated expiresAt field.
content:
application/json:
schema:
$ref: '#/components/schemas/RenewSandboxExpirationResponse'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
/sandboxes/{sandboxId}/endpoints/{port}:
get:
tags: [Sandboxes]
summary: Get sandbox access endpoint
description: |
Get the public access endpoint URL for accessing a service running on a specific port
within the sandbox. The service must be listening on the specified port inside
the sandbox for the endpoint to be available.
parameters:
- $ref: '#/components/parameters/SandboxId'
- name: port
in: path
required: true
description: Port number where the service is listening inside the sandbox
schema:
type: integer
minimum: 1
maximum: 65535
- name: use_server_proxy
in: query
description: Whether to return a server-proxied URL. Cannot be combined with `expires`.
schema:
type: boolean
default: false
- name: expires
in: query
required: false
description: |
Optional. When set, the server **issues a signed** access route (OSEP-0011). The value
is **Linux / Unix epoch seconds** — a decimal `uint64` count of **whole seconds** since
the Unix epoch (`1970-01-01 00:00:00` UTC, same as POSIX / `time(2)`), not
milliseconds. Normalized to `expires_b36` for the four-segment route token. Omit to
get the unsigned/legacy response shape. Cannot be combined with `use_server_proxy=true`.
schema:
type: string
pattern: '^(0|[1-9][0-9]*)$'
minLength: 1
maxLength: 20
responses:
'200':
description: |
Endpoint retrieved successfully.
Returns the public URL for accessing the service on the specified port.
content:
application/json:
schema:
$ref: '#/components/schemas/Endpoint'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
components:
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: OPEN-SANDBOX-API-KEY
description: |
API Key for authentication. Can be provided via:
1. HTTP Header: OPEN-SANDBOX-API-KEY: your-api-key
2. Environment variable: OPEN_SANDBOX_API_KEY (for SDK clients)
parameters:
SandboxId:
name: sandboxId
in: path
required: true
description: Unique sandbox identifier
schema:
type: string
SnapshotId:
name: snapshotId
in: path
required: true
description: Unique snapshot identifier
schema:
type: string
headers:
XRequestId:
description: Unique request identifier for tracing
schema:
type: string
format: uuid
Location:
description: URI of the newly created or related resource
schema:
type: string
format: uri
RetryAfter:
description: Suggested delay in seconds before retrying
schema:
type: integer
minimum: 1
responses:
Error:
description: Error response envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
BadRequest:
description: The request was invalid or malformed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
Unauthorized:
description: Authentication credentials are missing or invalid
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
Forbidden:
description: The authenticated user lacks permission for this operation
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
NotFound:
description: The requested resource does not exist
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
Conflict:
description: The operation conflicts with the current state
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
InternalServerError:
description: An unexpected server error occurred
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
headers:
X-Request-ID:
$ref: '#/components/headers/XRequestId'
schemas:
ListSandboxesResponse:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Sandbox'
pagination:
$ref: '#/components/schemas/PaginationInfo'
required: [items, pagination]
ListSnapshotsResponse:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Snapshot'
pagination:
$ref: '#/components/schemas/PaginationInfo'
required: [items, pagination]
PaginationInfo:
type: object
description: Pagination metadata for list responses
properties:
page:
type: integer
minimum: 1
description: Current page number
pageSize:
type: integer
minimum: 1
description: Number of items per page
totalItems:
type: integer
minimum: 0
description: Total number of items matching the filter
totalPages:
type: integer
minimum: 0
description: Total number of pages
hasNextPage:
type: boolean
description: Whether there are more pages after the current one
required: [page, pageSize, totalItems, totalPages, hasNextPage]
CreateSandboxResponse:
type: object
description: Response from creating a new sandbox. Contains essential information without startup source details and updatedAt.
properties:
id:
type: string
description: Unique sandbox identifier
status:
$ref: '#/components/schemas/SandboxStatus'
description: Current lifecycle status and detailed state information
metadata:
type: object
additionalProperties:
type: string
description: Custom metadata from creation request
extensions:
type: object
additionalProperties:
type: string
description: Opaque extension data restored from provider-specific storage
platform:
$ref: '#/components/schemas/PlatformSpec'
description: |
Platform constraint echoed from request or workload template.
Null when no scheduling constraint is provided.
expiresAt:
type: string
format: date-time
description: Timestamp when sandbox will auto-terminate. Omitted when manual cleanup is enabled.
createdAt:
type: string
format: date-time
description: Sandbox creation timestamp
entrypoint:
type: array
items:
type: string
description: |
Entry process specification for the sandbox. For image-created sandboxes,
this is copied from the creation request. For snapshot-created sandboxes,
this is restored from the snapshot.
required:
- id
- status
- createdAt
- entrypoint
CreateSnapshotRequest:
type: object
description: Optional settings for creating a sandbox snapshot.
properties:
name:
type: string
description: Optional human-readable snapshot name.
minLength: 1
additionalProperties: false
Snapshot:
type: object
description: Persistent point-in-time capture of a sandbox.
properties:
id:
type: string
description: Unique snapshot identifier
sandboxId:
type: string
description: Source sandbox identifier used to create this snapshot
name:
type: string
description: Optional human-readable snapshot name
status:
$ref: '#/components/schemas/SnapshotStatus'
description: Current snapshot lifecycle status and detailed state information
createdAt:
type: string
format: date-time
description: Snapshot creation timestamp
required:
- id
- sandboxId
- status
- createdAt
additionalProperties: false
SnapshotState:
type: string
description: |
Snapshot lifecycle state.
Common state values:
- Creating: Snapshot creation has been accepted and runtime capture is in progress.
- Deleting: Snapshot deletion has been requested and cleanup is in progress.
- Ready: Snapshot is available for restoring sandboxes.
- Failed: Snapshot creation failed.
Note: New state values may be added in future versions.
Clients should handle unknown state values gracefully.
SnapshotStatus:
type: object
description: Detailed snapshot status information with lifecycle state and transition details.
properties:
state:
$ref: '#/components/schemas/SnapshotState'
description: Current lifecycle state of the snapshot
reason:
type: string
description: |
Short machine-readable reason code for the current state.
Examples: "snapshot_accepted", "snapshot_ready", "snapshot_capture_failed"
message:
type: string
description: Human-readable message describing the current state or failure reason
lastTransitionAt:
type: string
format: date-time
description: Timestamp of the last state transition
required: [state]
additionalProperties: false
Sandbox:
type: object
description: Runtime execution environment provisioned from a container image or restored from a snapshot
properties:
id:
type: string
description: Unique sandbox identifier
image:
$ref: '#/components/schemas/ImageSpec'
description: |
Container image specification used to provision this sandbox.
Present when the sandbox was created directly from a container image.
Not returned in createSandbox response.
snapshotId:
type: string
description: |
Snapshot identifier used to restore this sandbox.
Present when the sandbox was restored from a snapshot.
Not returned in createSandbox response.
platform:
$ref: '#/components/schemas/PlatformSpec'
description: |
Platform constraint echoed from request or workload template.
Null when no scheduling constraint is provided.
status:
$ref: '#/components/schemas/SandboxStatus'
description: Current lifecycle status and detailed state information
metadata:
type: object
additionalProperties:
type: string
description: Custom metadata from creation request
extensions:
type: object
additionalProperties:
type: string
description: Opaque extension data restored from provider-specific storage
entrypoint:
type: array
items:
type: string
description: |
The command to execute as the sandbox's entry process.
Always present in responses. For image-created sandboxes, this is copied
from the creation request. For snapshot-created sandboxes, this is restored
from the snapshot.
expiresAt:
type: string
format: date-time
description: Timestamp when sandbox will auto-terminate. Omitted when manual cleanup is enabled.
createdAt:
type: string
format: date-time
description: Sandbox creation timestamp
required:
- id
- status
- createdAt
- entrypoint
SandboxState:
type: string
description: |
High-level lifecycle state of the sandbox.
Common state values:
- Pending: Sandbox is being provisioned
- Running: Sandbox is running and ready to accept requests
- Pausing: Sandbox is in the process of pausing
- Paused: Sandbox has been paused while retaining its state
- Resuming: Sandbox is being restored after a pause
- Stopping: Sandbox is being terminated
- Terminated: Sandbox has been successfully terminated
- Failed: Sandbox encountered a critical error
State transitions:
- Pending → Running (after creation completes)
- Running → Pausing (when pause is requested)
- Pausing → Paused (pause operation completes)
- Paused → Resuming (when resume is requested)
- Resuming → Running (when resume operation completes)
- Running/Paused → Stopping (when kill is requested or TTL expires)
- Stopping → Terminated (kill/timeout operation completes)
- Pending/Running/Paused/Resuming → Failed (on error)
Note: New state values may be added in future versions.
Clients should handle unknown state values gracefully.
SandboxStatus:
type: object
description: Detailed status information with lifecycle state and transition details
properties:
state:
$ref: '#/components/schemas/SandboxState'
description: Current lifecycle state of the sandbox
reason:
type: string
description: |
Short machine-readable reason code for the current state.
Examples: "user_delete", "ttl_expiry", "provision_timeout", "runtime_error"
message:
type: string
description: Human-readable message describing the current state or reason for state transition
lastTransitionAt:
type: string
format: date-time
description: Timestamp of the last state transition
required: [state]
ImageSpec:
type: object
required: [uri]
description: |
Container image specification for sandbox provisioning.
Supports public registry images and private registry images with authentication.
properties:
uri:
type: string
description: |
Container image URI in standard format.
Examples:
- "python:3.11" (Docker Hub)
- "ubuntu:22.04"
- "gcr.io/my-project/model-server:v1.0"
- "private-registry.company.com:5000/app:latest"
auth:
type: object
description: Registry authentication credentials (required for private registries)
properties:
username:
type: string
description: Registry username or service account
password:
type: string
description: Registry password or authentication token
additionalProperties: false
additionalProperties: false
PlatformSpec:
type: object
required: [os, arch]
description: |
Runtime platform constraint used for scheduling/provisioning.
This field is independent from `image` and expresses the expected target
OS and CPU architecture for sandbox execution.
Behavioral notes:
- If omitted, the runtime applies its own default platform selection behavior.
For Docker, requests are created without an explicit platform override.
For Kubernetes, no `kubernetes.io/os` or `kubernetes.io/arch` constraint
is injected unless provided by request or workload template.
- If provided and cannot be satisfied by runtime/template/pool constraints,
request must fail explicitly.
properties:
os:
type: string
enum: [linux, windows]
description: Target operating system (for example `linux` or `windows`).
example: linux
arch:
type: string
enum: [amd64, arm64]
description: Target CPU architecture (for example `amd64` or `arm64`).
example: arm64
additionalProperties: false
PatchSandboxMetadataRequest:
type: object
description: |
JSON Merge Patch (RFC 7396) request body for updating sandbox metadata.
The request body is the metadata object itself:
- Present keys with non-null values add or replace
- Keys with `null` values are deleted
- Absent keys are left unchanged
Keys with the `opensandbox.io/` prefix are reserved and rejected.
additionalProperties:
type:
- string
- 'null'
example:
project: "new-project"
team: null
environment: "production"
CreateSandboxRequest:
type: object
description: |
Request to create a new sandbox from either a container image, a snapshot,
or a pre-configured pool (via `extensions.poolRef`).
**Standard mode**: Exactly one of `image` or `snapshotId` must be provided,
and `resourceLimits` is required.
When `image` is provided, `entrypoint` is required. When `snapshotId` is
provided, `entrypoint` is optional. If omitted, the server defaults the
sandbox entrypoint to `["tail", "-f", "/dev/null"]`.
**Pool mode**: When `extensions.poolRef` is set, the sandbox is created from
a pre-configured pool. In this case `image`, `entrypoint`, and
`resourceLimits` are all optional (defined by the Pool CRD template).
`snapshotId` must not be provided together with `poolRef`.
**Note**: API Key authentication is required via the `OPEN-SANDBOX-API-KEY` header.
properties:
image:
$ref: '#/components/schemas/ImageSpec'
description: |
Container image specification for the sandbox.
Mutually exclusive with `snapshotId`.
snapshotId:
type: string
description: |
Snapshot identifier to restore from.
Mutually exclusive with `image`.
platform:
$ref: '#/components/schemas/PlatformSpec'
description: |
Optional platform constraint for sandbox scheduling/runtime selection.
If omitted, runtime default behavior applies (runtime-specific and not
a fixed architecture guarantee). If specified, the runtime must satisfy
this constraint or fail explicitly.
This field is only meaningful when scheduling constraints are set.
timeout:
oneOf:
- type: integer
minimum: 60
- type: 'null'
description: |
Sandbox timeout in seconds. The sandbox will automatically terminate after this duration.
The maximum is controlled by the server configuration (`server.max_sandbox_timeout_seconds`).
Omit this field or set it to null to disable automatic expiration and require explicit cleanup.
Note: manual cleanup support is runtime-dependent; Kubernetes providers may reject
omitted or null timeout when the underlying workload provider does not support non-expiring sandboxes.
resourceLimits:
$ref: '#/components/schemas/ResourceLimits'
description: |
Runtime resource constraints (hard caps) for the sandbox instance.
Required when `extensions.poolRef` is not set.
Optional when using pool mode (resource limits are defined by the Pool CRD template).
SDK clients should provide sensible defaults (e.g., cpu: "500m", memory: "512Mi").
resourceRequests:
$ref: '#/components/schemas/ResourceLimits'
description: |
Resource reservations (guaranteed minimums) for the sandbox instance.
When provided, these values are used as Kubernetes resource `requests`,
enabling Burstable QoS class (where `requests < limits`).
When omitted, `resourceLimits` values are used for both limits and requests,
resulting in Guaranteed QoS class.
Only meaningful for Kubernetes-based runtimes; ignored by Docker runtime.
env:
type: object
additionalProperties:
type: string
description: Environment variables to inject into the sandbox runtime.
example:
API_KEY: "secret-key"
DEBUG: "true"
LOG_LEVEL: "info"
metadata:
type: object
additionalProperties:
type: string
description: |
Custom key-value metadata for management, filtering, and tagging.
Use "name" key for a human-readable identifier.
example:
name: "Data Processing Sandbox"
project: "data-processing"
team: "ml"
environment: "staging"
entrypoint:
type: array
items:
type: string
minItems: 1
description: |
The command to execute as the sandbox's entry process.
Required when `image` is provided.
Optional when `snapshotId` is provided. If omitted for snapshot
restore, the server defaults to `["tail", "-f", "/dev/null"]`.
Explicitly specifies the user's expected main process, allowing the sandbox management
service to reliably inject control processes before executing this command.
Format: [executable, arg1, arg2, ...]
Examples:
- ["python", "/app/main.py"]
- ["/bin/bash"]
- ["java", "-jar", "/app/app.jar"]
- ["node", "server.js"]
example:
- "python"
- "/app/main.py"
networkPolicy:
$ref: '#/components/schemas/NetworkPolicy'
description: |
Optional outbound network policy for the sandbox.
Shape matches the sidecar `/policy` endpoint. If omitted or empty,
the sidecar starts in allow-all mode until updated.
credentialProxy:
$ref: '#/components/schemas/CredentialProxyConfig'
description: |
Optional Credential Vault proxy startup settings. Set `enabled: true`
to enable transparent MITM support for credential injection. Plain
`networkPolicy` does not enable transparent MITM unless this option
is set.
secureAccess:
type: boolean
default: false
description: |
Opts the sandbox into secured access for endpoint access.
This is currently supported only for Kubernetes sandboxes exposed
through ingress gateway mode. When enabled, the server provisions
access credentials and returns the required request headers with
endpoint responses. Clients must include those endpoint headers when
calling the sandbox. When omitted or false, endpoints remain
accessible without the additional access token for backward
compatibility.
volumes:
type: array
description: |
Storage mounts for the sandbox. Each volume entry specifies a named backend-specific
storage source and common mount settings. Exactly one backend type must be specified
per volume entry.
items:
$ref: '#/components/schemas/Volume'
extensions:
type: object
additionalProperties:
type: string
description: |
Opaque container for provider-specific or transient parameters not supported by the core API.
**Note**: This field is reserved for internal features, experimental flags, or temporary behaviors. Standard parameters should be proposed as core API fields.
**Best Practices**:
- **Namespacing**: Use prefixed keys (e.g., `storage.id`) to prevent collisions.
- **Pass-through**: SDKs and middleware must treat this object as opaque and pass it through transparently.
**Well-known keys**:
- `access.renew.extend.seconds` (optional): Decimal integer string from **300** to **86400** (5 minutes to 24 hours inclusive). Opts the sandbox into OSEP-0009 renew-on-access and sets per-renewal extension seconds. Omit to disable. Invalid values are rejected at creation with HTTP 400 (validated on the lifecycle create endpoint via `validate_extensions` in server `src/extensions/validation.py`).
ResourceLimits:
type: object
description: |
Runtime resource constraints as key-value pairs. Similar to Kubernetes resource specifications,
allows flexible definition of resource limits. Common resource types include:
- `cpu`: CPU allocation in millicores (e.g., "250m" for 0.25 CPU cores)
- `memory`: Memory allocation in bytes or human-readable format (e.g., "512Mi", "1Gi")
- `gpu`: Number of GPU devices (e.g., "1")
New resource types can be added without API changes.
additionalProperties:
type: string
example:
cpu: "500m"
memory: "512Mi"
gpu: "1"
RenewSandboxExpirationRequest:
type: object
required: [expiresAt]
properties:
expiresAt:
type: string
format: date-time
description: |
New absolute expiration time in UTC (RFC 3339 format).
Must be in the future and after the current expiresAt time.
Example: "2025-11-16T14:30:45Z"
additionalProperties: false
RenewSandboxExpirationResponse:
type: object
required: [expiresAt]
properties:
expiresAt:
type: string
format: date-time
description: |
The new absolute expiration time in UTC (RFC 3339 format).
Example: "2025-11-16T14:30:45Z"
additionalProperties: false
ErrorResponse:
type: object
description: |
Standard error response for all non-2xx HTTP responses.
HTTP status code indicates the error category; code and message provide details.
properties:
code:
type: string
description: |
Machine-readable error code (e.g., INVALID_REQUEST, NOT_FOUND, INTERNAL_ERROR).
Use this for programmatic error handling.
message:
type: string
description: Human-readable error message describing what went wrong and how to fix it.
required: [code, message]
additionalProperties: false
Endpoint:
type: object
description: |
Endpoint for accessing a service running in the sandbox.
The service must be listening on the specified port inside the sandbox for the endpoint to be available.
properties:
endpoint:
type: string
description: |
Public URL to access the service from outside the sandbox.
Format: {endpoint-host}/sandboxes/{sandboxId}/port/{port}
Example: endpoint.opensandbox.io/sandboxes/abc123/port/8080
headers:
type: object
additionalProperties:
type: string
description: |
Requests targeting the sandbox must include the corresponding header(s).
required:
- endpoint
additionalProperties: false
NetworkPolicy:
type: object
description: |
Egress network policy matching the sidecar `/policy` request body.
If `defaultAction` is omitted, the sidecar defaults to "deny"; passing an empty
object or null results in allow-all behavior at startup.
properties:
defaultAction:
type: string
enum: [allow, deny]
description: Default action when no egress rule matches. Defaults to "deny".
egress:
type: array
description: List of egress rules evaluated in order.
items:
$ref: '#/components/schemas/NetworkRule'
additionalProperties: false
CredentialProxyConfig:
type: object
description: |
Credential Vault proxy startup settings. This is an explicit opt-in for
transparent MITM support used by credential injection. Credential Vault
requires `dns+nft` enforcement and a network policy. A deny-default policy
is strongly recommended; default-allow remains temporarily supported for
backward compatibility and emits a security warning.
properties:
enabled:
type: boolean
default: false
description: |
When true, the server starts the egress sidecar with transparent
MITM enabled and installs the runtime-managed MITM CA bundle into
the sandbox container. Requires `networkPolicy` and server
`[egress].mode = "dns+nft"`. `defaultAction: deny` is strongly
recommended; default-allow support is deprecated.
additionalProperties: false
NetworkRule:
type: object
properties:
action:
type: string
enum: [allow, deny]
description: Whether to allow or deny matching targets.
target:
type: string
description: |
FQDN or wildcard domain (e.g., "example.com", "*.example.com").
IP/CIDR not yet supported in the egress MVP.
required: [action, target]
additionalProperties: false
Volume:
type: object
description: |
Storage mount definition for a sandbox. Each volume entry contains:
- A unique name identifier
- Exactly one backend struct (host, pvc, ossfs, etc.) with backend-specific fields
- Common mount settings (mountPath, readOnly, subPath)
required: [name, mountPath]
properties:
name:
type: string
description: |
Unique identifier for the volume within the sandbox.
Must be a valid DNS label (lowercase alphanumeric, hyphens allowed, max 63 chars).
pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$"
maxLength: 63
host:
$ref: '#/components/schemas/Host'
pvc:
$ref: '#/components/schemas/PVC'
ossfs:
$ref: '#/components/schemas/OSSFS'
mountPath:
type: string
description: |
Absolute path inside the container where the volume is mounted.
Must start with '/'.
pattern: "^/.*"
readOnly:
type: boolean
description: |
If true, the volume is mounted as read-only. Defaults to false (read-write).
default: false
subPath:
type: string
description: |
Optional subdirectory under the backend path to mount.
For `ossfs` backend, this field is used as the bucket prefix.
Must be a relative path without '..' components.
additionalProperties: false
Host:
type: object
description: |
Host path bind mount backend. Maps a directory on the host filesystem
into the container. Only available when the runtime supports host mounts.
Security note: Host paths are restricted by server-side allowlist.
Users must specify paths under permitted prefixes.
required: [path]
properties:
path:
type: string
description: |
Absolute path on the host filesystem to mount.
Must start with '/' (Unix) or a drive letter such as 'C:\' or 'D:/'
(Windows), and be under an allowed prefix.
pattern: "^(/|[A-Za-z]:[\\\\/])"
additionalProperties: false
PVC:
type: object
description: |
Platform-managed named volume backend. A runtime-neutral abstraction
for referencing a platform-managed named volume. If `createIfNotExists`
is true (the default) and the volume does not yet exist, it will be
created automatically using the provisioning hints below.
- Kubernetes: maps to a PersistentVolumeClaim in the same namespace.
- Docker: maps to a Docker named volume (created via `docker volume create`).
required: [claimName]
properties:
claimName:
type: string
description: |
Name of the volume on the target platform.
In Kubernetes this is the PVC name; in Docker this is the named
volume name. Must be a valid DNS label.
pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$"
maxLength: 253
createIfNotExists:
type: boolean
default: true
description: |
When true (the default), the volume is automatically created if
it does not exist. When false, referencing a non-existent volume
fails with an error.
deleteOnSandboxTermination:
type: boolean
default: false
description: |
When true, the volume is automatically removed when the sandbox
is deleted. Only applies to volumes that were auto-created by the
server on this request; pre-existing volumes are never removed.
For Kubernetes, the resulting PVC delete triggers the bound PV's
StorageClass reclaim policy (`Retain`/`Delete`).
storageClass:
type: string
nullable: true
description: |
Kubernetes StorageClass name for auto-created PVCs. Null means
use the cluster default. Ignored for Docker volumes.
storage:
type: string
nullable: true
description: |
Storage capacity request for auto-created PVCs (e.g. "1Gi",
"10Gi"). Defaults to the server-configured `volume_default_size`
when omitted. Ignored for Docker volumes.
pattern: "^\\d+(\\.\\d+)?(Ki|Mi|Gi|Ti|Pi|Ei)?$"
accessModes:
type: array
nullable: true
items:
type: string
description: |
Access modes for auto-created PVCs (e.g. ["ReadWriteOnce"]).
Defaults to ["ReadWriteOnce"] when omitted. Ignored for Docker
volumes.
additionalProperties: false
OSSFS:
type: object
description: |
Alibaba Cloud OSS mount backend via ossfs.
The runtime mounts a host-side OSS path under `storage.ossfs_mount_root`
and bind-mounts the resolved path into the sandbox container.
Prefix selection is expressed via `Volume.subPath`.
In Docker runtime, OSSFS backend requires OpenSandbox Server to run on a Linux host with FUSE support.
required: [bucket, endpoint, accessKeyId, accessKeySecret]
properties:
bucket:
type: string
description: OSS bucket name.
minLength: 3
maxLength: 63
endpoint:
type: string
description: OSS endpoint (e.g., `oss-cn-hangzhou.aliyuncs.com`).
minLength: 1
version:
type: string
description: ossfs major version used by runtime mount integration.
enum: ["1.0", "2.0"]
default: "2.0"
options:
type: array
description: |
Additional ossfs mount options.
Runtime encodes options by `version`:
- `1.0`: mounts with `ossfs ... -o <option>`
- `2.0`: mounts with `ossfs2 mount ... -c <config-file>` and encodes options as `--<option>` lines in the config file
Option values must be provided as raw payloads without leading `-`.
items:
type: string
accessKeyId:
type: string
description: OSS access key ID for inline credentials mode.
minLength: 1
accessKeySecret:
type: string
description: OSS access key secret for inline credentials mode.
minLength: 1
additionalProperties: false