Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions contracts/agents-api/sandbox-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ and node connections; it is not a replacement for `expected_generation`.
Treat `specification_digest` as the server-provided identity of the provider,
resource limits and Runtime release. Enrollment echoes it unchanged.

The typed `SandboxAdminClient` checks the deployment, node list, node detail and
allocation responses against exactly these shapes. An unknown or missing member,
or a wrong type, rejects the whole response with a 502 `invalid_admin_response`
error. A node's `diagnostic` is absent or a code, never empty; the client reads
an unknown code as `provider_unavailable`.

## Initialization and changes

POST validates the candidate before persistence and creates no compute, Session
Expand Down
120 changes: 111 additions & 9 deletions packages/agents-client/src/sandbox-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,109 @@ import { SandboxAdminClient, type SandboxNode } from "./sandbox-client";

function response(value: unknown, status = 200) { return new Response(JSON.stringify(value), { status }); }

// Shapes as Core serializes them (store.RuntimeNode, RuntimeNodeDetail, RuntimeNodeAllocation, RuntimeDeploymentView).
const created = "2026-09-25T08:00:00.123456789Z";
/** A ready node: Core omits `diagnostic`. */
const node = {
id: "3b0c1f4e-8a2d-4c6b-9e7f-1a2b3c4d5e6f", name: "core-01", provider: "docker", online: true, provider_ready: true,
cpu_count: 16, available_memory_bytes: 8589934592, available_disk_bytes: 107374182400, running: 1, snapshots: 0,
last_seen_at: "2026-09-25T09:00:00Z", max_active: 2, max_retained: 2, active: 1, reserved: 0, retained: 1, cleanup_pending: 0,
created_at: created, core_url: "https://core.example", enrollment_id: "9d2e6b1a-4c3f-4e8d-a7b6-5c4d3e2f1a0b",
};
/** Never heard from, enrolled before Core recorded enrollment IDs, with a fixed readiness code. */
const unready = {
...node, id: "7f6e5d4c-3b2a-4190-8f7e-6d5c4b3a2918", online: false, provider_ready: false, diagnostic: "kvm_unavailable",
cpu_count: null, available_memory_bytes: null, available_disk_bytes: null, running: 0, last_seen_at: null, active: 0, retained: 0, enrollment_id: null,
};
const detail = {
...node,
host: { effective_cpu_cores: 3.5, cpu_utilization: 0.35, total_memory_bytes: 17179869184, available_memory_bytes: 8589934592, available_disk_bytes: 107374182400, observed_at: "2026-09-25T09:00:00Z" },
history: { resolution_seconds: 60, points: [
{ start: "2026-09-25T08:58:00Z", cpu_utilization_max: 0.4, memory_used_bytes_max: 8589934592, available_disk_bytes_min: 107374182400 },
{ start: "2026-09-25T08:59:00Z", cpu_utilization_max: null, memory_used_bytes_max: null, available_disk_bytes_min: null },
] },
};
const unobserved = {
...unready,
host: { effective_cpu_cores: null, cpu_utilization: null, total_memory_bytes: null, available_memory_bytes: null, available_disk_bytes: null, observed_at: null },
history: { resolution_seconds: 900, points: [] },
};
const allocation = {
id: "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d", node_id: node.id, tenant_id: "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
session_id: "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f", environment_id: "3d4e5f6a-7b8c-4d9e-8f1a-2b3c4d5e6f7a",
state: "running", compute_phase: "running", compute_phase_changed_at: null, diagnostic: "", initialization: "ready", created_at: created,
};
const runtime = { source_commit: "a".repeat(40), image_id: "sha256:" + "b".repeat(64), image_manifest_digest: "sha256:" + "c".repeat(64), microsandbox_ref: "parsar-core-runtime@sha256:" + "d".repeat(64), runtime_sha256: "e".repeat(64), firmware_sha256: "f".repeat(64) };
const unconfigured = { installation_id: "", provider: "", core_url: "https://core.example", maintenance: false, owner_epoch: 0, generation: 0, mode: "", resources: { allocations: 0, pending: 0 }, suspension: null };
const docker = {
...unconfigured, installation_id: "94be54a1-138c-4f30-bc87-b13686272dbe", provider: "docker", owner_epoch: 1, generation: 1, mode: "nodes",
resources: { allocations: 2, pending: 1 }, specification: { resources: { cpus: 2, memory_mib: 2048 }, runtime }, specification_digest: "0".repeat(64),
};
const microsandbox = {
...docker, provider: "microsandbox", specification: { resources: { cpus: 2, memory_mib: 2048, root_disk_mib: 8192, environment_disk_mib: 8192 }, runtime },
suspension: { idle_seconds: 300, retention_seconds: 86400 },
};
/** An E2B selection saved before Core recorded its template build. */
const e2bDeployment = {
...docker, provider: "e2b", mode: "direct", specification: { resources: { cpus: 2, memory_mib: 2048 } },
e2b: { template: "runtime:00000000-0000-0000-0000-000000000001", credential_configured: true, template_build: { status: null, resources: { cpus: null, memory_mib: null, root_disk_mib: null } } },
};
const reads: Record<string, (client: SandboxAdminClient) => Promise<unknown>> = {
nodes: (client) => client.listNodes(),
detail: (client) => client.retrieveNode(node.id, "1h"),
unobserved: (client) => client.retrieveNode(unready.id, "24h"),
allocations: (client) => client.listAllocations(node.id),
deployment: (client) => client.retrieveDeployment(),
};
function read(name: string, body: unknown) {
return reads[name]!(new SandboxAdminClient({ fetch: vi.fn<typeof globalThis.fetch>().mockResolvedValue(response(body)) }));
}
const { enrollment_id: _enrollment, ...unenrolled } = node;
const { suspension: _suspension, ...unsuspended } = docker;
const { specification_digest: _digest, ...undigested } = docker;
const { compute_phase_changed_at: _changed, ...unphased } = allocation;

describe("strict sandbox administration projections", () => {
it.each([
["nodes", "ready and unready", { data: [node, unready] }], ["nodes", "empty", { data: [] }],
["detail", "observed", detail], ["unobserved", "never observed", unobserved],
["allocations", "known and unknown phase times", { data: [allocation, { ...allocation, compute_phase: "suspended", compute_phase_changed_at: created, diagnostic: "node_unavailable" }] }],
["deployment", "unconfigured", unconfigured], ["deployment", "Docker", docker], ["deployment", "microsandbox", microsandbox], ["deployment", "E2B", e2bDeployment],
])("accepts %s as Core serializes it: %s", async (name, _, body) => {
expect(await read(name, body)).toEqual(body);
});

it.each([
["nodes", "an unknown member", { data: [{ ...node, credential: "node-secret" }] }],
["nodes", "a missing enrollment_id", { data: [unenrolled] }],
["nodes", "an empty diagnostic", { data: [{ ...node, diagnostic: "" }] }],
["nodes", "a string count", { data: [{ ...node, cpu_count: "16" }] }],
["nodes", "a numeric timestamp", { data: [{ ...node, last_seen_at: 0 }] }],
["nodes", "a null list", { data: null }],
["detail", "a missing host", { ...node, history: detail.history }],
["detail", "an unknown host member", { ...detail, host: { ...detail.host, hostname: "core-01" } }],
["detail", "a string history point", { ...detail, history: { resolution_seconds: 60, points: [{ ...detail.history.points[0], cpu_utilization_max: "0.4" }] } }],
["detail", "another node", { ...detail, id: unready.id }],
["allocations", "a missing compute_phase_changed_at", { data: [unphased] }],
["allocations", "an unknown diagnostic", { data: [{ ...allocation, diagnostic: "raw provider text" }] }],
["allocations", "another node's allocation", { data: [{ ...allocation, node_id: unready.id }] }],
["deployment", "a missing suspension", unsuspended],
["deployment", "a specification without its digest", undigested],
["deployment", "an e2b member for Docker", { ...docker, e2b: e2bDeployment.e2b }],
["deployment", "E2B without its e2b member", { ...docker, provider: "e2b", mode: "direct" }],
["deployment", "an unknown mode", { ...docker, mode: "hybrid" }],
])("rejects %s with %s", async (name, _, body) => {
await expect(read(name, body)).rejects.toMatchObject({ status: 502, code: "invalid_admin_response" });
});

it("never passes a reflected E2B key through", async () => {
const reflected = { ...e2bDeployment, e2b: { ...e2bDeployment.e2b, api_key: "e2b-private-key" } };
const error = await read("deployment", reflected).catch((caught: unknown) => caught);
expect(error).toMatchObject({ status: 502, code: "invalid_admin_response" });
expect(JSON.stringify(error) + String(error)).not.toContain("e2b-private-key");
});
});

describe("Core sandbox credential boundaries", () => {
it("defaults to /core/v1/sandbox and is not a /v1 client", async () => {
const fetch = vi.fn<typeof globalThis.fetch>().mockImplementation(async () => response({ data: [] }));
Expand All @@ -24,16 +127,16 @@ describe("Core sandbox credential boundaries", () => {
expect(new Headers(fetch.mock.calls[0]?.[1]?.headers).has("Authorization")).toBe(false);
expect(fetch.mock.calls[0]?.[1]?.signal).toBe(controller.signal);
});
it("returns the node's fixed readiness diagnostic unchanged", async () => {
const fetch = vi.fn<typeof globalThis.fetch>().mockResolvedValue(response({ data: [{ id: "node", provider_ready: false, diagnostic: "kvm_unavailable" }] }));
it("returns the node's fixed readiness diagnostic unchanged and reads an unknown code as provider_unavailable", async () => {
const fetch = vi.fn<typeof globalThis.fetch>().mockResolvedValue(response({ data: [unready, { ...unready, diagnostic: "future_code" }, node] }));
const { data } = await new SandboxAdminClient({ baseUrl: "/core/v1/sandbox", fetch }).listNodes();
expect(data[0]?.diagnostic).toBe("kvm_unavailable");
expect(data.map((entry) => entry.diagnostic)).toEqual(["kvm_unavailable", "provider_unavailable", undefined]);
expectTypeOf<SandboxNode["diagnostic"]>().toEqualTypeOf<undefined | "" | "provider_unavailable" | "docker_unavailable" | "docker_limits_unsupported" | "runtime_image_unavailable" | "kvm_unavailable" | "microsandbox_artifacts_unavailable" | "capacity_insufficient">();
});
it("requires each node's enrollment ID: a string, or null for nodes enrolled before Core recorded it", async () => {
const fetch = vi.fn<typeof globalThis.fetch>().mockResolvedValue(response({ data: [{ id: "enrolled", enrollment_id: "3b0c1f4e-8a2d-4c6b-9e7f-1a2b3c4d5e6f" }, { id: "legacy", enrollment_id: null }] }));
const fetch = vi.fn<typeof globalThis.fetch>().mockResolvedValue(response({ data: [node, unready] }));
const { data } = await new SandboxAdminClient({ fetch }).listNodes();
expect(data.map((node) => node.enrollment_id)).toEqual(["3b0c1f4e-8a2d-4c6b-9e7f-1a2b3c4d5e6f", null]);
expect(data.map((entry) => entry.enrollment_id)).toEqual([node.enrollment_id, null]);
expectTypeOf<SandboxNode["enrollment_id"]>().toEqualTypeOf<string | null>();
expectTypeOf<{ enrollment_id: string }>().toExtend<Pick<SandboxNode, "enrollment_id">>();
expectTypeOf<{ enrollment_id: null }>().toExtend<Pick<SandboxNode, "enrollment_id">>();
Expand All @@ -47,7 +150,7 @@ describe("Core sandbox credential boundaries", () => {
});

it("initializes using only the explicit provider with cancellation and admin credentials", async () => {
const deployment = { installation_id: "installation", provider: "docker", core_url: "https://core.example", maintenance: false, owner_epoch: 1 };
const deployment = docker;
const fetch = vi.fn<typeof globalThis.fetch>().mockResolvedValue(response(deployment));
const admin = new SandboxAdminClient({ baseUrl: "/core/v1/sandbox", token: "admin-only", fetch });
const controller = new AbortController();
Expand Down Expand Up @@ -81,7 +184,7 @@ describe("Core sandbox credential boundaries", () => {
expect(fetch).toHaveBeenCalledTimes(1);
});
it("uses the explicit admin credential and admin routes without a project beta header", async () => {
const fetch = vi.fn<typeof globalThis.fetch>().mockImplementation(async () => response({ data: [] }));
const fetch = vi.fn<typeof globalThis.fetch>().mockImplementation(async (url) => response(String(url).endsWith("/deployment") ? docker : { data: [] }));
const admin = new SandboxAdminClient({ baseUrl: "https://core.example/core/v1/sandbox", token: "admin-only", fetch });
await admin.retrieveDeployment(); await admin.listNodes(); await admin.listAllocations("node/a"); await admin.createEnrollment(); await admin.removeNode("node/a");
expect(fetch.mock.calls.map(([url]) => url)).toEqual([
Expand All @@ -108,8 +211,7 @@ describe("hosted provider configuration", () => {
const e2b = { api_key: "test-only-secret", template: "runtime:00000000-0000-0000-0000-000000000001" };
it("writes E2B configuration and generation without beta headers or browser credentials", async () => {
const deployment = {
generation: 2, mode: "direct", resources: { allocations: 0, pending: 0 }, suspension: null,
specification: { resources: { cpus: 2, memory_mib: 2048 } },
...e2bDeployment, generation: 2, resources: { allocations: 0, pending: 0 },
e2b: { template: e2b.template, credential_configured: true, template_build: { status: "ready", resources: { cpus: 2, memory_mib: 2048, root_disk_mib: 24063 } } },
};
const fetch = vi.fn<typeof globalThis.fetch>().mockImplementation(async () => response(deployment));
Expand Down
Loading
Loading