diff --git a/go/catalogue/amqp_is_not_a_provision_test.go b/go/catalogue/amqp_is_not_a_provision_test.go index 0b0191c..ed82b61 100644 --- a/go/catalogue/amqp_is_not_a_provision_test.go +++ b/go/catalogue/amqp_is_not_a_provision_test.go @@ -50,7 +50,9 @@ func TestNoCatalogueManifestNamesAmqp(t *testing.T) { fset := token.NewFileSet() files, _ := filepath.Glob("*.go") for _, f := range files { - if strings.HasSuffix(f, "_test.go") { + // kept_until_delivered.go keeps, deprecated, the names removed while running parts still use them; the second + // group removes it and this exemption together. + if strings.HasSuffix(f, "_test.go") || f == "kept_until_delivered.go" { continue } parsed, err := parser.ParseFile(fset, f, nil, 0) diff --git a/go/catalogue/kept_until_delivered.go b/go/catalogue/kept_until_delivered.go new file mode 100644 index 0000000..c5205e1 --- /dev/null +++ b/go/catalogue/kept_until_delivered.go @@ -0,0 +1,188 @@ +package catalogue + +// This file keeps, deprecated, the exported names feat/l3b-bus removed from this package while a running part still +// uses them: an exported name is removed only after every user of it is delivered. The checker builds the running +// node-engine's composer (mesh-host main) beside this mesh-sdk (ADR 0548 ยง6), and mesh-host main, mesh-delivery main +// (the indexer's judge, the assigner's and mesh-grants' code and tests) and mesh-tools main (node-tools' tests) name +// them. Nothing in L3's own heads uses any of them. The second group removes this file, and its exemption in +// TestNoCatalogueManifestNamesAmqp, once mesh-host a24a1d72 and L3's mesh-delivery and mesh-tools heads run. + +import ( + "fmt" + "slices" + "sort" + "strings" +) + +// Deprecated: kept until its users are delivered (the head of this file). +// +// EndedControllerName is the name the ended controller had, as its module and as its seat: no manifest may name it. +const EndedControllerName = "mesh-controller" + +// The kinds of a declaration that names the controller. +// +// Deprecated: kept until their users are delivered (the head of this file). +const ( + DependsRead = "read" + DependsInvoke = "invoke" + DependsConsume = "consume" + DependsUses = "uses" + DependsWaits = "waits" + DependsClaims = "claims" + DependsRequires = "requires" + DependsIs = "is" +) + +// Deprecated: kept until its users are delivered (the head of this file). +// +// Dependency is one declaration of a manifest that names the controller. +type Dependency struct { + Module string `json:"module"` + // By is the account declaring it when it is not the module's own: `process ` or `tools `. + By string `json:"by,omitempty"` + Kind string `json:"kind"` + What string `json:"what"` +} + +// onController says whether a name `.` is the controller's. +func onController(name string) bool { return strings.HasPrefix(name, EndedControllerName+".") } + +// invokesController says whether an invoke names a verb of the controller's seat or a tool of its module. `*` names none: +// it is the console's grant to every tool. +func invokesController(invoke string) bool { + if seat, _, ok := SeatInvoke(invoke); ok { + return seat == EndedControllerName + } + return onController(invoke) +} + +// Deprecated: kept until its users are delivered (the head of this file). +// +// Dependencies are every declaration naming the controller in the manifests given, by module. +func Dependencies(manifests map[string]Manifest) []Dependency { + var out []Dependency + add := func(module, by, kind, what string) { + if d := (Dependency{Module: module, By: by, Kind: kind, What: what}); !slices.Contains(out, d) { + out = append(out, d) + } + } + for name, m := range manifests { + if name == EndedControllerName || m.Module == EndedControllerName { + add(name, "", DependsIs, EndedControllerName) + } + for _, r := range m.Reads { + if onController(r) { + add(name, "", DependsRead, r) + } + } + for _, i := range m.Invokes { + if invokesController(i) { + add(name, "", DependsInvoke, i) + } + } + for _, c := range m.Consumes { + if onController(c) { + add(name, "", DependsConsume, c) + } + } + for _, w := range m.Waits { + if onController(w) { + add(name, "", DependsWaits, w) + } + } + for _, u := range m.Uses { + if u == EndedControllerName { + add(name, "", DependsUses, u) + } + } + for _, c := range m.Claims { + if c.Name == EndedControllerName { + add(name, "", DependsClaims, c.Name) + } + } + for _, r := range m.Requires { + if r == EndedControllerName || onController(r) { + add(name, "", DependsRequires, r) + } + } + for _, a := range m.BusAccounts() { + by := "process " + a.ID + if a.Tools { + by = "tools " + a.ID + } + for _, i := range a.Bus.Invokes { + if invokesController(i) { + add(name, by, DependsInvoke, i) + } + } + } + } + sort.Slice(out, func(i, j int) bool { + a, b := out[i], out[j] + if a.Module != b.Module { + return a.Module < b.Module + } + if a.Kind != b.Kind { + return a.Kind < b.Kind + } + if a.What != b.What { + return a.What < b.What + } + return a.By < b.By + }) + return out +} + +// Deprecated: kept until its users are delivered (the head of this file). +// +// ManifestRefusals is the check over a repository's manifests, by module name: one reason per declaration naming the +// controller, none when it passes. None given fails it, since nothing read can hide a declaration. +func ManifestRefusals(manifests map[string]Manifest) []string { + if len(manifests) == 0 { + return []string{"no manifest was read: with nothing read, nothing naming the controller can be judged absent"} + } + var out []string + for _, d := range Dependencies(manifests) { + who := d.Module + if d.By != "" { + who += " (" + d.By + ")" + } + out = append(out, fmt.Sprintf("%s declares %s %s: the controller ended by its unassignment and nothing may name it "+ + "(ADR 0590 clause 5)", who, d.Kind, d.What)) + } + return out +} + +// Deprecated: a manifest says it (Manifest.CoreCredentials, CarriesCoreCredentials); kept until its users are +// delivered (the head of this file). +// +// CoreCredentialModules are the modules whose own secrets are the core's credentials: the bus, mesh-provisioner and +// its client. +var CoreCredentialModules = []string{"mesh-provisioner", "mesh-provisioner-client", "nats"} + +// Deprecated: a manifest says it (Manifest.ToolRunner, IsToolRunner); kept until its users are delivered (the head +// of this file). +// +// RuntimeModule is the module that is the node's tool runtime. +const RuntimeModule = "node-tools" + +// Deprecated: the kept streams are the indexer's judge's; kept until its users are delivered (the head of this file). +// +// StreamsKeptUntilMoved are the streams declared before the check that a module keeps its data in the bus's +// predefined forms, each allowed by name until its module moves it. +var StreamsKeptUntilMoved = map[string][]string{ + "brother": {"device-asks"}, + "mesh-build-go": {"toolchains-go"}, + "mesh-build-node": {"toolchains-node"}, + "mesh-mail": {"mail", "mail-sends"}, + "only-office": {"convert-asks"}, + "mesh-delivery-assigner": {"placement"}, + "mesh-delivery-checker": {"checks"}, + "mesh-delivery-forge-bridge": {"forge"}, +} + +// Deprecated: nothing derives it now (DerivedUpgrade reads the bus's own manifest); kept until its users are +// delivered (the head of this file). +// +// FromBus is the source an older DerivedUpgrade gave the bus's policy. +const FromBus = "the bus"