Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/client-v1-conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1185,7 +1185,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', 233186, '2e5fe8808230ad318aa86408bbad2004dbe4fd1c074f88de11fc581b227e0a51'),
@('scripts\phase1-schema-v2-producer.mjs', 233304, 'afe3509fc333b32b7af9a6de443db480ce7c1362aee82712713faa4c042fd3bc'),
@('scripts\process-owned-artifact-root.mjs', 13061, '103cc789f12a6bbde16b2414aecf05813d9d28a2c40c7d6eaa2073b86e8e5d77'),
@('scripts\supervised-exec.mjs', 2875, 'a5edfd985b934d3b46247a0da3141682c411d30bb582edf87ae7b29791dad65b'),
@('scripts\supervisor-status.mjs', 854, 'ac332ca7b6b040ecc846088bb3a6ad5e7112a0454eb3ea71d2a819d55e64254e')
Expand Down Expand Up @@ -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', [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', [233186, '2e5fe8808230ad318aa86408bbad2004dbe4fd1c074f88de11fc581b227e0a51']],\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', [233304, 'afe3509fc333b32b7af9a6de443db480ce7c1362aee82712713faa4c042fd3bc']],\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'
Expand Down
30 changes: 28 additions & 2 deletions docs/phase1-conformance.md
Original file line number Diff line number Diff line change
Expand Up @@ -1997,7 +1997,7 @@ revision authorities can therefore have different workflow hashes:

| File | Bytes | SHA-256 |
| --- | ---: | --- |
| `.github/workflows/client-v1-conformance.yml` | 177,934 | `73f665797b6d21de149949ca532bb814ac114a3682cff14c004919d95e3be2bb` |
| `.github/workflows/client-v1-conformance.yml` | 177,934 | `fb80c8c010c061c358a87507b98a2f29c3485e8ee02d2f52f4708742b5c4a0c8` |
| `scripts/contract-canary.mjs` | 40,618 | `a4c2fe0a5eb6a5ff4653de5374c34c0fb46907c6806a5d23b86d8b37206ef958` |
| `scripts/executable-resolution.mjs` | 9,154 | `31e3c412ff8c835f14522f36a59e91f4a4ba82913210ae8e3b4455217503f430` |
| `scripts/owned-temp-directory.mjs` | 7,762 | `95f546ef9ed614f2a0f55d356ddfc54c943fc53b595b4eebebfcbd4db68e5c0b` |
Expand All @@ -2010,7 +2010,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,186 | `2e5fe8808230ad318aa86408bbad2004dbe4fd1c074f88de11fc581b227e0a51` |
| `scripts/phase1-schema-v2-producer.mjs` | 233,304 | `afe3509fc333b32b7af9a6de443db480ce7c1362aee82712713faa4c042fd3bc` |
| `scripts/process-owned-artifact-root.mjs` | 13,061 | `103cc789f12a6bbde16b2414aecf05813d9d28a2c40c7d6eaa2073b86e8e5d77` |
| `scripts/supervised-exec.mjs` | 2,875 | `a5edfd985b934d3b46247a0da3141682c411d30bb582edf87ae7b29791dad65b` |
| `scripts/supervisor-status.mjs` | 854 | `ac332ca7b6b040ecc846088bb3a6ad5e7112a0454eb3ea71d2a819d55e64254e` |
Expand Down Expand Up @@ -2765,6 +2765,32 @@ Fresh reviewed source binding, SDK rebinding, and protected validation are
required before attributing the Windows failure or claiming a repaired run.


### Unsupported custody installation

`secure_store_unavailable` covered two unrelated causes on the installation
preflight. `KeyringError::Unavailable` is returned both by a secure store that
is genuinely unavailable and by `CredentialCustody::installation_id`'s default
trait body, which a custody implementation reaches only by never overriding it.
`InstallationStage::classify` already rewrites `Unavailable` into
`installation_lock_unavailable`, `installation_entry_unavailable`,
`installation_read_unavailable`, `installation_write_unavailable` and
`installation_persistence_unavailable`, so those five stages were already
distinguishable; the default trait body was the remaining unclassified path.

It now returns the fixed code `installation_custody_unsupported`, published as
`phase1.native-scenarios.native-preflight-installation-custody-unsupported`.
The outer launcher derives its native-stage allowlist from the producer
registry, so the identifier survives extraction without a second edit. Only the
fixed identifier is published: no message, stack, path, credential or
subprocess output is added.

Protected run
[35100084575](https://github.com/OpenCoven/chat/actions/runs/35100084575)
reported `native-preflight-installation-secure-store-unavailable` on Windows
while Linux and macOS passed. This change does not repair that failure and does
not establish its cause; it separates the two causes so the next protected run
attributes it.

### Unexpected installation RPC failures

Protected run `34964120550` used Chat `d84195c61b86598e691ccd47163e46a15b154417`
Expand Down
18 changes: 9 additions & 9 deletions phase1-conformance.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
},
"harness": {
"repository": "OpenCoven/chat",
"revision": "7dda439daa59ee350ff12cd195ff169b52e1085c"
"revision": "fe58cb1d4353b44fc61884ad76802ce924571526"
},
"harnessAuthority": {
"revision": "7dda439daa59ee350ff12cd195ff169b52e1085c",
"tree": "347c0b5300498d612f5411c1aee3372731ffc4f1",
"revision": "fe58cb1d4353b44fc61884ad76802ce924571526",
"tree": "7dc95a786f06770651b4755478727e8843f09400",
"files": [
{
"path": "scripts/phase1-conformance.mjs",
Expand Down Expand Up @@ -81,8 +81,8 @@
},
{
"path": "scripts/phase1-schema-v2-producer.mjs",
"blob": "76c8a0e31e55c8c1478dcb9657a1570d697b155c",
"sha256": "2e5fe8808230ad318aa86408bbad2004dbe4fd1c074f88de11fc581b227e0a51"
"blob": "08cebe6bad068657b9ee00efa2755cb8bd065066",
"sha256": "afe3509fc333b32b7af9a6de443db480ce7c1362aee82712713faa4c042fd3bc"
},
{
"path": "scripts/phase1-linux-secret-service.mjs",
Expand Down Expand Up @@ -146,8 +146,8 @@
},
{
"path": ".github/workflows/client-v1-conformance.yml",
"blob": "fe4072609b4c3e967881f93d82f86de0c0d4f23a",
"sha256": "73f665797b6d21de149949ca532bb814ac114a3682cff14c004919d95e3be2bb"
"blob": "c67ec1dc4e0acb797ef4f2f2f0a2d50fde5f96ed",
"sha256": "fb80c8c010c061c358a87507b98a2f29c3485e8ee02d2f52f4708742b5c4a0c8"
}
],
"productionDeltas": [
Expand Down Expand Up @@ -193,8 +193,8 @@
},
{
"path": "src-tauri/src/keyring.rs",
"blob": "b235ab40e02265ea3e9fbaedf0a842e7fc627f4f",
"sha256": "ba9be1f65792ae988ff64ca1348fc9ec4438925e4f4822f3c2d3057eee5d0568"
"blob": "11bd10925b3e18a27fd55fccbada1d0fb67db781",
"sha256": "72e1363f2f241e435136237731f3d84ca5a4ba9dad00f784027146331dcd8abc"
},
{
"path": "src-tauri/src/lib.rs",
Expand Down
2 changes: 2 additions & 0 deletions scripts/phase1-schema-v2-producer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ const nativeLaunchPublicationFailures = new WeakMap();
const nativeRpcFailureCategories = new WeakMap();
const nativeInstallationResponseCategories = new Map([
['secure_store_unavailable', 'secure-store-unavailable'],
['installation_custody_unsupported', 'custody-unsupported'],
['installation_lock_unavailable', 'lock-unavailable'],
['installation_entry_unavailable', 'entry-unavailable'],
['installation_read_unavailable', 'read-unavailable'],
Expand Down Expand Up @@ -173,6 +174,7 @@ const schemaV2NativeFailureStages = new Set([
'native-preflight-custody-proof',
'native-preflight-installation-rpc',
'native-preflight-installation-secure-store-unavailable',
'native-preflight-installation-custody-unsupported',
'native-preflight-installation-lock-unavailable',
'native-preflight-installation-entry-unavailable',
'native-preflight-installation-read-unavailable',
Expand Down
70 changes: 69 additions & 1 deletion src-tauri/src/keyring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ pub(crate) enum KeyringError {
Unavailable,
#[cfg(feature = "phase1-conformance")]
InstallationUnavailable(InstallationStage),
#[cfg(feature = "phase1-conformance")]
CustodyInstallationUnsupported,
Failure,
#[cfg(feature = "phase1-conformance")]
CleanupGrantRejected,
Expand Down Expand Up @@ -162,6 +164,10 @@ impl KeyringError {
},
true,
),
#[cfg(feature = "phase1-conformance")]
Self::CustodyInstallationUnsupported => {
NativeDiagnostic::new("installation_custody_unsupported", true)
}
Self::Failure => NativeDiagnostic::new("keychain_failure", true),
#[cfg(feature = "phase1-conformance")]
Self::CleanupGrantRejected => NativeDiagnostic::new("cleanup_grant_rejected", false),
Expand Down Expand Up @@ -287,8 +293,13 @@ pub(crate) enum CredentialSlot {
}

pub(crate) trait CredentialCustody: Send + Sync {
// A custody implementation that does not override this is a distinct
// condition from an unavailable secure store; keep them separable.
fn installation_id(&self) -> Result<String, KeyringError> {
Err(KeyringError::Unavailable)
#[cfg(feature = "phase1-conformance")]
return Err(KeyringError::CustodyInstallationUnsupported);
#[cfg(not(feature = "phase1-conformance"))]
return Err(KeyringError::Unavailable);
}

fn read(&self, instance_id: &str, origin: &str) -> Result<Credential, KeyringError>;
Expand Down Expand Up @@ -2349,6 +2360,63 @@ mod tests {
));
}
}
#[cfg(feature = "phase1-conformance")]
#[test]
fn unsupported_custody_installation_is_distinct_from_an_unavailable_store() {
// A custody type that does not override installation_id must not be
// reported as an unavailable secure store; the two are separate causes.
struct BareCustody;
impl super::CredentialCustody for BareCustody {
fn read(&self, _: &str, _: &str) -> Result<super::Credential, KeyringError> {
Err(KeyringError::Failure)
}
fn read_for_pairing_update(
&self,
_: &str,
_: &str,
) -> Result<super::CredentialSlot, KeyringError> {
Err(KeyringError::Failure)
}
fn store_if_current(
&self,
_: &str,
_: &str,
_: Option<&super::Credential>,
_: &str,
_: &str,
) -> Result<bool, KeyringError> {
Err(KeyringError::Failure)
}
fn replace_stale_if_current(
&self,
_: &str,
_: &str,
_: &super::Credential,
_: &str,
_: &str,
) -> Result<bool, KeyringError> {
Err(KeyringError::Failure)
}
fn delete_if_matches(
&self,
_: &str,
_: &str,
_: &super::Credential,
) -> Result<bool, KeyringError> {
Err(KeyringError::Failure)
}
}
let error = super::CredentialCustody::installation_id(&BareCustody)
.expect_err("the default custody implementation must fail");
assert!(matches!(
error,
KeyringError::CustodyInstallationUnsupported
));
let diagnostic = error.diagnostic();
assert_eq!(diagnostic.code, "installation_custody_unsupported");
assert_ne!(diagnostic.code, KeyringError::Unavailable.diagnostic().code);
assert!(diagnostic.retryable);
}
#[cfg(unix)]
use super::{
acquire_mutation_lock_detailed_with_timeout_at, acquire_mutation_lock_with_timeout_at,
Expand Down
1 change: 1 addition & 0 deletions src/native-preflight-diagnostics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ test.each([
'installation-rpc',
'installation-id',
'installation-secure-store-unavailable',
'installation-custody-unsupported',
'installation-lock-unavailable',
'installation-entry-unavailable',
'installation-read-unavailable',
Expand Down
12 changes: 6 additions & 6 deletions src/phase1-conformance-lock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ const committedHarnessAuthority = JSON.parse(
readFileSync(resolve(projectRoot, 'phase1-conformance.lock.json'), 'utf8'),
).harnessAuthority;
const expectedBehaviorAuthority = {
revision: '7dda439daa59ee350ff12cd195ff169b52e1085c',
tree: '347c0b5300498d612f5411c1aee3372731ffc4f1',
revision: 'fe58cb1d4353b44fc61884ad76802ce924571526',
tree: '7dc95a786f06770651b4755478727e8843f09400',
files: [
{
path: 'scripts/owned-temp-directory.mjs',
Expand All @@ -105,8 +105,8 @@ const expectedBehaviorAuthority = {
},
{
path: 'scripts/phase1-schema-v2-producer.mjs',
blob: '76c8a0e31e55c8c1478dcb9657a1570d697b155c',
sha256: '2e5fe8808230ad318aa86408bbad2004dbe4fd1c074f88de11fc581b227e0a51',
blob: '08cebe6bad068657b9ee00efa2755cb8bd065066',
sha256: 'afe3509fc333b32b7af9a6de443db480ce7c1362aee82712713faa4c042fd3bc',
},
{
path: 'scripts/unix-producer-supervisor.sh',
Expand Down Expand Up @@ -135,8 +135,8 @@ const expectedBehaviorAuthority = {
},
{
path: '.github/workflows/client-v1-conformance.yml',
blob: 'fe4072609b4c3e967881f93d82f86de0c0d4f23a',
sha256: '73f665797b6d21de149949ca532bb814ac114a3682cff14c004919d95e3be2bb',
blob: 'c67ec1dc4e0acb797ef4f2f2f0a2d50fde5f96ed',
sha256: 'fb80c8c010c061c358a87507b98a2f29c3485e8ee02d2f52f4708742b5c4a0c8',
},
{
path: 'scripts/process-owned-artifact-root.mjs',
Expand Down
Loading