The ownership boundary
You own your application containers. Onebox owns everything else on the box.
You provide and administer the Linux host, SSH access, and Docker installation. Inside that boundary, the proxy, TLS, networks, release staging, supporting data services, schedules, locks, and the evidence needed to operate them are not your application, and therefore sit on Onebox’s side of the line.
That sentence is the direction, not an inventory. What is owned today is listed on Shipped vs proposed, and the gap between the two is stated rather than blurred.
Three consequences
Section titled “Three consequences”This is the organising principle behind everything else.
It is why the project file declares intent rather than describing containers. If Onebox owns the runtime, then describing the runtime is Onebox’s job, and asking you to do it as well would mean two descriptions that can disagree.
It is why Compose became a generated artifact. Compose was once an input Onebox read. Under this boundary, reading a file you wrote would mean you own the runtime and Onebox merely operates it — which is the opposite arrangement. See Why Compose is generated.
It is why a database is something you select rather than something you
configure. services: {postgres: 17} is sufficient because the image, port,
data path, health check and credential all sit on Onebox’s side of the line.
The boundary needs a name on it
Section titled “The boundary needs a name on it”“Onebox owns everything else on the box” is only meaningful if exactly one application is doing the owning. Two Onebox applications on one host would both believe they own the proxy, the shared network, the release store and the host lock — and the second one to converge would quietly undo the first.
So ownership is written down. ob bootstrap records the owning application and
the environment that claimed the host, and every mutating command reads that
record before it does anything. A different application is refused with
host_owner_mismatch.
Runtime resources carry the same boundary. Containers, volumes, and networks
created by Onebox have an onebox.app label, and preflight includes the application
default network (<app>_default) and service network (onebox_services) in its
collision set. Both networks are external to a release’s Compose lifecycle: a
release can be removed without deleting a network still used by an unmanaged
proxy or a supporting service. Networks created by older versions cannot be
labelled in place; Onebox accepts one only when its Compose project or durable
service state independently proves the same legacy owner. A matching name by
itself is never ownership evidence. Full destruction removes both external
networks before deleting that evidence and releasing host ownership. If Docker
reports a remaining endpoint, destruction stops and tells the operator to detach
it, leaving Onebox’s state available for a safe retry.
A different environment of the same application is refused too, with
host_environment_mismatch, and that refusal is the less obvious one. Every
runtime name Onebox derives — the Compose project, container names, volume
names — carries the application and not the environment, because one box runs
one application. Point staging at production’s server and nothing collides:
staging finds names that look like its own and adopts production’s containers
and volumes. The owner record is the only place that difference is visible,
which is why it records the environment.
A host claimed before environments were recorded carries the application alone.
That still identifies the owner, so it is honoured rather than refused; the next
ob bootstrap completes the record.
ob bootstrap is the one mutation that may claim an unowned host — that is what
it is for. Every other mutation requires the record to exist and to name this
application, so a mistyped target cannot silently adopt a machine by deploying
to it. ob preflight reads without claiming, and reports an unowned host as
ready rather than as a failure.
The check fails closed in both directions. An owner file that cannot be read is not treated as an absent one — “unowned” and “unreadable” would otherwise be the same answer, and the wrong one is destructive.
Full destruction releases the record, which is what makes a host reusable for a different application rather than permanently claimed. Partial destruction does not: while volumes or service credentials remain, the record stays, because every command is gated on it and releasing early would strand the owner outside their own data.
The boundary cuts both ways
Section titled “The boundary cuts both ways”If Onebox owns a supporting database, it must say exactly when that ownership includes recovery. A boundary that only ever expands is a marketing claim, not an engineering one.
PostgreSQL has an executable backup contract, but declaring it is only a
request. Protection begins after ob backup enable has installed the runtime,
enabled continuous archiving, and taken the first base backup. Workload volumes
are not covered, and every other durable driver refuses a backup policy rather
than accepting one it cannot honour. ob doctor reports every durable surface
that still has no off-host copy, because silence there would read as approval.
Where the line is not
Section titled “Where the line is not”Onebox owns the box, not the world:
- A customer with root can still bypass it.
- A compromised host can lie about its own evidence.
- Onebox does not claim universal reversibility, high availability, or protection from an adversarial infrastructure provider.
Those are limits of the arrangement, not gaps in it.
Supporting services and guarantee levels
Section titled “Supporting services and guarantee levels”Breadth and honesty are reconciled by making the guarantee level part of the contract and visible wherever the service appears. A service is either user-authored or Onebox-managed, never both.
Every durable driver runs pinned, persisted, health-gated, capped, observed, and
outside application rollback. PostgreSQL alone can add the executable recovery
contract today: continuous archiving, point-in-time restore, repository status,
and an on-demand recovery drill. Other drivers remain explicit about the missing
contract and refuse backup at validation.
The ordering is the point: a declaration is never presented as proof that protection is running. See Evidence, not declaration.