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
1636 lines
58 KiB
YAML
1636 lines
58 KiB
YAML
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 filtering,keys 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
|