diff --git a/go/delivery/verdicts.go b/go/delivery/verdicts.go index 15a6a9c..a747897 100644 --- a/go/delivery/verdicts.go +++ b/go/delivery/verdicts.go @@ -5,6 +5,8 @@ import ( "fmt" "slices" "time" + + "git.novox.be/novox/mesh-sdk/go/catalogue" ) // The verdicts on manifests (novox/hq ADR 0578 §1, §3): the indexer judges every manifest it takes in once, with its own @@ -28,6 +30,11 @@ const ( // raises it as a condition beside the indexer's finding. ManifestRefusedEvent = "manifest-refused" + // ManifestAcceptedEvent is the indexer's event saying a manifest that asks for bus state was accepted + // (ManifestAccepted), carrying its bus-state entries whole, so the bus module creates them without reading the + // indexer's state (novox/hq ADR 0595 §4, design 25 § 12.2). + ManifestAcceptedEvent = "manifest-accepted" + // ManifestOutgrown is the finding of a manifest the indexer accepted before and a stricter judge finds problems in // (novox/hq ADR 0579 §1): it stays accepted, its problems are the verdict's Warnings, and the watchman raises it as a // warning until the manifest is mended. @@ -154,3 +161,24 @@ type ManifestRefused struct { func RefusedOf(digest string, v ManifestVerdict) ManifestRefused { return ManifestRefused{V: Version, Module: v.Module, Digest: digest, Judge: v.Judge, Problems: v.Problems} } + +// ManifestAccepted is the body of the indexer's event ManifestAcceptedEvent: the module, the digest of its manifest, the +// judge, and every bus-state entry the manifest asks for, whole (novox/hq ADR 0595 §4). +type ManifestAccepted struct { + V int `json:"v"` + Module string `json:"module"` + Digest string `json:"digest"` + Judge string `json:"judge"` + BusState []catalogue.BusStateEntry `json:"bus-state"` +} + +// AcceptedOf is the event body saying v, the verdict accepting the manifest m of digest. +func AcceptedOf(digest string, v ManifestVerdict, m catalogue.Manifest) ManifestAccepted { + return ManifestAccepted{V: Version, Module: v.Module, Digest: digest, Judge: v.Judge, BusState: m.BusState} +} + +// EventID is the event's id, one per manifest digest and judge, so the bus takes it once: +// `manifest-accepted--`. +func (a ManifestAccepted) EventID() string { + return ManifestAcceptedEvent + "-" + a.Digest + "-" + a.Judge +} diff --git a/go/delivery/verdicts_test.go b/go/delivery/verdicts_test.go index da05519..ca6cf2f 100644 --- a/go/delivery/verdicts_test.go +++ b/go/delivery/verdicts_test.go @@ -1,9 +1,13 @@ package delivery import ( + "encoding/json" + "reflect" "strings" "testing" "time" + + "git.novox.be/novox/mesh-sdk/go/catalogue" ) // A verdict on a manifest round-trips, refuses what it cannot be, and a reader takes a missing one as accepted (novox/hq @@ -72,4 +76,28 @@ func TestAManifestVerdictIsTheContractReadersTake(t *testing.T) { if r, _ := TakeManifestVerdict(m.VerdictOf("x")); r || len(m.VerdictOf("x").Warnings) != 1 { t.Fatalf("an outgrown module: %+v", m.VerdictOf("x")) } + + // 1966/AC6: the accepted event of a manifest with two bus-state entries carries both whole, and its id is + // manifest-accepted--. + entries := []catalogue.BusStateEntry{ + {Name: "drafts", Storage: catalogue.StorageKeyValue, Template: catalogue.TemplateState, + Options: map[string]json.RawMessage{catalogue.OptionPastValues: json.RawMessage(`5`)}}, + {Name: "records", Storage: catalogue.StorageLedger, Template: catalogue.TemplateLedger, + Types: []catalogue.LedgerType{{Name: "decision", Operations: []catalogue.LedgerOperation{{Name: "submit", Effect: catalogue.EffectSetFields}}}}}, + } + digest := strings.Repeat("d", 64) + accepted := AcceptedOf(digest, ManifestVerdict{Module: "mesh-knowledge", State: VerdictAccepted, Judge: "src2:j"}, + catalogue.Manifest{Module: "mesh-knowledge", BusState: entries}) + raw, err := json.Marshal(accepted) + if err != nil { + t.Fatal(err) + } + var heard ManifestAccepted + if err := json.Unmarshal(raw, &heard); err != nil || heard.Module != "mesh-knowledge" || heard.Digest != digest || + heard.V != Version || !reflect.DeepEqual(heard.BusState, entries) { + t.Fatalf("the accepted event reads as %+v (%v)", heard, err) + } + if id := heard.EventID(); id != "manifest-accepted-"+digest+"-src2:j" { + t.Fatalf("the accepted event's id is %q", id) + } }