diff --git a/internal/composer/composer.go b/internal/composer/composer.go index efd4688..2d97b9a 100644 --- a/internal/composer/composer.go +++ b/internal/composer/composer.go @@ -13,6 +13,7 @@ import ( "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient" "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner" "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" + "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" "git.novox.be/novox/mesh-networking/modules/mesh-wireguard/go/overlay" "slices" "sort" @@ -20,6 +21,7 @@ import ( sdk "git.novox.be/novox/mesh-delivery/sdk/composer" "git.novox.be/novox/mesh-sdk/go/catalogue" + "git.novox.be/novox/mesh-sdk/go/keys" "git.novox.be/novox/mesh-sdk/go/sdkversion" "github.com/novox/mesh-host/internal/compose" @@ -105,7 +107,7 @@ func parse(m map[string]Manifest, reads map[string]ManifestRead, verdicts map[st if err != nil { read.Refused = fmt.Sprintf("the manifest of %s does not decode: %v", name, err) } else if raw, ok := verdicts[name]; ok { - v, verr := meshcatalogclient.DecodeVerdict(raw) + v, verr := caseVerdict(raw) if verr != nil { return nil, fmt.Errorf("composer: the verdict of %s is not one: %w", name, verr) } @@ -128,6 +130,28 @@ func parse(m map[string]Manifest, reads map[string]ManifestRead, verdicts map[st return out, nil } +// caseVerdict reads a verdict a case carries. It is not the indexer's kept value but the checker's account of it, made +// from the indexer's modules value: a checker of the trunk writes it with version 0 and no judge, one of the registry +// milestone with no version and no judge, and the composer of a group's head is asked by the checker that runs. So it is +// read in the kept value's form at version 0 (or none) and at keys.Version, its judge optional; a later version, a value +// that does not decode and a state no reader knows are refused, never taken as accepted. +func caseVerdict(raw json.RawMessage) (meshcatalog.VerdictsByDigestValue, error) { + var v meshcatalog.VerdictsByDigestValue + if err := json.Unmarshal(raw, &v); err != nil { + return v, fmt.Errorf("the value does not fit a verdict's shape: %w", err) + } + if v.V != 0 && v.V != keys.Version { + return v, fmt.Errorf("%w: the value is version %d, this reader reads 0 and %d", keys.ErrUnknownVersion, v.V, keys.Version) + } + switch v.State { + case meshcatalogclient.VerdictAccepted, meshcatalogclient.VerdictRefused, meshcatalogclient.VerdictManifestWaits: + default: + return v, fmt.Errorf("the state %q is none of %s, %s and %s", v.State, meshcatalogclient.VerdictAccepted, + meshcatalogclient.VerdictRefused, meshcatalogclient.VerdictManifestWaits) + } + return v, nil +} + func runCase(r Request, c Case, depth string) (CaseVerdict, error) { cv := CaseVerdict{Name: c.Name, Manifests: map[string]ManifestRead{}} shelf, err := parse(c.Manifests, cv.Manifests, c.Verdicts) diff --git a/internal/composer/composer_test.go b/internal/composer/composer_test.go index bd2e9d6..75cefeb 100644 --- a/internal/composer/composer_test.go +++ b/internal/composer/composer_test.go @@ -3,6 +3,7 @@ package composer import ( "context" "encoding/json" + "errors" "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner" "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" @@ -15,6 +16,7 @@ import ( "testing" "git.novox.be/novox/mesh-sdk/go/catalogue" + "git.novox.be/novox/mesh-sdk/go/keys" "github.com/novox/mesh-host/internal/compose" "github.com/novox/mesh-host/internal/compose/frombus" "github.com/novox/mesh-host/internal/compose/frombus/frombustest" @@ -262,4 +264,18 @@ func TestTheComposerTakesTheVerdictsOfItsInput(t *testing.T) { !strings.Contains(got.Refused, "the indexer's judge (src2:j) refused the manifest of xterm: falls back to a key not listed") { t.Fatalf("xterm refused by its verdict: %+v, want refused in the verdict's words", got) } + // The verdict as the trunk's checker hands it, version 0 and no judge (group try 1793952957648659842 failed on all + // four nodes: "the verdict of f1-circuits is not one: ... the value is version 0"), holds the module too; a later + // version is refused. + r.Cases[0].Verdicts = map[string]json.RawMessage{"xterm": json.RawMessage(`{"v":0,"module":"xterm","state":"refused","problems":["falls back to a key not listed"],"judge":"","at":"0001-01-01T00:00:00Z"}`)} + if v, err = Run(r); err != nil { + t.Fatalf("a version-0 verdict of the trunk's checker: %v", err) + } + if got := v.Cases[0].Manifests["xterm"]; got.Accepted || !strings.Contains(got.Refused, "refused the manifest of xterm: falls back") { + t.Fatalf("xterm refused by a version-0 verdict: %+v, want refused", got) + } + r.Cases[0].Verdicts["xterm"] = json.RawMessage(`{"v":2,"module":"xterm","state":"refused","problems":["p"]}`) + if _, err = Run(r); !errors.Is(err, keys.ErrUnknownVersion) { + t.Fatalf("a version-2 verdict: %v, want keys.ErrUnknownVersion", err) + } }