Skip to content

feat(core): add the Sandbox resource type and its capability contract - #387

Merged
alongubkin merged 3 commits into
mainfrom
itamar/alien-75-sandbox-1-core
Aug 20, 2026
Merged

feat(core): add the Sandbox resource type and its capability contract#387
alongubkin merged 3 commits into
mainfrom
itamar/alien-75-sandbox-1-core

Conversation

@ItamarZand88

@ItamarZand88 ItamarZand88 commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds alien.Sandbox — a declaration for an isolated environment that runs untrusted
code, typically code an LLM just wrote. This layer is the type and its rules only: no
backend, no package emitters, no runtime.

What happens when a stack declaring a sandbox is planned:

  1. The declaration is checked against the capability set the target platform publishes.
  2. Anything that platform cannot enforce — a ceiling, an egress mode, a session
    deadline — is refused here, rather than accepted and quietly ignored.
  3. The stack proceeds only if every declared property can actually be applied.

This PR changes a sandbox from something you cannot express to something the platform
either honours exactly or rejects with the reason.

What I did

  • Added the Sandbox resource: where its filesystem comes from, its cpu/memory/disk
    ceilings, its outbound network policy, and its session lifetime.
  • Published a capability set per platform, so a caller can branch on what a backend
    supports instead of discovering a gap through a failure. Backends differ more than
    you would expect — one cannot reconnect to a session at all, and only one can
    restrict egress to a list of hostnames.
  • Added the plan-time checks that make the contract real: a sandbox is refused on a
    platform with no backend, a GCP sandbox is refused without a workload to host it,
    and a declared ceiling a platform cannot enforce is refused rather than dropped.
  • Added the capability token an agent checks before acting — session, generation,
    operation class and expiry, all verified after the signature.
  • Registered the type so it is allowed in a stack, has an ownership policy, and can be
    linked from a worker.
  • Added the matching TypeScript builder and generated schemas.

Files touched

  • crates/alien-core/src/resources/sandbox.rs — the type, its limits, egress and
    session policy, and the per-platform capability matrix
  • crates/alien-core/src/sandbox_capability{,_token}.rs — the operation classes and
    the claims an agent verifies
  • crates/alien-core/src/{ownership,gateability,resource_links}.rs — registration
  • crates/alien-preflights/src/compile_time/sandbox_*.rs — the plan-time refusals
  • packages/core/src/sandbox.ts — the TypeScript builder

How I tested

  • Manually: declared a sandbox in a stack and ran alien build against each target.
    A ceiling GCP cannot enforce, and a session deadline only Kubernetes has, are both
    refused at plan time naming the capability they needed — not accepted and dropped.
  • Unit tests: alien-core 32 sandbox tests (the per-platform capability matrix, the
    limit/egress/session refusals, quantity parsing); alien-preflights drives the
    platform gate through the runner rather than calling the check directly;
    @alienplatform/core 90 tests including the builder and its gateability.
  • Anything I couldn't test: nothing here runs a sandbox — there is no backend in
    this layer. Runtime behaviour is exercised in the layers that add it.

I also ran a security review on the diff. What it checked:

  • A capability minted for one session replayed against another — the claims carry the
    session id and the generation it started under, and both are checked after the
    signature (sandbox_capability_token.rs).
  • A stale capability outliving the session it was minted for — generation is part of the
    claims, so a replaced session voids them.
  • Widening an already-minted capability by adding a method — operation classes are
    deliberately coarse (execute vs manage), so a new method cannot fall inside one
    already granted.
  • A declared egress mode or ceiling silently degrading on a platform that cannot apply
    it — refused at plan time instead, which the preflight test drives through the runner.
    Nothing turned up.

What changed since the last review

Azure's sandbox data plane carries exec and lifecycle but no file transfer, so readFile,
writeFiles and mkdir are refused there. The capability contract called files part of the
guaranteed floor, which meant a caller had no way to find that out except by calling and failing.

When an application asks what a sandbox can do:

  1. SandboxCapabilities::for_platform returns the set for the platform it is running on.
  2. Azure now returns files: false, and every other backend files: true — this is the
    answer that was previously unavailable, because the floor was assumed rather than published.
  3. The application branches on it instead of calling and handling an error.

The floor is now create, exec and terminate; files moved out of it and became a capability.

Files touched

  • crates/alien-core/src/resources/sandbox.rs — the files field, its per-platform values, the
    SandboxCapability::Files variant, and the corrected floor in the struct doc
  • crates/alien-bindings/src/traits.rsRequires files`` on the three file operations
  • packages/core/src/generated/** — regenerated, four files

How I tested

  • cargo test -p alien-core — 523 pass, including two new assertions in
    capability_sets_are_per_platform
  • Flipped Azure to files: true and confirmed the test fails on "the Azure data plane has no
    file transfer"
    , then restored it
  • pnpm -C packages/core generate a second time produces no further diff, so the committed
    artifacts match the source

@greptile-apps

greptile-apps Bot commented Aug 10, 2026

Copy link
Copy Markdown

Greptile Summary

Adds the Sandbox resource contract, platform capability matrix, plan-time validation, binding vocabulary, and capability-token types. The follow-up makes file transfer an explicit capability and correctly reports it as unavailable on Azure.

  • Registers Sandbox across resource ownership, linking, gateability, heartbeat, and schema surfaces.
  • Adds platform-specific sandbox declarations and preflight refusal rules.
  • Exposes files separately from the guaranteed create/execute/terminate capability floor.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
crates/alien-core/src/resources/sandbox.rs Defines the Sandbox resource, capability matrix, validation contract, and explicit Azure file-transfer limitation.
crates/alien-bindings/src/traits.rs Adds the provider-neutral Sandbox session and operation trait surface, with file methods tied to the published files capability.
crates/alien-core/src/sandbox_capability.rs Defines operation classes and session-scoped capability claims with exact session, generation, expiry, and operation checks.
crates/alien-core/src/sandbox_capability_token.rs Adds feature-gated Ed25519 signing and signature-first verification for sandbox capability tokens.
crates/alien-preflights/src/compile_time/sandbox_platform_support.rs Enforces platform capability compatibility during planning rather than silently degrading declarations.
packages/core/src/sandbox.ts Adds the TypeScript Sandbox builder corresponding to the Rust resource contract.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Declaration["Sandbox declaration"] --> Preflight["Plan-time preflight"]
  Platform["Target platform"] --> Capabilities["Platform capability matrix"]
  Capabilities --> Preflight
  Preflight -->|All requirements supported| Plan["Continue planning"]
  Preflight -->|Unsupported requirement| Refusal["Typed refusal"]
  Capabilities --> Caller["Application capability query"]
  Caller -->|files = false on Azure| Avoid["Skip file operations"]
  Caller -->|files = true elsewhere| Files["Use file operations"]
Loading

Reviews (44): Last reviewed commit: "docs(core): correct the capability notes..." | Re-trigger Greptile

@ItamarZand88
ItamarZand88 force-pushed the itamar/alien-75-sandbox-1-core branch 29 times, most recently from a13b427 to e03d8a5 Compare August 12, 2026 07:22
@ItamarZand88
ItamarZand88 force-pushed the itamar/alien-75-sandbox-1-core branch 11 times, most recently from bca19ef to 79b3147 Compare August 17, 2026 22:14
Azure's data plane exposes exec and lifecycle and no file transfer, so
readFile, writeFiles and mkdir are refused there. The floor claimed
otherwise, and with no field for it a caller could not branch: it found
out by calling and failing, which is the outcome this type exists to
prevent.
No platform supports a hostname egress allowlist — domainEgressRules is
false on all five — and Azure additionally has no file transfer. The
comment named Azure as the one platform that could.
@alongubkin
alongubkin merged commit 76fb6ae into main Aug 20, 2026
25 checks passed
@alongubkin
alongubkin deleted the itamar/alien-75-sandbox-1-core branch August 20, 2026 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants