From 3aca67b9d08dfca7423087aacc594a00b0b39722 Mon Sep 17 00:00:00 2001 From: jochens Date: Fri, 13 Nov 2026 01:03:49 +0100 Subject: [PATCH] V5 judge-process-bus-requires: a process's bus may name the events and states its module asks for in requires MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Builds: design 42 zfs-owns-zfs §25, §26, A-37, A-38 --- modules/mesh-delivery-indexer/judge/rules.go | 14 ++++++++++++++ .../mesh-delivery-indexer/judge/rules_test.go | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/modules/mesh-delivery-indexer/judge/rules.go b/modules/mesh-delivery-indexer/judge/rules.go index f390cb24..1b69c235 100644 --- a/modules/mesh-delivery-indexer/judge/rules.go +++ b/modules/mesh-delivery-indexer/judge/rules.go @@ -3998,6 +3998,20 @@ func ProcessBusProblems(m catalogue.Manifest) []string { for _, e := range m.EmitsAll() { emits[e] = true } + // What the module asks for in `requires` is its own as well (novox/hq ADR 0595 §1, §2): the events of an events stream + // by template, and a key-value state by template (design 42 zfs-owns-zfs, lead answer A-38). + for _, e := range m.BusState { + switch { + case e.Template == catalogue.TemplateEvents && e.Storage == catalogue.StorageStream: + var events []string + _ = json.Unmarshal(e.Options["events"], &events) + for _, ev := range events { + emits[ev] = true + } + case e.Template == catalogue.TemplateState && e.Storage == catalogue.StorageKeyValue: + state[e.Name] = true + } + } for _, r := range m.Resources { if fmt.Sprint(r["type"]) != "process" { continue diff --git a/modules/mesh-delivery-indexer/judge/rules_test.go b/modules/mesh-delivery-indexer/judge/rules_test.go index da9eefba..abc533d4 100644 --- a/modules/mesh-delivery-indexer/judge/rules_test.go +++ b/modules/mesh-delivery-indexer/judge/rules_test.go @@ -2455,6 +2455,24 @@ func caseAProcessBusNamesOnlyTheModulesOwn(t *testing.T) { t.Errorf("%s: %v; want a refusal naming %q", name, err, c.says) } } + // Design 42 zfs-owns-zfs, A-38 (V5): what the module asks for in `requires` by template is its own too, an event of + // its events stream and a state of its key-value state, and a name it does not ask for there is refused as before. + asked := func(bus string) string { + raw := mailSenderProcessManifest(t, bus) + return strings.Replace(raw, `"resources"`, `"requires":[{"name":"mail-events","storage":"stream","template":"events",`+ + `"options":{"events":["mail.send.queued"]}},{"name":"mail-kept","storage":"key-value","template":"state"}],"resources"`, 1) + } + for name, c := range map[string]struct{ bus, says string }{ + "an event of the events stream asked for": {`{"emits":["mail.send.queued"]}`, ""}, + "a state asked for by template": {`{"state":["mail-kept"]}`, ""}, + "an event the events stream does not hold": {`{"emits":["mail.send.lost"]}`, "mail.send.lost"}, + "a state the module does not ask for": {`{"state":["mail-other"]}`, "mail-other"}, + } { + _, err := ParseManifest([]byte(asked(c.bus))) + if (c.says == "") != (err == nil) || (err != nil && !strings.Contains(err.Error(), c.says)) { + t.Errorf("%s: %v; want a refusal naming %q", name, err, c.says) + } + } } // 1179/AC4: a bus declaring serves, holds, claims or a seat is refused naming the key; a bus with invokes of