From acd8e985d196487884baa90b38ec42633431021c Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 5 Nov 2026 14:41:02 +0100 Subject: [PATCH] =?UTF-8?q?mesh-delivery-sdk=20kept:=20the=20version=20che?= =?UTF-8?q?ck,=20CheckName=20and=20IsHex64=20are=20mesh-sdk=20keys'=20now;?= =?UTF-8?q?=20kept=20keeps=20Decode=20and=20CheckDigest=20(ruling=202,=20A?= =?UTF-8?q?DR=200634=20=C2=A71;=20issue=201966)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i --- .../meshdeliverycheckerclient/client.go | 6 +-- .../mesh-delivery-builder/builds/builds.go | 8 +-- .../builds/builds_test.go | 5 +- modules/mesh-delivery-builder/builds/log.go | 3 +- .../takein/taken_test.go | 3 +- modules/mesh-delivery-view/viewstate/reach.go | 2 +- sdk/kept/kept.go | 49 ++----------------- sdk/kept/kept_test.go | 11 +---- 8 files changed, 19 insertions(+), 68 deletions(-) diff --git a/contracts/go/clients/meshdeliverycheckerclient/client.go b/contracts/go/clients/meshdeliverycheckerclient/client.go index c97e6ac3..80915d61 100644 --- a/contracts/go/clients/meshdeliverycheckerclient/client.go +++ b/contracts/go/clients/meshdeliverycheckerclient/client.go @@ -9,7 +9,7 @@ import ( "strings" checker "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshdeliverychecker" - "git.novox.be/novox/mesh-delivery/sdk/kept" + "git.novox.be/novox/mesh-sdk/go/keys" ) // The states of a verdict, the levels of a check and the compositions' states. @@ -44,10 +44,10 @@ func CheckRepository(repository string) error { if !ok || strings.Contains(name, "/") { return fmt.Errorf("meshdeliverycheckerclient: the repository %q is not /, with exactly one slash", repository) } - if err := kept.CheckName("repository owner", owner); err != nil { + if err := keys.CheckName("repository owner", owner); err != nil { return fmt.Errorf("meshdeliverycheckerclient: the repository %q: %w", repository, err) } - if err := kept.CheckName("repository name", name); err != nil { + if err := keys.CheckName("repository name", name); err != nil { return fmt.Errorf("meshdeliverycheckerclient: the repository %q: %w", repository, err) } return nil diff --git a/modules/mesh-delivery-builder/builds/builds.go b/modules/mesh-delivery-builder/builds/builds.go index 04bd7751..26e0973c 100644 --- a/modules/mesh-delivery-builder/builds/builds.go +++ b/modules/mesh-delivery-builder/builds/builds.go @@ -65,7 +65,7 @@ const ( // being the fingerprint's key part (fingerprint.KeyPart), since a bus key may not hold ':'. A module holding a dot or a // character a key refuses, and a fingerprint not of the new form, are refused, naming them. func BuilderBuildKey(module, fp string) (string, error) { - if err := kept.CheckName("module", module); err != nil { + if err := keys.CheckName("module", module); err != nil { return "", err } part, err := fingerprint.KeyPart(fp) @@ -81,7 +81,7 @@ func ParseBuilderBuildKey(key string) (module, fp string, err error) { if !ok { return "", "", fmt.Errorf("builds: %q is not a builder build key, .", key) } - if err := kept.CheckName("module", module); err != nil { + if err := keys.CheckName("module", module); err != nil { return "", "", fmt.Errorf("builds: %q is not a builder build key: %w", key, err) } if fp, err = fingerprint.ParseKeyPart(part); err != nil { @@ -265,7 +265,7 @@ func (b BuilderBuild) check() error { return fmt.Errorf("builds: the build state %q is not queued, building, done or failed", b.State) } if b.Manifest != "" { - if !kept.IsHex64(b.Manifest) { + if !keys.IsHex64(b.Manifest) { return fmt.Errorf("builds: %q is not a manifest digest, 64 lowercase hex digits", b.Manifest) } } @@ -355,7 +355,7 @@ func EncodeBuilderBuild(b BuilderBuild) ([]byte, error) { return json.Marshal(b) } -// DecodeBuilderBuild reads a builder build value; it refuses an unknown version (kept.ErrUnknownVersion) and what +// DecodeBuilderBuild reads a builder build value; it refuses an unknown version (keys.ErrUnknownVersion) and what // EncodeBuilderBuild refuses. func DecodeBuilderBuild(data []byte) (BuilderBuild, error) { var b BuilderBuild diff --git a/modules/mesh-delivery-builder/builds/builds_test.go b/modules/mesh-delivery-builder/builds/builds_test.go index e49c966e..8e272b67 100644 --- a/modules/mesh-delivery-builder/builds/builds_test.go +++ b/modules/mesh-delivery-builder/builds/builds_test.go @@ -9,7 +9,6 @@ import ( "testing" "git.novox.be/novox/mesh-delivery/sdk/buildrecord" - "git.novox.be/novox/mesh-delivery/sdk/kept" "git.novox.be/novox/mesh-sdk/go/keys" ) @@ -177,10 +176,10 @@ func TestBuilderBuildNamesItsToolchains(t *testing.T) { } } -// 1358/AC5: a value of another version, or none, is refused with kept.ErrUnknownVersion. +// 1358/AC5: a value of another version, or none, is refused with keys.ErrUnknownVersion. func TestBuilderBuildVersion(t *testing.T) { for _, in := range []string{`{"v":2,"state":"queued"}`, `{"state":"queued"}`} { - if _, err := DecodeBuilderBuild([]byte(in)); !errors.Is(err, kept.ErrUnknownVersion) { + if _, err := DecodeBuilderBuild([]byte(in)); !errors.Is(err, keys.ErrUnknownVersion) { t.Errorf("DecodeBuilderBuild(%s) = %v", in, err) } } diff --git a/modules/mesh-delivery-builder/builds/log.go b/modules/mesh-delivery-builder/builds/log.go index d7344eee..8bdc55e8 100644 --- a/modules/mesh-delivery-builder/builds/log.go +++ b/modules/mesh-delivery-builder/builds/log.go @@ -6,7 +6,6 @@ import ( "sort" "time" - "git.novox.be/novox/mesh-delivery/sdk/kept" "git.novox.be/novox/mesh-delivery/sdk/trunk" "git.novox.be/novox/mesh-sdk/go/keys" ) @@ -36,7 +35,7 @@ const ( // BuildLogKey is the key of a module's entries in the builder's log: the module's name, refused when a log key could not // hold it. func BuildLogKey(module string) (string, error) { - if err := kept.CheckName("module", module); err != nil { + if err := keys.CheckName("module", module); err != nil { return "", err } return module, nil diff --git a/modules/mesh-delivery-indexer/takein/taken_test.go b/modules/mesh-delivery-indexer/takein/taken_test.go index 7a0aca61..9e30603e 100644 --- a/modules/mesh-delivery-indexer/takein/taken_test.go +++ b/modules/mesh-delivery-indexer/takein/taken_test.go @@ -6,7 +6,6 @@ import ( "testing" "time" - "git.novox.be/novox/mesh-delivery/sdk/kept" "git.novox.be/novox/mesh-sdk/go/keys" ) @@ -26,7 +25,7 @@ func TestATakenValueRoundTripsAndRefusesWhatLacksARepositoryOrAMerge(t *testing. t.Errorf("taken without merge: %v", err) } for _, in := range []string{`{"v":2,"repository":"a/b","merge":"c"}`, `{"repository":"a/b","merge":"c"}`} { - if _, err := DecodeTaken([]byte(in)); !errors.Is(err, kept.ErrUnknownVersion) { + if _, err := DecodeTaken([]byte(in)); !errors.Is(err, keys.ErrUnknownVersion) { t.Errorf("decode of %s = %v, want ErrUnknownVersion", in, err) } } diff --git a/modules/mesh-delivery-view/viewstate/reach.go b/modules/mesh-delivery-view/viewstate/reach.go index 4cad0487..51574736 100644 --- a/modules/mesh-delivery-view/viewstate/reach.go +++ b/modules/mesh-delivery-view/viewstate/reach.go @@ -168,7 +168,7 @@ func EncodeViewAnswer(a ViewAnswer) ([]byte, error) { return json.Marshal(a) } -// DecodeViewAnswer reads an answer; it refuses an unknown version (kept.ErrUnknownVersion) and what EncodeViewAnswer refuses. +// DecodeViewAnswer reads an answer; it refuses an unknown version (keys.ErrUnknownVersion) and what EncodeViewAnswer refuses. func DecodeViewAnswer(data []byte) (ViewAnswer, error) { var a ViewAnswer if err := kept.Decode(data, &a); err != nil { diff --git a/sdk/kept/kept.go b/sdk/kept/kept.go index 1d907361..35fe7e48 100644 --- a/sdk/kept/kept.go +++ b/sdk/kept/kept.go @@ -1,59 +1,20 @@ -// Package kept holds what the layouts of the Delivery domain's kept values share: the version check on reading one, the -// rule a name must keep to be a key part, and the form of a digest. It names no seat and no module (ADR 0634 §2). The -// version itself (keys.Version) and the escaping of a name (keys.EscapeName) are mesh-sdk's, since more than one domain uses -// them. +// Package kept holds what the layouts of the Delivery domain's kept values share: the reading of one at its version and the form +// of a digest. It names no seat and no module (ADR 0634 §2). The version (keys.Version, keys.CheckVersion), the rule a name +// must keep to be a key part (keys.CheckName), keys.IsHex64 and the escaping of a name (keys.EscapeName) are mesh-sdk's, +// since more than one domain uses them. package kept import ( "encoding/json" - "errors" "fmt" "regexp" "git.novox.be/novox/mesh-sdk/go/keys" ) -// ErrUnknownVersion is what Decode returns for a value whose version is missing or not keys.Version. Test it with errors.Is. -var ErrUnknownVersion = errors.New("kept: unknown value version") - -var nameOK = regexp.MustCompile(`^[-/_=a-zA-Z0-9]+$`) - -// CheckName refuses a name that is empty or holds a dot, a wildcard, whitespace or a character a bus key refuses. -func CheckName(kind, name string) error { - if name == "" { - return fmt.Errorf("kept: the %s name is empty", kind) - } - if !nameOK.MatchString(name) { - return fmt.Errorf("kept: the %s name %q holds a dot, a wildcard, whitespace or a character a key refuses", kind, name) - } - return nil -} - -var hex64 = regexp.MustCompile(`^[0-9a-f]{64}$`) - -// IsHex64 says whether s is 64 lowercase hex digits. -func IsHex64(s string) bool { return hex64.MatchString(s) } - -// CheckVersion refuses a value with no version or one this reader does not read. -func CheckVersion(data []byte) error { - var probe struct { - V *int `json:"v"` - } - if err := json.Unmarshal(data, &probe); err != nil { - return fmt.Errorf("kept: value is not JSON: %w", err) - } - if probe.V == nil { - return fmt.Errorf("%w: no version in the value, this reader reads %d", ErrUnknownVersion, keys.Version) - } - if *probe.V != keys.Version { - return fmt.Errorf("%w: the value is version %d, this reader reads %d", ErrUnknownVersion, *probe.V, keys.Version) - } - return nil -} - // Decode reads data into into after CheckVersion. func Decode(data []byte, into any) error { - if err := CheckVersion(data); err != nil { + if err := keys.CheckVersion(data); err != nil { return err } if err := json.Unmarshal(data, into); err != nil { diff --git a/sdk/kept/kept_test.go b/sdk/kept/kept_test.go index aeff9ec0..870c6cf4 100644 --- a/sdk/kept/kept_test.go +++ b/sdk/kept/kept_test.go @@ -2,6 +2,7 @@ package kept import ( "errors" + "git.novox.be/novox/mesh-sdk/go/keys" "strings" "testing" ) @@ -10,21 +11,13 @@ func TestAKeptValueIsReadOnlyAtItsVersionAndAKeyPartOnlyOfKeyCharacters(t *testi var v struct{ V int } for data, ok := range map[string]bool{`{"v":1}`: true, `{"v":2}`: false, `{}`: false} { err := Decode([]byte(data), &v) - if (err == nil) != ok || (!ok && !errors.Is(err, ErrUnknownVersion)) { + if (err == nil) != ok || (!ok && !errors.Is(err, keys.ErrUnknownVersion)) { t.Errorf("Decode(%s) = %v", data, err) } } if Decode([]byte(`nope`), &v) == nil { t.Error("a value that is no JSON is read") } - for name, ok := range map[string]bool{"a-b_c/d=": true, "": false, "a.b": false, "a b": false, "a*": false} { - if (CheckName("module", name) == nil) != ok { - t.Errorf("CheckName(%q) = %v", name, CheckName("module", name)) - } - } - if !IsHex64(strings.Repeat("a", 64)) || IsHex64(strings.Repeat("A", 64)) || IsHex64("a") { - t.Error("IsHex64 reads a wrong form") - } if CheckDigest("sha256:"+strings.Repeat("0", 64), "x") != nil || CheckDigest("sha256:0", "x") == nil { t.Error("CheckDigest reads a wrong form") }