From fbd0ef5cd82ce9ad2012ccf78f4ce9d056d834b0 Mon Sep 17 00:00:00 2001 From: Trevor Walker Date: Fri, 11 Sep 2026 10:50:08 -0600 Subject: [PATCH] fix(prime): verify release upload publication policy 3 --- .../PrimeAgentDistributionVerifier.test.ts | 20 +++++++++++++++---- .../prime/PrimeAgentDistributionVerifier.ts | 7 +++++++ .../prime-agent-distribution-verification.md | 8 ++++---- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/apps/server/src/provider/prime/PrimeAgentDistributionVerifier.test.ts b/apps/server/src/provider/prime/PrimeAgentDistributionVerifier.test.ts index 1ce41a50e3..b7389a15d7 100644 --- a/apps/server/src/provider/prime/PrimeAgentDistributionVerifier.test.ts +++ b/apps/server/src/provider/prime/PrimeAgentDistributionVerifier.test.ts @@ -497,6 +497,13 @@ describe("Pylon Prime publication verification", () => { stableWorkflowPath: PRIME_STABLE_WORKFLOW, stableWorkflowSha256: "0f04d1f55f54312d933087d88de6883e8408bb0cd9f060d3b5851d710698b1af", }, + { + publicationPolicyRevision: 3, + previewWorkflowPath: PRIME_PREVIEW_WORKFLOW, + previewWorkflowSha256: "16f68e46801eccca5e7e99736f346b5ffd96ce7188792d4ac8fbc4580408a736", + stableWorkflowPath: PRIME_STABLE_WORKFLOW, + stableWorkflowSha256: "96e4f3ccd889a17a391f00b4398d132a4234b5bc337045fedd3605f4eb74c331", + }, ]); }); @@ -504,6 +511,9 @@ describe("Pylon Prime publication verification", () => { { preview: 1, build: 1, promotion: 1 }, { preview: 2, build: 2, promotion: 2 }, { preview: 1, build: 1, promotion: 2 }, + { preview: 3, build: 3, promotion: 3 }, + { preview: 1, build: 1, promotion: 3 }, + { preview: 2, build: 2, promotion: 3 }, ])("verifies independent build and promotion policies: %j", async (policies) => { const fixture = syntheticPublication("stable", policies); const verifySourcePolicy = vi.fn(validVerification.verifySourcePolicy); @@ -535,9 +545,9 @@ describe("Pylon Prime publication verification", () => { }); it.each([ - { preview: 3, build: 2, promotion: 2 }, - { preview: 2, build: 3, promotion: 2 }, - { preview: 2, build: 2, promotion: 3 }, + { preview: 4, build: 3, promotion: 3 }, + { preview: 3, build: 4, promotion: 3 }, + { preview: 3, build: 3, promotion: 4 }, ])("rejects an unknown policy revision in any manifest position: %j", async (policies) => { await expect( verifyPrimePublicationFixture(syntheticPublication("stable", policies), validVerification), @@ -547,13 +557,15 @@ describe("Pylon Prime publication verification", () => { it.each([ { preview: 1, build: 2, promotion: 2 }, { preview: 2, build: 1, promotion: 2 }, + { preview: 2, build: 3, promotion: 3 }, + { preview: 3, build: 2, promotion: 3 }, ])("rejects a stable build policy different from its exact preview: %j", async (policies) => { await expect( verifyPrimePublicationFixture(syntheticPublication("stable", policies), validVerification), ).rejects.toThrow(/Stable manifest does not bind the exact verified preview/u); }); - it.each([1, 2])("checks actual fetched workflow bytes under policy %i", async (revision) => { + it.each([1, 2, 3])("checks actual fetched workflow bytes under policy %i", async (revision) => { const fixture = syntheticPublication("preview", { preview: revision, build: revision, diff --git a/apps/server/src/provider/prime/PrimeAgentDistributionVerifier.ts b/apps/server/src/provider/prime/PrimeAgentDistributionVerifier.ts index 85e3617f30..1b2671c8b9 100644 --- a/apps/server/src/provider/prime/PrimeAgentDistributionVerifier.ts +++ b/apps/server/src/provider/prime/PrimeAgentDistributionVerifier.ts @@ -392,6 +392,13 @@ export const PRIME_PUBLICATION_POLICIES = Object.freeze([ stableWorkflowPath: PRIME_STABLE_WORKFLOW, stableWorkflowSha256: "0f04d1f55f54312d933087d88de6883e8408bb0cd9f060d3b5851d710698b1af", }), + Object.freeze({ + publicationPolicyRevision: 3, + previewWorkflowPath: PRIME_PREVIEW_WORKFLOW, + previewWorkflowSha256: "16f68e46801eccca5e7e99736f346b5ffd96ce7188792d4ac8fbc4580408a736", + stableWorkflowPath: PRIME_STABLE_WORKFLOW, + stableWorkflowSha256: "96e4f3ccd889a17a391f00b4398d132a4234b5bc337045fedd3605f4eb74c331", + }), ]); function publicationPolicyFor(revision: number) { diff --git a/docs/internals/prime-agent-distribution-verification.md b/docs/internals/prime-agent-distribution-verification.md index 01e5dd0d72..545c4ac9ce 100644 --- a/docs/internals/prime-agent-distribution-verification.md +++ b/docs/internals/prime-agent-distribution-verification.md @@ -23,12 +23,12 @@ Unknown recipes, policy revisions, fields, assets, or tag shapes fail closed. Th both publication workflow byte digests. A publication workflow change therefore needs a new reviewed policy revision rather than a permissive parser change. -The immutable registry retains revision 1 and adds revision 2 from the reviewed publication changes -in [Prime Agent PR #56](https://github.com/pylon-code/prime-agent/pull/56). Each revision pins its own +The immutable registry retains revisions 1 and 2 and supports revision 3, which uses the pinned +GitHub REST client to upload release assets. Each revision pins its own exact preview and stable workflow bytes. A stable receipt's build policy must equal its verified preview's policy; its promotion policy is checked independently against the promotion commit and tree. -This permits a revision-1 preview to be promoted under revision 2 without changing its original build -provenance. Network verification and real-artifact graduation resolve the same frozen policies. +This permits a preview built under an earlier supported policy to be promoted under revision 3 +without changing its original build provenance. Network verification and real-artifact graduation resolve the same frozen policies. The server uses `@sigstore/bundle`, `@sigstore/core`, `@sigstore/tuf`, and `@sigstore/verify` directly. It requires a current Sigstore bundle with an inclusion proof, one verified Rekor timestamp, one