Reconcile: adopt initialization's consolidated HQ as canonical, re-home this session's new work #24
@@ -0,0 +1,115 @@
|
|||||||
|
---
|
||||||
|
topic: what runs on it
|
||||||
|
status: accepted
|
||||||
|
date: 2026-08-31
|
||||||
|
deciders: jochen
|
||||||
|
reconstructed: false
|
||||||
|
extends: 02-DECISIONS/0034-the-local-account-owns-the-mesh.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# 35. One implementation, several surfaces, and what that costs
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The mesh is operated from a command line today. It needs to be operable from a browser and from a
|
||||||
|
model's tools as well, and the three must not be three different systems.
|
||||||
|
|
||||||
|
**The pattern is already in the code and unnamed.** `board` serves HTTP by calling the same
|
||||||
|
functions the CLI calls; it holds nothing and decides nothing. What follows makes that the rule
|
||||||
|
rather than a property of one command.
|
||||||
|
|
||||||
|
**The board is a presentation layer over the control plane.** Not an application beside it holding
|
||||||
|
a database credential — the thing that shows what the control plane knows, and asks it to do what
|
||||||
|
a person asked for.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
**The logic lives once, in the context that owns it. A surface is an adapter with no decisions in
|
||||||
|
it.**
|
||||||
|
|
||||||
|
| surface | for |
|
||||||
|
|---|---|
|
||||||
|
| **command line** | a person on a machine, and the recovery path below |
|
||||||
|
| **HTTP** | the board, and anything else that speaks to the mesh over a network |
|
||||||
|
| **model tools** | an agent asking the mesh to do something |
|
||||||
|
|
||||||
|
**Every surface refuses identically, because the refusal is not in the surface.** An assignment
|
||||||
|
that cannot be satisfied is refused by the same resolution whichever way it arrived. The moment a
|
||||||
|
surface can accept something another would reject, the mesh has two answers to one question and
|
||||||
|
people learn which to trust.
|
||||||
|
|
||||||
|
**Reading and doing are both exposed.** The HTTP surface is not read-only: managing the mesh from
|
||||||
|
a browser is the point. This takes the decision
|
||||||
|
[ADR 0034](0034-the-local-account-owns-the-mesh.md) said had to be taken deliberately —
|
||||||
|
**a browser login now carries authority over the mesh** — and takes it knowingly rather than
|
||||||
|
letting it arrive with a feature.
|
||||||
|
|
||||||
|
**The networked surfaces authenticate through an OAuth2 identity provider.** Named by protocol
|
||||||
|
rather than by product, like every other dependency the mesh takes — AMQP for the bus, S3 for an
|
||||||
|
object store, OCI for the registry
|
||||||
|
([ADR 0006](0006-the-substrate-and-the-control-plane.md)). What fills the role today is a module
|
||||||
|
running Keycloak; what the control plane knows is that it validates a token against a provider
|
||||||
|
speaking OAuth2, and replacing that provider is a migration rather than a redesign.
|
||||||
|
|
||||||
|
**The command line does not authenticate at all**: it is already behind the machine's own login,
|
||||||
|
which is what owns the mesh (ADR 0034).
|
||||||
|
|
||||||
|
## What this is not: a kernel every module imports
|
||||||
|
|
||||||
|
**The shared library is the failure this project was started over**, and the difference has to be
|
||||||
|
stated or it will be rebuilt. The old one is 155 files and 34,636 lines *containing code from
|
||||||
|
every context* — work-domain logic sitting in the kernel every module imports, each piece landing
|
||||||
|
there to avoid a cycle between two modules that both needed it.
|
||||||
|
|
||||||
|
**Shared surfaces are not a shared library.** What is shared here is that three adapters call the
|
||||||
|
same functions. Those functions stay in the context that owns them — provisioning's logic in
|
||||||
|
provisioning, identity's in identity — and no module imports another's. A surface may call many
|
||||||
|
contexts; a context still may not reach into another's store
|
||||||
|
([ADR 0008](0008-a-context-owns-its-store.md)).
|
||||||
|
|
||||||
|
The test, when something is about to be put "somewhere shared": *does this belong to a context, or
|
||||||
|
does it only belong to the surface?* If it belongs to a context it goes there, even if two
|
||||||
|
surfaces want it.
|
||||||
|
|
||||||
|
## The loop this creates, and the way out
|
||||||
|
|
||||||
|
**The control plane's networked surfaces will depend on a module the control plane assigns.**
|
||||||
|
An identity provider is an ordinary module ([ADR 0031](0031-the-control-plane-authenticates-nobody.md)). When
|
||||||
|
it is down, or being migrated, or misconfigured, the HTTP and tool surfaces cannot authenticate
|
||||||
|
anybody — including the person trying to fix it.
|
||||||
|
|
||||||
|
**The command line is the way out, and it is why local ownership matters more rather than less.**
|
||||||
|
It authenticates through nothing, needs no network, and is available on the machine to the account
|
||||||
|
that owns the mesh. **A mesh must always be operable by somebody standing at it.**
|
||||||
|
|
||||||
|
So the rule: **no capability exists only behind an authenticated surface.** Anything the board can
|
||||||
|
do, the command line can do. That is not a courtesy to CLI users; it is the recovery path, and a
|
||||||
|
capability that exists only over HTTP is one that disappears exactly when identity does.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
**Identity is still not substrate**, and the test still answers no: the control plane runs, applies
|
||||||
|
declarations and reaches nodes with no identity provider in existence
|
||||||
|
([ADR 0033](0033-the-substrate-is-a-store-and-a-broker.md)). What is unavailable without it is two
|
||||||
|
surfaces, not the mesh.
|
||||||
|
|
||||||
|
**Whoever the identity provider admits has authority over the mesh.** That is now a real perimeter
|
||||||
|
with real consequences, where before it guarded a page that only read. Who may log in, and to
|
||||||
|
which realm, becomes a decision about the mesh rather than about an application.
|
||||||
|
|
||||||
|
**A surface must not grow an opinion.** The likely erosion is a validation added to the board
|
||||||
|
because it was quicker there — and then the CLI accepts something the board rejects, or worse the
|
||||||
|
reverse. Adapters hold no decisions.
|
||||||
|
|
||||||
|
**Three surfaces over one implementation is a cost paid three times if it is not one
|
||||||
|
implementation.** The reason to write this down now is that the second surface is the cheapest
|
||||||
|
moment to get it right, and the third is where the drift usually starts.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [ADR 0034](0034-the-local-account-owns-the-mesh.md) — the local account owns the mesh, and the
|
||||||
|
line this record deliberately crosses
|
||||||
|
- [ADR 0001](0001-mesh-brokers-nodes-host-agents-think.md) — the shared library this must not
|
||||||
|
become
|
||||||
|
- [ADR 0008](0008-a-context-owns-its-store.md) — a context owns its store, which a surface does
|
||||||
|
not change
|
||||||
@@ -105,6 +105,7 @@ python3 00-META/checks/index.py fail if stale
|
|||||||
- **0024** — [Model access is a provision, and a licence is a thing with a name](0024-model-access-is-a-provision.md)
|
- **0024** — [Model access is a provision, and a licence is a thing with a name](0024-model-access-is-a-provision.md)
|
||||||
- **0026** — [The mesh has a session of its own, and it is the node session's mechanism](0026-the-mesh-has-a-session-of-its-own.md)
|
- **0026** — [The mesh has a session of its own, and it is the node session's mechanism](0026-the-mesh-has-a-session-of-its-own.md)
|
||||||
- **0027** — [A provision names what the consumer is coupled to, not the role it plays](0027-a-provision-names-what-the-consumer-is-coupled-to.md)
|
- **0027** — [A provision names what the consumer is coupled to, not the role it plays](0027-a-provision-names-what-the-consumer-is-coupled-to.md)
|
||||||
|
- **0035** — [One implementation, several surfaces, and what that costs](0035-one-implementation-several-surfaces.md)
|
||||||
|
|
||||||
### How it is built
|
### How it is built
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user