J4 (lead's item): the packages state's series value is a contract its readers take, not the indexer's own type

delivery.SeriesPackage and SeriesVersion, field for field as the indexer writes them (name, the ecosystem name;
package, <module>/<artifact>), with SeriesPackageKey, IsSeriesPackageKey and a checked encode and decode.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 14:54:33 +01:00
parent 28ce325c2e
commit 09cf1ea6fc
2 changed files with 133 additions and 0 deletions
+28
View File
@@ -56,6 +56,34 @@ func TestPublishedPackagesAndImportsRoundTripAndRefuse(t *testing.T) {
}
}
// The indexer's series value (design 51 *The versions*), as the indexer writes it: read back whole, and refused
// where a reader could not take it.
written := `{"v":1,"name":"` + sdk + `","package":"mesh-sdk/go","series":"0.1","seat":"go-package-registry","go-module":"` + sdk +
`","newest":{"version":"0.1.15","commit":"` + commit + `","digest":"sha256:0f","fingerprint":"fp1","contents":` + string(raw) +
`},"numbered":{"version":"0.1.16","commit":"` + commit + `"},"at":"2026-11-04T14:00:00Z"}`
series, err := DecodeSeriesPackage([]byte(written))
if err != nil || series.Name != sdk || series.Package != "mesh-sdk/go" || series.Newest.Contents == nil || series.Numbered.Version != "0.1.16" {
t.Fatalf("a series value as the indexer writes it reads %+v, %v", series, err)
}
if again, err := EncodeSeriesPackage(series); err != nil || string(again) != written {
t.Fatalf("a series value writes back as\n%s, %v, not\n%s", again, err, written)
}
if key := SeriesPackageKey(sdk, "0.1"); key != "git=2enovox=2ebe/novox/mesh-sdk/go.0.1" || !IsSeriesPackageKey(key) || IsSeriesPackageKey(EscapeName(sdk)) {
t.Fatalf("the series key %q is not told apart from a per-module key", key)
}
for name, mutate := range map[string]func(s *SeriesPackage){
"a series with no name": func(s *SeriesPackage) { s.Name = "" },
"a series that is no series": func(s *SeriesPackage) { s.Series = "0.1.15" },
"built from no artifact": func(s *SeriesPackage) { s.Package = "mesh-sdk" },
"a numbered version of nothing": func(s *SeriesPackage) { s.Numbered = &SeriesVersion{} },
} {
s := series
mutate(&s)
if _, err := EncodeSeriesPackage(s); err == nil {
t.Errorf("%s: encoded", name)
}
}
imports := []string{sdk, sdk + "/announce"}
outOfStep := []string{"go/seats/meshbroker/contract.go", "ts/seats/meshbroker/src/index.ts"}
end := BuildLogEntry{Event: BuildEndedEvent, Module: "netcheck", FP: "src2:x", Repository: "novox/mesh-catalog", Commit: commit,
+105
View File
@@ -0,0 +1,105 @@
package delivery
import (
"encoding/json"
"fmt"
"regexp"
"strings"
"time"
)
// The packages state per series (design 51 *The versions*, design 32; ADR 0606 §1, ADR 0609 §1): beside the per-module
// values (PublishedPackages), the indexer keeps one key per package and series, `<name>.<series>` (SeriesPackageKey),
// holding the newest trunk version of that series the builder numbered and the newest a registry seat published. The
// indexer alone writes it; its readers (the builder, the checker, the build modules) take this value's form from here.
// A series key always holds a dot, which EscapeName never leaves in a per-module key (IsSeriesPackageKey).
// SeriesPackage is the value of a series key. Name is the package's name in its own ecosystem (a Go package's module
// path in its go.mod at the commit, an npm package's package.json name): the key is named by it, and a user's
// `packages` names it. Package is the module and artifact it is built from, `<module>/<artifact>`, by which the builder
// finds the name to number under; Series its `<major>.<minor>`. Seat is the registry seat it is published through;
// GoModule the Go module path a Go package is fetched under, empty for any other. Newest is the newest version of the
// series a seat published (what a user accepting the series builds against), Numbered the newest the builder numbered,
// published or not yet.
type SeriesPackage struct {
V int `json:"v"`
Name string `json:"name"`
Package string `json:"package,omitempty"`
Series string `json:"series"`
Seat string `json:"seat,omitempty"`
GoModule string `json:"go-module,omitempty"`
Newest *SeriesVersion `json:"newest,omitempty"`
Numbered *SeriesVersion `json:"numbered,omitempty"`
At time.Time `json:"at"`
}
// SeriesVersion is one version of a series: its number, the source commit it was built from, the digest and
// fingerprint. Contents are, for a series' newest of a Go package, its Go module's requirements' and packages' digests
// at Commit: what a user accepting the series is fingerprinted against; nil when the forge could not list it, and on a
// numbered version.
type SeriesVersion struct {
Version string `json:"version"`
Commit string `json:"commit,omitempty"`
Digest string `json:"digest,omitempty"`
Fingerprint string `json:"fingerprint,omitempty"`
Contents *PublishedPackages `json:"contents,omitempty"`
}
// SeriesPackageKey is the key of a package's series in the packages state: its ecosystem name as a key part and the
// series.
func SeriesPackageKey(name, series string) string { return EscapeName(name) + "." + series }
// IsSeriesPackageKey says whether a key of the packages state is a series key, not a per-module one.
func IsSeriesPackageKey(key string) bool { return strings.Contains(key, ".") }
// builtFrom says whether pkg is `<module>/<artifact>`: a module name (no slash) and an artifact named after it.
func builtFrom(pkg string) bool {
module, artifact, ok := strings.Cut(pkg, "/")
return ok && module != "" && artifact != ""
}
var seriesForm = regexp.MustCompile(`^[0-9]+\.[0-9]+$`)
func (s SeriesPackage) check() error {
switch {
case s.Name == "":
return fmt.Errorf("delivery: a series of %q names no package in its ecosystem", s.Package)
case !seriesForm.MatchString(s.Series):
return fmt.Errorf("delivery: the series %q of %s is no <major>.<minor>", s.Series, s.Name)
case s.Package != "" && !builtFrom(s.Package):
return fmt.Errorf("delivery: the series %s of %s is built from %q, which is no <module>/<artifact>", s.Series, s.Name, s.Package)
}
for which, v := range map[string]*SeriesVersion{"newest": s.Newest, "numbered": s.Numbered} {
if v != nil && v.Version == "" {
return fmt.Errorf("delivery: the %s version of %s %s names no version", which, s.Name, s.Series)
}
if v != nil && v.Contents != nil {
if err := v.Contents.check(); err != nil {
return err
}
}
}
return nil
}
// EncodeSeriesPackage is s as JSON at Version; it refuses what a reader could not take.
func EncodeSeriesPackage(s SeriesPackage) ([]byte, error) {
if err := s.check(); err != nil {
return nil, err
}
s.V = Version
return json.Marshal(s)
}
// DecodeSeriesPackage reads a series key's value; it refuses an unknown version (ErrUnknownVersion) and what
// EncodeSeriesPackage refuses.
func DecodeSeriesPackage(data []byte) (SeriesPackage, error) {
var s SeriesPackage
if err := decode(data, &s); err != nil {
return SeriesPackage{}, err
}
if err := s.check(); err != nil {
return SeriesPackage{}, err
}
return s, nil
}