From 21fddffc6e3609b1b06025fad826eef19c5dfd63 Mon Sep 17 00:00:00 2001 From: jochen Date: Sat, 31 Oct 2026 09:23:56 +0100 Subject: [PATCH] Refuse a route received as a file, naming every module still on that path, since a route is a provision served from the seat's plans alone (issue 774, research 072 row 34) --- checks/credentialform/main.go | 26 ++++++++++++++++++++++++++ checks/credentialform/main_test.go | 15 ++++++++++----- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/checks/credentialform/main.go b/checks/credentialform/main.go index e5a15729..324175e3 100644 --- a/checks/credentialform/main.go +++ b/checks/credentialform/main.go @@ -1,6 +1,12 @@ // Package credentialform refuses an offer that does not say the form of its credential: an own secret, an issuer, or // `form` pair or none (the lead, 2026-10-29). It reads every modules/*/module.json through mesh-sdk's // CredentialFormProblems. +// +// It refuses a route received as a file too (issue 774, research 072 row 34, the operator on 2026-10-31: "there is only +// 1 path, the other is simply deprecated/invalid"): a route is a provision, served from the seat mesh-provisioner's +// plans alone, and a manifest's `receives.route` is the deprecated path. A module still moving off it is listed in +// stillReceivingRoutes with why; every refusal names them all, and a listed module that no longer receives one is +// refused too, so the list only shrinks. package credentialform import ( @@ -9,6 +15,7 @@ import ( "os" "path/filepath" "sort" + "strings" "git.novox.be/novox/mesh-sdk/go/catalogue" ) @@ -21,6 +28,7 @@ func Problems(root string) ([]string, error) { } sort.Strings(files) var out []string + var receiving []string reads := map[string]bool{} var binders []string for _, f := range files { @@ -33,6 +41,11 @@ func Problems(root string) ([]string, error) { return nil, fmt.Errorf("%s: %w", f, err) } out = append(out, catalogue.CredentialFormProblems(m)...) + if _, received := m.Receives["route"]; received { + receiving = append(receiving, m.Module) + } else if _, listed := stillReceivingRoutes[m.Module]; listed { + out = append(out, fmt.Sprintf("%s no longer receives route; take it off stillReceivingRoutes", m.Module)) + } var kept struct { Reads []string `json:"reads"` State []json.RawMessage `json:"state"` @@ -52,9 +65,22 @@ func Problems(root string) ([]string, error) { out = append(out, fmt.Sprintf("%s provides and keeps a `bound` state, and mesh-provisioner's manifest does not read %s.bound", module, module)) } } + for _, module := range receiving { + if _, listed := stillReceivingRoutes[module]; !listed { + out = append(out, fmt.Sprintf("%s receives route as a file: a route is a provision, served from the seat "+ + "mesh-provisioner's plans alone (issue 774); still on the deprecated path: %s", module, + strings.Join(receiving, ", "))) + } + } return out, nil } +// stillReceivingRoutes is every module still receiving its routes as a file, and why it has not moved yet. +var stillReceivingRoutes = map[string]string{ + "route-adapter": "migration scaffolding writing into a predecessor's proxy (novox/hq ADR 0104), deleted when that " + + "migration ends; it reads the received file its TypeScript adapter turns into the predecessor's route files", +} + // keepsBound says whether a manifest's `state` names `bound`, as a plain name or an object with a name. func keepsBound(state []json.RawMessage) bool { for _, s := range state { diff --git a/checks/credentialform/main_test.go b/checks/credentialform/main_test.go index 33c1c4f4..aebbb6b3 100644 --- a/checks/credentialform/main_test.go +++ b/checks/credentialform/main_test.go @@ -22,22 +22,27 @@ func aCatalogue(t *testing.T, manifests map[string]string) string { return root } -// An offer that says no form is refused and named; one that says pair, none or an own secret passes; and the real -// catalogue is clean. +// An offer that says no form is refused and named; one that says pair, none or an own secret passes; a route received +// as a file is refused but for the module still moving off it; and the real catalogue is clean. func TestEveryOfferSaysTheFormOfItsCredential(t *testing.T) { root := aCatalogue(t, map[string]string{ "silent": `{"module":"silent","provides":[{"name":"thing","scope":"mesh"}]}`, "binder": `{"module":"binder","provides":[{"name":"d","credential":{"form":"pair"}}],"state":["bound"]}`, "mesh-provisioner": `{"module":"mesh-provisioner","reads":["other.bound"]}`, "says": `{"module":"says","provides":[{"name":"a","credential":{"form":"pair"}},{"name":"b","credential":{"form":"none"}},{"name":"c","credential":{"own":"jwt"}}]}`, + // A route received as a file (issue 774, research 072 row 34): refused, naming every module still on it; the one + // listed as still moving passes. + "old-proxy": `{"module":"old-proxy","receives":{"route":"/var/lib/old-proxy/mesh.json"}}`, + "route-adapter": `{"module":"route-adapter","receives":{"route":"/var/lib/route-adapter/mesh.json"}}`, }) got, err := Problems(root) if err != nil { t.Fatal(err) } - if len(got) != 2 || !strings.Contains(got[0], `silent provides "thing"`) || - !strings.Contains(got[1], "binder") || !strings.Contains(got[1], "mesh-provisioner") { - t.Fatalf("refused %v, wanted the silent offer and the binder the provisioner does not read", got) + if len(got) != 3 || !strings.Contains(got[0], `silent provides "thing"`) || + !strings.Contains(got[1], "binder") || !strings.Contains(got[1], "mesh-provisioner") || + !strings.HasPrefix(got[2], "old-proxy receives route") || !strings.Contains(got[2], "old-proxy, route-adapter") { + t.Fatalf("refused %v, wanted the silent offer, the binder the provisioner does not read and the received route", got) } real, err := Problems(filepath.Join("..", "..")) if err != nil {