Novox Mesh, Nox, and HQ becomes company-scoped
ADR 0027 — the product is Novox Mesh, shortened to mesh internally. HAL was never chosen: it arrived with the dotfiles repository this grew out of, it is borrowed, and it is borrowed from the canonical untrustworthy machine intelligence, which is an odd flag for infrastructure trusted with credentials. Timing is the substance of the decision, not an aside — the skeleton is not built, so renaming costs a search and replace now and a migration later. Nox is an identity of Novox, and specifically the agent of the MESH rather than of a node. Nodes keep their own identities. Nox addresses them, and a human mostly talks to Nox — which makes it the concrete form of the mission's vision: state an intent, and the mesh works out which node holds the thing. It holds no private channel. The gap this opens is recorded: ADR 0012 binds every agent to a home node, and a mesh-scoped agent has none, so the model needs extending. ADR 0028 — HQ is company-scoped, novox/hq, with the mesh as its first product. Checked rather than assumed: the company organisation already holds live projects that the mesh builds and deploys, so they are tenants rather than peers, and the mesh is the ground they stand on. There is also company work outside the mesh already, which strengthens the case and means the eventual split is closer than "some day" — so each document's scope is fixed now, in a table, making that split mechanical instead of archaeological. The folders are deliberately not restructured yet. The skeleton takes the new vocabulary: mesh-host, mesh-substrate, mesh-control, mesh-surfaces, mesh-catalog. Substrate drops to four services now that identity is a hosted workload rather than a dependency. Research 009 opens the migration, with the reframing that lowers its risk: replace the control plane, do not move the workloads. Their data never moves, so it is re-declared rather than adopted — which keeps adoption out of scope, as the lab design requires. Self-hosting is the last phase, or a failed cutover takes away the means to fix it.
This commit is contained in:
@@ -31,7 +31,7 @@ Run the test. *Can the control plane exist without a relational store?* No. **Po
|
||||
tier 1.** It lives once:
|
||||
|
||||
```
|
||||
hal-substrate/store/postgres/
|
||||
mesh-substrate/store/postgres/
|
||||
```
|
||||
|
||||
There is no second copy in the catalogue, because the thing that differs between the mesh's own
|
||||
@@ -40,7 +40,7 @@ database and a project's database is **not the module**. It is how that instance
|
||||
| | The mesh's own instance | A project's database |
|
||||
|---|---|---|
|
||||
| Brought up by | the host, from the pinned bundle, with no control plane present | the ordinary delivery and provisioning path |
|
||||
| Declared in | `hal-substrate/bundle.yml` | the consuming module's `requires:` |
|
||||
| Declared in | `mesh-substrate/bundle.yml` | the consuming module's `requires:` |
|
||||
| Exists because | the control plane cannot start without it | something asked for it |
|
||||
|
||||
Same module, two roles. **Tier is a property of the module** — what must exist before what — and
|
||||
@@ -66,7 +66,7 @@ feels.
|
||||
## Becoming self-hosting — the forge and the registries
|
||||
|
||||
Self-improvement means the mesh hosts the things it improves itself with: a forge, an image
|
||||
registry, a package registry. The obvious worry is that these duplicate — a `hal-mesh-gitea`
|
||||
registry, a package registry. The obvious worry is that these duplicate — a `mesh-gitea`
|
||||
for the mesh and a `gitea` for everyone else. **They do not, and the reason is worth stating
|
||||
carefully, because it is the same reason the bootstrap keeps failing today.**
|
||||
|
||||
@@ -203,7 +203,7 @@ parts is not a module.
|
||||
Worked through for the substrate's relational store:
|
||||
|
||||
```
|
||||
hal-substrate/store/postgres/
|
||||
mesh-substrate/store/postgres/
|
||||
module.yml provides: database · profiles: [managed]
|
||||
parts/
|
||||
service/ the container, its volume, its network exposure
|
||||
@@ -215,7 +215,7 @@ hal-substrate/store/postgres/
|
||||
## The tree, at file level
|
||||
|
||||
```
|
||||
hal-host/ TIER 0
|
||||
mesh-host/ TIER 0
|
||||
cmd/host/
|
||||
internal/
|
||||
apply/ reconcile declared state
|
||||
@@ -230,14 +230,14 @@ hal-host/ TIER 0
|
||||
profile/ managed · user · edge
|
||||
substrate.lock pinned tier-1 descriptor
|
||||
|
||||
hal-substrate/ TIER 1
|
||||
mesh-substrate/ TIER 1
|
||||
bundle.yml the pinned set, by digest
|
||||
store/postgres/
|
||||
bus/<broker>/
|
||||
objects/<object-store>/
|
||||
images/<registry>/
|
||||
|
||||
hal-mesh/ TIER 2
|
||||
mesh-control/ TIER 2
|
||||
record/ the event log contexts integrate through
|
||||
inventory/ nodes · modules · assignments · versions
|
||||
config/ settings · secrets · derivation
|
||||
@@ -250,13 +250,13 @@ hal-mesh/ TIER 2
|
||||
knowledge/ memory · documents · retrieval
|
||||
api/ the one interface surfaces speak to
|
||||
|
||||
hal-surfaces/ TIER 3
|
||||
mesh-surfaces/ TIER 3
|
||||
tools/ web/ cli/
|
||||
|
||||
hal-catalog/ TIER 4
|
||||
mesh-catalog/ TIER 4
|
||||
<domain>/<module>/ layout as above
|
||||
|
||||
hal-lab/ hal-sdk/ hal-hq/
|
||||
mesh-lab/ mesh-sdk/ mesh-hq/
|
||||
```
|
||||
|
||||
## What this does not settle
|
||||
|
||||
@@ -20,8 +20,8 @@ bare machine
|
||||
│ one command lands ONE binary. Nothing else exists. TIER 0 host
|
||||
│
|
||||
│ it reads a pinned file it already carries and raises a
|
||||
│ database, a bus, an object store, a registry, an
|
||||
│ identity provider — locally, alone. TIER 1 substrate
|
||||
│ database, a bus, an object store and an image
|
||||
│ registry — locally, alone. TIER 1 substrate
|
||||
│
|
||||
│ on those, the mesh's brain starts: which nodes exist,
|
||||
│ what runs where, what is reachable. TIER 2 control plane
|
||||
@@ -46,7 +46,7 @@ A tier is not a repository and not a bounded context. Those are different cuts:
|
||||
## The tree
|
||||
|
||||
```
|
||||
hal-host/ TIER 0 — the only thing ever installed by hand
|
||||
mesh-host/ TIER 0 — the only thing ever installed by hand
|
||||
apply/ reconcile declared state on this machine
|
||||
inventory/ what this node is, has, and is capable of
|
||||
link/ the single outbound connection to the control plane
|
||||
@@ -54,15 +54,14 @@ hal-host/ TIER 0 — the only thing ever installed by hand
|
||||
profile/ capability detection: managed · user · edge
|
||||
substrate.lock pinned tier-1 descriptor, appliable with no mesh present
|
||||
|
||||
hal-substrate/ TIER 1 — declarations only, no logic of its own
|
||||
mesh-substrate/ TIER 1 — declarations only, no logic of its own
|
||||
store/ relational state
|
||||
bus/ commands and events
|
||||
objects/ blobs and build artifacts
|
||||
images/ container images
|
||||
identity/ the identity provider
|
||||
bundle.yml the pinned set tier 0 can raise alone
|
||||
|
||||
hal-mesh/ TIER 2 — the control plane
|
||||
mesh-control/ TIER 2 — the control plane
|
||||
record/ the event log every context integrates through
|
||||
inventory/ nodes · modules · assignments · versions
|
||||
config/ settings · secrets · derivation onto nodes
|
||||
@@ -75,17 +74,17 @@ hal-mesh/ TIER 2 — the control plane
|
||||
knowledge/ memory · documents · retrieval
|
||||
api/ the one interface every surface speaks to
|
||||
|
||||
hal-surfaces/ TIER 3 — thin; no logic lives here
|
||||
mesh-surfaces/ TIER 3 — thin; no logic lives here
|
||||
tools/ the agent-facing tool surface
|
||||
web/ the operator-facing interface
|
||||
cli/ the shell-facing interface
|
||||
|
||||
hal-catalog/ TIER 4 — what the mesh hosts
|
||||
mesh-catalog/ TIER 4 — what the mesh hosts
|
||||
<domain>/ grouped per ADR 0017, list per research 005
|
||||
|
||||
hal-lab/ the whole mesh, disposable, on one machine
|
||||
hal-sdk/ contracts shared across tiers — types, not behaviour
|
||||
hal-hq/ this repository
|
||||
mesh-lab/ the whole mesh, disposable, on one machine
|
||||
mesh-sdk/ contracts shared across tiers — types, not behaviour
|
||||
mesh-hq/ this repository
|
||||
```
|
||||
|
||||
## The dependency rule
|
||||
@@ -101,15 +100,15 @@ rule enforced by intention is the same as no tier rule — that is
|
||||
|
||||
## Move 1 — the substrate is applied, not delivered
|
||||
|
||||
**The problem.** The mesh needs a database, a bus, an object store, a registry and an identity
|
||||
provider. Today those are modules, and modules are installed by the delivery pipeline, which
|
||||
**The problem.** The mesh needs a database, a bus, an object store and an image registry.
|
||||
Today those are modules, and modules are installed by the delivery pipeline, which
|
||||
needs the database and the bus. The first node is therefore raised by a special script that
|
||||
exists only because of the circularity, and every later change to the substrate has to pretend
|
||||
the circularity is not there.
|
||||
|
||||
**The move.** The host can apply a declaration without anyone telling it to. The substrate is
|
||||
a **pinned bundle** the host carries: a fixed, versioned, self-contained descriptor of the
|
||||
five services and nothing else. Raising a first node is `host apply substrate.lock` — not a
|
||||
four services and nothing else. Raising a first node is `host apply substrate.lock` — not a
|
||||
special path, just the ordinary one with no control plane on the other end.
|
||||
|
||||
The circularity disappears rather than being worked around: **the substrate is applied by tier
|
||||
@@ -217,9 +216,10 @@ confusing.
|
||||
|
||||
Tiers 0–3 are the mesh. Tier 4 is everything it carries, and the boundary is stated by
|
||||
requirement rather than by taste: **a module is part of the mesh if removing it stops the mesh
|
||||
managing nodes.** A media server does not. An identity provider does — which is why identity
|
||||
sits in the substrate and not the catalogue, despite being, in every other respect, an
|
||||
application like any other.
|
||||
managing nodes.** A media server does not. A relational store does — which is why it sits in the
|
||||
substrate and not the catalogue, despite being, in every other respect, an application like any
|
||||
other. An identity provider, notably, does **not**: the control plane authenticates its own
|
||||
callers, so identity is a hosted service like the media server.
|
||||
|
||||
That test also settles the IT-company goal without a special category. Development, design and
|
||||
deployment tooling are **workloads** — tier 4, hosted, provisioned, delivered like anything
|
||||
@@ -261,7 +261,7 @@ being the one thing nobody exercises until it breaks.
|
||||
|
||||
## A naming near-miss, recorded
|
||||
|
||||
The tier-0 binary was first called `hal-agent`, because "node agent" is the reflex everywhere
|
||||
The tier-0 binary was first called `mesh-agent`, because "node agent" is the reflex everywhere
|
||||
else in the industry. That is wrong here, and wrong in the specific way
|
||||
[`how-we-build.md`](../../00-META/how-we-build.md) §4 exists to catch: **Agent** is a
|
||||
first-class concept in this mesh — a participant, some of whom are human, holding identity and
|
||||
@@ -273,8 +273,8 @@ pointing at infrastructure.
|
||||
|
||||
[ADR 0015](../../02-DECISIONS/0015-mesh-brokers-nodes-host-agents-think.md) supplies the fix in
|
||||
its own title — *the mesh brokers capabilities; nodes host; agents think.* Three verbs, three
|
||||
components: the control plane **brokers** (`hal-mesh`), the tier-0 binary **hosts**
|
||||
(`hal-host`), the participant **thinks** (`agents`, untouched).
|
||||
components: the control plane **brokers** (`mesh-control`), the tier-0 binary **hosts**
|
||||
(`mesh-host`), the participant **thinks** (`agents`, untouched).
|
||||
|
||||
`hal-node` was the alternative and was rejected: *Node* is the aggregate in the inventory — the
|
||||
`mesh-node` was the alternative and was rejected: *Node* is the aggregate in the inventory — the
|
||||
record of a machine — while the binary is what runs on it and does the hosting.
|
||||
|
||||
Reference in New Issue
Block a user