Unify trunk on main: initialization → main #3
@@ -195,3 +195,29 @@ repository carries implementation and does not carry decisions.
|
||||
- `02-DECISIONS/0039-the-link-is-the-security-boundary.md` — a node owns no password
|
||||
- `02-DECISIONS/0041-the-host-depends-on-nothing.md` — why this is a static binary, and Go
|
||||
- `04-ISSUES/007-an-installed-package-is-not-a-capability` — why detection works this way
|
||||
|
||||
## Checks that cross into the control plane's repository
|
||||
|
||||
Two things are agreed between this repository and `novox/mesh-control`, and each is a separate
|
||||
struct on each side. A field renamed on one of them fails **silently** — the crossing succeeds and
|
||||
something is simply absent — so both are checked by handing one side's real output to the other's
|
||||
real parser. Neither runs by default; each skips with a reason, because a repository that fails
|
||||
without its neighbour checked out is a repository nobody can build.
|
||||
|
||||
**What the mesh sends, read by this host:**
|
||||
|
||||
```
|
||||
mesh-control: ./build/mesh-control plan <node> --json > /tmp/d.json
|
||||
mesh-host: MESH_EMITTED=/tmp/d.json go test ./internal/declaration/ -v
|
||||
```
|
||||
|
||||
**What this node says when it joins, read by the mesh:**
|
||||
|
||||
```
|
||||
mesh-host: MESH_ENROL_OUT=/tmp/enrol.json go test ./internal/link/
|
||||
mesh-control: MESH_ENROL=/tmp/enrol.json make check
|
||||
```
|
||||
|
||||
The second writes the private half of the sealing key beside the request, so the mesh's suite can
|
||||
prove that what it sealed is openable rather than merely present. A key that is correctly named
|
||||
and simply *wrong* passes every check that only looks at the message.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/novox/mesh-host/internal/identity"
|
||||
)
|
||||
|
||||
// What this node says when it joins, written out so the mesh's own suite can accept it.
|
||||
//
|
||||
// The two ends are separate structs in separate repositories. Every field here is one somebody
|
||||
// could rename on one side, and the failure would be silent: enrolment succeeds, a key is simply
|
||||
// absent, and the node looks joined until the first thing sealed to it cannot be opened. That is
|
||||
// exactly the shape of fault this project keeps finding late.
|
||||
//
|
||||
// Skipped unless MESH_ENROL_OUT names a file, so this is a check somebody runs deliberately
|
||||
// rather than a dependency between two repositories.
|
||||
func TestWhatThisNodeSaysWhenItJoins(t *testing.T) {
|
||||
path := os.Getenv("MESH_ENROL_OUT")
|
||||
if path == "" {
|
||||
t.Skip("set MESH_ENROL_OUT to write the enrolment request the mesh's suite reads")
|
||||
}
|
||||
|
||||
// A real one. Generated the way enrolment generates them rather than typed as literals, so a
|
||||
// key that stopped being a key would be caught here rather than travelling.
|
||||
mine, err := identity.Generate("workstation")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
overlay, err := identity.GenerateOverlayKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sealing, err := identity.GenerateSealingKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
request := EnrolRequest{
|
||||
Node: "workstation",
|
||||
Secret: "a-one-time-secret",
|
||||
PublicKey: mine.Public,
|
||||
OverlayKey: overlay.Public,
|
||||
SealingKey: sealing.Public,
|
||||
Profile: map[string]any{"seat": true},
|
||||
}
|
||||
body, err := json.MarshalIndent(request, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(path, append(body, '\n'), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// The private half of the sealing key goes beside it, so the mesh's suite can prove what it
|
||||
// sealed is openable rather than merely present.
|
||||
if err := os.WriteFile(path+".sealing-private", []byte(sealing.Private), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("wrote %s", path)
|
||||
}
|
||||
Reference in New Issue
Block a user