Name system seats by scope; let a module define its own (ADR 0121)
System seats are mesh-* (one, mesh-wide) or node-* (one per node). Renamed: the-build-machine -> mesh-build-machine (+scope mesh), the-catalogue -> mesh-catalog, the-dns-port -> node-dns-resolver, the-intrusion-prevention -> node-intrusion-prevention, the-packet-filter -> node-packet-filter, the-resolver-configuration -> node-resolver-config, the-uplink -> node-uplink. Removed the-showcase from the set — it becomes the first module-defined seat. A manifest may declare its own seats (DefinesSeats); a claim is a system seat, a reserved mesh-*/node-* name the mesh does not define (refused), or a module-defined seat valid only when the manifest declares it. Deferred: the delivering registry seats (git, npm-package-registry, the-artifact-store) and the-private-network (a scope + server/client model change), per ADR 0121.
This commit is contained in:
+67
-24
@@ -37,23 +37,36 @@ var seats = []Seat{
|
||||
{Name: "mesh-store", Scope: ScopeMesh, Delivers: "postgres-database", Decision: "novox/hq ADR 0079"},
|
||||
{Name: "mesh-broker", Scope: ScopeMesh, Delivers: "amqp", Decision: "novox/hq ADR 0079"},
|
||||
{Name: "the-artifact-store", Scope: ScopeMesh, Delivers: "artifact-store", Decision: "novox/hq ADR 0075"},
|
||||
{Name: "the-catalogue", Scope: ScopeMesh, Decision: "novox/hq ADR 0110"},
|
||||
{Name: "mesh-catalog", Scope: ScopeMesh, Decision: "novox/hq ADR 0121"},
|
||||
// Deferred renames (novox/hq ADR 0121): these deliver a provision, so renaming them is a
|
||||
// delivering-seat migration with a mesh-wide cascade if a holder stops resolving mid-flight.
|
||||
// They keep their names until that migration is done deliberately, apart from the node-* pass.
|
||||
{Name: "npm-package-registry", Scope: ScopeMesh, Delivers: "npm-package-registry", Decision: "novox/hq ADR 0109"},
|
||||
{Name: "git", Scope: ScopeMesh, Delivers: "git", Decision: "novox/hq ADR 0111"},
|
||||
{Name: "the-build-machine", Scope: ScopeNode, Decision: "novox/hq ADR 0110"},
|
||||
{Name: "the-dns-port", Scope: ScopeNode, Decision: "novox/hq ADR 0110"},
|
||||
{Name: "the-intrusion-prevention", Scope: ScopeNode, Decision: "novox/hq ADR 0110"},
|
||||
{Name: "the-packet-filter", Scope: ScopeNode, Decision: "novox/hq ADR 0110"},
|
||||
{Name: "mesh-build-machine", Scope: ScopeMesh, Decision: "novox/hq ADR 0121"},
|
||||
{Name: "node-dns-resolver", Scope: ScopeNode, Decision: "novox/hq ADR 0121"},
|
||||
{Name: "node-intrusion-prevention", Scope: ScopeNode, Decision: "novox/hq ADR 0121"},
|
||||
{Name: "node-packet-filter", Scope: ScopeNode, Decision: "novox/hq ADR 0121"},
|
||||
// Deferred (novox/hq ADR 0121): renaming to mesh-private-network is a scope + server/client
|
||||
// model change, not a rename, so it stays until that is built.
|
||||
{Name: "the-private-network", Scope: ScopeNode, Decision: "novox/hq ADR 0110"},
|
||||
{Name: "the-resolver-configuration", Scope: ScopeNode, Decision: "novox/hq ADR 0110"},
|
||||
{Name: "the-showcase", Scope: ScopeNode, Decision: "novox/hq ADR 0110"},
|
||||
{Name: "node-resolver-config", Scope: ScopeNode, Decision: "novox/hq ADR 0121"},
|
||||
// The program that manages the machine's own network. It delivers nothing: its holder only
|
||||
// keeps the manager and the mesh from contradicting each other — the resolver file left to the
|
||||
// mesh, the private network's interface left alone — and never declares a link, an address or
|
||||
// a wireless network, because the link is the only channel a fix could arrive on. A seat
|
||||
// rather than a condition in the resolver's module, so a machine running two managers is
|
||||
// refused at assignment instead of found by the resolver being rewritten (novox/hq ADR 0117).
|
||||
{Name: "the-uplink", Scope: ScopeNode, Decision: "novox/hq ADR 0117"},
|
||||
{Name: "node-uplink", Scope: ScopeNode, Decision: "novox/hq ADR 0117"},
|
||||
}
|
||||
|
||||
// A system seat name is the control plane's namespace: `mesh-*` for a mesh-wide role, `node-*` for
|
||||
// a per-node one (novox/hq ADR 0121). A claim to a system name the mesh does not define is refused;
|
||||
// any other name is a module's own to define and claim. Some of the mesh's own seats predate this
|
||||
// convention and are not yet renamed (git, npm-package-registry, the-artifact-store,
|
||||
// the-private-network) — those are in the set, so they resolve by name, not by prefix.
|
||||
func isSystemSeatName(name string) bool {
|
||||
return strings.HasPrefix(name, "mesh-") || strings.HasPrefix(name, "node-")
|
||||
}
|
||||
|
||||
// Seats is every seat the mesh defines, in reading order.
|
||||
@@ -84,30 +97,60 @@ func SeatDelivering(provision string) (Seat, bool) {
|
||||
return Seat{}, false
|
||||
}
|
||||
|
||||
// claimProblems is what is wrong with a manifest's claims against the set.
|
||||
// claimProblems is what is wrong with a manifest's claims and the seats it defines.
|
||||
//
|
||||
// Three refusals, each naming the seat: a seat the mesh does not define, a seat claimed at another
|
||||
// scope, and a seat that delivers a provision claimed by a module that does not provide it — which
|
||||
// would make the module the mesh's answer for something it cannot answer.
|
||||
// A claim is one of three things (novox/hq ADR 0121): a **system seat** the control plane defines —
|
||||
// checked for scope and, if it delivers a provision, that the claimant provides it; a **system name
|
||||
// the mesh does not define** (`mesh-*`/`node-*`) — refused, because that namespace is the control
|
||||
// plane's; or a **module-defined seat** — valid only when this manifest also declares it, since a
|
||||
// module may coordinate its own instances through a seat of its own but may not invent one by
|
||||
// claiming it. A module's own seat declaration may not sit in the system namespace or shadow a
|
||||
// system seat.
|
||||
func claimProblems(m Manifest) []string {
|
||||
var problems []string
|
||||
for _, c := range m.Claims {
|
||||
seat, known := SeatNamed(c.Name)
|
||||
if !known {
|
||||
|
||||
defined := map[string]Claim{}
|
||||
for _, d := range m.DefinesSeats {
|
||||
if _, isSystem := SeatNamed(d.Name); isSystem || isSystemSeatName(d.Name) {
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%s claims %q, which is not a seat this mesh defines (novox/hq ADR 0110) — "+
|
||||
"the seats are: %s", m.Module, c.Name, seatNames()))
|
||||
"%s defines a seat %q in the mesh's own namespace; a module's seat is named outside "+
|
||||
"mesh-*/node-* (novox/hq ADR 0121)", m.Module, d.Name))
|
||||
continue
|
||||
}
|
||||
if c.At() != seat.Scope {
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%s claims %s at scope %q, and %s is a %s seat",
|
||||
m.Module, c.Name, c.At(), c.Name, seat.Scope))
|
||||
defined[d.Name] = d
|
||||
}
|
||||
|
||||
for _, c := range m.Claims {
|
||||
if seat, known := SeatNamed(c.Name); known {
|
||||
if c.At() != seat.Scope {
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%s claims %s at scope %q, and %s is a %s seat",
|
||||
m.Module, c.Name, c.At(), c.Name, seat.Scope))
|
||||
}
|
||||
if seat.Delivers != "" && !providesAt(m, seat.Delivers, seat.Scope) {
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%s claims %s, whose holder answers for %q, and %s does not provide %q at %s scope",
|
||||
m.Module, c.Name, seat.Delivers, m.Module, seat.Delivers, seat.Scope))
|
||||
}
|
||||
continue
|
||||
}
|
||||
if seat.Delivers != "" && !providesAt(m, seat.Delivers, seat.Scope) {
|
||||
if isSystemSeatName(c.Name) {
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%s claims %s, whose holder answers for %q, and %s does not provide %q at %s scope",
|
||||
m.Module, c.Name, seat.Delivers, m.Module, seat.Delivers, seat.Scope))
|
||||
"%s claims %q, which is a seat in the mesh's own namespace (mesh-*/node-*) that it "+
|
||||
"does not define (novox/hq ADR 0121) — the seats are: %s", m.Module, c.Name, seatNames()))
|
||||
continue
|
||||
}
|
||||
d, ours := defined[c.Name]
|
||||
if !ours {
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%s claims %q, which is not a seat this mesh defines and not one %s declares itself "+
|
||||
"(novox/hq ADR 0121) — the seats are: %s", m.Module, c.Name, m.Module, seatNames()))
|
||||
continue
|
||||
}
|
||||
if c.At() != d.At() {
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%s claims its own seat %s at scope %q, having declared it at %q",
|
||||
m.Module, c.Name, c.At(), d.At()))
|
||||
}
|
||||
}
|
||||
return problems
|
||||
|
||||
Reference in New Issue
Block a user