ADR-0003 — No lowest common denominator: capabilities + .native¶
Status: Accepted Date: 2026-09-19 Related: ADR-0001, ADR-0007
Context¶
apache-libcloud is the cautionary tale: a portable API narrowed to the intersection of all
providers, plus ex_-prefixed provider extensions that were undiscoverable and untyped.
Users who needed anything distinctive dropped to the raw SDK, and the abstraction became a
liability.
The distinctive features here are exactly the reasons people pick a backend: E2B's rich
interpreter outputs and PTY, Modal's GPUs, Volumes with per-tenant sub_path, memory
snapshots and tunnels, Daytona's LSP and git operations. An abstraction that hides them is
not worth installing.
Decision¶
We will never narrow the API to the common subset. Three mechanisms:
Capabilityflags. Every optional behaviour is a flag on the backend and on the sandbox. Callers branch onCapability.GPU in sb.capabilitiesrather than on backend name.CapabilityNotSupported, never a silent no-op. A typed argument a backend cannot honour raises. Accepting and ignoringnetwork=on a backend without network policy is the single worst thing this library could do — it turns a security control into a lie..nativeescape hatch. Every sandbox exposes the raw provider client or sandbox object. Nothing is hidden and nothing is wrapped for the sake of wrapping.
Capability honesty is testable: every declared flag must have a passing contract test, and every undeclared flag must raise. An adapter cannot claim a capability it does not have.
.native is explicitly outside the semver contract and must be documented as such at every
mention.
Consequences¶
- Portable code and native code are visibly different at the call site, which is the point.
- Users who reach for
.nativelose portability knowingly, and can come back when the capability is promoted into core. - Promotion rule: a feature moves from
.nativeinto the typed API once at least two backends support it stably. This is why pause/resume and snapshot/fork are deferred — E2B's is beta and Modal's model differs. - The
Capabilityflag set will grow. It is aFlagenum, so additions are backwards compatible; removals are breaking.