ADR 0625 §3, ADR 0627 §4: mesh-sdk imports the seat set in catalogue alone, and names no client seat outside it

buscompose, delivery's builder and step asks, handacts, health and provisions take their seat names from catalogue.
The package-list test refuses any other contracts import, the client seats' names outside catalogue, and the moved
packages (asks, asker, publish) by name; what the group's join still moves (asks, asker, the vault module's name in
delivery and provisions) is listed and only shrinks.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 13:20:35 +01:00
parent de3af0cc65
commit d15c1bc814
9 changed files with 106 additions and 25 deletions
+2 -4
View File
@@ -1,6 +1,6 @@
package buscompose
import contractseats "git.novox.be/novox/mesh-contracts/go/seats"
import "git.novox.be/novox/mesh-sdk/go/catalogue"
// Declared is one module on one node, as composing its authority needs it.
type Declared struct {
@@ -104,6 +104,4 @@ type ProcessPrincipal struct {
}
// VaultSeat is the vault's seat: its holder alone asks the desks and the issuing providers in its own name.
//
// Deprecated: a whole seat's name is mesh-contracts' (seats.MeshVault); kept until its importers take it from there.
const VaultSeat = contractseats.MeshVault
const VaultSeat = catalogue.VaultSeat
+21 -2
View File
@@ -47,7 +47,7 @@ func isRegistryHost(component string) bool {
// through container-image-registry or oci-artifact-registry, whose blob it names the way the older form did.
func InArtifactStore(reference string) (path string, kept bool) {
if seat, rest, ok := InRegistrySeat(reference); ok {
if seat == contractseats.OciArtifactRegistry {
if seat == OciArtifactRegistrySeat {
name, digest, _ := strings.Cut(rest, "@")
return name + "/blobs/" + digest, true
}
@@ -58,7 +58,26 @@ func InArtifactStore(reference string) (path string, kept bool) {
// RegistrySeats are the seats a reference of the registry form names first, the two that front the artifact store
// (novox/hq ADR 0605 §1, §9).
var RegistrySeats = []string{contractseats.ContainerImageRegistry, contractseats.OciArtifactRegistry}
var RegistrySeats = []string{ContainerImageRegistrySeat, OciArtifactRegistrySeat}
// The four registry seats (novox/hq ADR 0605 §1), named here so the rest of mesh-sdk takes them from the seat set
// through catalogue alone (ADR 0625 §3).
const (
NpmPackageRegistrySeat = contractseats.NpmPackageRegistry
GoPackageRegistrySeat = contractseats.GoPackageRegistry
ContainerImageRegistrySeat = contractseats.ContainerImageRegistry
OciArtifactRegistrySeat = contractseats.OciArtifactRegistry
)
// PublishSeats are the seats an artifact is published through (ADR 0605 §1).
var PublishSeats = []string{NpmPackageRegistrySeat, GoPackageRegistrySeat, ContainerImageRegistrySeat, OciArtifactRegistrySeat}
// The seats of the vault, the provisioner, the hand acts' record and the conditions' keeper, as the seat set names them,
// for the rest of mesh-sdk (ADR 0625 §3).
const (
VaultSeat = contractseats.MeshVault
ProvisionerSeat = contractseats.MeshProvisioner
)
// InRegistrySeat reads a reference in the form a registry seat answers, `<seat>/<module>/<artifact>@sha256:<digest>`:
// the seat it came through and the rest. A seat's name holds no dot or port, so no image of an outside registry reads
+2 -3
View File
@@ -6,7 +6,6 @@ import (
"reflect"
"strings"
contractseats "git.novox.be/novox/mesh-contracts/go/seats"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
@@ -100,9 +99,9 @@ func (a BuiltArtifact) referenceProblem() string {
return ""
}
if seat, path, ok := catalogue.InRegistrySeat(r); ok {
want := contractseats.ContainerImageRegistry
want := catalogue.ContainerImageRegistrySeat
if a.Kind == "bundle" || a.Kind == "archive" {
want = contractseats.OciArtifactRegistry
want = catalogue.OciArtifactRegistrySeat
}
module, rest, _ := strings.Cut(path, "/")
if a.Kind == "package" || seat != want || module == "" || rest != a.Name+"@"+a.Digest {
+2 -3
View File
@@ -12,7 +12,7 @@ import (
"strings"
"time"
contractseats "git.novox.be/novox/mesh-contracts/go/seats"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// **Asks: a build or a check step is a message a build node pulls when it has a free slot** (novox/hq ADR 0525, as
@@ -466,8 +466,7 @@ func (c ComposeJob) check(id string) error {
}
// registrySeats are the seats an artifact is published through (ADR 0605 §1).
var registrySeats = []string{contractseats.NpmPackageRegistry, contractseats.GoPackageRegistry,
contractseats.ContainerImageRegistry, contractseats.OciArtifactRegistry}
var registrySeats = catalogue.PublishSeats
func (b BuildJob) check(id string) error {
if err := checkName("module", b.Module); err != nil {
+2 -2
View File
@@ -11,12 +11,12 @@ import (
"strings"
"time"
contractseats "git.novox.be/novox/mesh-contracts/go/seats"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// The seat, its holder and what it keeps (ADR 0565 clause 10).
const (
Seat = contractseats.MeshHandActs
Seat = catalogue.HandActsSeat
Module = "mesh-hand-acts"
// ActsLog is the log of every act, kept 400 days; WarrantsState one key `<asker>.<ask>` per warrant, made once.
ActsLog = "acts"
+3 -3
View File
@@ -11,7 +11,7 @@ import (
"strings"
"time"
contractseats "git.novox.be/novox/mesh-contracts/go/seats"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// The modules holding the four health seats, and the states between them, as `<module>_<state>` buckets.
@@ -274,6 +274,6 @@ type Would struct {
// KeeperSeat and the self-check's run as `checked` on SelfCheckSeat: the controller's events and the take-over key that
// chose between the two sources ended with it (novox/hq ADR 0590 clause 3).
const (
KeeperSeat = contractseats.MeshConditions
SelfCheckSeat = contractseats.MeshSelfCheck
KeeperSeat = catalogue.ConditionsSeat
SelfCheckSeat = catalogue.SelfCheckSeat
)
+67 -1
View File
@@ -29,6 +29,28 @@ var meshSDKPackages = []string{
"sdkversion", "seal", "seatdef", "testbus", "views",
}
// clientSeats are the seats whose logic is their client's in mesh-contracts (novox/hq ADR 0627 §1, §4): mesh-sdk names
// none of them outside catalogue, and holds no package over them.
var clientSeats = []string{contractseats.OperatorChannel, contractseats.MeshVault, "node-engine",
contractseats.NpmPackageRegistry, contractseats.GoPackageRegistry, contractseats.ContainerImageRegistry,
contractseats.OciArtifactRegistry}
// notInSDK are the packages that moved to a seat's client or contract (ADR 0627 §1, §4) and may not come back.
var notInSDK = []string{"asks", "asker", "publish"}
// untilTheJoin is what ADR 0627 still moves at the group's join, each `<file>: <what>`, naming what the checks below
// would refuse; it only shrinks, and is empty when the group is pinned: asks and asker are operator-channel's client
// (mesh-contracts go/clients/operatorchannelclient) once delivery's gate and assigner asks no longer hold the
// router's ask as asks.Ask; the vault module's name in delivery and provisions goes with the vault's client.
var untilTheJoin = []string{
"asks/asks.go: imports git.novox.be/novox/mesh-contracts/go/seats",
"asks/asks.go: Seat",
"asks: a package that moved",
"asker: a package that moved",
"delivery/signers.go: mesh-vault",
"provisions/provisions.go: mesh-vault",
}
// computesNot are the functions whose computation is one owner's alone (ADR 0593 §2, §7): the indexer computes a
// fingerprint, its named tree and a package's version; the node-engine composes.
var computesNot = []string{"SourceFingerprint", "SourceFingerprint2", "NamedTree", "MeshPackagesOf", "PackageVersionsOf",
@@ -55,7 +77,15 @@ func TestMeshSDKHoldsOnlyWhatEveryModuleShares(t *testing.T) {
}
return false
}
var seatNames []string
var seatNames, pending []string
clientNamed := func(v string) bool {
for _, seat := range clientSeats {
if v == seat || strings.HasPrefix(v, "mesh.seat."+seat+".") {
return true
}
}
return false
}
err := filepath.WalkDir(".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
@@ -78,11 +108,22 @@ func TestMeshSDKHoldsOnlyWhatEveryModuleShares(t *testing.T) {
return err
}
where := filepath.ToSlash(path) + ": "
inCatalogue := dir == "catalogue"
// ADR 0625 §3: mesh-sdk's only import of a contracts module is catalogue's of the seat set.
for _, imp := range file.Imports {
p, _ := strconv.Unquote(imp.Path.Value)
if strings.HasPrefix(p, "git.novox.be/novox/mesh-contracts/") && (!inCatalogue || p != contractsSeatSet) {
pending = append(pending, where+"imports "+p)
}
}
ast.Inspect(file, func(n ast.Node) bool {
switch n := n.(type) {
case *ast.BasicLit:
if v, err := strconv.Unquote(n.Value); err == nil && n.Kind == token.STRING && namesSeat(v) {
seatNames = append(seatNames, where+v)
if !inCatalogue && clientNamed(v) {
pending = append(pending, where+v)
}
}
case *ast.ValueSpec:
for i, name := range n.Names {
@@ -90,6 +131,10 @@ func TestMeshSDKHoldsOnlyWhatEveryModuleShares(t *testing.T) {
if sel, ok := n.Values[i].(*ast.SelectorExpr); ok {
if x, ok := sel.X.(*ast.Ident); ok && x.Name == "contractseats" {
seatNames = append(seatNames, where+name.Name)
if !inCatalogue && slices.Contains([]string{"OperatorChannel", "MeshVault", "NodeEngine",
"NpmPackageRegistry", "GoPackageRegistry", "ContainerImageRegistry", "OciArtifactRegistry"}, sel.Sel.Name) {
pending = append(pending, where+name.Name)
}
}
}
}
@@ -146,6 +191,24 @@ func TestMeshSDKHoldsOnlyWhatEveryModuleShares(t *testing.T) {
}
}
slices.Sort(found)
for _, dir := range found {
if slices.Contains(notInSDK, dir) {
pending = append(pending, dir+": a package that moved")
}
}
// ADR 0627 §4, ADR 0625 §3: no package over a client's seat, no client seat's name outside catalogue, no contracts
// import but the seat set's in catalogue; what the join still moves is untilTheJoin's.
for _, p := range pending {
if !slices.Contains(untilTheJoin, p) {
t.Errorf("%s: mesh-sdk holds no logic over a seat whose client is in mesh-contracts, names none of them outside "+
"catalogue, and imports no contracts module but the seat set in catalogue (ADR 0627, ADR 0625 §3)", p)
}
}
for _, k := range untilTheJoin {
if !slices.Contains(pending, k) {
t.Errorf("untilTheJoin keeps %q, which is gone: take it off the list", k)
}
}
for _, dir := range found {
if !slices.Contains(meshSDKPackages, dir) {
t.Errorf("mesh-sdk holds the package %s, which it does not keep (ADR 0593 §1): it is its owner module's package", dir)
@@ -230,5 +293,8 @@ func TestMeshSDKHoldsOnlyWhatEveryModuleShares(t *testing.T) {
}
}
// contractsSeatSet is the seat-set package of mesh-contracts, catalogue's one import of a contracts module.
const contractsSeatSet = "git.novox.be/novox/mesh-contracts/go/seats"
// sdkModule is mesh-sdk's Go module path.
const sdkModule = "git.novox.be/novox/mesh-sdk/go"
+1 -2
View File
@@ -13,13 +13,12 @@ import (
"strings"
"time"
contractseats "git.novox.be/novox/mesh-contracts/go/seats"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// The seat, its holder and its two states, and the names a reader declares in its `reads`.
const (
Seat = contractseats.MeshProvisioner
Seat = catalogue.ProvisionerSeat
Module = "mesh-provisioner"
ProvisionsState = "provisions"
PlansState = "plans"
+6 -5
View File
@@ -1,7 +1,12 @@
asks/asks.go: Seat
buscompose/health_grants.go: mesh.seat.mesh-self-check.event.
buscompose/users.go: VaultSeat
catalogue/artifact_sweep_seat.go: ArtifactSweepSeat
catalogue/artifacts.go: ContainerImageRegistrySeat
catalogue/artifacts.go: GoPackageRegistrySeat
catalogue/artifacts.go: NpmPackageRegistrySeat
catalogue/artifacts.go: OciArtifactRegistrySeat
catalogue/artifacts.go: ProvisionerSeat
catalogue/artifacts.go: VaultSeat
catalogue/catalog_seat.go: CatalogSeat
catalogue/checker_seat.go: CheckerSeat
catalogue/control_records_seats.go: HandActsSeat
@@ -48,14 +53,10 @@ delivery/provided.go: the-private-network
delivery/signers.go: mesh-vault
delivery/stepasks.go: node-build-node
handacts/handacts.go: mesh-hand-acts
handacts/handacts.go: Seat
health/findings.go: KeeperSeat
health/findings.go: mesh-conditions
health/findings.go: mesh-healers
health/findings.go: mesh-self-check
health/findings.go: SelfCheckSeat
internal/beside/beside.go: mesh-catalog
overlay/overlay.go: the-private-network
provisions/provisions.go: mesh-provisioner
provisions/provisions.go: mesh-vault
provisions/provisions.go: Seat