Reconcile: adopt initialization's consolidated HQ as canonical, re-home this session's new work #24
@@ -155,9 +155,13 @@ a file or a unit — and at bootstrap it is, at least, local: the store is on th
|
|||||||
the host applying the bundle.
|
the host applying the bundle.
|
||||||
|
|
||||||
Later it is not. A consumer on one node provisioned from a store on another is the ordinary
|
Later it is not. A consumer on one node provisioned from a store on another is the ordinary
|
||||||
case, and reaching it is not the host's job. So the same operation is local at bootstrap and
|
case, and reaching it is not the host's job.
|
||||||
remote afterwards, which is either two mechanisms or one mechanism with a boundary crossing in
|
|
||||||
it. Undecided, and it is the sharpest unresolved thing in this file.
|
**Resolved as two mechanisms, which is the answer rather than a compromise**
|
||||||
|
([ADR 0047](../../02-DECISIONS/0047-the-bundle-may-carry-actions-the-link-may-not.md)). The host
|
||||||
|
runs bootstrap actions locally from the bundle; the control plane provisions across the mesh
|
||||||
|
afterwards. Different actors, different scopes, different trust paths — so there is no single
|
||||||
|
operation with a tier boundary running through it.
|
||||||
|
|
||||||
## Several modules, one database — and the case for refusing
|
## Several modules, one database — and the case for refusing
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -93,16 +93,20 @@ The order, from [research 011](../../01-RESEARCH/011-the-module-graph/worked-pro
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Steps 2 and 3 happen before there is a mesh to do them**, which is why provisioning is part of
|
**Steps 2 and 3 happen before there is a mesh to do them**, which is why provisioning is part of
|
||||||
the bootstrap rather than a service consumers use later — and why the host's declaration
|
the bootstrap rather than a service consumers use later. They are **actions** the bundle
|
||||||
vocabulary has to reach further than files, directories and units.
|
declares and the host runs
|
||||||
|
([ADR 0047](../../02-DECISIONS/0047-the-bundle-may-carry-actions-the-link-may-not.md)) — so the
|
||||||
|
host's vocabulary grows by one shape rather than by one resource type per substrate service.
|
||||||
|
|
||||||
## Open
|
## Open
|
||||||
|
|
||||||
- **Whether identity is the fifth.** Above; it follows from a decision not yet taken.
|
- **Whether identity is the fifth.** Above; it follows from a decision not yet taken.
|
||||||
- **Whether the host can do step 2.** Creating a database inside a running store is not node
|
- ~~**Whether the host can do step 2.**~~ **Resolved** by
|
||||||
state, and [ADR 0043](../../02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md)
|
[ADR 0047](../../02-DECISIONS/0047-the-bundle-may-carry-actions-the-link-may-not.md). A service
|
||||||
has the host applying *state on this machine*. At bootstrap the store is on that machine, so it
|
running on this machine is part of this machine, so the scope was never in question — the real
|
||||||
is at least local. It is the sharpest unresolved thing in the bootstrap path.
|
question was whether the host must learn what a database is, and it must not. The bundle
|
||||||
|
declares an **action**; the host runs it and verifies it, and what a database means stays with
|
||||||
|
the module that provides one.
|
||||||
- **Whether one host can raise all four.** The claim under stage 2 of
|
- **Whether one host can raise all four.** The claim under stage 2 of
|
||||||
[the node host](05-the-node-host.md), never proved. If it is false, the tier boundary moves.
|
[the node host](05-the-node-host.md), never proved. If it is false, the tier boundary moves.
|
||||||
- **How the substrate is updated once a mesh exists.** Pinned by hand at bootstrap; afterwards
|
- **How the substrate is updated once a mesh exists.** Pinned by hand at bootstrap; afterwards
|
||||||
|
|||||||
Reference in New Issue
Block a user