--- layer: to-be status: designed code: [] updated: 2026-08-30 decisions: - 02-DECISIONS/0008-a-context-owns-its-store.md - 02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md --- # A board **A place to see the mesh.** Read from a survey of the one that exists, so what is proposed here is a shorter list than what is there, deliberately. ## What the existing board does, and what of it belongs here Eight sections. Four are about work and workers and are held back with the rest of that domain; the other four are about the mesh itself. | | what it shows | where it stands here | |---|---|---| | **the mesh** | every node, what each runs, what each takes from another, module versions | **everything behind it exists** — it is a reader, not a second source | | **what is wrong** | machines not doing what they were told, machines not answering | **the page nobody had thought to ask for**, and the one a person opens first | | **builds** | a build, its stages, its log | **everything behind it exists** — every result is kept, failures included | | **sessions** | model sessions, their usage, and switching between accounts | [ADR 0024](../../02-DECISIONS/0024-model-access-is-a-provision.md) | | **channels** | nodes messaging each other | the agent layer | ## The constraint that matters, and it is not a feature **The existing board is one service that reads every context's database.** It joins nodes to provisions to modules to sessions by querying each store directly, because that is the shortest path to a page that shows all of them at once. That is [ADR 0008](../../02-DECISIONS/0008-a-context-owns-its-store.md) violated by the one component with a reason to violate it, and the cost is not hypothetical — it is the same cost the shared library has: **a boundary nothing may cross is a boundary that can move; one thing crossing it is enough to freeze it.** A board that reads the provisioning tables directly is a board that breaks when provisioning changes its tables, and the change then gets weighed against the board. **So a board reads through interfaces and holds nothing.** Everything on the mesh page above is already answerable by asking the control plane — what nodes exist, what each resolves to, what it takes from elsewhere, which module came from which commit. A board that asks those questions is a client. A board that queries `inventory` is a second control plane with a worse contract. **It stores nothing of its own.** No cache that can disagree, no table of "what the mesh looked like last time". If a question is slow to answer, the answer belongs in the context that owns it, where everything else asking gets it too. ## What it is not - **Not the way to change things.** Reading is the whole of it to begin with. Every action the board could offer already exists as a command, and a button that does something no command does is a second implementation of a decision. - **Not a dashboard of graphs.** What a person needs from a mesh is *which machine is not doing what it was told*, and that is a list, not a chart. ## The three questions, in order Written down because the order is the design. A person opens this when something is wrong, and a page that led with the third would bury the first: 1. **Is anything broken?** A machine whose last declaration was refused or partly failed. It has consequences now. 2. **Is anything not answering?** A machine not heard from. It may be new, switched off or unreachable — **which is not the same as tried and could not**, and collapsing the two sends somebody to debug a machine that was never sent anything. 3. **Is anything out of date?** A module behind its source, and the machines running the old one. A plan for later rather than a problem now. **Refused and failed stay distinct all the way to the page.** Refused means the machine is exactly as it was and what is wrong is in what was sent; failed means it is in a state nobody declared and what is wrong is on the machine. They are fixed in different places, so a page that said "error" for both would send half its readers to the wrong one.