From be2d52ca189538bc22c86952269bbd24d48de330 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 20 Sep 2026 08:22:12 +0000 Subject: [PATCH 1/2] Initial plan From f2813bb6dbd80f2483ee2f78fa684179e2d7383f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 20 Sep 2026 08:32:39 +0000 Subject: [PATCH 2/2] fix: use validator-approved schema-v2 producer checkout Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com> --- .github/workflows/client-v1-conformance.yml | 4 +- docs/phase1-conformance.md | 9 ++-- phase1-conformance.lock.json | 8 ++-- scripts/phase1-schema-v2-producer.mjs | 51 ++++++++++++++------- src/phase1-conformance-lock.test.ts | 8 ++-- src/phase1-conformance.test.ts | 10 +++- 6 files changed, 58 insertions(+), 32 deletions(-) diff --git a/.github/workflows/client-v1-conformance.yml b/.github/workflows/client-v1-conformance.yml index 2204f8f5..4b318d24 100644 --- a/.github/workflows/client-v1-conformance.yml +++ b/.github/workflows/client-v1-conformance.yml @@ -1238,7 +1238,7 @@ jobs: @('scripts\phase1-macos-keychain.mjs', 5091, 'ab0c2dd08cf606d9502f5da206175707d471d99f484e8c8c79b5b08a5772b9a4'), @('scripts\phase1-process-supervisor.mjs', 3820, '16b51fb1a33b4bfef98daca549aacf5dc2d2c098cfbd664753b69c940d1e6f6c'), @('scripts\phase1-schema-v2-evidence.mjs', 52505, '0aede2ab3abd76fabf5ac61d64d2dbaaffa497c8647b82236403de16a47751c8'), - @('scripts\phase1-schema-v2-producer.mjs', 233914, 'ea32a0b7d43f0558521de091666d66960bc033afafd5e619a728da1ec5d45929'), + @('scripts\phase1-schema-v2-producer.mjs', 234449, '11b5a90250556e2709c078089be3251fd586bad60c9d16cdfd5d35151e36a3a2'), @('scripts\process-owned-artifact-root.mjs', 13061, '103cc789f12a6bbde16b2414aecf05813d9d28a2c40c7d6eaa2073b86e8e5d77'), @('scripts\supervised-exec.mjs', 2875, 'a5edfd985b934d3b46247a0da3141682c411d30bb582edf87ae7b29791dad65b'), @('scripts\supervisor-status.mjs', 854, 'ac332ca7b6b040ecc846088bb3a6ad5e7112a0454eb3ea71d2a819d55e64254e') @@ -1963,7 +1963,7 @@ jobs: - name: Prepare trusted Unix supervisor if: matrix.platform != 'win32-x64' shell: bash - run: "set -euo pipefail\nnode --input-type=module <<'EOF'\nimport { createHash } from 'node:crypto';\nimport { lstatSync, readFileSync } from 'node:fs';\nconst expected = new Map([\n ['scripts/contract-canary.mjs', [40618, 'a4c2fe0a5eb6a5ff4653de5374c34c0fb46907c6806a5d23b86d8b37206ef958']],\n ['scripts/executable-resolution.mjs', [9154, '31e3c412ff8c835f14522f36a59e91f4a4ba82913210ae8e3b4455217503f430']],\n ['scripts/owned-temp-directory.mjs', [7762, '95f546ef9ed614f2a0f55d356ddfc54c943fc53b595b4eebebfcbd4db68e5c0b']],\n ['scripts/phase1-artifact-secret-scan.mjs', [21183, 'be0ec302b9c4372f232d6bd1efcba873fd3380cc5de7f756cd0b9eeeec07222a']],\n ['scripts/phase1-conformance-lock.mjs', [48960, '92f981c43f75bc65c81e9e9ee16084aae658617b929d451a9db0d7c9e6bedbe2']],\n ['scripts/phase1-conformance.mjs', [219462, 'fd90e35308ea6b8dd0488cb874d00d7ad40aa16b33e38b46a9a76c3ea13d5056']],\n ['scripts/phase1-evidence-contract.mjs', [15088, '24180ae03835fa6aac45559682adb3c1e626bab76466eddc55b9e2300f0a2b7f']],\n ['scripts/phase1-evidence-runtime.mjs', [6572, 'b09a0d20abc7ebbc6289c57c985fd42b8a4b5d196895bc035b8fca40281d9315']],\n ['scripts/phase1-linux-secret-service.mjs', [4270, 'ddf834c6f57853c5116b4b1f345952a218ff0687c5d741737c68e20bc2ecda92']],\n ['scripts/phase1-macos-keychain.mjs', [5091, 'ab0c2dd08cf606d9502f5da206175707d471d99f484e8c8c79b5b08a5772b9a4']],\n ['scripts/phase1-process-supervisor.mjs', [3820, '16b51fb1a33b4bfef98daca549aacf5dc2d2c098cfbd664753b69c940d1e6f6c']],\n ['scripts/phase1-schema-v2-evidence.mjs', [52505, '0aede2ab3abd76fabf5ac61d64d2dbaaffa497c8647b82236403de16a47751c8']],\n ['scripts/phase1-schema-v2-producer.mjs', [233914, 'ea32a0b7d43f0558521de091666d66960bc033afafd5e619a728da1ec5d45929']],\n ['scripts/process-owned-artifact-root.mjs', [13061, '103cc789f12a6bbde16b2414aecf05813d9d28a2c40c7d6eaa2073b86e8e5d77']],\n ['scripts/supervised-exec.mjs', [2875, 'a5edfd985b934d3b46247a0da3141682c411d30bb582edf87ae7b29791dad65b']],\n ['scripts/supervisor-status.mjs', [854, 'ac332ca7b6b040ecc846088bb3a6ad5e7112a0454eb3ea71d2a819d55e64254e']],\n ['scripts/phase1-linux-secret-service.sh', [5650, '83ce19c0dd6da5002f6853fa37addb4fc2d39f3d17beee1b1c39e1fce232b476']],\n ['scripts/unix-artifact-handoff.c', [18704, '2a003f9aa1d1886b9a593371a73cb65fe3a4a8b703f1c59fec8a27694367b7fc']],\n ['scripts/unix-producer-command.sh', [3223, 'ce9ec2ff00947f3ec0db53f144c99d34bc27de6085062d00dccff7c934c2e3c8']],\n ['scripts/unix-producer-supervisor.sh', [29424, 'b73036415744c80ed27d5667f255ceea149096ca517b47c93a154299802206ff']],\n]);\nfor (const [path, [size, digest]] of expected) {\n const stats = lstatSync(path);\n const bytes = readFileSync(path);\n if (\n !stats.isFile() ||\n stats.isSymbolicLink() ||\n stats.nlink !== 1 ||\n bytes.byteLength !== size ||\n createHash('sha256').update(bytes).digest('hex') !== digest\n ) {\n throw new Error('Trusted Unix supervisor source bytes do not match');\n }\n}\nconsole.log('Frozen harness module graph verified.');\nEOF\nbroker_root=\"/tmp/opencoven-unix-broker\"\n(umask 077 && mkdir \"$broker_root\")\ncc -std=c11 -D_DARWIN_C_SOURCE -Wall -Wextra -Werror -O2 \\\n scripts/unix-artifact-handoff.c \\\n -o \"$broker_root/unix-artifact-handoff\"\nchmod 500 \"$broker_root/unix-artifact-handoff\"\n" + run: "set -euo pipefail\nnode --input-type=module <<'EOF'\nimport { createHash } from 'node:crypto';\nimport { lstatSync, readFileSync } from 'node:fs';\nconst expected = new Map([\n ['scripts/contract-canary.mjs', [40618, 'a4c2fe0a5eb6a5ff4653de5374c34c0fb46907c6806a5d23b86d8b37206ef958']],\n ['scripts/executable-resolution.mjs', [9154, '31e3c412ff8c835f14522f36a59e91f4a4ba82913210ae8e3b4455217503f430']],\n ['scripts/owned-temp-directory.mjs', [7762, '95f546ef9ed614f2a0f55d356ddfc54c943fc53b595b4eebebfcbd4db68e5c0b']],\n ['scripts/phase1-artifact-secret-scan.mjs', [21183, 'be0ec302b9c4372f232d6bd1efcba873fd3380cc5de7f756cd0b9eeeec07222a']],\n ['scripts/phase1-conformance-lock.mjs', [48960, '92f981c43f75bc65c81e9e9ee16084aae658617b929d451a9db0d7c9e6bedbe2']],\n ['scripts/phase1-conformance.mjs', [219462, 'fd90e35308ea6b8dd0488cb874d00d7ad40aa16b33e38b46a9a76c3ea13d5056']],\n ['scripts/phase1-evidence-contract.mjs', [15088, '24180ae03835fa6aac45559682adb3c1e626bab76466eddc55b9e2300f0a2b7f']],\n ['scripts/phase1-evidence-runtime.mjs', [6572, 'b09a0d20abc7ebbc6289c57c985fd42b8a4b5d196895bc035b8fca40281d9315']],\n ['scripts/phase1-linux-secret-service.mjs', [4270, 'ddf834c6f57853c5116b4b1f345952a218ff0687c5d741737c68e20bc2ecda92']],\n ['scripts/phase1-macos-keychain.mjs', [5091, 'ab0c2dd08cf606d9502f5da206175707d471d99f484e8c8c79b5b08a5772b9a4']],\n ['scripts/phase1-process-supervisor.mjs', [3820, '16b51fb1a33b4bfef98daca549aacf5dc2d2c098cfbd664753b69c940d1e6f6c']],\n ['scripts/phase1-schema-v2-evidence.mjs', [52505, '0aede2ab3abd76fabf5ac61d64d2dbaaffa497c8647b82236403de16a47751c8']],\n ['scripts/phase1-schema-v2-producer.mjs', [234449, '11b5a90250556e2709c078089be3251fd586bad60c9d16cdfd5d35151e36a3a2']],\n ['scripts/process-owned-artifact-root.mjs', [13061, '103cc789f12a6bbde16b2414aecf05813d9d28a2c40c7d6eaa2073b86e8e5d77']],\n ['scripts/supervised-exec.mjs', [2875, 'a5edfd985b934d3b46247a0da3141682c411d30bb582edf87ae7b29791dad65b']],\n ['scripts/supervisor-status.mjs', [854, 'ac332ca7b6b040ecc846088bb3a6ad5e7112a0454eb3ea71d2a819d55e64254e']],\n ['scripts/phase1-linux-secret-service.sh', [5650, '83ce19c0dd6da5002f6853fa37addb4fc2d39f3d17beee1b1c39e1fce232b476']],\n ['scripts/unix-artifact-handoff.c', [18704, '2a003f9aa1d1886b9a593371a73cb65fe3a4a8b703f1c59fec8a27694367b7fc']],\n ['scripts/unix-producer-command.sh', [3223, 'ce9ec2ff00947f3ec0db53f144c99d34bc27de6085062d00dccff7c934c2e3c8']],\n ['scripts/unix-producer-supervisor.sh', [29424, 'b73036415744c80ed27d5667f255ceea149096ca517b47c93a154299802206ff']],\n]);\nfor (const [path, [size, digest]] of expected) {\n const stats = lstatSync(path);\n const bytes = readFileSync(path);\n if (\n !stats.isFile() ||\n stats.isSymbolicLink() ||\n stats.nlink !== 1 ||\n bytes.byteLength !== size ||\n createHash('sha256').update(bytes).digest('hex') !== digest\n ) {\n throw new Error('Trusted Unix supervisor source bytes do not match');\n }\n}\nconsole.log('Frozen harness module graph verified.');\nEOF\nbroker_root=\"/tmp/opencoven-unix-broker\"\n(umask 077 && mkdir \"$broker_root\")\ncc -std=c11 -D_DARWIN_C_SOURCE -Wall -Wextra -Werror -O2 \\\n scripts/unix-artifact-handoff.c \\\n -o \"$broker_root/unix-artifact-handoff\"\nchmod 500 \"$broker_root/unix-artifact-handoff\"\n" - name: Compute reviewed Unix tool path id: unix-tool-path if: matrix.platform != 'win32-x64' diff --git a/docs/phase1-conformance.md b/docs/phase1-conformance.md index b9a9a1a3..79e87857 100644 --- a/docs/phase1-conformance.md +++ b/docs/phase1-conformance.md @@ -1978,7 +1978,10 @@ polling, traversal, identity, cleanup, or diagnostic bound is widened. No platform evidence is claimed until an SDK validator commit contains a compatible producer entry naming the reviewed Chat producer commit, harness -bytes, workflow bytes, protected environment, and artifact conventions. A +bytes, workflow bytes, protected environment, and artifact conventions. The +platform producer clones that reviewed Chat commit from the workflow checkout +before running observations or packaging, instead of trusting the triggering +checkout HEAD directly. A missing, malformed, stale, or otherwise incompatible `validator_revision` fails before evidence publication. The SDK metadata update must also record the `validate-conformance-artifacts` and `attest-conformance-artifacts` job @@ -2020,7 +2023,7 @@ revision authorities can therefore have different workflow hashes: | File | Bytes | SHA-256 | | --- | ---: | --- | -| `.github/workflows/client-v1-conformance.yml` | 180,386 | `be7f36a7ce1b3dd6834b565e33825c5af410c49ed0e193ffaffda91ef79125b3` | +| `.github/workflows/client-v1-conformance.yml` | 180,394 | `3d37a3c78e5bf741764b6a0604423decde75d5e4351139a3c286382477b487e2` | | `scripts/contract-canary.mjs` | 40,618 | `a4c2fe0a5eb6a5ff4653de5374c34c0fb46907c6806a5d23b86d8b37206ef958` | | `scripts/executable-resolution.mjs` | 9,154 | `31e3c412ff8c835f14522f36a59e91f4a4ba82913210ae8e3b4455217503f430` | | `scripts/owned-temp-directory.mjs` | 7,762 | `95f546ef9ed614f2a0f55d356ddfc54c943fc53b595b4eebebfcbd4db68e5c0b` | @@ -2033,7 +2036,7 @@ revision authorities can therefore have different workflow hashes: | `scripts/phase1-macos-keychain.mjs` | 5,091 | `ab0c2dd08cf606d9502f5da206175707d471d99f484e8c8c79b5b08a5772b9a4` | | `scripts/phase1-process-supervisor.mjs` | 3,820 | `16b51fb1a33b4bfef98daca549aacf5dc2d2c098cfbd664753b69c940d1e6f6c` | | `scripts/phase1-schema-v2-evidence.mjs` | 52,505 | `0aede2ab3abd76fabf5ac61d64d2dbaaffa497c8647b82236403de16a47751c8` | -| `scripts/phase1-schema-v2-producer.mjs` | 233,914 | `ea32a0b7d43f0558521de091666d66960bc033afafd5e619a728da1ec5d45929` | +| `scripts/phase1-schema-v2-producer.mjs` | 234,449 | `11b5a90250556e2709c078089be3251fd586bad60c9d16cdfd5d35151e36a3a2` | | `scripts/process-owned-artifact-root.mjs` | 13,061 | `103cc789f12a6bbde16b2414aecf05813d9d28a2c40c7d6eaa2073b86e8e5d77` | | `scripts/supervised-exec.mjs` | 2,875 | `a5edfd985b934d3b46247a0da3141682c411d30bb582edf87ae7b29791dad65b` | | `scripts/supervisor-status.mjs` | 854 | `ac332ca7b6b040ecc846088bb3a6ad5e7112a0454eb3ea71d2a819d55e64254e` | diff --git a/phase1-conformance.lock.json b/phase1-conformance.lock.json index 666ae9a5..08ea04c3 100644 --- a/phase1-conformance.lock.json +++ b/phase1-conformance.lock.json @@ -81,8 +81,8 @@ }, { "path": "scripts/phase1-schema-v2-producer.mjs", - "blob": "720445dfaf8ceb071f966bccbc8111a350c31ed0", - "sha256": "ea32a0b7d43f0558521de091666d66960bc033afafd5e619a728da1ec5d45929" + "blob": "4cc226cb7c946ee664174d37de225831530b9ec0", + "sha256": "11b5a90250556e2709c078089be3251fd586bad60c9d16cdfd5d35151e36a3a2" }, { "path": "scripts/phase1-linux-secret-service.mjs", @@ -146,8 +146,8 @@ }, { "path": ".github/workflows/client-v1-conformance.yml", - "blob": "2204f8f5f4e9bc9b787e23e624038c376d518f7f", - "sha256": "be7f36a7ce1b3dd6834b565e33825c5af410c49ed0e193ffaffda91ef79125b3" + "blob": "4b318d246dc9e9c7b13e76d2d118b048684fc9d8", + "sha256": "3d37a3c78e5bf741764b6a0604423decde75d5e4351139a3c286382477b487e2" } ], "productionDeltas": [ diff --git a/scripts/phase1-schema-v2-producer.mjs b/scripts/phase1-schema-v2-producer.mjs index 720445df..4cc226cb 100644 --- a/scripts/phase1-schema-v2-producer.mjs +++ b/scripts/phase1-schema-v2-producer.mjs @@ -3317,8 +3317,25 @@ export function readSchemaV2ProducerIdentity(sourceRoot) { }; } -async function cloneProducerCheckout(artifactRoot, sourceRoot, environment) { - const identity = readSchemaV2ProducerIdentity(sourceRoot); +function reviewedSchemaV2ProducerIdentity(sdkContract) { + const producer = sdkContract.contract.assertEvidenceProducerCompatibility(sdkContract.frozenLock); + if ( + producer === null || + typeof producer !== 'object' || + producer.repository !== 'OpenCoven/chat' || + !/^[0-9a-f]{40}$/u.test(producer.commit ?? '') || + !/^[0-9a-f]{40}$/u.test(producer.tree ?? '') + ) { + throw new Error('Schema-v2 producer identity is invalid.'); + } + return { + revision: producer.commit, + tree: producer.tree, + }; +} + +async function cloneProducerCheckout(artifactRoot, sourceRoot, sdkContract, environment) { + const identity = reviewedSchemaV2ProducerIdentity(sdkContract); const producerRoot = resolve(artifactRoot.rootPath, 'checkouts', 'producer'); await cloneExactCheckout({ artifactRoot, @@ -3454,12 +3471,6 @@ async function createExactCheckouts(artifactRoot, options, lock, environment) { return validatorIdentity; }, ); - Object.assign( - roots, - await runSchemaV2StageAsync('phase1.stage.checkouts.producer.failed', () => - cloneProducerCheckout(artifactRoot, options.chatSourceRoot, environment), - ), - ); } return roots; } @@ -6264,14 +6275,6 @@ export async function runSchemaV2Conformance(options, lock, harnessAuthorityVeri roots = await createExactCheckouts(executionRoot, options, lock, environment); if (schemaV2) { activeStage = 'phase1.stage.evidence-authority.failed'; - runSchemaV2PreflightStage('phase1.stage.evidence-authority.producer', () => - validateSchemaV2AuthorityCheckouts({ - lock, - harnessRoot: projectRoot, - producerRoot: roots.producerRoot, - producerIdentity: roots.producerIdentity, - }), - ); sdkContract = await runSchemaV2StageAsync('phase1.stage.evidence-authority.validator', () => loadSdkEvidenceContract({ validatorRoot: roots.validatorRoot, @@ -6283,11 +6286,25 @@ export async function runSchemaV2Conformance(options, lock, harnessAuthorityVeri }), ); runSchemaV2PreflightStage('phase1.stage.evidence-authority.compatibility', () => - sdkContract.contract.assertEvidenceProducerCompatibility(sdkContract.frozenLock), + reviewedSchemaV2ProducerIdentity(sdkContract), ); runSchemaV2PreflightStage('phase1.stage.evidence-authority.lock', () => assertSdkContractMatchesPhase1Lock(sdkContract, lock), ); + Object.assign( + roots, + await runSchemaV2StageAsync('phase1.stage.checkouts.producer.failed', () => + cloneProducerCheckout(executionRoot, options.chatSourceRoot, sdkContract, environment), + ), + ); + runSchemaV2PreflightStage('phase1.stage.evidence-authority.producer', () => + validateSchemaV2AuthorityCheckouts({ + lock, + harnessRoot: projectRoot, + producerRoot: roots.producerRoot, + producerIdentity: roots.producerIdentity, + }), + ); producer = await runSchemaV2StageAsync('phase1.stage.evidence-authority.checkout', () => verifySchemaV2ProducerCheckout({ producerRoot: roots.producerRoot, diff --git a/src/phase1-conformance-lock.test.ts b/src/phase1-conformance-lock.test.ts index 9a72369a..deee75d9 100644 --- a/src/phase1-conformance-lock.test.ts +++ b/src/phase1-conformance-lock.test.ts @@ -105,8 +105,8 @@ const expectedBehaviorAuthority = { }, { path: 'scripts/phase1-schema-v2-producer.mjs', - blob: '720445dfaf8ceb071f966bccbc8111a350c31ed0', - sha256: 'ea32a0b7d43f0558521de091666d66960bc033afafd5e619a728da1ec5d45929', + blob: '4cc226cb7c946ee664174d37de225831530b9ec0', + sha256: '11b5a90250556e2709c078089be3251fd586bad60c9d16cdfd5d35151e36a3a2', }, { path: 'scripts/unix-producer-supervisor.sh', @@ -135,8 +135,8 @@ const expectedBehaviorAuthority = { }, { path: '.github/workflows/client-v1-conformance.yml', - blob: '2204f8f5f4e9bc9b787e23e624038c376d518f7f', - sha256: 'be7f36a7ce1b3dd6834b565e33825c5af410c49ed0e193ffaffda91ef79125b3', + blob: '4b318d246dc9e9c7b13e76d2d118b048684fc9d8', + sha256: '3d37a3c78e5bf741764b6a0604423decde75d5e4351139a3c286382477b487e2', }, { path: 'scripts/process-owned-artifact-root.mjs', diff --git a/src/phase1-conformance.test.ts b/src/phase1-conformance.test.ts index 773eeac0..6c3ae77b 100644 --- a/src/phase1-conformance.test.ts +++ b/src/phase1-conformance.test.ts @@ -1948,7 +1948,7 @@ describe('Phase 1 real-authority conformance harness', () => { ); }); - test('binds schema-v2 producer identity to the supplied workflow checkout', async () => { + test('checks out the schema-v2 producer from the validator-approved Chat revision', async () => { const producerModulePath = '../scripts/phase1-schema-v2-producer.mjs'; const { readSchemaV2ProducerIdentity } = await import(producerModulePath); const revision = execFileSync('git', ['rev-parse', 'HEAD'], { @@ -1965,8 +1965,14 @@ describe('Phase 1 real-authority conformance harness', () => { resolve(projectRoot, 'scripts', 'phase1-schema-v2-producer.mjs'), 'utf8', ); + expect(source).toContain('const identity = reviewedSchemaV2ProducerIdentity(sdkContract);'); expect(source).toContain( - 'cloneProducerCheckout(artifactRoot, options.chatSourceRoot, environment)', + 'cloneProducerCheckout(executionRoot, options.chatSourceRoot, sdkContract, environment)', + ); + expect(source.indexOf('loadSdkEvidenceContract({')).toBeLessThan( + source.indexOf( + 'cloneProducerCheckout(executionRoot, options.chatSourceRoot, sdkContract, environment)', + ), ); });