Skip to content

feat(sandbox): grants as mediated host functions, and on_crash - #8

Closed
Immanuel-Fowler wants to merge 2 commits into
feat/sandbox-arrays-structsfrom
feat/sandbox-crash-and-grants
Closed

Immanuel-Fowler wants to merge 2 commits into
feat/sandbox-arrays-structsfrom
feat/sandbox-crash-and-grants

Conversation

@Immanuel-Fowler

Copy link
Copy Markdown
Owner

Stacked on #7 (feat/sandbox-arrays-structs); merge that first.

What

The two things a sandboxed serverlet could not do that the other boundaries could, both were compile errors until now.

grant call on a sandboxed serverlet. In a library build, a sandboxed serverlet takes the same grant lines a landline does. There they are the only way the guest reaches the host at all:

  • Each grant is exactly one import defined in the guest's wasmtime linker (orch_host.<group>_<function>), behind which the Host trait method runs on the host. Nothing is defined for anything ungranted, so it does not exist inside the guest. This is step 7 of docs/design/sandboxed-serverlets.md: containment and consent as one mechanism.
  • The guest carries the call through a generated stub over the landline wire codec, so host functions take and return numbers, booleans, strings, arrays, and structs.
  • A handler that calls an ungranted host function is refused by orchestrate check, naming the serverlet, the call, and the grant that would allow it.
  • A host error or panic fails that one call inside the guest, which logs it and continues with the return type's default. A host call counts against the serverlet's timeout, since the guest is still inside its call while the host runs.

on_crash on a sandboxed serverlet runs on the host after a call ran past its timeout, exhausted its memory, or stopped itself, with the trap's message bound, before the guest is replaced and the caller gets the default. It cannot reach the guest's state, which is inside the instance being thrown away; a handler that names a state binding is a compile error saying so.

Not an impossibility

The brief allowed a written argument that these cannot exist for a WASM guest. They can, so this implements them rather than arguing otherwise.

Tests

  • library_sandbox_grants_are_mediated_host_functions: a granted call with an int, a struct, and an array, a host error answered with a default, across two ticks, with the host's log captured.
  • runtime_sandbox_on_crash_runs_on_the_host: a timed-out call runs the handler with the trap message, and the fresh guest starts over.
  • Error cases: sandbox_ungranted_host_call.orch (refused by check) and sandbox_crash_uses_state.orch.
  • Parser test for grant call and on_crash inside a sandboxed serverlet, and the refusal on a plain one.
  • Snapshot sandbox_guest regenerated: the guest gains the host-call helper.

Found on the way

A handler named move reached rustc as a keyword. Any Rust keyword used as an OrchestrateLang name does; recorded in LIMITATIONS-notes.md, not fixed here.

Changelog entries are under [Unreleased]. No version bump.

🤖 Generated with Claude Code

Immanuel-Fowler and others added 2 commits September 20, 2026 23:04
A sandboxed serverlet could not be granted anything and could not
declare on_crash; both were compile errors, the two things the
contained boundary could not do that the others could.

Each `grant call group.function` is now exactly one import defined in
the guest's wasmtime linker, behind which the Host trait method runs on
the host, and nothing is defined for anything ungranted, so it does not
exist inside the guest. That is step 7 of the sandbox design: the grant
declares what the guest may reach and the linker makes everything else
unreachable, containment and consent as one mechanism. The guest
carries a call through a generated stub over the landline wire codec,
so a host function takes and returns what a landline grant does. The
typechecker refuses a handler that calls an ungranted host function,
naming the grant that would allow it, so the refusal is `check`'s
rather than a trap. A host error or panic fails the one call inside the
guest, which logs it and continues with the default. Library builds
only, where host functions exist.

on_crash runs on the host after a call trapped, with the trap's message
bound, before the guest is replaced and the caller gets the default. It
cannot reach the guest's state, which is inside the instance being
thrown away; a handler that names a state binding is refused with the
binding named.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The reference, library guide, README, roadmap and design doc describe
the grant as the only hole in the wall and on_crash as host-side. The
notes gain a per-boundary table of host reach and the Rust-keyword
identifier gap found on the way.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.

1 participant