Files
mesh-controller/internal/inventory/busrecords_test.go
T

93 lines
4.0 KiB
Go

package inventory
import (
"strings"
"testing"
"github.com/novox/mesh-controller/internal/broker"
"github.com/novox/mesh-controller/internal/catalogue"
)
// Reading the bus's user list out of the mesh's records, against a real store.
//
// What each of these is about is a user that would be **missing or wrong in a way nothing reports**:
// the server reads whatever file it is given, and a module whose user is absent fails on its first
// publish with an authorisation error that says nothing about a missing assignment.
func theSeatDeclarer() catalogue.Manifest {
return catalogue.Manifest{
Module: "telegram", Version: "1",
DefinesSeats: []catalogue.SeatDeclaration{{
Name: "telegram-sender", Accepts: []string{"send"}, Emits: []string{"delivered"},
}},
Claims: []catalogue.Claim{{Name: "telegram-sender", Scope: catalogue.ScopeMesh}},
}
}
// A module assigned to a machine becomes a user with the authority its manifest declared — and the
// protocol of a seat declared by a *different* module, which is the whole reason a seat exists.
// A machine holding a live token gets an enrolment user; one whose token is spent or expired does
// not. **An enrolment user outliving its token is a right to join that nobody issued.**
// A module assigned and absent from the catalogue is refused rather than composed with no authority.
//
// **The catalogue refuses to forget an assigned module, so this is the second line and not the
// first** — and it earns its place there: relying on another package's invariant is how a rule ends
// up enforced by nothing. Checked against the derivation directly, because the situation cannot be
// reached through the store.
func TestAnAssignmentWithNoManifestDerivesNoAuthority(t *testing.T) {
// What BusRecords would have produced had it composed a ghost: a module with nothing declared.
users, err := broker.Users(broker.Records{
Nodes: []string{"one"},
Assigned: map[string][]broker.Declared{"one": {{Module: "ghost"}}},
})
if err != nil {
t.Fatal(err)
}
perms, err := broker.PermissionsFor(users[len(users)-1])
if err != nil {
t.Fatal(err)
}
// Its inbox and its ack subject, and nothing it could say. That is a module which starts,
// connects, and is refused by the server on its first publish — an authorisation error that
// says nothing about a missing manifest, which is why BusRecords names it instead.
for _, p := range perms.Publish {
if strings.HasPrefix(p, "mesh.mod.ghost.event.") {
t.Fatalf("a module with no manifest was granted %s", p)
}
}
}
func granted(all []string, one string) bool {
for _, s := range all {
if s == one {
return true
}
}
return false
}
// **A token is an account on the bus, or it is a string nothing accepts** (novox/hq 04-ISSUES/146).
//
// The composed list names an enrolment user for every machine with a live token, and nothing minted
// a credential for it — so the composer left it out as a user with no password, and every enrolment
// since the mesh moved to this bus was refused by the server before the mesh heard of it. Nothing
// caught it because nothing had enrolled since.
//
// The password cannot be minted, because it is the token's own secret: the machine will present
// exactly that string. So this checks the two halves that make the account usable — that a row
// exists under the name the composer asks for, and that the secret handed out is what that row
// accepts.
// The module holding mesh-broker is the bus, and its user is the bus's own: granted the snapshot API
// for the night's backup and nothing else, whatever tools it declares (novox/hq ADR 0235). Another
// module on the same machine is granted none of it.
// The bar's holder reads the state the modules beside it offer in its blocks (novox/hq ADR 0255),
// without naming them: granted on the machine where both are, and nowhere else.
// A module running the machine's provisioner client gives that machine a client account of its own, apart from the
// module's and the tool runner's (novox/hq ADR 0349 clause 11, design 57 P3); one with nowhere to read the account
// gives none.