diff --git a/contracts/go/clients/meshwantsclient/wants_test.go b/contracts/go/clients/meshwantsclient/wants_test.go index 490fa692..a621583d 100644 --- a/contracts/go/clients/meshwantsclient/wants_test.go +++ b/contracts/go/clients/meshwantsclient/wants_test.go @@ -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) diff --git a/contracts/go/seats/meshwants/contract.go b/contracts/go/seats/meshwants/contract.go index 7e958b08..1030ce77 100644 --- a/contracts/go/seats/meshwants/contract.go +++ b/contracts/go/seats/meshwants/contract.go @@ -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"` diff --git a/contracts/go/seats/meshwants/contract_test.go b/contracts/go/seats/meshwants/contract_test.go index b21c64c9..32f26b23 100644 --- a/contracts/go/seats/meshwants/contract_test.go +++ b/contracts/go/seats/meshwants/contract_test.go @@ -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 diff --git a/contracts/seats/mesh-wants/fixtures/states.json b/contracts/seats/mesh-wants/fixtures/states.json index 818850d5..85e5d74c 100644 --- a/contracts/seats/mesh-wants/fixtures/states.json +++ b/contracts/seats/mesh-wants/fixtures/states.json @@ -8,6 +8,19 @@ "rule": 3 } }, + { + "name": "a want for a kept build, naming the node that keeps it", + "of": "state:wants/want..", + "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", diff --git a/contracts/seats/mesh-wants/seat.json b/contracts/seats/mesh-wants/seat.json index ca64e17c..445971f7 100644 --- a/contracts/seats/mesh-wants/seat.json +++ b/contracts/seats/mesh-wants/seat.json @@ -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)" } } }, diff --git a/contracts/ts/seats/meshwants/index.d.ts b/contracts/ts/seats/meshwants/index.d.ts index 134842cd..81fbc682 100644 --- a/contracts/ts/seats/meshwants/index.d.ts +++ b/contracts/ts/seats/meshwants/index.d.ts @@ -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;