generated from coulomb/repo-seed
Implement SAND-WP-0005: extension SDK and ext.vm-packer
Add SandboxExtension base class, extension SDK docs, vm-packer attach mode for build-machines VMs, profile.vm-haskell-build, SSH port support, tests, and migration docs.
This commit is contained in:
102
docs/extension-sdk.md
Normal file
102
docs/extension-sdk.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Extension SDK
|
||||
|
||||
Author guide for sand-boxer backend adapters. Version 0.1 — SAND-WP-0005.
|
||||
|
||||
## Contract
|
||||
|
||||
Every extension implements three methods:
|
||||
|
||||
```text
|
||||
provision(profile, inputs, host) → handle dict
|
||||
wait_ready(handle) → reachability dict
|
||||
teardown(handle) → cleanup report dict
|
||||
```
|
||||
|
||||
Optional (SaaS, deferred): `estimate_cost(profile, duration) → MeterQuote`
|
||||
|
||||
### Base class
|
||||
|
||||
```python
|
||||
from sandboxer.extensions.base import SandboxExtension
|
||||
|
||||
class MyExtension(SandboxExtension):
|
||||
def provision(self, profile, inputs, host): ...
|
||||
def wait_ready(self, handle): ...
|
||||
def teardown(self, handle): ...
|
||||
```
|
||||
|
||||
Reference implementations:
|
||||
|
||||
| Extension | Module | Mode |
|
||||
|-----------|--------|------|
|
||||
| `ext.compose-ssh` | `compose_ssh.py` | Remote compose stack |
|
||||
| `ext.vm-packer` | `vm_packer.py` | Attach workspace on pre-built VM |
|
||||
|
||||
## Registration
|
||||
|
||||
1. Add `extensions/ext.<name>.yaml`:
|
||||
|
||||
```yaml
|
||||
id: ext.my-backend
|
||||
title: My Backend
|
||||
handler: sandboxer.extensions.my_backend:MyExtension
|
||||
capabilities:
|
||||
isolation_levels: [container]
|
||||
pricing_model: self-hosted
|
||||
config:
|
||||
key: value
|
||||
```
|
||||
|
||||
2. Add a profile binding in `profiles/profile.<slug>.yaml` with `extension: ext.my-backend`.
|
||||
3. Register capability metadata in `registry/` when ready for reuse-surface.
|
||||
|
||||
Loader validates `capabilities.isolation_levels` and `capabilities.pricing_model`
|
||||
at startup (`sandboxer.extensions.registry`).
|
||||
|
||||
## Handle and reachability
|
||||
|
||||
**Handle** (returned by `provision`, stored in manager): opaque dict passed to
|
||||
`wait_ready` and `teardown`. Include at minimum:
|
||||
|
||||
- `sandbox_id`
|
||||
- `host` (placement host)
|
||||
- Fields your extension needs for SSH/API (e.g. `remote_dir`, `vm_target`)
|
||||
|
||||
**Reachability** (returned by `wait_ready`): exposed on `SandboxStatus.reachability`:
|
||||
|
||||
- `ssh` — SSH destination string
|
||||
- `remote_dir` — workspace path on remote
|
||||
- `host` — placement host
|
||||
- `compose_project` — compose-ssh only
|
||||
|
||||
## Inputs convention
|
||||
|
||||
Profiles declare semantics; extensions validate required `inputs` keys:
|
||||
|
||||
| Extension | Required inputs | Optional |
|
||||
|-----------|-----------------|----------|
|
||||
| compose-ssh | `repo` | `sandbox_id` |
|
||||
| vm-packer | `vm` or `ssh_target` | `repo`, `tunnel_port`, `ssh_port`, `workspace_dir` |
|
||||
|
||||
Consumer attribution travels on `SandboxCreateRequest.consumer`, not extension inputs.
|
||||
|
||||
## Testing
|
||||
|
||||
Mock SSH/subprocess in unit tests. See `tests/test_compose_ssh.py`, `tests/test_vm_packer.py`.
|
||||
|
||||
Pattern:
|
||||
|
||||
```python
|
||||
with patch.object(SSHConfig, "run", return_value=(0, "ready")):
|
||||
ext = VMPackerExtension()
|
||||
handle = ext.provision(profile, {"vm": "haskell-build"}, "localhost")
|
||||
```
|
||||
|
||||
## Deferred
|
||||
|
||||
| Feature | Workplan |
|
||||
|---------|----------|
|
||||
| Packer build orchestration from `create` | Future WP |
|
||||
| SaaS adapters + `estimate_cost` | SAND-WP-0006 |
|
||||
| Multi-backend routing engine | SAND-WP-0006 |
|
||||
| Snapshot / restore hooks | SAND-WP-0007 |
|
||||
Reference in New Issue
Block a user