All checks were successful
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 5s
`Locality { region: String, jurisdiction: String }` — two free-text strings,
supplied by the party under audit, checked for presence and nothing else, at the
one tier whose entire purpose is jurisdictional. SPEC §7.7 already said a host
"MUST NOT seal an S7 run whose execution it cannot bind to the stated locality",
which was an obligation with no mechanism behind it. It is the weakest normative
claim in the ladder and the first thing a data-residency auditor attacks.
Round-trip time to an anchor of known position bounds distance: a signal cannot
outrun light, so `rtt/2 × c` is the farthest the host can be from that anchor.
The asymmetry is what makes it worth anything — **latency is trivial to add and
impossible to remove** — so a host can always appear farther away than it is and
never closer than physics permits.
What that buys is narrow, and the code is named for it. The evidence
**falsifies; it does not verify**:
- It can refute a claim. If the claimed position is farther from an anchor than
light could travel in the observed time, the claim is impossible, and that
conclusion does not rest on trusting anyone.
- It can never confirm one. Surviving every bound means "not excluded" and
nothing more: the feasible region is an intersection of discs that routinely
spans several jurisdictions. So the passing verdict is `NotRefuted`, there is
deliberately no `is_proven`, and §7.7 forbids reporting a surviving claim as
proven, verified, or attested.
Three rules that matter more than the arithmetic:
- **Only an independent anchor's signed observation counts.** A round-trip time
the host measured about itself is the same unchecked assertion as the region
string it was meant to improve on — now with a number attached. Unsigned
observations return `Unsubstantiated` rather than being blended in, and that
holds even when they would *refute*: the rule is about provenance, not about
which answer they happen to give.
- **A host cannot seal an attestation its own evidence refutes.** That is not a
marginal judgement about trust; it is a physical impossibility the host itself
just recorded.
- **The bound uses vacuum c, not a fibre constant.** This costs sensitivity and
buys certainty in the only direction that matters: a refutation under vacuum-c
cannot be argued away by an unusual path.
It is timing-derived, so by this codebase's own rule (`TimingIsNotAShunt`, §6.3)
it is its own evidence class — it never reaches the standing of the verified
`tee` evidence at S6 and carries no `Provenance` at all.
Absent, the field is omitted and the canonical bytes are unchanged, so S7
attestations sealed before this section still verify — C12 asserts that
alongside the refutation, the unsigned-observation rule, and the below-S7
rejection.
Verified: 203 workspace tests pass, conformance passes all 12 classes with no
skips, published vectors unchanged on disk, no clippy warnings in the new file.
387 lines
38 KiB
Markdown
387 lines
38 KiB
Markdown
# Sandbox v0.1 — Isolated, Capability-Gated, Metered, Attested Execution Across the Heterogeneous Compute Fabric
|
||
|
||
Status: **Draft Standard**. Reference implementation: [`sandbox-rs/`](sandbox-rs/) (Rust workspace, Apache-2.0). Specification text: CC-BY-4.0.
|
||
|
||
The keywords **MUST**, **MUST NOT**, **REQUIRED**, **SHALL**, **SHALL NOT**, **SHOULD**, **SHOULD NOT**, **MAY**, and **OPTIONAL** are to be interpreted as described in RFC 2119.
|
||
|
||
---
|
||
|
||
## 1. Scope and doctrine
|
||
|
||
Sandbox specifies how a **unit of work** is isolated, granted a bounded set of capabilities, executed, metered for energy across the compute fabric it touches, and accounted for in a signed attestation. It is the isolated-execution substrate of the Transaction Science open standards.
|
||
|
||
The **doctrine** is one sentence: *isolation per joule, across the whole fabric.* Three normative consequences follow.
|
||
|
||
### 1.1 The isolation ladder (REQUIRED)
|
||
|
||
A conforming **host** **MUST** run a unit at the lowest tier of the eight-rung isolation ladder (§2.1) whose guarantees satisfy the unit's capability set, and **MUST NOT** escalate to a higher tier than the grants require. A host **MAY** decline to run a unit whose grants require a tier it does not implement; it **MUST NOT** run the unit at a tier weaker than required. The tier at which a unit ran **MUST** be recorded in its attestation (§7).
|
||
|
||
### 1.2 The capability grant (REQUIRED)
|
||
|
||
A unit's access to every resource — network, storage, key-value, host services, subprocess execution, browser, display, and **each compute device class** (§2.3) — **MUST** be governed by an explicit **grant** (§5). Access to a resource not named by a grant **MUST** be denied (deny-by-default). A host **MUST NOT** widen a unit's grants during a run; a mutation to the granted capability set **MUST** terminate the run and invalidate its attestation.
|
||
|
||
### 1.3 The attested receipt (REQUIRED)
|
||
|
||
Every completed run **MUST** emit (a) an **energy receipt** (§6) accounting joules per device class, two-part (`measured + estimated`, integer microjoules), each reading carrying a `Provenance` tag, sealed as a JCR-1 envelope; and (b) an **attestation** (§7) binding the unit, its image, the tier it ran at, the grants it ran under, the hardware it ran on, and the receipt — signed Ed25519 over JCS-canonicalized JSON. A host **MUST NOT** report a `measured` figure it did not obtain from a hardware energy interface (§6.3).
|
||
|
||
### 1.4 No capture (REQUIRED)
|
||
|
||
The protocol carries **no token**. A conforming host **MUST** perform its core function — isolate a unit, enforce its grants, meter its energy, seal its attestation — without contacting any single steward's servers as a condition of operation. Where a unit's grants permit network egress (§5.3), that egress is the unit's own; it **MUST NOT** be a precondition of the host's operation.
|
||
|
||
---
|
||
|
||
## 2. The model
|
||
|
||
### 2.1 The three entities
|
||
|
||
Every Sandbox run involves three entities, kept separated, generalizing the ARL Sandbox model:
|
||
|
||
- **Unit** — the code under execution. Sealed inside the sandbox boundary. It can read and influence only what its grants permit, and nothing outside the boundary.
|
||
- **Host** — the runtime that establishes the boundary, mediates every capability the unit exercises, meters energy, and runs the unit. The host is itself subject to telemetry but is trusted to enforce the boundary at the tier in force.
|
||
- **Supervisor** — the process outside the boundary that orchestrates the run, reads physical telemetry, and signs the attestation. The signing key is held where the unit and the host's in-boundary code cannot reach it (§7.4).
|
||
|
||
### 2.2 The isolation ladder (S0–S7)
|
||
|
||
A host runs a unit at exactly one **tier**. Each tier strictly contains the guarantees of the tier below it.
|
||
|
||
| Tier | Wire tag | Name | Boundary mechanism (reference) | Typical use |
|
||
|------|----------|------|--------------------------------|-------------|
|
||
| S0 | `S0` | Bare | process only; no added boundary | trusted code, local development |
|
||
| S1 | `S1` | Capability | unforgeable capability tokens; no ambient authority | capability-confined modules |
|
||
| S2 | `S2` | Sandbox | managed runtime + fuel/instruction metering + memory caps (e.g. WASM) | untrusted single-tenant units (default for agent tools) |
|
||
| S3 | `S3` | Partition | temporal + spatial partitioning over a shared kernel | multi-tenant on one host |
|
||
| S4 | `S4` | Unikernel | VMM + single-address-space unikernel guest | minimal-surface confined service |
|
||
| S5 | `S5` | MicroVM | VMM + full guest kernel; dedicated vCPU/memory | untrusted multi-tenant, Firecracker-class |
|
||
| S6 | `S6` | Confidential | S5 + hardware memory encryption + remote attestation (TEE) | confidential workloads on untrusted hosts |
|
||
| S7 | `S7` | Sovereign | S6 + geographic pinning + immutable audit trail | jurisdiction-bound, fully provenanced |
|
||
|
||
A host **MUST** treat the tags `S0`–`S7` as the canonical wire identifiers. The reference mechanisms are non-normative: a host **MAY** satisfy a tier's guarantees by any means that provides them. The **guarantees**, not the named technology, define the tier (§ `spec/tiers.md`).
|
||
|
||
A unit's required tier is the **lowest** tier whose guarantees satisfy every grant it holds (§5 fixes the per-capability minimum tiers). The host computes this tier and runs there (§1.1).
|
||
|
||
### 2.3 Device classes (REQUIRED)
|
||
|
||
The compute fabric is enumerated as a fixed set of **device classes**:
|
||
|
||
```
|
||
DeviceClass = Cpu | Simd | Gpu | Npu | Tpu | Lpu | Photonic | Quantum
|
||
```
|
||
|
||
A device class is a first-class subject of the capability model (§5.1), the receipt (§6.2), and the attestation (§7.2). A host **MUST NOT** grant, meter, or attest accelerator work as undifferentiated CPU work. The `Cpu` class denotes scalar host compute; `Simd` denotes vector lanes on the host CPU; the remaining classes denote distinct accelerators. A host **MAY** support any subset of classes; it **MUST** reject a grant naming a class it cannot isolate and meter (§5.1).
|
||
|
||
### 2.4 Shared resources and side channels (REQUIRED)
|
||
|
||
Logical isolation separates memory and code; it does not partition the **physical resources** a tier shares, and a shared resource is a channel. At S0–S2 the host kernel and device I/O paths are shared, so co-tenants can observe one another through **contention** with no privileged access (see `SECURITY.md` for the storage-I/O worked example). Tier minimization (§2.2) is therefore **side-channel-aware**: a unit's required tier accounts not only for what its grants *name* but for what they *expose*. A workload sensitive to — or, as an untrusted neighbor, capable of — cross-tenant leakage through a shared resource **MUST** either carry the capability that bounds the channel (e.g. a storage I/O ceiling, §5.2) or run at the tier that partitions it (**S3**), or assigns the device exclusively (**S5**). A host **MUST NOT** silently colocate such a workload at a tier whose shared resources leave the channel open.
|
||
|
||
---
|
||
|
||
## 3. Identity and content addressing
|
||
|
||
Every load-bearing object (unit descriptor, image, grant set, receipt, attestation) is identified by the **content address** of its canonical serialization (§4): `id = "b3:" + base64url-unpadded( BLAKE3-256( canonical_bytes ) )`. Identity is independently computable by any party; no central authority assigns it.
|
||
|
||
- A **unit id** is the content address of the unit descriptor (the image id, the entrypoint, and the declared grant request) excluding any signature.
|
||
- An **image id** is the content address of the executable artifact the unit runs.
|
||
- A **grants id** is the content address of the granted capability set (§5).
|
||
|
||
A signature over an object binds its content address, not the reverse (§7.3).
|
||
|
||
## 4. Canonical serialization
|
||
|
||
The canonical form of receipt and attestation cores is **deterministic CBOR** (RFC 8949 §4.2 core deterministic encoding) for the JCR-1 receipt, and **JCS** (RFC 8785) for the JSON attestation. A conforming implementation **MUST** produce byte-identical canonical encodings for equal objects across platforms. **Floats MUST NOT appear in any canonical form or decision path.** All energy figures are integer microjoules; all budgets, counts, and limits are unsigned integers.
|
||
|
||
---
|
||
|
||
## 5. The capability grant
|
||
|
||
A **grant set** is the complete, explicit description of what a unit may touch. The normative type is in [`spec/capabilities.md`](spec/capabilities.md); this section fixes the load-bearing structure and the per-capability minimum tiers.
|
||
|
||
```
|
||
Grants {
|
||
compute : ComputeGrant,
|
||
storage : StorageGrant,
|
||
network : NetworkGrant,
|
||
kv : KvGrant,
|
||
host : HostGrant, // logging, clock, randomness, inference
|
||
process : ProcessGrant, // subprocess / shell (§5.5)
|
||
browser : BrowserGrant, // browser automation (§5.6)
|
||
display : DisplayGrant, // framebuffer / desktop (§5.7)
|
||
}
|
||
```
|
||
|
||
### 5.1 Compute grant (REQUIRED; the heterogeneity clause)
|
||
|
||
```
|
||
ComputeGrant {
|
||
devices : Set<DeviceClass>, // which classes the unit may use
|
||
energy_budget_uj : u64, // total joule budget for the run, microjoules
|
||
cpu_time_ms : u64, // wall/CPU time bound
|
||
memory_bytes : u64, // resident memory cap
|
||
}
|
||
```
|
||
|
||
A unit **MUST NOT** dispatch work to a device class not present in `devices`. A host **MUST** deny a dispatch to an ungranted class. A host **MUST** reject the whole grant (refuse to run) if `devices` names a class the host cannot both **isolate** (confine per the tier in force) and **meter** (attribute energy to per §6.2). Granting any class other than `Cpu`/`Simd` requires a tier of at least **S2**; granting a class via direct device assignment (passthrough/SR-IOV) requires at least **S5**; granting a confidential-compute device requires **S6**.
|
||
|
||
When the run exceeds `energy_budget_uj`, `cpu_time_ms`, or `memory_bytes`, the host **MUST** terminate the unit and record the breached bound in the attestation.
|
||
|
||
### 5.2 Storage grant
|
||
|
||
```
|
||
StorageGrant { read : [Glob], write : [Glob], delete : [Glob],
|
||
max_iops : u64?, max_read_bps : u64? }
|
||
```
|
||
|
||
A path operation **MUST** match an allow-glob for its access mode or be denied. The empty grant denies all storage. A grant **MAY** carry sustained-I/O ceilings (`max_iops`, `max_read_bps`); a sustained rate is permitted **iff** it stays within every ceiling that is set. A ceiling is the deny-by-default lever against storage-contention side channels (§2.4, `SECURITY.md`); it is bound into the grant's content id and attested. Omitted ceilings (`null`) do not bound that dimension and serialize to nothing, leaving pre-ceiling grants byte-identical.
|
||
|
||
### 5.3 Network grant
|
||
|
||
```
|
||
NetworkGrant { outbound : [Endpoint], inbound : bool }
|
||
```
|
||
|
||
`outbound` is an allowlist of `host:port` endpoints; an egress to an endpoint not on the list **MUST** be denied. The empty grant denies all network. Network access is never a precondition of the host's own operation (§1.4).
|
||
|
||
### 5.4 Key-value and host grants
|
||
|
||
```
|
||
KvGrant { read : bool, write : bool, prefixes : [Bytes] }
|
||
HostGrant { logging : bool, clock : bool, random : bool, inference : bool }
|
||
```
|
||
|
||
`inference` gates the unit's access to an on-host model endpoint; when granted, inference energy is metered to the device class that served it (§6.2), never hidden.
|
||
|
||
### 5.5 Process grant
|
||
|
||
```
|
||
ProcessGrant { exec : bool, programs : [String],
|
||
allow_hashes : [ContentId], deny_hashes : [ContentId],
|
||
max_processes : u32 }
|
||
```
|
||
|
||
Governs the unit's ability to **spawn subprocesses** — the substrate for shell access and code-interpreter capabilities. A unit **MUST NOT** spawn a program unless `exec` is true **and** the program is permitted; deny-by-default, so an empty grant permits nothing. Granting `exec` requires a tier of at least **S2** (§2.2): subprocess execution crosses a brokered host boundary and is untrusted-execution class.
|
||
|
||
Name-based control (`programs`) is advisory: rename, relocation, or a wrapper script defeats it. Against an untrusted unit the binding that holds is **content-addressed**. The host **MUST** decide on the BLAKE3 content address of the executable's bytes: a binary whose address is on `deny_hashes` **MUST** be refused regardless of its name, path, or wrapping, and the denylist **MUST** override every allow rule; when `allow_hashes` is non-empty it is authoritative, so a binary absent from it **MUST** be refused even if its name is allowed. With no hash allowlist the name allowlist applies. Both hash lists are omitted when empty, so a name-only grant is byte-identical to a pre-hash grant and its content address is unchanged. Conformance class **C8**.
|
||
|
||
### 5.6 Browser grant
|
||
|
||
```
|
||
BrowserGrant { enabled : bool, origins : [Origin], headless : bool }
|
||
```
|
||
|
||
Governs **browser automation** — the substrate for browser and GUI-agent capabilities. A navigation **MUST** be denied unless `enabled` is true and the target origin (`scheme://host[:port]`) is on the `origins` allowlist. Granting `enabled` requires a tier of at least **S2**.
|
||
|
||
### 5.7 Display grant
|
||
|
||
```
|
||
DisplayGrant { enabled : bool, vnc : bool, max_width : u32, max_height : u32 }
|
||
```
|
||
|
||
Governs access to a **framebuffer / desktop** and an optional remote (VNC) export — the substrate for desktop capabilities. Display access **MUST** be denied unless `enabled` is true; a VNC export **MUST** additionally require `vnc`. The framebuffer is bounded by `max_width × max_height`. Granting `enabled` requires a tier of at least **S2**.
|
||
|
||
> The filesystem capability is `storage` (§5.2) and a code-interpreter is a composition of `process` (§5.5) and `storage`; this standard models the underlying resources, not the composed product.
|
||
|
||
---
|
||
|
||
## 6. The energy receipt (JCR-1)
|
||
|
||
A **receipt** accounts for one run's energy. The normative schema is in [`spec/receipts.md`](spec/receipts.md).
|
||
|
||
### 6.1 Structure
|
||
|
||
A `Receipt` **MUST** carry:
|
||
|
||
- `unit_id` — the unit it accounts for (§3).
|
||
- `tier` — the tier the unit ran at (§2.2).
|
||
- `devices` — a non-empty list of per-device-class energy records (§6.2).
|
||
- `total` — the summed two-part energy `{ measured_uj: Option<u64>, estimated_uj: u64 }` over all device records.
|
||
- `sequence`, `nonce` — a monotonic sequence number and a per-receipt nonce.
|
||
|
||
### 6.2 Per-device energy (REQUIRED; the heterogeneity clause)
|
||
|
||
`devices` **MUST** contain exactly one `DeviceEnergy` record per device class the unit actually used:
|
||
|
||
```
|
||
DeviceEnergy {
|
||
class : DeviceClass,
|
||
measured_uj : Option<u64>, // present ONLY from a hardware energy interface for THIS class
|
||
estimated_uj : u64, // always present
|
||
provenance : Provenance, // HwShunt | ModelBased | Estimator
|
||
}
|
||
```
|
||
|
||
A host that ran accelerated work **MUST** emit a separate record for each accelerator class used; it **MUST NOT** fold accelerator energy into the `Cpu` record or omit it. The `total` **MUST** equal the field-wise sum of the device records (a `measured` total is present only if every used class has a `measured` figure).
|
||
|
||
### 6.3 Provenance discipline
|
||
|
||
`provenance` is one of:
|
||
|
||
- `HwShunt` — read from a hardware energy interface for that class (RAPL/powercap for CPU; NVML for NVIDIA; ROCm SMI for AMD; Level Zero for Intel; an SMC/shunt otherwise). **MUST** correspond to a present `measured_uj`.
|
||
- `ModelBased` — computed from a calibrated per-operation model for that class. `measured_uj` **MAY** be absent.
|
||
- `Estimator` — a coarse constant estimator. **MUST NOT** carry a `measured_uj`.
|
||
|
||
A host **MUST NOT** report `measured_uj` it did not obtain from a hardware interface for that specific device class. At tiers **S5 and above**, where a hardware energy interface for a used class is available on the host, the host **MUST** use it (`HwShunt`) rather than estimate.
|
||
|
||
### 6.4 Signed form
|
||
|
||
The receipt's on-the-wire form is a **JCR-1 envelope** — the signed-receipt format shared across the Transaction Science family: a canonical det-CBOR signed core (RFC 8949 §4.2.1, length-first key order, no floats/bools/nulls) inside a COSE_Sign1 envelope (RFC 9052, EdDSA/Ed25519, `alg = -8`). A Sandbox receipt uses the `sandbox/1` profile tag and verifies under the family's existing JCR-1 tooling.
|
||
|
||
---
|
||
|
||
## 7. The attestation
|
||
|
||
An **attestation** is the Supervisor's signed statement of what a run was. The normative schema is in [`spec/attestation.md`](spec/attestation.md).
|
||
|
||
### 7.1 Structure
|
||
|
||
An `Attestation` **MUST** carry:
|
||
|
||
- `unit_id`, `image_id`, `grants_id` — content addresses (§3) of the unit, the image that ran, and the granted capability set.
|
||
- `tier` — the tier the unit ran at (§2.2).
|
||
- `devices` — the device identities used (§7.2).
|
||
- `receipt_id` — the content address of the energy receipt (§6) for this run.
|
||
- `journal_root` — the BLAKE3 root of the deterministic-replay journal (§8) where one was produced; absent otherwise.
|
||
- `outcome` — `Completed | Failed | Terminated{ breach }`, recording any resource breach (§5.1) or detected tamper (§7.5).
|
||
- `tee` — TEE evidence (§7.6) when the tier is S6 or above; absent otherwise.
|
||
- `locality` — the region and jurisdiction the run was bound to (§7.7); **REQUIRED** when the tier is S7, absent otherwise.
|
||
- `audit_prev` — the audit-chain head before this run was appended (§7.7); **REQUIRED** when the tier is S7, absent otherwise.
|
||
- `host_id`, `started_at_us`, `finished_at_us` — the host identity and the run window.
|
||
|
||
### 7.2 Device identity (REQUIRED; the heterogeneity clause)
|
||
|
||
`devices` **MUST** name, for each device class the unit used, its `{ class, model, driver }` — for example `{ Gpu, "NVIDIA H100", "560.x" }`. A run that used an accelerator but does not record its identity is **not conformant**.
|
||
|
||
### 7.3 Signing
|
||
|
||
The attestation signs **Ed25519 over JCS-canonicalized JSON** (RFC 8032 + RFC 8785), with SHA-256 used for the content addresses it references. This is the attestation primitive of the ARL Sandbox; a Sandbox attestation and an ARL-S session attestation verify under the same tooling. The signature binds the canonical bytes; any change to any field invalidates it.
|
||
|
||
### 7.4 Key custody
|
||
|
||
The Supervisor's signing key **MUST** be held where neither the unit nor the host's in-boundary code can read it — a TPM, HSM, or secure enclave for production tiers. The unit **MUST** have no access to the telemetry stream or the signing path.
|
||
|
||
### 7.5 Anti-evasion
|
||
|
||
The host **MUST** normalize hostnames, paths, process tree, time, timezone, and locale visible to the unit to deployment-realistic values, and **MUST** record probing (hardware enumeration, root filesystem walks, evasion of the energy interface) in the attestation. A detected VM-escape, privilege escalation, or out-of-allocation write **MUST** set `outcome = Terminated` and invalidate the run. The grant set, image, and any harness configuration are content-addressed before the run begins; a mutation to any of them during the run invalidates the attestation (§1.2).
|
||
|
||
**Tier-claim trust boundary.** A host **MUST NOT** seal an attestation at a tier the run did not execute at. The strength of that obligation differs by tier, and a verifier **MUST** treat it accordingly: for **S0–S5** the tier is *host-asserted* — there is no in-band cryptographic proof that the named boundary was established, so the claim is only as trustworthy as the host. From **S6** up the attestation carries verified `tee` evidence (§7.6) bound to the run identity, which is independently checkable. A relying party that requires proof of isolation rather than host assertion **MUST** require S6+. The reference enforces the executor↔tier binding in its run-and-seal path (the executor's tier is checked against the grants' required tier before sealing); the bare sealing primitive trusts its caller for the execution tier.
|
||
|
||
### 7.6 TEE evidence (S6+)
|
||
|
||
At S6 and above, `tee` **MUST** carry a summary of the hardware attestation report (`kind ∈ { SevSnp, Tdx, ArmCca }`, the launch measurement, and the platform TCB) so a verifier can establish the boundary was hardware-enforced. A host **MUST** obtain the report from the platform's attestation interface, bind it to the run by placing a value derived from the run identity (the unit and receipt content addresses) in the report's 64-byte `report_data` field, and **MUST** verify the report — its signature against the platform's VCEK and its measurement/TCB/debug-state/report-data against policy — before sealing the attestation. A host **MUST NOT** present a `tee` summary it did not verify.
|
||
|
||
The reference splits this honestly (§9): *verification* — parsing the SEV-SNP report, the policy checks, and the ECDSA-P384/SHA-384 signature — is implemented and vectored (`sandbox-tee`). *Generation* of a genuine vendor-signed report requires the CPU's security processor: the reference `configfs-tsm` provider requests one on Linux confidential hardware and reports `Unavailable` elsewhere, and a software-grounded provider (explicitly tagged, never claiming a hardware root) covers wiring and tests.
|
||
|
||
### 7.7 Sovereign binding (S7)
|
||
|
||
At S7, the attestation **MUST** additionally carry:
|
||
|
||
- `locality` — the `{ region, jurisdiction }` the run was pinned to. A host **MUST NOT** seal an S7 run whose execution it cannot bind to the stated locality.
|
||
- `locality_evidence` (RECOMMENDED) — observations bounding where the run could **not** have been. See below.
|
||
- `audit_prev` — the head of the host's append-only, hash-chained audit log **before** this run. After signing, the host **MUST** append the attestation's content address to the log, advancing the head: `head' = BLAKE3(head ‖ attestation_id)`. The chain is tamper-evident — reordering or removing any entry breaks it — so the sequence of sovereign runs is itself attestable.
|
||
|
||
**Locality evidence.** Left as two free-text strings, `locality` is the weakest normative claim in the ladder: an assertion by the party under audit, checked for presence and nothing else, at the one tier whose entire purpose is jurisdictional. The obligation above is real but had no mechanism behind it, and a data-residency auditor attacks exactly this.
|
||
|
||
`locality_evidence` supplies a partial one. Round-trip time to an anchor of known position bounds distance — a signal cannot outrun light, so `rtt/2 × c` is the farthest the host can be from that anchor. The asymmetry is what makes it useful: **latency is trivial to add and impossible to remove**, so a host can always appear farther away than it is and never closer than physics permits.
|
||
|
||
That gives a test that **falsifies but does not verify**:
|
||
|
||
- It can **refute** a claim. If the claimed position is farther from an anchor than light could travel in the observed time, the claim is impossible, and that conclusion does not rest on trusting anyone.
|
||
- It can **never confirm** one. Surviving every bound means "not excluded" and nothing more: the feasible region is an intersection of discs that routinely spans several jurisdictions, and being somewhere inside it is not evidence of being at any particular point in it.
|
||
|
||
Accordingly:
|
||
|
||
- An implementation **MUST NOT** report a surviving claim as proven, verified, or attested. The reference names the passing verdict `NotRefuted` for this reason.
|
||
- Only observations signed by an **independent anchor** count. A round-trip time the host measured about itself is the same unchecked assertion as the region string it was meant to improve on, and **MUST** be reported as unsubstantiated rather than blended into a verdict.
|
||
- Observations **MUST** be bound to the run by a challenge, or an observation taken in a real datacentre can be replayed onto a later run somewhere else.
|
||
- A host **MUST NOT** seal an attestation whose own evidence refutes its own locality claim.
|
||
- `locality_evidence` **MUST** be absent below S7, where no locality is claimed.
|
||
- The bound **SHOULD** be computed with the vacuum speed of light rather than a fibre constant. This costs sensitivity and buys certainty in the only direction that matters: a refutation under vacuum-c cannot be argued away by an unusual path.
|
||
|
||
Locality evidence is **timing-derived**, and this specification already holds that a timing-derived measurement may not claim a hardware-rooted provenance (§6.3). It is therefore its own evidence class: it never reaches the standing of the verified `tee` evidence at S6, and carries no `Provenance` of any kind.
|
||
|
||
### 7.8 EAT interoperability (RECOMMENDED)
|
||
|
||
The native attestation (§7.3) is the standard's own signed form. A host **SHOULD** additionally emit the attestation as an **EAT** (Entity Attestation Token, RFC 9711) — a CWT (RFC 8392) signed as a COSE_Sign1/EdDSA token — so a generic RATS (RFC 9334) verifier can appraise it without understanding this format. The EAT is a *view* of the attestation, signed by the same Supervisor key; it is not a second source of truth.
|
||
|
||
The claims-set carries the IANA-registered EAT/CWT claims `iat` (6), `nonce` (10) — bound to the run as `BLAKE3(unit_id ‖ receipt_id)`, `ueid` (256), `eat_profile` (265) = `https://transaction.science/sandbox/eat/v1`, and `measurements` (273) — plus a profile-scoped private claim referencing the canonical attestation by content address and naming the tier and receipt. A verifier checks the COSE_Sign1 signature and `alg = EdDSA`, the `eat_profile`, and (for this profile) resolves the referenced attestation. See `spec/eat.md`; the reference implements both directions (`sandbox-attest::{seal_eat, verify_eat}`) and every sealed run carries the EAT alongside the native attestation.
|
||
|
||
### 7.9 Enforcement mechanism (S1–S5; RECOMMENDED)
|
||
|
||
Below S6 the tier is host-asserted (§7.5): the standard offers no in-band evidence that the named boundary was ever established, so `tier = "S2"` is the host's word with a signature around it. An attestation at S1–S5 **SHOULD** therefore carry `mechanism`, a commitment to *how* confinement was established:
|
||
|
||
- `runtime` — the enforcement runtime that established the boundary, name **and** version (e.g. `"seatbelt/14.5"`, `"bubblewrap/0.11"`, `"wasmtime/28"`). A bare name is insufficient: the same profile under a different runtime version is a different enforcement.
|
||
- `profile_id` — a BLAKE3 commitment over the **length-prefixed** encoding of the runtime identity, the policy profile actually applied, and the egress allowlist actually installed. Fields are length-prefixed rather than concatenated because bare concatenation is not injective: two distinct configurations whose fields split differently at the same boundary would share a commitment.
|
||
|
||
An attestation carrying `mechanism` uses the profile tag `sandbox.attestation/2`. One without it remains `sandbox.attestation/1` and canonicalizes to byte-identical JSON, so attestations sealed before this section existed verify unchanged.
|
||
|
||
**What a mechanism does and does not establish.** It is **not** proof of isolation, and a verifier **MUST NOT** treat it as such. A host willing to misstate its tier is equally able to misstate its profile; a commitment made by the party under scrutiny cannot bootstrap its own trustworthiness. What changes is the *shape* of the claim. An unadorned tier label is unfalsifiable — there is nothing to check it against. A `profile_id` is checkable against a known-good profile the relying party already trusts, and a false one is a specific, attributable falsehood about a named artifact rather than a vague assertion. This narrows the gap at S1–S5; it does not close it. A relying party that requires proof of isolation rather than assertion still **MUST** require S6+ (§7.5).
|
||
|
||
Normative rules:
|
||
|
||
- A host **MUST NOT** seal a `mechanism` at S0. S0 is "process only; trusted code" — there is no boundary, so a mechanism there is incoherent rather than merely redundant.
|
||
- A host **MUST NOT** publish a `profile_id` it did not derive from the configuration it actually applied.
|
||
- A `mechanism` **MUST** name a runtime version; a runtime name alone is non-conformant.
|
||
- A verifier **MUST NOT** accept `mechanism` in place of the `tee` evidence required at S6+ (§7.6).
|
||
|
||
Requiring a mechanism is a **relying-party** decision, not a producer obligation: making it mandatory for all producers would retroactively invalidate every attestation sealed before this section, and the standard does not make honest historical records non-conformant. A consumer that needs the guarantee demands it at appraisal time — the same posture §7.5 already takes for isolation proof. The reference exposes this as `require_mechanism_evidence()`, under which S0 passes trivially (it claims no confinement) and S6+ passes on its `tee` evidence (strictly stronger).
|
||
|
||
---
|
||
|
||
## 8. Determinism and replay
|
||
|
||
A host **MAY** record a **deterministic-replay journal**: an ordered log of the unit's nondeterministic inputs (host-call results, timer fires, randomness draws) with a hash at each entry, plus periodic state-hash checkpoints. When a journal is produced, its BLAKE3 root **MUST** appear as `journal_root` in the attestation (§7.1), and the run **MUST** be replayable from the journal to the identical sequence of state hashes. Replay is for **audit** — reconstructing what occurred — not for re-execution. A journal that does not replay to its recorded root invalidates the attestation.
|
||
|
||
## 9. Readiness classification
|
||
|
||
Each part is classified by how much of it is proven in the reference implementation:
|
||
|
||
| Part | Class | Note |
|
||
|------|-------|------|
|
||
| Content addressing, canonical forms (§3, §4) | **Solid** | BLAKE3 + det-CBOR + JCS, vectored |
|
||
| Capability grant + deny-by-default enforcement (§5) | **Solid** | reference enforcer, vectored |
|
||
| Per-device energy receipt + JCR-1 sealing (§6) | **Solid** | JCR-1 envelope, family-compatible |
|
||
| Attestation + Ed25519/JCS signing (§7.1–§7.4) | **Solid** | ARL-S-compatible primitive |
|
||
| Isolation ladder S0–S3 (§2.2) | **Engineering** | guarantees specified; `sandbox-exec-wasm` runs and meters real WASM guests at S2 (wasmtime, fuel + memory caps) |
|
||
| Isolation ladder S4–S5 (§2.2) | **Engineering** | `sandbox-exec-microvm` is a real Firecracker driver (boots a guest on Linux+KVM) with pluggable per-device power metering; lifecycle wait/teardown is the host integration point |
|
||
| Deterministic replay journal (§8) | **Engineering** | journal + root specified; reference records and verifies |
|
||
| Anti-evasion (§7.5) | **Engineering** | normalization + probing record specified |
|
||
| TEE report verification — SEV-SNP (§7.6) | **Solid** | `sandbox-tee` parses the SEV-SNP report, checks version/measurement/TCB/debug/report-data, and verifies the real ECDSA-P384/SHA-384 signature; vectored |
|
||
| TEE report verification — Intel TDX (§7.6) | **Solid** | `sandbox-tee::tdx` parses a DCAP v4 quote + TD10 report body and verifies the ECDSA-P256 quote signature, the QE-report endorsement of the attestation key, and the PCK signature over the QE report, then policy (MR_TD/debug/report-data); self-tested |
|
||
| Accelerator attestation — NVIDIA GPU EAT (§7.6) | **Solid** | `sandbox-tee::gpu` verifies an NRAS GPU EAT (JWT/ES384) — the real ECDSA-P384/SHA-384 signature, `alg` pinning (never `none`), and the `eat_nonce` binding — and surfaces the device claims; self-tested |
|
||
| TEE/quote/JWKS chaining to vendor roots (§7.6) | **Engineering** | the reference verifies signatures against the supplied key; fetching and pinning the endorsing key to the vendor root (AMD KDS VCEK, Intel PCS PCK, NVIDIA NRAS JWKS) is the production wiring, documented and not faked |
|
||
| TEE report generation (§2.2 S6, §7.6) | **Engineering** | the `configfs-tsm` provider requests a report on Linux confidential hardware and returns `Unavailable` elsewhere; a software-grounded provider (tagged, never claiming hardware) covers wiring |
|
||
| EAT / RATS interoperability (§7.8) | **Solid** | `sandbox-attest::eat` emits and verifies the attestation as a CWT/COSE_Sign1 EAT (RFC 9711); round-trip tested, carried on every sealed run |
|
||
| Sovereign tier — locality + audit chain (§2.2 S7) | **Engineering** | locality binding and the hash-chained, tamper-evident audit log are implemented and signed into the attestation; vectored |
|
||
| MCP agent server (§11) | **Solid** | `sandbox-mcp` runs units at S2 over JSON-RPC and returns the attested, metered receipt + EAT as the tool result; tested |
|
||
|
||
A host **MUST NOT** advertise a part at a readiness it does not deliver.
|
||
|
||
## 10. Conformance
|
||
|
||
A host is **conformant** if it satisfies every **REQUIRED** clause of §1–§7 for the tiers it advertises and round-trips the conformance vectors in [`conformance/`](conformance/). The test obligations are enumerated in [`spec/conformance.md`](spec/conformance.md): canonicality (C1), capability enforcement / deny-by-default (C2), per-device receipt integrity and provenance coupling (C3), attestation signing and verification (C4), tier-minimization (C5), durable run records (C6, §13), environment-manifest ingestion and addressing (C7, §14), content-addressed process control (C8, §5.5), warm-pool idle-energy accounting (C9, §15), and fleet merkle aggregation (C10, §16). A conforming host **MUST** pass the full pack with no skips for its advertised tiers.
|
||
|
||
---
|
||
|
||
## 11. Agent integration (MCP)
|
||
|
||
A host **MAY** expose the sandbox to agents over the **Model Context Protocol**. The distinguishing requirement is the tool **result**: a tool that runs a unit **MUST** return the run's attested, energy-metered receipt — the JCR-1 receipt, the attestation, and (RECOMMENDED) the EAT (§7.8) — not merely the program output. Agent-supplied code is untrusted and therefore minimizes to at least **S2** (§2.3). The tool input *is* the capability grant: a resource not named is not granted (deny-by-default, §5), and whatever is named is metered and attested. See [`spec/mcp.md`](spec/mcp.md); the reference `sandbox-mcp` implements it.
|
||
|
||
---
|
||
|
||
## 12. The attested build loop
|
||
|
||
A coding agent acts in many steps. A host that exposes a "build" capability **MUST** return a **build receipt**: a signed, content-addressed account of the whole build, with — per step — the content address of the unit that ran, the tier, the outcome, the joules it cost (§6), the attestation (§7), and the EAT (§7.8), each verified before it is recorded. The build's identity is `BLAKE3(intent ‖ each step's image id)`, so an identical build is identical by address (reproducibility). Receipts **MUST** chain into an append-only, tamper-evident **build ledger** (`prev` = the previous build's id). This is the verifiable, metered, reproducible account of how an artifact was built and what it costs to run — the record regulated use and energy-disclosure regimes require. See [`spec/build.md`](spec/build.md); the reference `sandbox-build` implements it and `sandbox-mcp` exposes it as the `build` tool.
|
||
|
||
## 13. Durable run records
|
||
|
||
Long-horizon work outlives the sandbox that started it. A host that suspends and resumes units **MUST** keep a **run record**: an append-only hash chain over the run's segments — executed intervals (by attestation address, §7), suspensions (by snapshot content addresses: filesystem root, optional memory image, environment manifest) and resumptions (same snapshot, plus the **idle energy** the retained state drew while parked). The genesis head binds `unit_id` and `grants_id`, so records cannot be spliced across units or grant sets. Resumption **MUST** be refused unless the offered snapshot is content-identical to the one recorded at suspension and the chain verifies from genesis. The run's total cost is its receipts' energy **plus** its idle energy — a parked run is not free, and a conformant host does not pretend it is. Conformance class **C6** exercises the chain, the refusals and the tamper-evidence. See [`spec/durable-runs.md`](spec/durable-runs.md); the reference `sandbox-attest::runrecord` implements it.
|
||
|
||
## 14. The environment manifest
|
||
|
||
A durable run is only the same run if it resumes into the same toolchain — checkable by hash, not asserted by trust. The **environment manifest** is one canonical, content-addressed object standing for the declared environment: base image (pinned by digest where honest claims require it), tool features, environment variables and mounts. Declarations are ingested from the open `devcontainer.json` format — its **declarative subset only**: fields that execute commands or widen the sandbox (`build`, the lifecycle `*Command` hooks, `privileged`, …) are refused, and unknown fields are refused rather than silently dropped. Networking fields are excluded from identity: the network surface belongs to the grant (§5). The manifest is JCS-canonicalized, BLAKE3-addressed, Ed25519-signed (§7.3 convention); `SnapshotRef.manifest` (§13) records it at suspension and resumption **MUST** be refused on a drifted address. Conformance class **C7**. See [`spec/environment-manifest.md`](spec/environment-manifest.md); the reference `sandbox-attest::manifest` implements it.
|
||
|
||
## 15. Warm pools
|
||
|
||
Pre-warmed environments make an agent's first action fast — the toolchain is already booted. Every platform that does this hides the same cost: a warm slot draws power while it waits, used or not. This standard does not hide it. A slot is warmed for one environment (its manifest address, §14) and accrues **idle microjoules**; a host that serves a run from a warm slot **MUST** attribute that accrued energy to the run, so a fast start carries a visible joule price. A slot evicted unclaimed **MUST** record its idle energy as pool **overhead** (attributed to the operator), never zero. A claim **MUST** match the slot's environment address — a run cannot be served a slot warmed for a different toolchain. Every microjoule the pool draws is accounted as claimed, overhead, or pending; a pool that reports only the energy of served runs does not conform. Conformance class **C9**. The reference `sandbox-attest::warmpool` implements it.
|
||
|
||
## 16. Fleet records
|
||
|
||
A single intent often fans out across many units — patch every repo, render every frame. Each item runs in its own bounded sandbox and produces its own receipt and attestation (§6, §7). A **fleet record** commits to the whole fan-out with one root: a merkle tree over the per-item `(item, attestation)` leaves, domain-separated so a node hash can never be taken for a leaf. The root is a single **aggregate receipt** — sign it once and the whole fan-out is sealed — and any one item's membership is provable against it with a logarithmic proof, without holding all N envelopes. A foreign item, or any change to a leaf, **MUST** fail to verify against the original root. Conformance class **C10**. The reference `sandbox-attest::fleet` implements it.
|