go/keys: the version of a kept value and the key-part escaping that more than one domain shares (ADR 0634 §4; issue 1966)

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-05 13:42:59 +01:00
parent b611bb9ad5
commit e8ae3ec8d3
3 changed files with 89 additions and 1 deletions
+59
View File
@@ -0,0 +1,59 @@
// Package keys holds what the mesh's kept values of more than one domain share: the version a kept value carries and
// the escaping of a name into a key part (novox/hq ADR 0634 §1, §4; they were go/delivery's and are used by the
// Delivery, Placement and Identity and access domains alike). It names no seat and no module.
package keys
import (
"encoding/hex"
"fmt"
"regexp"
"strings"
)
// Version is the version of every kept value that carries one and the only one its readers read.
const Version = 1
var nameOK = regexp.MustCompile(`^[-/_=a-zA-Z0-9]+$`)
// EscapeName is name as a key part: a character outside letters, digits, `-`, `/` and `_` is written `=` and its
// two lowercase hex digits per byte, and `=` itself is escaped, so any non-empty name keys and a name of allowed
// characters only keys as it is. UnescapeName is its inverse.
func EscapeName(name string) string {
var b strings.Builder
for i := 0; i < len(name); i++ {
c := name[i]
switch {
case c >= 'a' && c <= 'z', c >= 'A' && c <= 'Z', c >= '0' && c <= '9', c == '-', c == '/', c == '_':
b.WriteByte(c)
default:
fmt.Fprintf(&b, "=%02x", c)
}
}
return b.String()
}
// UnescapeName is the inverse of EscapeName; it refuses a part with a bare `=` or any character EscapeName leaves
// escaped.
func UnescapeName(part string) (string, error) {
var out []byte
for i := 0; i < len(part); i++ {
c := part[i]
if c != '=' {
if !nameOK.MatchString(string(c)) {
return "", fmt.Errorf("keys: %q holds %q, which a key part escapes", part, c)
}
out = append(out, c)
continue
}
if i+3 > len(part) {
return "", fmt.Errorf("keys: %q ends in an incomplete escape", part)
}
v, err := hex.DecodeString(part[i+1 : i+3])
if err != nil || part[i+1:i+3] != strings.ToLower(part[i+1:i+3]) {
return "", fmt.Errorf("keys: %q holds a malformed escape %q", part, part[i:i+3])
}
out = append(out, v[0])
i += 2
}
return string(out), nil
}
+29
View File
@@ -0,0 +1,29 @@
package keys
import (
"strings"
"testing"
)
func TestNamesEscapeIntoKeyPartsAndBack(t *testing.T) {
for _, c := range []struct{ name, esc string }{
{"fix/1.2", "fix/1=2e2"}, {"a.b", "a=2eb"}, {"a=b", "a=3db"}, {"a+b", "a=2bb"}, {"plain-name_1/x", "plain-name_1/x"},
{"fix/ü", "fix/=c3=bc"}, {"x y", "x=20y"},
} {
esc := EscapeName(c.name)
if esc != c.esc || strings.ContainsAny(esc, ".+ ") {
t.Errorf("escape of %q = %q, want %q", c.name, esc, c.esc)
}
if back, err := UnescapeName(esc); err != nil || back != c.name {
t.Errorf("unescape(%q) = %q, %v; want %q", esc, back, err, c.name)
}
}
for _, bad := range []string{"a.b", "a=", "a=2", "a=zz", "a=2E", "a b"} {
if got, err := UnescapeName(bad); err == nil {
t.Errorf("unescape(%q) = %q, accepted", bad, got)
}
}
if Version != 1 {
t.Errorf("Version = %d: a kept value's readers read the one version", Version)
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ import (
// request: does every module share it, or is it a shape more than one part reads?
var meshSDKPackages = []string{
".", "announce", "announcetest", "buildstep", "buscalls", "buscompose", "busstate", "busretry", "calladdress", "catalogue", "channel",
"composer", "declaration", "delivery", "forgekey", "handacts", "health", "internal/beside", "kvlimit", "membership",
"composer", "declaration", "delivery", "forgekey", "handacts", "health", "internal/beside", "keys", "kvlimit", "membership",
"objectlink", "outward", "overlay", "parts", "pernode", "process", "provider", "provider/harness", "provisions",
"sdkversion", "seal", "seatdef", "seatlist", "seatlist/seatlisttest", "testbus", "views", "views/viewstest",
}