diff --git a/crates/alien-core/src/resources/sandbox.rs b/crates/alien-core/src/resources/sandbox.rs index 383202cd7..3f693c2d7 100644 --- a/crates/alien-core/src/resources/sandbox.rs +++ b/crates/alien-core/src/resources/sandbox.rs @@ -169,7 +169,7 @@ pub struct SandboxSessionPolicy { pub struct SandboxCapabilities { /// Files can be moved in and out of a session /// - /// Every backend but Azure, whose data plane exposes exec and lifecycle and no transfer. + /// Every backend but Azure, whose binding implements no transfer. pub files: bool, /// A later call can reach a session created by an earlier one pub reconnect: bool, @@ -862,9 +862,9 @@ mod tests { assert!(!gcp.enforced_limits); let azure = SandboxCapabilities::for_platform(Platform::Azure).expect("azure is supported"); - assert!(!azure.files, "the Azure data plane has no file transfer"); + assert!(!azure.files, "the Azure binding implements no file transfer"); assert!(gcp.files, "every other backend moves files"); - // The Azure data plane takes neither an egress policy nor a ceiling, so a declaration of + // The Azure binding renders neither an egress policy nor a ceiling, so a declaration of // either is refused rather than accepted and dropped. assert!(!azure.domain_egress_rules); assert!(!azure.egress_deny); @@ -911,7 +911,7 @@ mod tests { } /// No backend expresses a hostname allowlist: AWS and Kubernetes match CIDRs, and the Azure - /// data plane takes no egress policy at all. Accepting one anywhere would leave a stack + /// binding renders no egress policy at all. Accepting one anywhere would leave a stack /// reading as restricted while the sandbox reaches the whole internet. #[test] fn a_hostname_allowlist_is_refused_on_every_backend() { @@ -973,7 +973,7 @@ mod tests { let error = egress_only .validate_for_platform(Platform::Azure) - .expect_err("the Azure data plane takes no egress policy, so deny cannot be kept"); + .expect_err("the Azure binding renders no egress policy, so deny cannot be kept"); assert_eq!(error.code, "SANDBOX_CAPABILITY_UNSUPPORTED"); assert!( error.message.contains("egressDeny"), diff --git a/packages/core/src/generated/schemas/sandboxCapabilities.json b/packages/core/src/generated/schemas/sandboxCapabilities.json index d002e19d6..98a055f00 100644 --- a/packages/core/src/generated/schemas/sandboxCapabilities.json +++ b/packages/core/src/generated/schemas/sandboxCapabilities.json @@ -1 +1 @@ -{"type":"object","description":"What a platform's sandbox backend can actually do.\n\nPublished so portable code can branch before calling rather than discovering a gap through\nan error. Every field here corresponds to a capability that at least one platform lacks;\ncreate, exec and terminate are the guaranteed floor and are therefore not listed.","required":["files","reconnect","preview","suspendResume","snapshot","domainEgressRules","egressDeny","enforcedLimits","processLimit","sessionLifetime","supervisorPidNamespace"],"properties":{"domainEgressRules":{"type":"boolean","description":"Egress can be restricted to a hostname allowlist"},"egressDeny":{"type":"boolean","description":"Whether a declared `deny` is actually enforced, rather than accepted and dropped"},"enforcedLimits":{"type":"boolean","description":"The platform enforces the declared cpu, memory and disk ceilings"},"files":{"type":"boolean","description":"Files can be moved in and out of a session\n\nEvery backend but Azure, whose data plane exposes exec and lifecycle and no transfer."},"preview":{"type":"boolean","description":"An authenticated, port-scoped capability to reach a service inside the sandbox"},"processLimit":{"type":"boolean","description":"The platform can cap how many processes a session runs"},"reconnect":{"type":"boolean","description":"A later call can reach a session created by an earlier one"},"sessionLifetime":{"type":"boolean","description":"The platform terminates a session at a declared wall-clock deadline"},"snapshot":{"type":"boolean","description":"A session's full state can be captured and used to create another"},"supervisorPidNamespace":{"type":"boolean","description":"A command runs in its own PID namespace and cannot see or signal the agent's processes.\n\nOnly where an agent runs as root. Creating the namespace needs `CAP_SYS_ADMIN`, and the\nKubernetes sandbox pod drops every capability — which is also what denies `ptrace` by\nconstruction, so granting it there would remove a lock to add one."},"suspendResume":{"type":"boolean","description":"Session state can be suspended and resumed"}},"additionalProperties":false,"x-readme-ref-name":"SandboxCapabilities"} \ No newline at end of file +{"type":"object","description":"What a platform's sandbox backend can actually do.\n\nPublished so portable code can branch before calling rather than discovering a gap through\nan error. Every field here corresponds to a capability that at least one platform lacks;\ncreate, exec and terminate are the guaranteed floor and are therefore not listed.","required":["files","reconnect","preview","suspendResume","snapshot","domainEgressRules","egressDeny","enforcedLimits","processLimit","sessionLifetime","supervisorPidNamespace"],"properties":{"domainEgressRules":{"type":"boolean","description":"Egress can be restricted to a hostname allowlist"},"egressDeny":{"type":"boolean","description":"Whether a declared `deny` is actually enforced, rather than accepted and dropped"},"enforcedLimits":{"type":"boolean","description":"The platform enforces the declared cpu, memory and disk ceilings"},"files":{"type":"boolean","description":"Files can be moved in and out of a session\n\nEvery backend but Azure, whose binding implements no transfer."},"preview":{"type":"boolean","description":"An authenticated, port-scoped capability to reach a service inside the sandbox"},"processLimit":{"type":"boolean","description":"The platform can cap how many processes a session runs"},"reconnect":{"type":"boolean","description":"A later call can reach a session created by an earlier one"},"sessionLifetime":{"type":"boolean","description":"The platform terminates a session at a declared wall-clock deadline"},"snapshot":{"type":"boolean","description":"A session's full state can be captured and used to create another"},"supervisorPidNamespace":{"type":"boolean","description":"A command runs in its own PID namespace and cannot see or signal the agent's processes.\n\nOnly where an agent runs as root. Creating the namespace needs `CAP_SYS_ADMIN`, and the\nKubernetes sandbox pod drops every capability — which is also what denies `ptrace` by\nconstruction, so granting it there would remove a lock to add one."},"suspendResume":{"type":"boolean","description":"Session state can be suspended and resumed"}},"additionalProperties":false,"x-readme-ref-name":"SandboxCapabilities"} \ No newline at end of file diff --git a/packages/core/src/generated/zod/sandbox-capabilities-schema.ts b/packages/core/src/generated/zod/sandbox-capabilities-schema.ts index dd1bb47fc..fec2da979 100644 --- a/packages/core/src/generated/zod/sandbox-capabilities-schema.ts +++ b/packages/core/src/generated/zod/sandbox-capabilities-schema.ts @@ -12,7 +12,7 @@ export const SandboxCapabilitiesSchema = z.object({ "domainEgressRules": z.boolean().describe("Egress can be restricted to a hostname allowlist"), "egressDeny": z.boolean().describe("Whether a declared `deny` is actually enforced, rather than accepted and dropped"), "enforcedLimits": z.boolean().describe("The platform enforces the declared cpu, memory and disk ceilings"), -"files": z.boolean().describe("Files can be moved in and out of a session\n\nEvery backend but Azure, whose data plane exposes exec and lifecycle and no transfer."), +"files": z.boolean().describe("Files can be moved in and out of a session\n\nEvery backend but Azure, whose binding implements no transfer."), "preview": z.boolean().describe("An authenticated, port-scoped capability to reach a service inside the sandbox"), "processLimit": z.boolean().describe("The platform can cap how many processes a session runs"), "reconnect": z.boolean().describe("A later call can reach a session created by an earlier one"), diff --git a/packages/core/src/sandbox.ts b/packages/core/src/sandbox.ts index ecbb928d4..05a2945a9 100644 --- a/packages/core/src/sandbox.ts +++ b/packages/core/src/sandbox.ts @@ -33,8 +33,8 @@ export { SandboxSchema as SandboxConfigSchema } from "./generated/index.js" * * Capabilities are not uniform. Call `capabilities()` on the binding and branch, or handle the * typed error — an unsupported capability never silently succeeds. Notably GCP cannot - * reconnect to a session (its session id is scoped to one Cloud Run instance), Azure has no - * file transfer, and no platform supports a hostname egress allowlist. + * reconnect to a session (its session id is scoped to one Cloud Run instance), the Azure + * binding implements no file transfer, and no binding renders a hostname egress allowlist. * * Limits are enforced ceilings, not scheduling hints, and are validated when the stack is * planned. A platform that cannot enforce them rejects the sandbox rather than ignoring them.