diff --git a/release/bom.v1.json b/release/bom.v1.json index 9b9c2cc..1bcfd20 100644 --- a/release/bom.v1.json +++ b/release/bom.v1.json @@ -1,7 +1,7 @@ { "schema_version": 1, "state": "candidate", - "id": "kosmos-package-catalog-12", + "id": "kosmos-package-catalog-13", "release": { "version": "0.9.15", "channel": "production", @@ -56,8 +56,8 @@ "package_schema": 2 }, "catalog": { - "sequence": 12, - "previous_sequence": 11, + "sequence": 13, + "previous_sequence": 12, "store_sequence": 13, "channel": "production", "signing_key_id": "kosmos-release-2026", @@ -88,17 +88,17 @@ "manifest_id": "com.kosmos.dictation", "kind": "app", "engine_api": ">=1.0.0", - "version": "0.2.2", + "version": "0.2.3", "repository": "makekosmos/dictation", - "ref": "1f103810ffcd0fc0aee36a9784d51d06f26a1989", - "release_tag": "v0.2.2", + "ref": "3b28142c48026d5cb485facce2dca65473365cac", + "release_tag": "v0.2.3", "entrypoint": "dist/index.html", "icon": "icon.png", "artifact": { - "name": "dictation-0.2.2.kspkg", - "url": "https://github.com/makekosmos/dictation/releases/download/v0.2.2/dictation-0.2.2.kspkg", - "sha256": "4ce3d5e438a3598af06e3152e513f7a11a0a1d252ec69a2e22b14b3a9688e0f9", - "size": 1302770 + "name": "dictation-0.2.3.kspkg", + "url": "https://github.com/makekosmos/dictation/releases/download/v0.2.3/dictation-0.2.3.kspkg", + "sha256": "2571d1aff891a32f5ae3175e2ae19745bbf11999dabe203edfce89397ce94273", + "size": 1403994 } }, { diff --git a/scripts/publish-catalog.mjs b/scripts/publish-catalog.mjs index a6f6117..a487e75 100644 --- a/scripts/publish-catalog.mjs +++ b/scripts/publish-catalog.mjs @@ -205,7 +205,14 @@ export async function inspectArchive(spec, archivePath, zipUtils, sequence) { try { manifest = JSON.parse(manifestEntry.data.toString("utf8")); } catch { fail(`${spec.id}: archive manifest.json is invalid JSON`); } requiredManifest(manifest, spec, spec.build?.provider ?? spec.id); const licenseEntry = files.find((entry) => /^license(?:[._-].*)?$/i.test(path.posix.basename(entry.name))); - const expected = ["manifest.json", spec.entrypoint, spec.icon, ...(licenseEntry ? [licenseEntry.name] : [])].sort(); + const compatibilityEntry = files.find((entry) => entry.name === "compatibility.json"); + const expected = [ + "manifest.json", + spec.entrypoint, + spec.icon, + ...(licenseEntry ? [licenseEntry.name] : []), + ...(spec.kind === "app" && compatibilityEntry ? [compatibilityEntry.name] : []), + ].sort(); const actual = files.map((entry) => entry.name).sort(); if (spec.kind === "app" ? (expected.some((name) => !actual.includes(name)) || actual.some((name) => !expected.includes(name) && !name.startsWith("dist/"))) : diff --git a/scripts/publish-catalog.test.mjs b/scripts/publish-catalog.test.mjs index d19cf3f..96e0d7a 100644 --- a/scripts/publish-catalog.test.mjs +++ b/scripts/publish-catalog.test.mjs @@ -154,6 +154,7 @@ test("archive policy rejects traversal, collisions, and extra files", async () = { name: "dist/assets/app.js", data: Buffer.from("js") }, { name: "icon.png", data: Buffer.from("icon") }, { name: "manifest.json", data: JSON.stringify(completeManifest(appSpec)) }, + { name: "compatibility.json", data: JSON.stringify({ schema_version: 1 }) }, ]); const inspectedApp = await inspectArchive(appSpec, app, { readZip }, 8); assert.equal(inspectedApp.archive_url, "https://github.com/makekosmos/package-index/releases/download/catalog-8/app.kspkg"); diff --git a/scripts/validate-bom.test.mjs b/scripts/validate-bom.test.mjs index e35d608..b655421 100644 --- a/scripts/validate-bom.test.mjs +++ b/scripts/validate-bom.test.mjs @@ -11,7 +11,7 @@ const bomPath = path.join(root, "release", "bom.v1.json"); const builder = await readFile(path.join(root, "scripts", "build-source-packages.mjs"), "utf8"); test("checked-in BOM is v1 and contains all catalog package inputs", async () => { - const bom = await loadBom(bomPath, { expectedSequence: 12, allowPendingBuilds: true }); + const bom = await loadBom(bomPath, { expectedSequence: 13, allowPendingBuilds: true }); assert.equal(bom.packages.length, 11); assert.equal(bom.packages.filter((entry) => entry.kind === "app").length, 5); assert.equal(bom.packages.filter((entry) => entry.kind === "source").length, 6); @@ -20,7 +20,7 @@ test("checked-in BOM is v1 and contains all catalog package inputs", async () => }); test("reviewed BOM pins the authorized Store commit and envelope sequence", async () => { - const bom = await loadBom(bomPath, { expectedSequence: 12, allowPendingBuilds: true }); + const bom = await loadBom(bomPath, { expectedSequence: 13, allowPendingBuilds: true }); assert.equal(bom.source.store.commit, "7d185a52ad1eb444f197f2d664af2cdb96738add"); assert.equal(bom.catalog.store_sequence, 13); });