|
|
|
@@ -0,0 +1,99 @@
|
|
|
|
|
---
|
|
|
|
|
status: accepted
|
|
|
|
|
date: 2026-08-26
|
|
|
|
|
deciders: jochen
|
|
|
|
|
reconstructed: false
|
|
|
|
|
extends: 0043-a-declaration-is-an-ordered-list-of-owned-resources.md
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# 47. The bundle may carry actions the link may not
|
|
|
|
|
|
|
|
|
|
## Context
|
|
|
|
|
|
|
|
|
|
[The substrate](../03-DESIGN/01-to-be/07-the-substrate.md) is raised in five steps, and steps two
|
|
|
|
|
and three happen before a mesh exists:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
1 the host applies the bundle the store runs; no mesh exists
|
|
|
|
|
2 a database is created in it before there is anything to ask
|
|
|
|
|
3 the control plane's schema applied a migration against that database
|
|
|
|
|
4 the control plane starts
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
That was recorded as *the sharpest unresolved thing in the bootstrap path*, on the grounds that
|
|
|
|
|
creating a database inside a running store is not state on a machine.
|
|
|
|
|
|
|
|
|
|
**That framing was wrong, and it was reading
|
|
|
|
|
[ADR 0043](0043-a-declaration-is-an-ordered-list-of-owned-resources.md) too narrowly.** *State
|
|
|
|
|
on this machine* does not mean the filesystem and the service manager. A service running on this
|
|
|
|
|
machine is part of this machine. Writing a file and creating a database in a local store differ
|
|
|
|
|
in mechanism, not in scope.
|
|
|
|
|
|
|
|
|
|
The real question was underneath: **must the host learn what a database is?**
|
|
|
|
|
|
|
|
|
|
## Considered options
|
|
|
|
|
|
|
|
|
|
1. **Give the host a `database` resource type.** Then tier 0 knows Postgres — and next a bucket,
|
|
|
|
|
a virtual host, a repository. The host acquires the substrate's vocabulary one service at a
|
|
|
|
|
time, which is what [ADR 0037](0037-the-host-applies-it-does-not-decide.md) exists to stop.
|
|
|
|
|
Rejected.
|
|
|
|
|
2. **Have the control plane do all provisioning, including the bootstrap.** Rejected because it
|
|
|
|
|
is not there yet: at step 2 the thing that would do the provisioning does not exist.
|
|
|
|
|
3. **The bundle declares an action; the host runs it and reads back.** Chosen.
|
|
|
|
|
|
|
|
|
|
## Decision
|
|
|
|
|
|
|
|
|
|
**The host runs actions the bundle declares, and never learns what they mean.**
|
|
|
|
|
|
|
|
|
|
A bundle step says *run this, against this, and here is how to tell whether it worked*. The host
|
|
|
|
|
executes it and verifies. What a database is stays knowledge of the module that provides one;
|
|
|
|
|
the host knows only how to run a declared action against something local and check the result.
|
|
|
|
|
|
|
|
|
|
**Actions are permitted in the bundle and forbidden over the link.**
|
|
|
|
|
|
|
|
|
|
[ADR 0039](0039-the-link-is-the-security-boundary.md) says what arrives over the link is
|
|
|
|
|
*declarations of known shape, never a command to run*. That stands, unchanged. The bundle is a
|
|
|
|
|
different trust path and the asymmetry is deliberate:
|
|
|
|
|
|
|
|
|
|
| | the bundle | the link |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| where it comes from | the installer somebody built and copied onto the machine | a remote party |
|
|
|
|
|
| when it is fixed | at build time, pinned and reviewable | at any moment |
|
|
|
|
|
| what compromise means | whoever built the installer, who also built the binary | a control plane, which may be compromised separately |
|
|
|
|
|
| may contain an action | **yes** | **no** |
|
|
|
|
|
|
|
|
|
|
The reasoning is that a bundle arrives *with* the binary. Anyone able to put a hostile action in
|
|
|
|
|
it could equally have put it in the host itself, so refusing actions there buys nothing while
|
|
|
|
|
costing the bootstrap. The link has no such property: it is a separate party, reachable
|
|
|
|
|
separately, and an action there is the unbounded blast radius ADR 0039 refuses.
|
|
|
|
|
|
|
|
|
|
**And ongoing provisioning is not the host's at all.** Once a mesh exists, a consumer on one
|
|
|
|
|
node granted a database on another is provisioned by the control plane. The host never performs
|
|
|
|
|
a provisioning action from the link, so the asymmetry costs it nothing.
|
|
|
|
|
|
|
|
|
|
## Consequences
|
|
|
|
|
|
|
|
|
|
- **There are two provisioning paths, and that is the answer rather than a problem.** The host
|
|
|
|
|
runs bootstrap actions locally from the bundle; the control plane provisions across the mesh
|
|
|
|
|
afterwards. The earlier worry — *one mechanism with a tier boundary inside it* — dissolves,
|
|
|
|
|
because they are two mechanisms with different actors, scopes and trust models.
|
|
|
|
|
- **The host's vocabulary grows by one shape, not one per service.** `action` joins `directory`,
|
|
|
|
|
`file` and `service`. Adding a substrate service does not add a host resource type.
|
|
|
|
|
- **An action must say how to verify itself.** A step that runs and reports success without a
|
|
|
|
|
read-back is the fault this project is about, and an action is the easiest place to reintroduce
|
|
|
|
|
it — so the verification is part of the declaration rather than left to the applier.
|
|
|
|
|
- **This is the escape hatch [research 011](../01-RESEARCH/011-the-module-graph/features.md)
|
|
|
|
|
warned about.** Arbitrary code, in the one place it is hardest to remove later. It is bounded
|
|
|
|
|
by being bundle-only and by requiring its own verification, and that boundary is the whole
|
|
|
|
|
defence — it should be watched rather than trusted.
|
|
|
|
|
- **The bundle becomes something a person must be able to read.** If it can run commands, the
|
|
|
|
|
reason to keep it small and pinned stops being convenience and becomes review.
|
|
|
|
|
|
|
|
|
|
## References
|
|
|
|
|
|
|
|
|
|
- [ADR 0043](0043-a-declaration-is-an-ordered-list-of-owned-resources.md) — what a declaration is.
|
|
|
|
|
- [ADR 0039](0039-the-link-is-the-security-boundary.md) — bounded by form, over the link.
|
|
|
|
|
- [ADR 0037](0037-the-host-applies-it-does-not-decide.md) — why the host must not learn a
|
|
|
|
|
service's vocabulary.
|
|
|
|
|
- [`07-the-substrate.md`](../03-DESIGN/01-to-be/07-the-substrate.md) — the bootstrap order this
|
|
|
|
|
unblocks.
|