diff --git a/contracts/go/seats/meshcatalog/contract.go b/contracts/go/seats/meshcatalog/contract.go index 1a6b43f6..db822342 100644 --- a/contracts/go/seats/meshcatalog/contract.go +++ b/contracts/go/seats/meshcatalog/contract.go @@ -736,7 +736,9 @@ type CatalogEntry struct { Main string `json:"main,omitempty"` // the validated manifest whole, kept as an object by the entry's digest, so no size limit applies; read by anyone but the indexer through the entry, never as a manifest (design 47 G section 443, section 442) Manifest map[string]any `json:"manifest"` - Module string `json:"module"` + // the sha256: digest of the manifest's bytes as the forge answered them, set by the indexer at take-in and never computed again from the manifest whole; the module's value and the manifests key are this digest (design 47 G section 506) + ManifestDigest string `json:"manifest-digest,omitempty"` + Module string `json:"module"` // the manifest reads a node-engine must state to compose it, its templates' forms included, as the forge bridge read them at the merge (ADR 0614 §4, ADR 0632 §2) Needs []string `json:"needs,omitempty"` // why it has none diff --git a/contracts/go/seats/meshcatalog/contract_test.go b/contracts/go/seats/meshcatalog/contract_test.go index 5ef39f04..e6bca015 100644 --- a/contracts/go/seats/meshcatalog/contract_test.go +++ b/contracts/go/seats/meshcatalog/contract_test.go @@ -85,7 +85,7 @@ func TestFixtures(t *testing.T) { err := json.Unmarshal(b, &v) return v, err }, subjectIs: nil}, - {name: "a catalog graph entry (xclip)", subject: "", given: "{\"bases\":[\"arch\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"inputs\":{\"fp-src\":41,\"from\":{\"bases\":[\"arch\"],\"locks\":{\"go.sum\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"},\"packages\":[\"git.novox.be/novox/mesh-sdk/go@v0.0.0-20261101000000-f469eb387a30\"],\"tree\":\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"},\"src\":41,\"toolchains\":{\"go\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}}},\"invokes\":[\"node-files.read\"],\"manifest\":{\"module\":\"xclip\",\"version\":\"1\"},\"module\":\"xclip\",\"packages\":{\"git.novox.be/novox/mesh-sdk/go\":\"v0.0.0-20261101000000-f469eb387a30\"},\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"toolchains\":{\"go\":{\"module\":\"mesh-build-go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"v\":1,\"verdict\":\"accepted\"}", wire: "{\"bases\":[\"arch\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"inputs\":{\"fp-src\":41,\"from\":{\"bases\":[\"arch\"],\"locks\":{\"go.sum\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"},\"packages\":[\"git.novox.be/novox/mesh-sdk/go@v0.0.0-20261101000000-f469eb387a30\"],\"tree\":\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"},\"src\":41,\"toolchains\":{\"go\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}}},\"invokes\":[\"node-files.read\"],\"manifest\":{\"module\":\"xclip\",\"version\":\"1\"},\"module\":\"xclip\",\"packages\":{\"git.novox.be/novox/mesh-sdk/go\":\"v0.0.0-20261101000000-f469eb387a30\"},\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"toolchains\":{\"go\":{\"module\":\"mesh-build-go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"v\":1,\"verdict\":\"accepted\"}", + {name: "a catalog graph entry (xclip)", subject: "", given: "{\"bases\":[\"arch\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"inputs\":{\"fp-src\":41,\"from\":{\"bases\":[\"arch\"],\"locks\":{\"go.sum\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"},\"packages\":[\"git.novox.be/novox/mesh-sdk/go@v0.0.0-20261101000000-f469eb387a30\"],\"tree\":\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"},\"src\":41,\"toolchains\":{\"go\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}}},\"invokes\":[\"node-files.read\"],\"manifest\":{\"module\":\"xclip\",\"version\":\"1\"},\"manifest-digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"module\":\"xclip\",\"packages\":{\"git.novox.be/novox/mesh-sdk/go\":\"v0.0.0-20261101000000-f469eb387a30\"},\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"toolchains\":{\"go\":{\"module\":\"mesh-build-go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"v\":1,\"verdict\":\"accepted\"}", wire: "{\"bases\":[\"arch\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"inputs\":{\"fp-src\":41,\"from\":{\"bases\":[\"arch\"],\"locks\":{\"go.sum\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"},\"packages\":[\"git.novox.be/novox/mesh-sdk/go@v0.0.0-20261101000000-f469eb387a30\"],\"tree\":\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"},\"src\":41,\"toolchains\":{\"go\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}}},\"invokes\":[\"node-files.read\"],\"manifest\":{\"module\":\"xclip\",\"version\":\"1\"},\"manifest-digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"module\":\"xclip\",\"packages\":{\"git.novox.be/novox/mesh-sdk/go\":\"v0.0.0-20261101000000-f469eb387a30\"},\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"toolchains\":{\"go\":{\"module\":\"mesh-build-go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"v\":1,\"verdict\":\"accepted\"}", decode: func(b []byte) (any, error) { var v CatalogRevisionsByEntryDigestValue err := json.Unmarshal(b, &v) diff --git a/contracts/seats/mesh-catalog/fixtures/states.json b/contracts/seats/mesh-catalog/fixtures/states.json index c3c1aacc..b1174d11 100644 --- a/contracts/seats/mesh-catalog/fixtures/states.json +++ b/contracts/seats/mesh-catalog/fixtures/states.json @@ -302,6 +302,7 @@ "module": "xclip", "version": "1" }, + "manifest-digest": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "verdict": "accepted", "fp": "src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56", "inputs": { diff --git a/contracts/seats/mesh-catalog/seat.json b/contracts/seats/mesh-catalog/seat.json index fd80e3bf..978e31dd 100644 --- a/contracts/seats/mesh-catalog/seat.json +++ b/contracts/seats/mesh-catalog/seat.json @@ -1872,6 +1872,10 @@ "type": "object", "description": "the validated manifest whole, kept as an object by the entry's digest, so no size limit applies; read by anyone but the indexer through the entry, never as a manifest (design 47 G section 443, section 442)" }, + "manifest-digest": { + "type": "string", + "description": "the sha256: digest of the manifest's bytes as the forge answered them, set by the indexer at take-in and never computed again from the manifest whole; the module's value and the manifests key are this digest (design 47 G section 506)" + }, "verdict": { "type": "string", "description": "its manifest's verdict: accepted, refused or held" diff --git a/contracts/ts/seats/meshcatalog/index.d.ts b/contracts/ts/seats/meshcatalog/index.d.ts index f935a038..53832de7 100644 --- a/contracts/ts/seats/meshcatalog/index.d.ts +++ b/contracts/ts/seats/meshcatalog/index.d.ts @@ -247,6 +247,8 @@ export interface CatalogEntry { "main"?: string; /** the validated manifest whole, kept as an object by the entry's digest, so no size limit applies; read by anyone but the indexer through the entry, never as a manifest (design 47 G section 443, section 442) */ "manifest": Record; + /** the sha256: digest of the manifest's bytes as the forge answered them, set by the indexer at take-in and never computed again from the manifest whole; the module's value and the manifests key are this digest (design 47 G section 506) */ + "manifest-digest"?: string; "module": string; /** the manifest reads a node-engine must state to compose it, its templates' forms included, as the forge bridge read them at the merge (ADR 0614 §4, ADR 0632 §2) */ "needs"?: string[];