generated from coulomb/repo-seed
feat: TTL enforcement and operational hardening (SAND-WP-0009)
Add TTL parser, expires_at on create, extend_ttl and expire/reap APIs, activity-core integration doc, repo classification, registry refresh, HTTP parity, and 69 tests.
This commit is contained in:
42
docs/integrations/activity-core.md
Normal file
42
docs/integrations/activity-core.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# activity-core integration
|
||||
|
||||
activity-core schedules bounded work on Railiance01. sand-boxer provides
|
||||
**sandbox venues** with TTL enforcement; activity-core owns **when** expire runs.
|
||||
|
||||
## Scheduled TTL reap
|
||||
|
||||
Run periodically (cron, Temporal activity, or CI):
|
||||
|
||||
```bash
|
||||
sandboxer expire --apply
|
||||
```
|
||||
|
||||
HTTP equivalent:
|
||||
|
||||
```http
|
||||
POST /v1/sandboxes/expire?apply=true
|
||||
```
|
||||
|
||||
Returns a list of `ExpireActionResult` entries (`dry-run`, `destroyed`, `failed`).
|
||||
|
||||
## Lifecycle events
|
||||
|
||||
Each expired sandbox emits a State Hub progress event:
|
||||
|
||||
- `state`: `expired` (`event_type`: `milestone`)
|
||||
- Followed by `destroying` → `destroyed`
|
||||
|
||||
Event `detail` includes `ttl`, `expires_at`, and reachability fields.
|
||||
|
||||
## What sand-boxer does not do
|
||||
|
||||
- No Temporal workflows or activity-core code in this repo
|
||||
- No push webhook to activity-core on expiry (poll/schedule only in v0)
|
||||
- TTL parsing and destroy orchestration live in sand-boxer
|
||||
|
||||
## Consumer pattern
|
||||
|
||||
1. activity-core activity provisions via `sandboxer create` (or HTTP)
|
||||
2. Work runs in the sandbox (glas-harness, wise-validator, etc.)
|
||||
3. Scheduled `sandboxer expire --apply` reaps past-TTL sandboxes
|
||||
4. State Hub records full lifecycle for audit
|
||||
@@ -82,7 +82,7 @@ Extends the `build-agent` self-register pattern: generic sandbox identities carr
|
||||
| `create` | Provision from profile + inputs | **Yes** |
|
||||
| `get` | Inspect sandbox status | **Yes** |
|
||||
| `list` | List sandboxes (filter by consumer optional) | **Yes** |
|
||||
| `extend_ttl` | Extend time-to-live | Stub |
|
||||
| `extend_ttl` | Extend time-to-live | **Yes** |
|
||||
| `recreate` | Destroy and reprovision from stored seed | **Yes** |
|
||||
| `destroy` | Idempotent teardown | **Yes** |
|
||||
| `snapshot` / `restore` | Checkpoint workspace | **Yes** (compose-ssh, saas-stub) |
|
||||
@@ -97,6 +97,9 @@ HTTP surface (optional v0; CLI calls core library directly):
|
||||
- `POST /v1/sandboxes/{id}/snapshot` — checkpoint
|
||||
- `POST /v1/snapshots/{id}/restore` — restore
|
||||
- `GET /v1/snapshots` — list checkpoints
|
||||
- `POST /v1/sandboxes/{id}/recreate` — recreate
|
||||
- `PATCH /v1/sandboxes/{id}/ttl` — extend TTL
|
||||
- `POST /v1/sandboxes/expire` — TTL reap (query `apply=true`)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -46,4 +46,4 @@ Deferred: Packer orchestration from API, `make remote-build` shim.
|
||||
| ~~SaaS extensions + payments v0~~ | SAND-WP-0006 — stub + routing + credits |
|
||||
| E2B / Modal real adapters | Post SAND-WP-0006 |
|
||||
| ~~Snapshot / restore~~ | SAND-WP-0007 — `docs/snapshots.md` |
|
||||
| TTL enforcement + scheduled reap | **SAND-WP-0009** |
|
||||
| ~~TTL enforcement + scheduled reap~~ | SAND-WP-0009 — `docs/ttl.md` |
|
||||
23
docs/security.md
Normal file
23
docs/security.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Security posture
|
||||
|
||||
sand-boxer limits **blast radius** — it does not enforce **intent**.
|
||||
|
||||
## What sandboxing provides
|
||||
|
||||
- Isolated compose projects and workspace directories on placement hosts
|
||||
- Profile-declared network default-deny (declarative in v0; enforcement varies by extension)
|
||||
- TTL-bound disposable venues with automated expire/reap
|
||||
- Consumer attribution (`adm` / `agt` / `atm`) on lifecycle events
|
||||
|
||||
## What sandboxing does not provide
|
||||
|
||||
- Protection against a malicious or compromised agent *inside* the sandbox
|
||||
- Guarantee that an agent follows instructions or policy
|
||||
- Replacement for secrets management (use OpenBao / operator paths via `warden route`)
|
||||
- Production isolation on Railiance01 (sandboxes run on sandboxer01 / CoulombCore)
|
||||
|
||||
Per INTENT: *"Honest security — sandboxing limits blast radius; it is not intent
|
||||
enforcement."*
|
||||
|
||||
Operators should combine sand-boxer with flex-auth, credential routing, and
|
||||
harness-level controls for end-to-end safety.
|
||||
65
docs/ttl.md
Normal file
65
docs/ttl.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Time-to-live (TTL)
|
||||
|
||||
Disposable-by-default sandboxes — SAND-WP-0009.
|
||||
|
||||
## Semantics
|
||||
|
||||
Each ready sandbox has:
|
||||
|
||||
| Field | Meaning |
|
||||
|-------|---------|
|
||||
| `ttl` | Active duration string (e.g. `4h`) |
|
||||
| `expires_at` | UTC timestamp when the sandbox should be reaped |
|
||||
|
||||
On `create`, TTL comes from `SandboxCreateRequest.ttl` or the profile
|
||||
`ttl.default`, capped at `ttl.max`. Anchor is `ready_at`.
|
||||
|
||||
Duration format: positive integer + unit — `s`, `m`, `h`, `d` (e.g. `30m`, `4h`).
|
||||
|
||||
## extend_ttl
|
||||
|
||||
Extend a live sandbox (`ready` or `active`):
|
||||
|
||||
```bash
|
||||
sandboxer extend-ttl <sandbox_id> --duration 2h
|
||||
```
|
||||
|
||||
HTTP: `PATCH /v1/sandboxes/{id}/ttl` with `{"duration": "2h"}`.
|
||||
|
||||
Extension adds to the current `expires_at` (or now if already past). Total lifetime
|
||||
from `ready_at` cannot exceed profile `ttl.max`.
|
||||
|
||||
## expire / reap
|
||||
|
||||
TTL reap is distinct from host inventory `reap-stale`:
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `sandboxer expire` | Sandboxes past `expires_at` or profile `ttl.idle_reap` |
|
||||
| `sandboxer reap-stale` | Orphan host resources vs store inventory |
|
||||
|
||||
```bash
|
||||
sandboxer expire # dry-run (default)
|
||||
sandboxer expire --apply # mark expired, destroy
|
||||
```
|
||||
|
||||
HTTP: `POST /v1/sandboxes/expire?apply=true`
|
||||
|
||||
Flow on `--apply`:
|
||||
|
||||
1. Transition to `expired` (State Hub milestone)
|
||||
2. `destroy` (idempotent teardown)
|
||||
|
||||
## Profile fields
|
||||
|
||||
```yaml
|
||||
ttl:
|
||||
default: 4h
|
||||
max: 24h
|
||||
idle_reap: null # optional; reap when updated_at + idle_reap elapsed
|
||||
```
|
||||
|
||||
## activity-core
|
||||
|
||||
Scheduled jobs should invoke `sandboxer expire --apply` (or HTTP equivalent).
|
||||
See `docs/integrations/activity-core.md`.
|
||||
Reference in New Issue
Block a user