Contract: the seat mesh-wants' want names the node that keeps a kept build in kept-on

Builds: design 47 G §526, §379, §271
This commit is contained in:
2026-11-11 23:23:30 +01:00
parent 844a2443a5
commit a245c2f1e9
6 changed files with 29 additions and 1 deletions
@@ -42,6 +42,7 @@ func TestWantsAreWhatTheEarlierCodecWrote(t *testing.T) {
"put": {Want{Fp: a, Self: true, Put: true, Hold: true, Yes: d, Release: "r1"}, `{"v":1,"fp":"` + a + `","put":true,"hold":true,"yes":"` + d + `","release":"r1","self":true}`},
"removed": {Want{Removed: true, Words: "gone"}, `{"v":1,"removed":true,"words":"gone"}`},
"released": {Want{Fp: a, Composed: c, Version: "0.1.15", Parts: map[string]string{"mesh-sdk:go": d}}, `{"v":1,"fp":"` + a + `","composed":"` + c + `","version":"0.1.15","parts":{"mesh-sdk:go":"` + d + `"}}`},
"kept": {Want{Fp: a, Composed: c, Parts: map[string]string{"x:image": d}, KeptOn: "n1"}, `{"v":1,"fp":"` + a + `","composed":"` + c + `","parts":{"x:image":"` + d + `"},"kept-on":"n1"}`},
} {
t.Run(name, func(t *testing.T) {
raw, err := EncodeWant(row.w)
+3 -1
View File
@@ -895,7 +895,9 @@ type WantsByWantNodeModuleValue struct {
Composed string `json:"composed,omitempty"`
Fp string `json:"fp,omitempty"`
Hold bool `json:"hold,omitempty"`
Newest string `json:"newest,omitempty"`
// for a kept build, the build node that keeps it, from the builder's build.ended; the node-engine fetches the build through that node's seat verb kept-artifact, and a want with none from the store (design 47 G section 526)
KeptOn string `json:"kept-on,omitempty"`
Newest string `json:"newest,omitempty"`
// the digest of each of the module's parts, by artifact reference; the node-engine fetches and checks each part by it (design 47 G section 379)
Parts map[string]string `json:"parts,omitempty"`
Put bool `json:"put,omitempty"`
@@ -65,6 +65,12 @@ func TestFixtures(t *testing.T) {
err := json.Unmarshal(b, &v)
return v, err
}, subjectIs: nil},
{name: "a want for a kept build, naming the node that keeps it", subject: "", given: "{\"fp\":\"ab12\",\"kept-on\":\"n1\",\"parts\":{\"x:image\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"},\"v\":1,\"version\":\"0.1.15\"}", wire: "{\"fp\":\"ab12\",\"kept-on\":\"n1\",\"parts\":{\"x:image\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"},\"v\":1,\"version\":\"0.1.15\"}",
decode: func(b []byte) (any, error) {
var v WantsByWantNodeModuleValue
err := json.Unmarshal(b, &v)
return v, err
}, subjectIs: nil},
{name: "a node's own want", subject: "", given: "{\"composed\":\"sha256:aa\",\"self\":true,\"v\":1}", wire: "{\"composed\":\"sha256:aa\",\"self\":true,\"v\":1}",
decode: func(b []byte) (any, error) {
var v WantsByWantNodeNodeValue
@@ -8,6 +8,19 @@
"rule": 3
}
},
{
"name": "a want for a kept build, naming the node that keeps it",
"of": "state:wants/want.<node>.<module>",
"given": {
"v": 1,
"fp": "ab12",
"version": "0.1.15",
"parts": {
"x:image": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
},
"kept-on": "n1"
}
},
{
"name": "a node's own want",
"of": "state:wants/want.<node>.node",
+4
View File
@@ -542,6 +542,10 @@
"type": "string"
},
"description": "the digest of each of the module's parts, by artifact reference; the node-engine fetches and checks each part by it (design 47 G section 379)"
},
"kept-on": {
"type": "string",
"description": "for a kept build, the build node that keeps it, from the builder's build.ended; the node-engine fetches the build through that node's seat verb kept-artifact, and a want with none from the store (design 47 G section 526)"
}
}
},
+2
View File
@@ -513,6 +513,8 @@ export interface WantsByWantNodeModuleValue {
"composed"?: string;
"fp"?: string;
"hold"?: boolean;
/** for a kept build, the build node that keeps it, from the builder's build.ended; the node-engine fetches the build through that node's seat verb kept-artifact, and a want with none from the store (design 47 G section 526) */
"kept-on"?: string;
"newest"?: string;
/** the digest of each of the module's parts, by artifact reference; the node-engine fetches and checks each part by it (design 47 G section 379) */
"parts"?: Record<string, string>;