From 7af45e33c2331bca1d7881045ef9c12d123e02f0 Mon Sep 17 00:00:00 2001 From: Val Alexander <68980965+BunsDev@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:40:31 -0500 Subject: [PATCH 1/4] fix(conformance): classify isolation failures with bounded diagnostics --- .github/workflows/client-v1-conformance.yml | 8 +- docs/phase1-conformance.md | 8 +- docs/roadmap.md | 19 ++- phase1-conformance.lock.json | 16 +-- scripts/phase1-conformance.mjs | 13 ++ scripts/phase1-evidence-runtime.mjs | 28 ++-- scripts/phase1-schema-v2-producer.mjs | 13 ++ src/phase1-conformance-lock.test.ts | 12 +- src/phase1-evidence-runtime.test.ts | 4 +- src/phase1-isolation-diagnostics.test.ts | 143 ++++++++++++++++++++ 10 files changed, 229 insertions(+), 35 deletions(-) create mode 100644 src/phase1-isolation-diagnostics.test.ts diff --git a/.github/workflows/client-v1-conformance.yml b/.github/workflows/client-v1-conformance.yml index 9db15bd6..3b47508d 100644 --- a/.github/workflows/client-v1-conformance.yml +++ b/.github/workflows/client-v1-conformance.yml @@ -1178,14 +1178,14 @@ jobs: @('scripts\owned-temp-directory.mjs', 6965, 'a9c55c85cf2b7d70310d278bafd2c8e7695d66f4ae38b9c3f1f12fce0b442095'), @('scripts\phase1-artifact-secret-scan.mjs', 21183, 'be0ec302b9c4372f232d6bd1efcba873fd3380cc5de7f756cd0b9eeeec07222a'), @('scripts\phase1-conformance-lock.mjs', 48960, '92f981c43f75bc65c81e9e9ee16084aae658617b929d451a9db0d7c9e6bedbe2'), - @('scripts\phase1-conformance.mjs', 218262, 'e18e7f45b44738a4a100f76d6b8548dd9d8e1d84796131c71dc8dbde193083c4'), + @('scripts\phase1-conformance.mjs', 219211, 'daaa5fb660765b9d6c21bea4e4a3c9ebf1a92f14f052b7ed96593f579c7534ad'), @('scripts\phase1-evidence-contract.mjs', 15088, '24180ae03835fa6aac45559682adb3c1e626bab76466eddc55b9e2300f0a2b7f'), - @('scripts\phase1-evidence-runtime.mjs', 6078, '3d227c354e6d908c5912d2b8244336e3b79c3bbd4dec79b0ad219ed65b8cb159'), + @('scripts\phase1-evidence-runtime.mjs', 6523, '9b1f61c83e8bacf22aaf3fb9f670c879b4bd78be002b2d258cf80af57064a7c8'), @('scripts\phase1-linux-secret-service.mjs', 4270, 'ddf834c6f57853c5116b4b1f345952a218ff0687c5d741737c68e20bc2ecda92'), @('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', 231880, '3da17a07b70ec3b2468072fd81f4023c7eead42e6496a953d7b862fe19abd4ec'), + @('scripts\phase1-schema-v2-producer.mjs', 232829, '9b2b295170d37f45b5d860fd8cd82c65ab6538caa7cd8d599ce19c8680643174'), @('scripts\process-owned-artifact-root.mjs', 11788, '426c2c8e36dc3bffddb35a565c07a60998b010660f6248ebc4264d9c4b502624'), @('scripts\supervised-exec.mjs', 2875, 'a5edfd985b934d3b46247a0da3141682c411d30bb582edf87ae7b29791dad65b'), @('scripts\supervisor-status.mjs', 854, 'ac332ca7b6b040ecc846088bb3a6ad5e7112a0454eb3ea71d2a819d55e64254e') @@ -1910,7 +1910,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', [6965, 'a9c55c85cf2b7d70310d278bafd2c8e7695d66f4ae38b9c3f1f12fce0b442095']],\n ['scripts/phase1-artifact-secret-scan.mjs', [21183, 'be0ec302b9c4372f232d6bd1efcba873fd3380cc5de7f756cd0b9eeeec07222a']],\n ['scripts/phase1-conformance-lock.mjs', [48960, '92f981c43f75bc65c81e9e9ee16084aae658617b929d451a9db0d7c9e6bedbe2']],\n ['scripts/phase1-conformance.mjs', [218262, 'e18e7f45b44738a4a100f76d6b8548dd9d8e1d84796131c71dc8dbde193083c4']],\n ['scripts/phase1-evidence-contract.mjs', [15088, '24180ae03835fa6aac45559682adb3c1e626bab76466eddc55b9e2300f0a2b7f']],\n ['scripts/phase1-evidence-runtime.mjs', [6078, '3d227c354e6d908c5912d2b8244336e3b79c3bbd4dec79b0ad219ed65b8cb159']],\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', [231880, '3da17a07b70ec3b2468072fd81f4023c7eead42e6496a953d7b862fe19abd4ec']],\n ['scripts/process-owned-artifact-root.mjs', [11788, '426c2c8e36dc3bffddb35a565c07a60998b010660f6248ebc4264d9c4b502624']],\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', [6965, 'a9c55c85cf2b7d70310d278bafd2c8e7695d66f4ae38b9c3f1f12fce0b442095']],\n ['scripts/phase1-artifact-secret-scan.mjs', [21183, 'be0ec302b9c4372f232d6bd1efcba873fd3380cc5de7f756cd0b9eeeec07222a']],\n ['scripts/phase1-conformance-lock.mjs', [48960, '92f981c43f75bc65c81e9e9ee16084aae658617b929d451a9db0d7c9e6bedbe2']],\n ['scripts/phase1-conformance.mjs', [219211, 'daaa5fb660765b9d6c21bea4e4a3c9ebf1a92f14f052b7ed96593f579c7534ad']],\n ['scripts/phase1-evidence-contract.mjs', [15088, '24180ae03835fa6aac45559682adb3c1e626bab76466eddc55b9e2300f0a2b7f']],\n ['scripts/phase1-evidence-runtime.mjs', [6523, '9b1f61c83e8bacf22aaf3fb9f670c879b4bd78be002b2d258cf80af57064a7c8']],\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', [232829, '9b2b295170d37f45b5d860fd8cd82c65ab6538caa7cd8d599ce19c8680643174']],\n ['scripts/process-owned-artifact-root.mjs', [11788, '426c2c8e36dc3bffddb35a565c07a60998b010660f6248ebc4264d9c4b502624']],\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 44bcfbba..43932e88 100644 --- a/docs/phase1-conformance.md +++ b/docs/phase1-conformance.md @@ -1969,20 +1969,20 @@ revision authorities can therefore have different workflow hashes: | File | Bytes | SHA-256 | | --- | ---: | --- | -| `.github/workflows/client-v1-conformance.yml` | 177,934 | `bd8331c6d82e22b7618ee5beda8fd10fad4e022e794c8d762dc62cf3f27d5049` | +| `.github/workflows/client-v1-conformance.yml` | 177,934 | `e1f6c32f587dd8dca1a2530902d8194002fbd2e855f0579294c51ac1fe7c25dc` | | `scripts/contract-canary.mjs` | 40,618 | `a4c2fe0a5eb6a5ff4653de5374c34c0fb46907c6806a5d23b86d8b37206ef958` | | `scripts/executable-resolution.mjs` | 9,154 | `31e3c412ff8c835f14522f36a59e91f4a4ba82913210ae8e3b4455217503f430` | | `scripts/owned-temp-directory.mjs` | 6,965 | `a9c55c85cf2b7d70310d278bafd2c8e7695d66f4ae38b9c3f1f12fce0b442095` | | `scripts/phase1-artifact-secret-scan.mjs` | 21,183 | `be0ec302b9c4372f232d6bd1efcba873fd3380cc5de7f756cd0b9eeeec07222a` | | `scripts/phase1-conformance-lock.mjs` | 48,960 | `92f981c43f75bc65c81e9e9ee16084aae658617b929d451a9db0d7c9e6bedbe2` | -| `scripts/phase1-conformance.mjs` | 218,262 | `e18e7f45b44738a4a100f76d6b8548dd9d8e1d84796131c71dc8dbde193083c4` | +| `scripts/phase1-conformance.mjs` | 219,211 | `daaa5fb660765b9d6c21bea4e4a3c9ebf1a92f14f052b7ed96593f579c7534ad` | | `scripts/phase1-evidence-contract.mjs` | 15,088 | `24180ae03835fa6aac45559682adb3c1e626bab76466eddc55b9e2300f0a2b7f` | -| `scripts/phase1-evidence-runtime.mjs` | 6,078 | `3d227c354e6d908c5912d2b8244336e3b79c3bbd4dec79b0ad219ed65b8cb159` | +| `scripts/phase1-evidence-runtime.mjs` | 6,523 | `9b1f61c83e8bacf22aaf3fb9f670c879b4bd78be002b2d258cf80af57064a7c8` | | `scripts/phase1-linux-secret-service.mjs` | 4,270 | `ddf834c6f57853c5116b4b1f345952a218ff0687c5d741737c68e20bc2ecda92` | | `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` | 231,880 | `3da17a07b70ec3b2468072fd81f4023c7eead42e6496a953d7b862fe19abd4ec` | +| `scripts/phase1-schema-v2-producer.mjs` | 232,829 | `9b2b295170d37f45b5d860fd8cd82c65ab6538caa7cd8d599ce19c8680643174` | | `scripts/process-owned-artifact-root.mjs` | 11,788 | `426c2c8e36dc3bffddb35a565c07a60998b010660f6248ebc4264d9c4b502624` | | `scripts/supervised-exec.mjs` | 2,875 | `a5edfd985b934d3b46247a0da3141682c411d30bb582edf87ae7b29791dad65b` | | `scripts/supervisor-status.mjs` | 854 | `ac332ca7b6b040ecc846088bb3a6ad5e7112a0454eb3ea71d2a819d55e64254e` | diff --git a/docs/roadmap.md b/docs/roadmap.md index 8b4f682a..99282097 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,6 +1,23 @@ # Delivery roadmap and consolidation audit -## Current delivery and authority checkpoint, 2026-09-15 +## Current delivery and consolidation checkpoint, 2026-09-16 + +GitHub issues and repository roadmaps hold current ownership, blockers, and evidence. Original acceptance criteria and historical records below remain preserved. + +- Chat [#297](https://github.com/OpenCoven/chat/pull/297) landed at `43504f646e7ffe01ee6019d468401f99be839420`. Its complete tree equals signed reviewed head `1e007af60a6224d8d4f80d06cd3c974064cabd48`, whose direct executable source is `6e74fb60e44549b91aa75fb956eb63a85dc668fc`. All eleven jobs in [CI35100844684](https://github.com/OpenCoven/chat/actions/runs/35100844684) passed, including the native profile lifecycle, owner cleanup, installation roundtrip, and residual confinement controls. Local sequential suites passed 2,082 tests with 98 skips; default-parallel PowerShell timeouts remain recorded, with deadlines unchanged. +- SDK [#290](https://github.com/OpenCoven/sdk/pull/290) landed at `ca3f4ed1ab7f5732ff51e30c29ddbcab529eee0e`. Its signed reviewed head `0999547bf9c24f3a8791bfa2251b1341332d608b` passed all eight CI checks, including 2,675 tests in both pinned-runtime normal and coverage runs. Three documentation review findings were corrected and resolved. Both validator scopes were rotated and read back at the actual merge. +- Fresh protected [run35111662551](https://github.com/OpenCoven/chat/actions/runs/35111662551) targets those exact Chat and SDK merges. The frozen workflow, run-bound supervisor archive, and binary size/SHA-256 passed independent authentication. Protected environment approval was verified by readback. The run failed in Windows at `phase1.stage.evidence-authority.isolation.failed`, with no Windows record. Linux and macOS records independently passed exact identities, privacy, Cave timing, and all 197 ordered assertions each. Downstream validation, attestation, and aggregation were skipped; no accepted aggregate exists. +- The latest main-equivalent native Chat app built and opened from the preserved Chat #297 worktree. Its exact running executable, familiar sidebar, saved conversation, and Coven 0.4.2 / coven-code 0.7.0 connection were verified. This local launch is not protected conformance or publication acceptance. +- Historical run35100084575 used Chat #302 and SDK #288. Linux and macOS records passed independent identity, timing, privacy, and all 197 ordered assertions each. Windows failed installation secure-store preflight and deletion-purpose child-open cleanup, uploaded no record, and downstream validation, attestation, and aggregation were skipped. That result predates the current Chat #297 repair. +- The working inventory includes nine Chat and three SDK worktrees after creating a dedicated, locked isolation-diagnostics tree. Counts are an audit snapshot, not retirement proof. Preserve active, dirty, primary, open-PR, and ownership-uncertain state. Chat #86 remains parked for feature and vendor-artifact reconciliation; WorkOS #303 and its implementation tree remain active. The retired HPKE tip `c4ab99e` is preserved in a restore-tested full-history bundle, while selective managed iterator/authority continuity remains open. SDK #242's clean tree remains ownership-uncertain. Consolidation is incomplete. + +The next protected run needs bounded isolation diagnostics. Thirteen fixed categories distinguish invalid or duplicate opaque IDs, invalid or changed native credential state, and missing/invalid snapshots, path mismatches, or digest changes for each operator root. The original acceptance predicates remain enforced; errors expose no paths, digests, or input values. This instrumentation does not yet identify or repair the Windows isolation failure. Land the reviewed source and its binding, rebind SDK to the actual Chat delivery, rotate both validator scopes, and obtain fresh protected evidence. + +Chat [#304](https://github.com/OpenCoven/chat/pull/304) was closed after verifying that its complete tree equals main and its changed-file list is empty; its remote branch is preserved. Remaining work includes ownership confirmation before retirement, Chat #86 reconciliation, the managed HPKE iterator authority gap, and the Project 9 tracking refresh. + +Candidate `96804bc4`, counterpart identities, and publication restrictions remain frozen. Follow [Chat #219](https://github.com/OpenCoven/chat/issues/219), [SDK #38](https://github.com/OpenCoven/sdk/issues/38), and [SDK #45](https://github.com/OpenCoven/sdk/issues/45). Preserve this chat and active worktrees. + +## Historical delivery and authority checkpoint, 2026-09-15 (Chat #293) Chat [#291](https://github.com/OpenCoven/chat/pull/291) landed as `490908c46bf6f3b00c00aef0a5edb27af426e7ee` after all eleven jobs in diff --git a/phase1-conformance.lock.json b/phase1-conformance.lock.json index 8907bfb6..3f81277d 100644 --- a/phase1-conformance.lock.json +++ b/phase1-conformance.lock.json @@ -26,8 +26,8 @@ "files": [ { "path": "scripts/phase1-conformance.mjs", - "blob": "bb72abd30263fc7d756a392cd2f67a1fcd7c622f", - "sha256": "e18e7f45b44738a4a100f76d6b8548dd9d8e1d84796131c71dc8dbde193083c4" + "blob": "327a6952259a7d171517c66367206a465f8a8c0f", + "sha256": "daaa5fb660765b9d6c21bea4e4a3c9ebf1a92f14f052b7ed96593f579c7534ad" }, { "path": "scripts/phase1-conformance-launcher.sh", @@ -71,8 +71,8 @@ }, { "path": "scripts/phase1-evidence-runtime.mjs", - "blob": "56767afb7b5e04bf5acf3a902f2ce196dbc7b960", - "sha256": "3d227c354e6d908c5912d2b8244336e3b79c3bbd4dec79b0ad219ed65b8cb159" + "blob": "b4b6a256d2f62fc7542e04106acfbd5b0df01f36", + "sha256": "9b1f61c83e8bacf22aaf3fb9f670c879b4bd78be002b2d258cf80af57064a7c8" }, { "path": "scripts/phase1-schema-v2-evidence.mjs", @@ -81,8 +81,8 @@ }, { "path": "scripts/phase1-schema-v2-producer.mjs", - "blob": "f9799f2a66bf5e182c72c49a8b325619d076bd70", - "sha256": "3da17a07b70ec3b2468072fd81f4023c7eead42e6496a953d7b862fe19abd4ec" + "blob": "ad3605e1d7a72928dfca14a5063ed37625ddb613", + "sha256": "9b2b295170d37f45b5d860fd8cd82c65ab6538caa7cd8d599ce19c8680643174" }, { "path": "scripts/phase1-linux-secret-service.mjs", @@ -146,8 +146,8 @@ }, { "path": ".github/workflows/client-v1-conformance.yml", - "blob": "9db15bd6fa0f8f3baa660b551e68d83862bee09d", - "sha256": "bd8331c6d82e22b7618ee5beda8fd10fad4e022e794c8d762dc62cf3f27d5049" + "blob": "3b47508d6f0bb541aa042f426da36ae647fb5f4f", + "sha256": "e1f6c32f587dd8dca1a2530902d8194002fbd2e855f0579294c51ac1fe7c25dc" } ], "productionDeltas": [ diff --git a/scripts/phase1-conformance.mjs b/scripts/phase1-conformance.mjs index bb72abd3..327a6952 100644 --- a/scripts/phase1-conformance.mjs +++ b/scripts/phase1-conformance.mjs @@ -364,6 +364,19 @@ const publicPhase1DiagnosticIds = new Set([ 'phase1.stage.evidence-authority.report.failed', 'phase1.stage.evidence-authority.operator-state.failed', 'phase1.stage.evidence-authority.isolation.failed', + 'phase1.stage.evidence-authority.isolation.opaque-ids.invalid', + 'phase1.stage.evidence-authority.isolation.opaque-ids.duplicate', + 'phase1.stage.evidence-authority.isolation.native-credential-store.invalid', + 'phase1.stage.evidence-authority.isolation.native-credential-store.changed', + 'phase1.stage.evidence-authority.isolation.operator.cave-home.invalid', + 'phase1.stage.evidence-authority.isolation.operator.cave-home.path', + 'phase1.stage.evidence-authority.isolation.operator.cave-home.changed', + 'phase1.stage.evidence-authority.isolation.operator.coven-home.invalid', + 'phase1.stage.evidence-authority.isolation.operator.coven-home.path', + 'phase1.stage.evidence-authority.isolation.operator.coven-home.changed', + 'phase1.stage.evidence-authority.isolation.operator.projects.invalid', + 'phase1.stage.evidence-authority.isolation.operator.projects.path', + 'phase1.stage.evidence-authority.isolation.operator.projects.changed', 'phase1.stage.evidence-authority.assertions.failed', 'phase1.stage.evidence-authority.build.failed', 'phase1.stage.evidence-authority.build.environment', diff --git a/scripts/phase1-evidence-runtime.mjs b/scripts/phase1-evidence-runtime.mjs index 56767afb..b4b6a256 100644 --- a/scripts/phase1-evidence-runtime.mjs +++ b/scripts/phase1-evidence-runtime.mjs @@ -144,17 +144,21 @@ export function buildIsolationEvidence({ if ( !Array.isArray(opaqueIds) || opaqueIds.length !== isolationRootIds.length || - opaqueIds.some((value) => typeof value !== 'string' || !opaqueIdPattern.test(value)) || - new Set(opaqueIds).size !== opaqueIds.length + opaqueIds.some((value) => typeof value !== 'string' || !opaqueIdPattern.test(value)) ) { - throw new Error('Isolation roots require four unique opaque identifiers.'); + throw new Error('phase1.stage.evidence-authority.isolation.opaque-ids.invalid'); + } + if (new Set(opaqueIds).size !== opaqueIds.length) { + throw new Error('phase1.stage.evidence-authority.isolation.opaque-ids.duplicate'); } if ( !digestPattern.test(nativeBeforeSha256 ?? '') || - !digestPattern.test(nativeAfterSha256 ?? '') || - nativeBeforeSha256 !== nativeAfterSha256 + !digestPattern.test(nativeAfterSha256 ?? '') ) { - throw new Error('Native credential state changed or is invalid.'); + throw new Error('phase1.stage.evidence-authority.isolation.native-credential-store.invalid'); + } + if (nativeBeforeSha256 !== nativeAfterSha256) { + throw new Error('phase1.stage.evidence-authority.isolation.native-credential-store.changed'); } const filesystemState = operatorStateIds.map((id) => { const before = operatorBefore?.[id]; @@ -162,12 +166,16 @@ export function buildIsolationEvidence({ if ( before === undefined || after === undefined || - before.path !== after.path || !digestPattern.test(before.sha256 ?? '') || - !digestPattern.test(after.sha256 ?? '') || - before.sha256 !== after.sha256 + !digestPattern.test(after.sha256 ?? '') ) { - throw new Error(`Operator state ${id} changed or is invalid.`); + throw new Error(`phase1.stage.evidence-authority.isolation.operator.${id}.invalid`); + } + if (before.path !== after.path) { + throw new Error(`phase1.stage.evidence-authority.isolation.operator.${id}.path`); + } + if (before.sha256 !== after.sha256) { + throw new Error(`phase1.stage.evidence-authority.isolation.operator.${id}.changed`); } return { id, diff --git a/scripts/phase1-schema-v2-producer.mjs b/scripts/phase1-schema-v2-producer.mjs index f9799f2a..ad3605e1 100644 --- a/scripts/phase1-schema-v2-producer.mjs +++ b/scripts/phase1-schema-v2-producer.mjs @@ -449,6 +449,19 @@ const publicFailureDiagnosticSet = new Set([ 'phase1.stage.evidence-authority.report.failed', 'phase1.stage.evidence-authority.operator-state.failed', 'phase1.stage.evidence-authority.isolation.failed', + 'phase1.stage.evidence-authority.isolation.opaque-ids.invalid', + 'phase1.stage.evidence-authority.isolation.opaque-ids.duplicate', + 'phase1.stage.evidence-authority.isolation.native-credential-store.invalid', + 'phase1.stage.evidence-authority.isolation.native-credential-store.changed', + 'phase1.stage.evidence-authority.isolation.operator.cave-home.invalid', + 'phase1.stage.evidence-authority.isolation.operator.cave-home.path', + 'phase1.stage.evidence-authority.isolation.operator.cave-home.changed', + 'phase1.stage.evidence-authority.isolation.operator.coven-home.invalid', + 'phase1.stage.evidence-authority.isolation.operator.coven-home.path', + 'phase1.stage.evidence-authority.isolation.operator.coven-home.changed', + 'phase1.stage.evidence-authority.isolation.operator.projects.invalid', + 'phase1.stage.evidence-authority.isolation.operator.projects.path', + 'phase1.stage.evidence-authority.isolation.operator.projects.changed', 'phase1.stage.evidence-authority.assertions.failed', 'phase1.stage.evidence-authority.build.failed', 'phase1.stage.evidence-authority.build.environment', diff --git a/src/phase1-conformance-lock.test.ts b/src/phase1-conformance-lock.test.ts index 72cab783..69f431c1 100644 --- a/src/phase1-conformance-lock.test.ts +++ b/src/phase1-conformance-lock.test.ts @@ -85,8 +85,8 @@ const expectedBehaviorAuthority = { files: [ { path: 'scripts/phase1-conformance.mjs', - blob: 'bb72abd30263fc7d756a392cd2f67a1fcd7c622f', - sha256: 'e18e7f45b44738a4a100f76d6b8548dd9d8e1d84796131c71dc8dbde193083c4', + blob: '327a6952259a7d171517c66367206a465f8a8c0f', + sha256: 'daaa5fb660765b9d6c21bea4e4a3c9ebf1a92f14f052b7ed96593f579c7534ad', }, { path: 'scripts/phase1-conformance-lock.mjs', @@ -100,8 +100,8 @@ const expectedBehaviorAuthority = { }, { path: 'scripts/phase1-schema-v2-producer.mjs', - blob: 'f9799f2a66bf5e182c72c49a8b325619d076bd70', - sha256: '3da17a07b70ec3b2468072fd81f4023c7eead42e6496a953d7b862fe19abd4ec', + blob: 'ad3605e1d7a72928dfca14a5063ed37625ddb613', + sha256: '9b2b295170d37f45b5d860fd8cd82c65ab6538caa7cd8d599ce19c8680643174', }, { path: 'scripts/unix-producer-supervisor.sh', @@ -130,8 +130,8 @@ const expectedBehaviorAuthority = { }, { path: '.github/workflows/client-v1-conformance.yml', - blob: '9db15bd6fa0f8f3baa660b551e68d83862bee09d', - sha256: 'bd8331c6d82e22b7618ee5beda8fd10fad4e022e794c8d762dc62cf3f27d5049', + blob: '3b47508d6f0bb541aa042f426da36ae647fb5f4f', + sha256: 'e1f6c32f587dd8dca1a2530902d8194002fbd2e855f0579294c51ac1fe7c25dc', }, { path: 'scripts/process-owned-artifact-root.mjs', diff --git a/src/phase1-evidence-runtime.test.ts b/src/phase1-evidence-runtime.test.ts index 974ce798..0ba2917c 100644 --- a/src/phase1-evidence-runtime.test.ts +++ b/src/phase1-evidence-runtime.test.ts @@ -68,7 +68,7 @@ describe('Phase 1 evidence runtime isolation', () => { nativeAfterSha256: 'a'.repeat(64), opaqueIds: ['1'.repeat(32), '2'.repeat(32), '3'.repeat(32), '4'.repeat(32)], }), - ).toThrow(/operator state/iu); + ).toThrow(/isolation\.operator\.cave-home\.changed/u); expect(() => buildIsolationEvidence({ operatorBefore: before, @@ -77,7 +77,7 @@ describe('Phase 1 evidence runtime isolation', () => { nativeAfterSha256: 'b'.repeat(64), opaqueIds: ['1'.repeat(32), '2'.repeat(32), '3'.repeat(32), '4'.repeat(32)], }), - ).toThrow(/native credential state/iu); + ).toThrow(/isolation\.native-credential-store\.changed/u); }); test('rejects duplicate or non-opaque isolation identifiers', () => { diff --git a/src/phase1-isolation-diagnostics.test.ts b/src/phase1-isolation-diagnostics.test.ts new file mode 100644 index 00000000..0015677b --- /dev/null +++ b/src/phase1-isolation-diagnostics.test.ts @@ -0,0 +1,143 @@ +import { describe, expect, test } from 'vitest'; +import { + extractVerifiedRunnerDiagnostic, + publicPhase1FailureDiagnostic, + runPublicPhase1StageAsync, +} from '../scripts/phase1-conformance.mjs'; +import { buildIsolationEvidence } from '../scripts/phase1-evidence-runtime.mjs'; +// @ts-expect-error The executable script intentionally has no declaration file. +import * as producer from '../scripts/phase1-schema-v2-producer.mjs'; + +type Input = Parameters[0]; +const prefix = 'phase1.stage.evidence-authority.isolation'; +const ids = ['cave-home', 'coven-home', 'projects'] as const; +function input(): Input { + const state = { + 'cave-home': { path: '/private/cave', sha256: 'a'.repeat(64) }, + 'coven-home': { path: '/private/coven', sha256: 'b'.repeat(64) }, + projects: { path: '/private/projects', sha256: 'c'.repeat(64) }, + }; + return { + operatorBefore: structuredClone(state), + operatorAfter: structuredClone(state), + nativeBeforeSha256: 'd'.repeat(64), + nativeAfterSha256: 'd'.repeat(64), + opaqueIds: ['1'.repeat(32), '2'.repeat(32), '3'.repeat(32), '4'.repeat(32)], + }; +} +const cases: Array<{ name: string; category: string; mutate: (value: Input) => void }> = [ + { + name: 'missing opaque root', + category: 'opaque-ids.invalid', + mutate: (v) => { + v.opaqueIds.pop(); + }, + }, + { + name: 'private opaque root', + category: 'opaque-ids.invalid', + mutate: (v) => { + v.opaqueIds[0] = '/private/root'; + }, + }, + { + name: 'duplicate opaque roots', + category: 'opaque-ids.duplicate', + mutate: (v) => { + v.opaqueIds[0] = '2'.repeat(32); + }, + }, + { + name: 'invalid native before digest', + category: 'native-credential-store.invalid', + mutate: (v) => { + v.nativeBeforeSha256 = '/private/credential'; + }, + }, + { + name: 'invalid native after digest', + category: 'native-credential-store.invalid', + mutate: (v) => { + v.nativeAfterSha256 = '/private/credential'; + }, + }, + { + name: 'changed native digest', + category: 'native-credential-store.changed', + mutate: (v) => { + v.nativeAfterSha256 = 'e'.repeat(64); + }, + }, +]; +for (const id of ids) { + for (const side of ['operatorBefore', 'operatorAfter'] as const) { + cases.push({ + name: `${id} missing ${side}`, + category: `operator.${id}.invalid`, + mutate: (v) => { + Reflect.deleteProperty(v[side], id); + }, + }); + cases.push({ + name: `${id} invalid ${side} digest`, + category: `operator.${id}.invalid`, + mutate: (v) => { + v[side][id].sha256 = '/private/digest'; + }, + }); + } + cases.push({ + name: `${id} path mismatch`, + category: `operator.${id}.path`, + mutate: (v) => { + v.operatorAfter[id].path = '/private/replacement'; + }, + }); + cases.push({ + name: `${id} digest mismatch`, + category: `operator.${id}.changed`, + mutate: (v) => { + v.operatorAfter[id].sha256 = 'f'.repeat(64); + }, + }); +} + +describe('bounded evidence isolation diagnostics', () => { + test.each(cases)('preserves $name through the public runner', async ({ category, mutate }) => { + const value = input(); + mutate(value); + let failure: unknown; + try { + producer.runSchemaV2PreflightStage(`${prefix}.failed`, () => buildIsolationEvidence(value)); + } catch (error) { + failure = error; + } + expect(failure).toBeInstanceOf(Error); + const diagnostic = `${prefix}.${category}`; + const wrapped = producer.wrapInfrastructureFailure(failure, {}); + const caught = await runPublicPhase1StageAsync( + 'phase1.stage.schema-v2-production.failed', + async () => { + throw wrapped; + }, + ).catch((error: unknown) => error); + expect(publicPhase1FailureDiagnostic(caught)).toBe(diagnostic); + expect(extractVerifiedRunnerDiagnostic(`phase1-conformance: ${diagnostic}`)).toBe(diagnostic); + expect((caught as Error).message).toBe(diagnostic); + expect((failure as Error).cause).toBeInstanceOf(Error); + expect(((failure as Error).cause as Error).message).toBe(diagnostic); + }); + + test.each([ + 'operator.private.changed', + 'operator.cave-home.changed.private', + 'native-credential-store.changed.private', + ])('rejects arbitrary category %s', (suffix) => { + const diagnostic = `${prefix}.${suffix}`; + expect(publicPhase1FailureDiagnostic(new Error(diagnostic))).toBeUndefined(); + expect(extractVerifiedRunnerDiagnostic(`phase1-conformance: ${diagnostic}`)).toBeUndefined(); + expect(producer.schemaV2FailureDiagnostic(new Error(diagnostic), `${prefix}.failed`)).toBe( + `${prefix}.failed`, + ); + }); +}); From c95da6e3ae76646d8d864c36c5f19289b47fdf00 Mon Sep 17 00:00:00 2001 From: Val Alexander <68980965+BunsDev@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:43:51 -0500 Subject: [PATCH 2/4] chore(conformance): bind verified isolation diagnostic source --- docs/phase1-conformance.md | 4 ++-- phase1-conformance.lock.json | 6 +++--- src/phase1-conformance-lock.test.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/phase1-conformance.md b/docs/phase1-conformance.md index 43932e88..ed32770a 100644 --- a/docs/phase1-conformance.md +++ b/docs/phase1-conformance.md @@ -163,8 +163,8 @@ assignment, RPC decoder and primary/secondary exception pipeline. This fixture correction does not establish the protected installation failure's cause or relax the round-trip assertions. -The lock now selects reviewed source `6e74fb60e44549b91aa75fb956eb63a85dc668fc`, -tree `a1002364401a1788f8210a35b87d202711e67042`, including all 25 governed files +The lock now selects reviewed source `7af45e33c2331bca1d7881045ef9c12d123e02f0`, +tree `f6a4f435fd573ada742a046c0e744db26084a20f`, including all 25 governed files and ten production deltas. The checkout regression exercises all five labels from that immutable revision. SDK rebinding, both scope rotations and fresh protected validation remain required; this binding alone is not acceptance. diff --git a/phase1-conformance.lock.json b/phase1-conformance.lock.json index 3f81277d..d745858b 100644 --- a/phase1-conformance.lock.json +++ b/phase1-conformance.lock.json @@ -18,11 +18,11 @@ }, "harness": { "repository": "OpenCoven/chat", - "revision": "6e74fb60e44549b91aa75fb956eb63a85dc668fc" + "revision": "7af45e33c2331bca1d7881045ef9c12d123e02f0" }, "harnessAuthority": { - "revision": "6e74fb60e44549b91aa75fb956eb63a85dc668fc", - "tree": "a1002364401a1788f8210a35b87d202711e67042", + "revision": "7af45e33c2331bca1d7881045ef9c12d123e02f0", + "tree": "f6a4f435fd573ada742a046c0e744db26084a20f", "files": [ { "path": "scripts/phase1-conformance.mjs", diff --git a/src/phase1-conformance-lock.test.ts b/src/phase1-conformance-lock.test.ts index 69f431c1..9598cc26 100644 --- a/src/phase1-conformance-lock.test.ts +++ b/src/phase1-conformance-lock.test.ts @@ -80,8 +80,8 @@ const committedHarnessAuthority = JSON.parse( readFileSync(resolve(projectRoot, 'phase1-conformance.lock.json'), 'utf8'), ).harnessAuthority; const expectedBehaviorAuthority = { - revision: '6e74fb60e44549b91aa75fb956eb63a85dc668fc', - tree: 'a1002364401a1788f8210a35b87d202711e67042', + revision: '7af45e33c2331bca1d7881045ef9c12d123e02f0', + tree: 'f6a4f435fd573ada742a046c0e744db26084a20f', files: [ { path: 'scripts/phase1-conformance.mjs', From 2dd79ec1505d9c12051552109244067b35813357 Mon Sep 17 00:00:00 2001 From: Val Alexander <68980965+BunsDev@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:54:04 -0500 Subject: [PATCH 3/4] fix(conformance): classify null isolation snapshots --- .github/workflows/client-v1-conformance.yml | 4 ++-- docs/phase1-conformance.md | 4 ++-- phase1-conformance.lock.json | 8 ++++---- scripts/phase1-evidence-runtime.mjs | 2 ++ src/phase1-conformance-lock.test.ts | 4 ++-- src/phase1-isolation-diagnostics.test.ts | 7 +++++++ 6 files changed, 19 insertions(+), 10 deletions(-) diff --git a/.github/workflows/client-v1-conformance.yml b/.github/workflows/client-v1-conformance.yml index 3b47508d..9662a44c 100644 --- a/.github/workflows/client-v1-conformance.yml +++ b/.github/workflows/client-v1-conformance.yml @@ -1180,7 +1180,7 @@ jobs: @('scripts\phase1-conformance-lock.mjs', 48960, '92f981c43f75bc65c81e9e9ee16084aae658617b929d451a9db0d7c9e6bedbe2'), @('scripts\phase1-conformance.mjs', 219211, 'daaa5fb660765b9d6c21bea4e4a3c9ebf1a92f14f052b7ed96593f579c7534ad'), @('scripts\phase1-evidence-contract.mjs', 15088, '24180ae03835fa6aac45559682adb3c1e626bab76466eddc55b9e2300f0a2b7f'), - @('scripts\phase1-evidence-runtime.mjs', 6523, '9b1f61c83e8bacf22aaf3fb9f670c879b4bd78be002b2d258cf80af57064a7c8'), + @('scripts\phase1-evidence-runtime.mjs', 6572, 'b09a0d20abc7ebbc6289c57c985fd42b8a4b5d196895bc035b8fca40281d9315'), @('scripts\phase1-linux-secret-service.mjs', 4270, 'ddf834c6f57853c5116b4b1f345952a218ff0687c5d741737c68e20bc2ecda92'), @('scripts\phase1-macos-keychain.mjs', 5091, 'ab0c2dd08cf606d9502f5da206175707d471d99f484e8c8c79b5b08a5772b9a4'), @('scripts\phase1-process-supervisor.mjs', 3820, '16b51fb1a33b4bfef98daca549aacf5dc2d2c098cfbd664753b69c940d1e6f6c'), @@ -1910,7 +1910,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', [6965, 'a9c55c85cf2b7d70310d278bafd2c8e7695d66f4ae38b9c3f1f12fce0b442095']],\n ['scripts/phase1-artifact-secret-scan.mjs', [21183, 'be0ec302b9c4372f232d6bd1efcba873fd3380cc5de7f756cd0b9eeeec07222a']],\n ['scripts/phase1-conformance-lock.mjs', [48960, '92f981c43f75bc65c81e9e9ee16084aae658617b929d451a9db0d7c9e6bedbe2']],\n ['scripts/phase1-conformance.mjs', [219211, 'daaa5fb660765b9d6c21bea4e4a3c9ebf1a92f14f052b7ed96593f579c7534ad']],\n ['scripts/phase1-evidence-contract.mjs', [15088, '24180ae03835fa6aac45559682adb3c1e626bab76466eddc55b9e2300f0a2b7f']],\n ['scripts/phase1-evidence-runtime.mjs', [6523, '9b1f61c83e8bacf22aaf3fb9f670c879b4bd78be002b2d258cf80af57064a7c8']],\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', [232829, '9b2b295170d37f45b5d860fd8cd82c65ab6538caa7cd8d599ce19c8680643174']],\n ['scripts/process-owned-artifact-root.mjs', [11788, '426c2c8e36dc3bffddb35a565c07a60998b010660f6248ebc4264d9c4b502624']],\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', [6965, 'a9c55c85cf2b7d70310d278bafd2c8e7695d66f4ae38b9c3f1f12fce0b442095']],\n ['scripts/phase1-artifact-secret-scan.mjs', [21183, 'be0ec302b9c4372f232d6bd1efcba873fd3380cc5de7f756cd0b9eeeec07222a']],\n ['scripts/phase1-conformance-lock.mjs', [48960, '92f981c43f75bc65c81e9e9ee16084aae658617b929d451a9db0d7c9e6bedbe2']],\n ['scripts/phase1-conformance.mjs', [219211, 'daaa5fb660765b9d6c21bea4e4a3c9ebf1a92f14f052b7ed96593f579c7534ad']],\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', [232829, '9b2b295170d37f45b5d860fd8cd82c65ab6538caa7cd8d599ce19c8680643174']],\n ['scripts/process-owned-artifact-root.mjs', [11788, '426c2c8e36dc3bffddb35a565c07a60998b010660f6248ebc4264d9c4b502624']],\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 ed32770a..34592b35 100644 --- a/docs/phase1-conformance.md +++ b/docs/phase1-conformance.md @@ -1969,7 +1969,7 @@ revision authorities can therefore have different workflow hashes: | File | Bytes | SHA-256 | | --- | ---: | --- | -| `.github/workflows/client-v1-conformance.yml` | 177,934 | `e1f6c32f587dd8dca1a2530902d8194002fbd2e855f0579294c51ac1fe7c25dc` | +| `.github/workflows/client-v1-conformance.yml` | 177,934 | `5a43c25032b4eb040c1f3e378dc6456b1ef4e5bdeb36d5c58f71d8ec9d43c3d9` | | `scripts/contract-canary.mjs` | 40,618 | `a4c2fe0a5eb6a5ff4653de5374c34c0fb46907c6806a5d23b86d8b37206ef958` | | `scripts/executable-resolution.mjs` | 9,154 | `31e3c412ff8c835f14522f36a59e91f4a4ba82913210ae8e3b4455217503f430` | | `scripts/owned-temp-directory.mjs` | 6,965 | `a9c55c85cf2b7d70310d278bafd2c8e7695d66f4ae38b9c3f1f12fce0b442095` | @@ -1977,7 +1977,7 @@ revision authorities can therefore have different workflow hashes: | `scripts/phase1-conformance-lock.mjs` | 48,960 | `92f981c43f75bc65c81e9e9ee16084aae658617b929d451a9db0d7c9e6bedbe2` | | `scripts/phase1-conformance.mjs` | 219,211 | `daaa5fb660765b9d6c21bea4e4a3c9ebf1a92f14f052b7ed96593f579c7534ad` | | `scripts/phase1-evidence-contract.mjs` | 15,088 | `24180ae03835fa6aac45559682adb3c1e626bab76466eddc55b9e2300f0a2b7f` | -| `scripts/phase1-evidence-runtime.mjs` | 6,523 | `9b1f61c83e8bacf22aaf3fb9f670c879b4bd78be002b2d258cf80af57064a7c8` | +| `scripts/phase1-evidence-runtime.mjs` | 6,572 | `b09a0d20abc7ebbc6289c57c985fd42b8a4b5d196895bc035b8fca40281d9315` | | `scripts/phase1-linux-secret-service.mjs` | 4,270 | `ddf834c6f57853c5116b4b1f345952a218ff0687c5d741737c68e20bc2ecda92` | | `scripts/phase1-macos-keychain.mjs` | 5,091 | `ab0c2dd08cf606d9502f5da206175707d471d99f484e8c8c79b5b08a5772b9a4` | | `scripts/phase1-process-supervisor.mjs` | 3,820 | `16b51fb1a33b4bfef98daca549aacf5dc2d2c098cfbd664753b69c940d1e6f6c` | diff --git a/phase1-conformance.lock.json b/phase1-conformance.lock.json index d745858b..d777ef56 100644 --- a/phase1-conformance.lock.json +++ b/phase1-conformance.lock.json @@ -71,8 +71,8 @@ }, { "path": "scripts/phase1-evidence-runtime.mjs", - "blob": "b4b6a256d2f62fc7542e04106acfbd5b0df01f36", - "sha256": "9b1f61c83e8bacf22aaf3fb9f670c879b4bd78be002b2d258cf80af57064a7c8" + "blob": "fb744e9f11ec002418ff42741c23f8a5f2f346e6", + "sha256": "b09a0d20abc7ebbc6289c57c985fd42b8a4b5d196895bc035b8fca40281d9315" }, { "path": "scripts/phase1-schema-v2-evidence.mjs", @@ -146,8 +146,8 @@ }, { "path": ".github/workflows/client-v1-conformance.yml", - "blob": "3b47508d6f0bb541aa042f426da36ae647fb5f4f", - "sha256": "e1f6c32f587dd8dca1a2530902d8194002fbd2e855f0579294c51ac1fe7c25dc" + "blob": "9662a44ce710dc2d0aa4989eb2bf7bd88000a445", + "sha256": "5a43c25032b4eb040c1f3e378dc6456b1ef4e5bdeb36d5c58f71d8ec9d43c3d9" } ], "productionDeltas": [ diff --git a/scripts/phase1-evidence-runtime.mjs b/scripts/phase1-evidence-runtime.mjs index b4b6a256..fb744e9f 100644 --- a/scripts/phase1-evidence-runtime.mjs +++ b/scripts/phase1-evidence-runtime.mjs @@ -165,7 +165,9 @@ export function buildIsolationEvidence({ const after = operatorAfter?.[id]; if ( before === undefined || + before === null || after === undefined || + after === null || !digestPattern.test(before.sha256 ?? '') || !digestPattern.test(after.sha256 ?? '') ) { diff --git a/src/phase1-conformance-lock.test.ts b/src/phase1-conformance-lock.test.ts index 9598cc26..fccc987c 100644 --- a/src/phase1-conformance-lock.test.ts +++ b/src/phase1-conformance-lock.test.ts @@ -130,8 +130,8 @@ const expectedBehaviorAuthority = { }, { path: '.github/workflows/client-v1-conformance.yml', - blob: '3b47508d6f0bb541aa042f426da36ae647fb5f4f', - sha256: 'e1f6c32f587dd8dca1a2530902d8194002fbd2e855f0579294c51ac1fe7c25dc', + blob: '9662a44ce710dc2d0aa4989eb2bf7bd88000a445', + sha256: '5a43c25032b4eb040c1f3e378dc6456b1ef4e5bdeb36d5c58f71d8ec9d43c3d9', }, { path: 'scripts/process-owned-artifact-root.mjs', diff --git a/src/phase1-isolation-diagnostics.test.ts b/src/phase1-isolation-diagnostics.test.ts index 0015677b..bea5c1ef 100644 --- a/src/phase1-isolation-diagnostics.test.ts +++ b/src/phase1-isolation-diagnostics.test.ts @@ -78,6 +78,13 @@ for (const id of ids) { Reflect.deleteProperty(v[side], id); }, }); + cases.push({ + name: `${id} null ${side}`, + category: `operator.${id}.invalid`, + mutate: (v) => { + Reflect.set(v[side], id, null); + }, + }); cases.push({ name: `${id} invalid ${side} digest`, category: `operator.${id}.invalid`, From 291698a369eb796397a567886dcd5d694fd62080 Mon Sep 17 00:00:00 2001 From: Val Alexander <68980965+BunsDev@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:57:42 -0500 Subject: [PATCH 4/4] chore(conformance): bind null-safe isolation diagnostics --- docs/phase1-conformance.md | 4 ++-- phase1-conformance.lock.json | 6 +++--- src/phase1-conformance-lock.test.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/phase1-conformance.md b/docs/phase1-conformance.md index 34592b35..5fa8fadd 100644 --- a/docs/phase1-conformance.md +++ b/docs/phase1-conformance.md @@ -163,8 +163,8 @@ assignment, RPC decoder and primary/secondary exception pipeline. This fixture correction does not establish the protected installation failure's cause or relax the round-trip assertions. -The lock now selects reviewed source `7af45e33c2331bca1d7881045ef9c12d123e02f0`, -tree `f6a4f435fd573ada742a046c0e744db26084a20f`, including all 25 governed files +The lock now selects reviewed source `2dd79ec1505d9c12051552109244067b35813357`, +tree `5187dc5f385bb07f2a5c2f637ffe58898741017b`, including all 25 governed files and ten production deltas. The checkout regression exercises all five labels from that immutable revision. SDK rebinding, both scope rotations and fresh protected validation remain required; this binding alone is not acceptance. diff --git a/phase1-conformance.lock.json b/phase1-conformance.lock.json index d777ef56..d2fdf1cd 100644 --- a/phase1-conformance.lock.json +++ b/phase1-conformance.lock.json @@ -18,11 +18,11 @@ }, "harness": { "repository": "OpenCoven/chat", - "revision": "7af45e33c2331bca1d7881045ef9c12d123e02f0" + "revision": "2dd79ec1505d9c12051552109244067b35813357" }, "harnessAuthority": { - "revision": "7af45e33c2331bca1d7881045ef9c12d123e02f0", - "tree": "f6a4f435fd573ada742a046c0e744db26084a20f", + "revision": "2dd79ec1505d9c12051552109244067b35813357", + "tree": "5187dc5f385bb07f2a5c2f637ffe58898741017b", "files": [ { "path": "scripts/phase1-conformance.mjs", diff --git a/src/phase1-conformance-lock.test.ts b/src/phase1-conformance-lock.test.ts index fccc987c..66b5d3c8 100644 --- a/src/phase1-conformance-lock.test.ts +++ b/src/phase1-conformance-lock.test.ts @@ -80,8 +80,8 @@ const committedHarnessAuthority = JSON.parse( readFileSync(resolve(projectRoot, 'phase1-conformance.lock.json'), 'utf8'), ).harnessAuthority; const expectedBehaviorAuthority = { - revision: '7af45e33c2331bca1d7881045ef9c12d123e02f0', - tree: 'f6a4f435fd573ada742a046c0e744db26084a20f', + revision: '2dd79ec1505d9c12051552109244067b35813357', + tree: '5187dc5f385bb07f2a5c2f637ffe58898741017b', files: [ { path: 'scripts/phase1-conformance.mjs',