A daemon says what to run, not how it is hosted
The mechanism was leaking into every module. Code of one's own meant a container and therefore an image; a script meant a service and a unit somebody else had to install. One intent — run this and keep it running — expressed two unrelated ways, with the hosting chosen before anything could be declared. A daemon names a bundle and a command. The host fetches it, refuses it unless it hashes to what was declared, unpacks it where the mesh keeps such things, writes the unit and puts it in the state asked for. The unit is the mesh's, generated whole and saying so, because an edit that survives until the next declaration and then vanishes is worse than one that is refused. Its identity is the bytes AND how it is run: two daemons from one bundle differing only in their command are different daemons, and tracking the digest alone would call the second unchanged and leave the first running. The unit is rendered deterministically for the same reason — environment from a map would be written in Go's iteration order, so every apply would see a different unit and restart an unchanged daemon for ever. restart-on is honoured as a service's is: a running process does not re-read its configuration, so replacing a file and finding the daemon already up leaves the machine behaving as before while every check passes. A full-host shape, not a portable one: it needs a process supervisor to install into. It does NOT need a container runtime, which is the point. Two guards caught this properly and both were updated deliberately rather than silenced: the vocabulary count, which exists because every addition widens what a compromised control plane can express, and the shape test that catches a kind the language has and a host cannot apply — added after `network` did exactly that. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
This commit is contained in:
@@ -266,7 +266,7 @@ func TestAFieldTheNewTypesDoNotUseIsRefused(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTheVocabularyIsTheEightShapesTheMeshNeeds(t *testing.T) {
|
||||
func TestTheVocabularyIsTheElevenShapesTheMeshNeeds(t *testing.T) {
|
||||
// Six of them the bootstrap uses (novox/hq 07-the-substrate.md), and removing one is a
|
||||
// failing test rather than a discovery during a first-node install.
|
||||
//
|
||||
@@ -282,7 +282,7 @@ func TestTheVocabularyIsTheEightShapesTheMeshNeeds(t *testing.T) {
|
||||
}
|
||||
for _, want := range []Type{
|
||||
TypeDirectory, TypeFile, TypeService, TypePackage, TypeContainer, TypeAction,
|
||||
TypeUser, TypeArchive, TypeNetwork, TypeAccess,
|
||||
TypeUser, TypeArchive, TypeNetwork, TypeAccess, TypeDaemon,
|
||||
} {
|
||||
if !speaks[want] {
|
||||
t.Errorf("the host no longer speaks %q", want)
|
||||
@@ -298,8 +298,19 @@ func TestTheVocabularyIsTheEightShapesTheMeshNeeds(t *testing.T) {
|
||||
// `access` is the tenth, and novox/hq ADR 0051 is its decision: shared, pre-existing data is
|
||||
// the operator's, and a module is granted use of it without owning it — a shape the host must
|
||||
// tell apart from a directory precisely because it must NOT create, chown or remove it.
|
||||
if len(speaks) != 10 {
|
||||
t.Errorf("the vocabulary is %d shapes rather than 10; every addition widens what a compromised "+
|
||||
//
|
||||
// `daemon` is the eleventh, and it exists because the mechanism was leaking into every module.
|
||||
// Running code of one's own meant a `container` and therefore an image; running a script meant
|
||||
// a `service` and a unit somebody else had to install. One intent — run this and keep it
|
||||
// running — expressed two unrelated ways, with the hosting chosen before anything could be
|
||||
// declared. A daemon says what to run; the machine's own supervisor is how, and the mesh owns
|
||||
// the unit because it is the mesh's own code (novox/hq 03-DESIGN/01-to-be/18-building-a-module.md).
|
||||
//
|
||||
// It is a full-host shape rather than a portable one: it needs a process supervisor to install
|
||||
// into. It does NOT need a container runtime, which is the point — only software that
|
||||
// genuinely needs isolation asks for a container.
|
||||
if len(speaks) != 11 {
|
||||
t.Errorf("the vocabulary is %d shapes rather than 11; every addition widens what a compromised "+
|
||||
"control plane can express, so a change here is a decision: %s",
|
||||
len(speaks), vocabulary())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user