PtcRunner.Kernel.ToolGrant (PtcRunner v0.14.0)

Copy Markdown View Source

Builds the capability callbacks handed to a sandboxed evaluation.

Every callback here is copied into the sandbox process, and that copy is flatspawn does not preserve sharing. A callback must therefore close over only what it reads. Dispatcher.dispatch/8 resolves one name, so each capability callback carries one capability via PtcRunner.Kernel.Environment.capability_view/2; only the runtime discovery routes carry the whole map, via capability_view/1.

The cost of getting this wrong is not linear. A term every callback captures is copied once per callback, so capturing anything environment-sized makes the hand-over O(capabilities²) — enough for a tool-rich MCP environment to blow the sandbox setup ceiling before the program runs, and enough for a modest environment to eat the program's whole heap budget through the measured baseline. PtcRunner.Sandbox documents how that baseline is billed.

Size a grant with :erts_debug.flat_size (plus referenced binaries for byte units); that is what the sandbox's own baseline measurement bills.

Summary

Functions

Returns the capability dispatch callbacks plus reserved runtime routes for one environment.

Functions

capability_callbacks(state, kind, environment, dispatch_context, event_sink, inspection_sink)

@spec capability_callbacks(
  term(),
  :workflow | :mission,
  map(),
  %{
    mission_name: binary() | nil,
    timeout_ms: non_neg_integer(),
    validation_heap_words: pos_integer(),
    evaluation_lease: reference() | nil,
    validation_deadline_ms: integer() | nil
  },
  term(),
  term()
) :: %{required(binary()) => (map() -> map())}

Returns the capability dispatch callbacks plus reserved runtime routes for one environment.

Callers add their own environment-specific routes (kernel-eval, the workflow inventory routes, TrustedTool wrapping) to the result. Those extra routes are not capability callbacks and are not refusal-counted; wrapping happens inside this grant, after RuntimeTools.tools/5 is merged.