diff --git a/01-RESEARCH/012-the-minimum-viable-node/00-overview.md b/01-RESEARCH/012-the-minimum-viable-node/00-overview.md new file mode 100644 index 0000000..1f04e1e --- /dev/null +++ b/01-RESEARCH/012-the-minimum-viable-node/00-overview.md @@ -0,0 +1,92 @@ +--- +status: active +initiated: 2026-08-26 +touches: + - 02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md + - 02-DECISIONS/0004-managed-files-are-generated-never-edited.md + - 03-DESIGN/01-to-be/05-the-node-host.md + - 03-DESIGN/00-as-is/05-runtime-and-installation.md + - 01-RESEARCH/011-the-module-graph/00-overview.md +--- + +# 012 — The minimum viable node, and adopting what is already there + +## What is being investigated + +Two questions that turn out to be one: + +**What is the bare minimum to run a one-node mesh?** Not the tiers as asserted, but the actual +closure — take the thing that must run, walk what it needs, and the set that comes back is the +answer. + +**And how does a machine that is already in use become that?** A candidate node is not empty. It +has a package manager, probably a container runtime, possibly a git installation, each with +configuration somebody chose. The mesh must **own** those, and owning is not the same as finding +them present. + +## Why + +Building tier 0 reached a wall that looked like a packaging problem and is not. + +The host can be told to run a container or install a package. Both need a file — an image, an +archive — and the question was where the host gets it. That framing produced a bad trilemma: +carry everything in the bundle, download at apply time, or have something push the files in +first. Downloading fails on the first node, which cannot fetch the image registry from the image +registry it is trying to start. + +**The reframing:** the machine is not offline. What matters is *when* the fetching happens. Move +it from apply time to **build time** — build the installer on a machine that has a network, +tailored to the target, and apply it on a target that then needs nothing. That is the same move +the lab already made for its router image, and the same property the delivery design already +claims: what ships is self-contained and a deploy touches no network. + +Which makes the interesting question not *where do artifacts come from* but **what is missing +from this particular machine**, and that needs both of the questions above answered. + +## What tailoring implies + +- **The binary stays generic; the payload is tailored.** One static host per architecture. What + is machine-specific is the bundle it applies. Rebuilding the host per machine would buy + nothing. +- **Detection is the input, not a report.** What the host already reports about a machine — + its profile and inventory — is what the difference is computed against. This is the first use + of stage 1 by something other than a person reading it. + +## Adoption + +**Simply having a package installed is not enough.** If the mesh manages the container runtime, +it decides that runtime's configuration; a runtime found already installed carries settings +somebody chose, and those cannot be discovered by noticing the binary exists. + +So a machine already in use is **adopted**: what is there is read, taken over, and thereafter +generated. + +**This was the original path.** [`00-as-is/05`](../../03-DESIGN/00-as-is/05-runtime-and-installation.md) +records adoption of a pre-existing machine's configuration as the original mechanism, since made +legacy and explicitly out of scope for the lab. It returns here for a different reason than it +was dropped for, which is a thing to notice rather than to gloss. + +**It creates a state that does not exist today.** [ADR 0004](../../02-DECISIONS/0004-managed-files-are-generated-never-edited.md) +has managed files generated and never edited; adoption needs a one-time import before that rule +starts applying. Three states, and the middle one is new: + +> unmanaged → **adopted once** → generated + +**And it crosses a boundary just drawn.** [ADR 0043](../../02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md) +says the host never touches what it did not create — the rule that stops a converger deleting +what the mesh never put there. Adoption is the deliberate act of taking ownership of exactly +that. The rule needs a companion rather than an exception: *never, unless adoption made it the +host's*, with adoption being explicit, recorded, and visible in what the host says it owns. + +## Open questions + +| Question | Why it is open | +|---|---| +| What is the closure for a one-node mesh? | The skeleton asserts four pinned services. [Research 006](../006-mesh-from-scratch/00-overview.md) already asks whether it is four or five and does not answer. A graph gives a computed answer instead of an asserted one, which is [research 011](../011-the-module-graph/00-overview.md). | +| Is "tier" the same thing as a graph level? | Tiers were named as a bootstrap order. If the closure is computed, tiers may be a derived view of the graph rather than a separate concept — or they may be a coarser boundary that survives for a different reason. | +| What happens when existing configuration contradicts what the mesh needs? | A runtime configured one way and a mesh wanting another. Silently winning in either direction is wrong; refusing may make a machine unadoptable. | +| Is adoption reversible? | If the configuration that was there is not recoverable, adoption is a one-way door on a machine somebody was already using. | +| Does owning a package mean owning its version? | Owning configuration and owning the package are different scopes. The second means the mesh decides which version is installed, and that decision then has to survive the machine's own package manager updating it. | +| How does a bundle stay true between building and applying? | It is built against a scan of the target. The machine can move between the scan and the apply, so the host has to verify rather than assume — and fail plainly when the bundle no longer fits. | +| What cannot be precomputed at all? | Anything built from source on the target still needs a toolchain and a network at that moment. Tailoring moves that cost rather than removing it, and *minimal viable* has to be honest about what it cannot ship ahead. | +| Does presence differencing understate the gap? | Knowing a package manager is installed does not say it is the version the mesh needs. A difference computed on presence alone is optimistic. |