diff --git a/docs/specification.md b/docs/specification.md index dbe7bd381..2b99c7958 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -46531,11 +46531,11 @@ New backends are registered via configuration: The sandbox layer supports custom isolation strategies for specialized resource types: -
class SandboxStrategy(Protocol):
+
class SandboxStrategyProtocol(Protocol):
     """Interface for sandbox isolation strategies."""
     def create(self, plan_id: str, resource: Resource) -> SandboxRef: ...
     def read(self, ref: SandboxRef, path: str) -> bytes: ...
-    def write(self, ref: SandboxRef, path: str, content: bytes) -> Change: ...
+    def write(self, ref: SandboxRef, path: str, content: bytes) -> DiffEntry: ...
     def diff(self, ref: SandboxRef) -> DiffView: ...
     def commit(self, ref: SandboxRef) -> None: ...
     def rollback(self, ref: SandboxRef) -> None: ...
@@ -46544,7 +46544,31 @@ The sandbox layer supports custom isolation strategies for specialized resource
     def cleanup(self, ref: SandboxRef) -> None: ...
 
-Custom strategies are mapped to resource types via the resource type configuration's `sandbox_strategy` field, or globally via `sandbox.strategy` config. +Custom strategies are registered via configuration and then referenced by name in the resource type's `sandbox_strategy` field: + +```toml +# config.toml — register the custom strategy +[sandbox.custom_strategies.my-strategy] +module = "cleveragents.extensions.my_module" +class = "MySandboxClass" +``` + +!!! warning "Module prefix security guard" + The sandbox plugin loader only imports modules whose fully-qualified + name starts with an allowed prefix. The default allowlist is + `("cleveragents.",)`, so the example above uses a + `cleveragents.extensions.*` module. If you need to load strategies + from another namespace (for example, `mycompany.sandbox.*`), extend + the registry's `allowed_prefixes` configuration per + [Development › Custom Sandbox Strategy Registration](development/custom_sandbox_strategy.md). + Otherwise the loader raises a `PluginLoadError` at startup. + +```yaml +# resource-types/my-resource.yaml — reference the strategy by name +resource_type: + name: local/my-resource + sandbox_strategy: my-strategy +``` #### ACMS Extensions