From 474b660a52f915c96dbc4701e39219743d852266 Mon Sep 17 00:00:00 2001 From: sammiller Date: Mon, 21 Sep 2026 21:37:16 -0700 Subject: [PATCH 1/3] [WP02 SubStep 02.05] Enforce reviewed dependency admission --- AGENTS.md | 2 + CONTRIBUTING.md | 2 + docs/dependency-policy.md | 15 + eng/policy/dependency-policy.json | 921 ++++++++++++++++++ .../dependency-reviews/admission-r1.json | 184 ++++ eng/provenance/files.json | 5 + package.json | 6 +- tooling/dependency-policy.test.ts | 80 ++ tooling/dependency-policy.ts | 184 ++++ 9 files changed, 1397 insertions(+), 2 deletions(-) create mode 100644 docs/dependency-policy.md create mode 100644 eng/policy/dependency-policy.json create mode 100644 eng/policy/dependency-reviews/admission-r1.json create mode 100644 tooling/dependency-policy.test.ts create mode 100644 tooling/dependency-policy.ts diff --git a/AGENTS.md b/AGENTS.md index 690ad12..599d48a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,3 +16,5 @@ Plan bounded changes before implementation. This repository owns the C# Native A ## Required validation limits Follow [validation policy](docs/validation-policy.md), which supersedes older runtime and release-test requirements. Never add or execute macOS CI, device/emulator/GUI/browser E2E CI, live service or inference CI, installed-consumer CI or public-download verification. Keep runtime checks explicit local opt-in. Do not repeat public archive/hash checks, passing tests or post-merge runtime cycles. Preserve lock/signature/licence/provenance checks at actual trust handoffs. Do not invoke wsl.exe, configure proxy 7890 or install toolchains solely for testing. Stop and report the exact failed network operation. Hooks do not rebuild/test on commit or push. + +Dependency additions and upgrades follow [the enforced admission policy](docs/dependency-policy.md); update its input-bound review and retain the existing class and provenance gates. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9059b06..b461c2e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,3 +24,5 @@ All original source and tooling in this repository use AGPL-3.0-only. Preserve t Follow [the provenance process](docs/provenance.md) before introducing reused material. The source gate includes immutable records, complete inventory and deterministic NOTICE; the candidate gate also verifies the actual Worker and image legal contents. + +Dependency additions and upgrades follow [the enforced admission policy](docs/dependency-policy.md); update its input-bound review and retain the existing class and provenance gates. diff --git a/docs/dependency-policy.md b/docs/dependency-policy.md new file mode 100644 index 0000000..bc34007 --- /dev/null +++ b/docs/dependency-policy.md @@ -0,0 +1,15 @@ +# Dependency admission + +`npm run check:dependencies` enforces `eng/policy/dependency-policy.json` against the actual workspace manifests, complete external npm lock closure, source imports and reviewed dependency input hashes. `npm run test:dependencies` contains offline refusal fixtures. Both are part of the existing source check; no extra CI job or runtime test is introduced. + +The inventory preserves exact registry URLs, versions, integrity and declared licence expressions. These expressions identify locked build inputs; they do not authorize redistribution by themselves. Existing source provenance and immutable shipped-artifact profiles remain mandatory file-level licence, source-hash, generator, notice and output-closure authorities. Build tooling, including LGPL/MPL components, does not become shipped product code through this inventory. New native capability admission requires AD-01 through AD-08 and a reviewed owning artifact profile. + +Dependency changes must update manifests and locks together, inspect the exact upstream terms and transitive closure, and update the input-bound owner/reviewer/date/rationale record. Retain actual maintenance, compatibility, security, SBOM and class compilation assessments. Framework majors also require an explicit runtime/native/transport and migration assessment. Runtime/performance diagnostics are local opt-in only for affected behavior supported by the existing environment; absent coverage is reported, never silently passed or provisioned as a new task. Existing provenance records remain append-only; use successors when their inputs change. A class or artifact-profile change requires review. + +Public Contracts packages come only from `ArcForges/Contracts` through the exact npm registry coordinates and committed SHA512 locks. Source imports, re-exports and literal dynamic imports cannot reference private Contracts packages/subpaths or escape into a sibling checkout. Current owners have not adopted an internal generated package. Future internal consumers need an explicit owner admission and compatible licence boundary; public clients remain excluded. Package publisher ownership is an admission assertion reviewed against the existing producer receipt, not a claim that npm lock integrity independently authenticates an account. + +Existing exact prerelease Contracts versions are named foundation candidate inputs only. A stable closure rejects them. Mutable tags such as `latest`, ranges, local paths and Git selectors are not consumer coordinates. Candidate/stable promotion uses the original sealed bytes and existing provider identity handoff; no public package downloads, replacement versions or tags are used for policy validation. This repository does not publish tooling packages. Its existing `cloudflare` environment restricts deployment credentials to the trusted main workflow; PR checks have no publisher credentials. Publication success remains provider status, not live runtime acceptance. + +Policy edits require normal complete PR review; refreshing a hash alone is not admission. The offline gate proves matching evidence and refusal behavior, not independent authorship, legal approval or commercial acceptance. + +Each admission has an immutable `eng/policy/dependency-reviews/` receipt. A successor names the retained predecessor. The checker compares every historical receipt with its original committed bytes and rejects changed integrity for any previously admitted name/version even when the new policy, lock and review all agree. Missing or edited historical receipts fail. diff --git a/eng/policy/dependency-policy.json b/eng/policy/dependency-policy.json new file mode 100644 index 0000000..1c11656 --- /dev/null +++ b/eng/policy/dependency-policy.json @@ -0,0 +1,921 @@ +{ + "schemaVersion": 1, + "repository": "Cloud", + "sourceCommit": "aa50596b1299c4c56b0568de5d8cc61851df0ca0", + "manifests": ["package.json"], + "inputs": { + ".java-version": "b8481af4c809b46f02fc334825116cbe9e6d6a7bc8e2363511fa77044fca8016", + ".node-version": "73fb1b615e2043a933be1c0895cde4358036acc28d785692509b822aa53c761f", + ".npmrc": "857e18055c0f5d75719d253033954c10511c4b16ae5bd68bc45bb75d93a411bc", + "Directory.Packages.props": "b842214f27a1b95af27bfba82a786df28ed41f0443b545976c4fffc195df4c55", + "Dockerfile": "cbe3e60d8b49be36901370e80b5171832642dd30680af83356431910edb07537", + "NuGet.Config": "cb93c65e28718aa9075fce221e9f9cea9e72d3fe1b30462383448a591f5b3aa1", + "global.json": "67381be18aa807c04218165844967cf58235875477f30495ba98c3648248a9d4", + "package-lock.json": "ffc439bd73191160b61b7f660690291799bad6f7d247d51593114707a25adbbe", + "package.json": "48f40f2eaed6e329a4282cc3f7ee39d58e767984fd4c8000f36315744cf3a6a2", + "src/ArcForges.Cloud/ArcForges.Cloud.csproj": "d2b84581970f81643c43207cb1e24557cd44abb7867e2ddfca6c18b6ed5c7851", + "src/ArcForges.Cloud/packages.lock.json": "cbd7175143f33615d861ed2dc65e7b8cb30671a0e0ce62b81781943df6b2520c", + "tests/ArcForges.Cloud.Consumer/ArcForges.Cloud.Consumer.csproj": "8fe4c5800be3ea425701ac46d4134424a896a00b3d7e7c2bb37ee5c1168d81f4", + "tests/ArcForges.Cloud.Consumer/packages.lock.json": "cd85ca972fa1b8879607189ce2a54de43ba657992d19361a1b68cd9827295192", + "tests/ArcForges.Cloud.Tests/ArcForges.Cloud.Tests.csproj": "f57aefcd844e2a90c36c484b85e3df4f3938a4358c3f60bc2206d7e950c47565", + "tests/ArcForges.Cloud.Tests/packages.lock.json": "22d18c888de531539283b7a38ae536c9843a84811c999d456f85476cf1f2487d", + "tests/kotlin-consumer/build.gradle.kts": "05c1cb296b5f5b66c4f75282c44383a32a8a596c330c14fd782e1912919c8394", + "tests/kotlin-consumer/gradle.lockfile": "0a6640ce98f60bf6e38bf19158fc87e68e33e1934eb3ede2df75b614a6b18c47", + "tests/kotlin-consumer/gradle/verification-metadata.xml": "a3636c4a18cfc8319359129f8c037bf0e2c455512beeff6846414301e8f99639", + "tests/kotlin-consumer/gradle/wrapper/gradle-wrapper.properties": "176fcae7ef9cfcdd82903d41888fe11fe197a674f752e9275aa51d0d8427a2c5", + "tests/kotlin-consumer/settings.gradle.kts": "64675e4ff0bb4d84e56a315bb017e2adac9e58eb1efb86e409fb148806b38a55", + "wrangler.json": "7b22ead0f7b327bc56332ca0692e4ac3f07053063d5daea531c56a6a0206c24e", + "eng/provenance/artifact-profiles/cloud-release-r12.json": "2240b17719fa5131582045b6164735ae79c2880fd79c6c0c4e6479e0d4626321", + "eng/provenance/records/cloud-runtime-notices-r13.json": "3e2f656c04197bdd90f28f2c12e78cd9fb9ab24ce6c4c4407767a223b9d5357d", + "eng/provenance/records/cloud-worker-bundle-r12.json": "04df6106636eda1b201456cca48dc4344b7126aad72f782e6a8b780150ed8665", + "Directory.Build.props": "594fe799ea787c02d4406e14360c4b1902a5aee8679b76c8ac797ae34a9e792c", + "Directory.Build.targets": "fa4bf35487140fecd21b71a2fb524792631a292df2313f9440f8c6e7e90a82d2", + ".github/workflows/ci.yml": "81ec9755c880b522146e6737281c080c77dd8958623dd3a754db3e9c5e89e8a3" + }, + "review": { + "owner": "Cloud dependency maintainer", + "reviewer": "Codex, maintainer-authorized implementation review", + "date": "2026-09-21", + "rationale": "WP02.05 reconciles the unchanged current lock closure. Registry integrity and declared licence expressions identify build inputs; exact existing artifact profiles, file-level records and complete legal notices remain the redistribution authority. This admission creates no new native capability or broader source reuse permission.", + "inputs": { + ".java-version": "b8481af4c809b46f02fc334825116cbe9e6d6a7bc8e2363511fa77044fca8016", + ".node-version": "73fb1b615e2043a933be1c0895cde4358036acc28d785692509b822aa53c761f", + ".npmrc": "857e18055c0f5d75719d253033954c10511c4b16ae5bd68bc45bb75d93a411bc", + "Directory.Packages.props": "b842214f27a1b95af27bfba82a786df28ed41f0443b545976c4fffc195df4c55", + "Dockerfile": "cbe3e60d8b49be36901370e80b5171832642dd30680af83356431910edb07537", + "NuGet.Config": "cb93c65e28718aa9075fce221e9f9cea9e72d3fe1b30462383448a591f5b3aa1", + "global.json": "67381be18aa807c04218165844967cf58235875477f30495ba98c3648248a9d4", + "package-lock.json": "ffc439bd73191160b61b7f660690291799bad6f7d247d51593114707a25adbbe", + "package.json": "48f40f2eaed6e329a4282cc3f7ee39d58e767984fd4c8000f36315744cf3a6a2", + "src/ArcForges.Cloud/ArcForges.Cloud.csproj": "d2b84581970f81643c43207cb1e24557cd44abb7867e2ddfca6c18b6ed5c7851", + "src/ArcForges.Cloud/packages.lock.json": "cbd7175143f33615d861ed2dc65e7b8cb30671a0e0ce62b81781943df6b2520c", + "tests/ArcForges.Cloud.Consumer/ArcForges.Cloud.Consumer.csproj": "8fe4c5800be3ea425701ac46d4134424a896a00b3d7e7c2bb37ee5c1168d81f4", + "tests/ArcForges.Cloud.Consumer/packages.lock.json": "cd85ca972fa1b8879607189ce2a54de43ba657992d19361a1b68cd9827295192", + "tests/ArcForges.Cloud.Tests/ArcForges.Cloud.Tests.csproj": "f57aefcd844e2a90c36c484b85e3df4f3938a4358c3f60bc2206d7e950c47565", + "tests/ArcForges.Cloud.Tests/packages.lock.json": "22d18c888de531539283b7a38ae536c9843a84811c999d456f85476cf1f2487d", + "tests/kotlin-consumer/build.gradle.kts": "05c1cb296b5f5b66c4f75282c44383a32a8a596c330c14fd782e1912919c8394", + "tests/kotlin-consumer/gradle.lockfile": "0a6640ce98f60bf6e38bf19158fc87e68e33e1934eb3ede2df75b614a6b18c47", + "tests/kotlin-consumer/gradle/verification-metadata.xml": "a3636c4a18cfc8319359129f8c037bf0e2c455512beeff6846414301e8f99639", + "tests/kotlin-consumer/gradle/wrapper/gradle-wrapper.properties": "176fcae7ef9cfcdd82903d41888fe11fe197a674f752e9275aa51d0d8427a2c5", + "tests/kotlin-consumer/settings.gradle.kts": "64675e4ff0bb4d84e56a315bb017e2adac9e58eb1efb86e409fb148806b38a55", + "wrangler.json": "7b22ead0f7b327bc56332ca0692e4ac3f07053063d5daea531c56a6a0206c24e", + "eng/provenance/artifact-profiles/cloud-release-r12.json": "2240b17719fa5131582045b6164735ae79c2880fd79c6c0c4e6479e0d4626321", + "eng/provenance/records/cloud-runtime-notices-r13.json": "3e2f656c04197bdd90f28f2c12e78cd9fb9ab24ce6c4c4407767a223b9d5357d", + "eng/provenance/records/cloud-worker-bundle-r12.json": "04df6106636eda1b201456cca48dc4344b7126aad72f782e6a8b780150ed8665", + "Directory.Build.props": "594fe799ea787c02d4406e14360c4b1902a5aee8679b76c8ac797ae34a9e792c", + "Directory.Build.targets": "fa4bf35487140fecd21b71a2fb524792631a292df2313f9440f8c6e7e90a82d2", + ".github/workflows/ci.yml": "81ec9755c880b522146e6737281c080c77dd8958623dd3a754db3e9c5e89e8a3" + }, + "checks": [ + "locked-restore", + "licence-provenance", + "security", + "class-compilation", + "compatibility", + "sbom", + "framework-posture" + ], + "runtimeAssessment": "No framework version changed. Existing C# Native AOT and JVM verification compiler posture is preserved. Future framework majors require explicit runtime, native, transport and migration assessment. Local runtime/performance coverage runs only for affected behavior supported by the existing environment; none is asserted here.", + "maintenance": "Current exact producer and package locks remain unchanged; dependency review and the existing high-severity audit remain required. Lockfile licence labels are metadata, not replacement file-level redistribution grants. Updates must refresh this reviewed input-bound record and pass applicable existing class checks.", + "previous": null, + "immutableHistory": "Admitted review records are retained in Git history. A dependency change requires a new reviewed source commit and updated input-bound rationale; never amend an already accepted provenance record." + }, + "closure": { + "node_modules/@arcforges/api-client": { + "version": "1.0.0-ci.74.1", + "resolved": "https://registry.npmjs.org/@arcforges/api-client/-/api-client-1.0.0-ci.74.1.tgz", + "integrity": "sha512-G2Gri9QnBPKcVdkOtMpFBS/nYgQ0Ug4xrest5auUxcLZXRRXbq9Q7ueQNeGtmWgDjhA54QZT/R7SMfRinm0g1A==", + "license": "Apache-2.0" + }, + "node_modules/@arcforges/proto": { + "version": "1.0.0-ci.74.1", + "resolved": "https://registry.npmjs.org/@arcforges/proto/-/proto-1.0.0-ci.74.1.tgz", + "integrity": "sha512-tjGTLa/mCfY7d2kMrnJhGZ7nLgONPb7rM+OSrM68kfeseKEjp/fUPkEASjYq+VKYbh9drZsXVQo1kLw1Ejl09Q==", + "license": "Apache-2.0" + }, + "node_modules/@biomejs/biome": { + "version": "2.5.14", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.14.tgz", + "integrity": "sha512-0FabLIjd4M/dm8VFI86RMaLLdgepzbdfiAL2R8cr7V81OYYrP1w7Z73KfAwPK5h9SrEBXTzNG2y+mBwPo9xRnw==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.5.14", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.14.tgz", + "integrity": "sha512-UnzaXO65L4tsZimFITFP2M121GyhDcWFrT3pL5ZJ5U4XcS/0L5VHYytVohdCf/gnDUFHgl2I9xnt5bV/J1kxHQ==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.5.14", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.14.tgz", + "integrity": "sha512-kiy8qA16K93J7uvFfWi4LgjqDpnRKyePAna6A0Y4jxyUga35SYpIZ2cNWlhy0lsfgqRenCpfymnJWEZ6mgpRgA==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.5.14", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.14.tgz", + "integrity": "sha512-vO/9BaU1n30CiFNLx49gMTMtbCAAqlo/EqFoG0BU3deQInTbJrmXSmTQ9e3FoDZIKQnvSLDVNL4lx1ci7y1T1Q==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.5.14", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.14.tgz", + "integrity": "sha512-SJ9PrZkBnnH9dHJDnxk34vKs0GB2dbsioaft6/hPhWJ7AHpwYH83Isnhj0FSRpFkGgpVfJ1lds23ApB2czUDLQ==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.5.14", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.14.tgz", + "integrity": "sha512-VHZRa7CCQBUWKxNwUvHJeuW03WFRgN5NWO//SDGOitc9QIeNyfA42V9zlKm+x82xFSG9Bzi5fi+hbhm9anO8yA==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.5.14", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.14.tgz", + "integrity": "sha512-2kI5PrMgW5dcEZYrstLPmUmCwkUwZY39rP4BN93Vxbwcs2O57LDQOktUZZYPvvspN5i0mhGr3TJtF5sU26NUWg==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.5.14", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.14.tgz", + "integrity": "sha512-pHgAFffmZtaYoxavEsWEYNvcA7NwOIjLyqw2HXyLbt16xYryX0L4fMV2u0G9ag6LNYPIoqWaWqzUcnc6rLGGXg==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.5.14", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.14.tgz", + "integrity": "sha512-oJWmBhoHsnhUKIke+0gXDX0mltJrWHA1UyHsrTlXwX0TL64ilVZAo+TYZm97baecV0esBdpzy3k96q+09JaZUQ==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.15.0.tgz", + "integrity": "sha512-DAheWUkVr/SJTWCc+lg9dhY0eN4SaWlf4+bG1KzHeXbnqt0AfB/NX0Z+VunGlM1ki1B4zVvye27MpKh/svySUA==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@cloudflare/containers": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/@cloudflare/containers/-/containers-0.3.7.tgz", + "integrity": "sha512-DM9dm3FnIBSyiSJ1FLavKwl/lk3oAmTaynCzZQ9pZR0ncRPquSxkxd8Nu2MFILxmDDsPkxKsSNEh9mHHMty4Fw==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz", + "integrity": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.1.tgz", + "integrity": "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260918.1.tgz", + "integrity": "sha512-H5Em6Wd0jjxaloYh2rp+WLBl2eWbkk7nSP1svGt6K1RSv/rNVqmKdpjZPJTBSavOmeYGa88qvtOWwS+33OHTqQ==", + "license": "Apache-2.0" + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260918.1.tgz", + "integrity": "sha512-CR9JRZEQo93fNgBVF4Df2H2/VYO4n7rxSseSwCVv3bJQEb0huADUSCj2FK4ipxar8ToOEB4wawyw0vJo5U/rQQ==", + "license": "Apache-2.0" + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260918.1.tgz", + "integrity": "sha512-UQ2nnY3qpXLzQ80frmWO+8HvtqyWaQILe8QYZwpemdjT+sqwCz4Dz+0/WVkFco0v/04kIIqikVeLTY/7gEhmkw==", + "license": "Apache-2.0" + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260918.1.tgz", + "integrity": "sha512-4rib51MaLNWweUIUxM/Xj558M5QmyZoBSf0ffv+lYah5VTrvwnez3XGxX72pElnBKHROvAPOi5msQ5Ts8JSI0A==", + "license": "Apache-2.0" + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260918.1.tgz", + "integrity": "sha512-sATrMx5ShYYgmgUGrcTmvsFSJBFuN95NEkX3xwb1qk8w1A6h5N11sea7yN2IeibwPyPmXKjWNjXOno0hZAM71Q==", + "license": "Apache-2.0" + }, + "node_modules/@cloudflare/workers-types": { + "version": "5.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-5.20260918.1.tgz", + "integrity": "sha512-bUGc9gIdooYPi6lAUoB/eBXmy/ev9ok0XvDLzfJZQVCT8WCEQwv9f6smz6XeE83JzpX6ZSVi9CG1aDORnErYRQ==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@connectrpc/connect": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect/-/connect-2.2.0.tgz", + "integrity": "sha512-M63OQ1ZFcPUm85CuewJ9G9CMV8LjzGR9935xOnXNQGSazAbwMb3x2W7vXBYM1zqrP7XFD8uxp/dUAhirclgwnQ==", + "license": "Apache-2.0" + }, + "node_modules/@connectrpc/connect-web": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect-web/-/connect-web-2.2.0.tgz", + "integrity": "sha512-uuBUcBTYfb/r1o98LzCCZk1H90yx0vmZ5m21dpw/q4EUwsKwkCDGI8H0aEdjcZld+Q2jJ5A5ADvPqfb6lzQ/sg==", + "license": "Apache-2.0" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "license": "MIT" + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "license": "MIT" + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "license": "MIT" + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "license": "MIT" + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "license": "MIT" + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "license": "MIT" + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "license": "MIT" + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "license": "MIT" + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "license": "MIT" + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "license": "MIT" + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "license": "MIT" + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "license": "MIT" + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "license": "MIT" + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "license": "MIT" + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "license": "MIT" + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "license": "MIT" + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "license": "MIT" + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "license": "MIT" + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "license": "MIT" + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "license": "MIT" + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "license": "MIT" + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "license": "MIT" + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "license": "MIT" + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "license": "MIT" + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "license": "MIT" + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "license": "MIT" + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "license": "MIT" + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT" + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", + "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", + "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", + "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", + "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", + "license": "LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", + "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", + "license": "LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", + "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", + "license": "LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", + "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", + "license": "LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", + "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", + "license": "LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", + "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", + "license": "LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", + "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", + "license": "LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", + "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", + "license": "LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", + "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", + "license": "LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", + "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", + "license": "LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", + "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", + "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", + "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", + "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", + "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", + "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", + "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", + "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", + "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT" + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", + "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", + "license": "Apache-2.0" + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", + "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", + "license": "Apache-2.0 AND LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", + "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", + "license": "Apache-2.0 AND LGPL-3.0-or-later" + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", + "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", + "license": "Apache-2.0 AND LGPL-3.0-or-later" + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "license": "MIT" + }, + "node_modules/@poppinss/colors": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", + "license": "MIT" + }, + "node_modules/@poppinss/dumper": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "license": "MIT" + }, + "node_modules/@poppinss/exception": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "license": "MIT" + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.24", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.24.tgz", + "integrity": "sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw==", + "license": "CC0-1.0" + }, + "node_modules/@types/node": { + "version": "24.13.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.5.tgz", + "integrity": "sha512-TXyindR+lBr22aJIdMQzCFHPHR6cR4js838mRDCSz5hOKWZvZwsXSSiXDmjRj4iJmgl+sR9O+1mkoVBSMadNug==", + "license": "MIT" + }, + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "license": "Apache-2.0" + }, + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "license": "Apache-2.0" + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0" + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "license": "MIT" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "license": "MIT" + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT" + }, + "node_modules/miniflare": { + "version": "5.20260918.0-alpha", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260918.0-alpha.tgz", + "integrity": "sha512-vyIes7yW/OTzHtz4GhcBCTohZfqk2eQNiIkngZ07VRA5Qu24aNgW/TrFwlPkMLMjWDQ8R4JJBBHR/KX+liSDtg==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/prettier": { + "version": "3.9.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.8.tgz", + "integrity": "sha512-WRFq3Wn3WId7LLROfMLdH7xaFr2jR62wU8nLO6rQUOLOxNZUviyJQs1M0iIhLexSFy+L+w0ch66wtoO2jRjG0A==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC" + }, + "node_modules/sharp": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", + "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", + "license": "Apache-2.0" + }, + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "license": "Apache-2.0" + }, + "node_modules/undici": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "license": "MIT" + }, + "node_modules/unenv": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "license": "MIT" + }, + "node_modules/workerd": { + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260918.1.tgz", + "integrity": "sha512-NsjfQlBNQ0iEniv/STOy4zbp8s5k60PzL1Ter02Eg44arbDhHtf6UOs03E31XDRmmBFxSIkAZuCyld3RKH1wqA==", + "license": "Apache-2.0" + }, + "node_modules/wrangler": { + "version": "4.135.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.135.0.tgz", + "integrity": "sha512-WrNBQSfIG6YcILJcodYr5ty8vgkzGsV8YX+kfd+uZ5/Bd8cUW0GnUIRKAVfn5kYKqh1m/BPcji9h1d7mE8euFw==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT" + }, + "node_modules/youch": { + "version": "4.1.0-beta.10", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "license": "MIT" + }, + "node_modules/youch-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "license": "MIT" + } + }, + "foundationCandidates": { + "@arcforges/api-client": "1.0.0-ci.74.1", + "@arcforges/proto": "1.0.0-ci.74.1" + }, + "firstParty": { + "@arcforges/api-client": { + "publisher": "ArcForges/Contracts", + "visibility": "public" + }, + "@arcforges/proto": { + "publisher": "ArcForges/Contracts", + "visibility": "public" + } + }, + "registry": "https://registry.npmjs.org/", + "channel": "foundation-candidate", + "artifactRecords": ["cloud-runtime-notices-r13", "cloud-worker-bundle-r12"], + "native": { + "mode": "existing-artifact-closure-only", + "evidence": [ + "eng/provenance/artifact-profiles/cloud-release-r12.json", + "eng/provenance/records/cloud-runtime-notices-r13.json", + "eng/provenance/records/cloud-worker-bundle-r12.json" + ] + }, + "buildToolPrereleases": { + "miniflare": "5.20260918.0-alpha", + "unenv": "2.0.0-rc.24", + "youch": "4.1.0-beta.10" + }, + "reviewRecord": "eng/policy/dependency-reviews/admission-r1.json", + "dependencyClasses": { + "build-inputs": "Complete exact npm lock inventory; licence metadata is preserved, not inferred as a redistribution grant. Existing transitive development prereleases are named build-only migration inputs and cannot enter runtime/stable closures.", + "runtime": "Only the independently enforced existing shipped artifact records admit runtime inputs and legal scopes.", + "native": "No new product native capability; existing tooling and Cloud base image/native runtime obligations remain with the exact artifact profiles." + }, + "publication": { + "role": "deployment-consumer", + "repository": "ArcForges/Cloud", + "workflow": ".github/workflows/ci.yml", + "environment": "cloudflare", + "trustedRef": "refs/heads/main", + "promotion": "sealed candidate; existing provider identity verification; no registry tooling publication or credential in PR" + }, + "additionalFeeds": { + "nuget": "https://api.nuget.org/v3/index.json", + "maven": "https://repo.maven.apache.org/maven2/", + "gradlePlugins": "https://plugins.gradle.org/m2/", + "ociBuildAndRuntime": "mcr.microsoft.com/dotnet; exact Dockerfile digests" + } +} diff --git a/eng/policy/dependency-reviews/admission-r1.json b/eng/policy/dependency-reviews/admission-r1.json new file mode 100644 index 0000000..b5d591f --- /dev/null +++ b/eng/policy/dependency-reviews/admission-r1.json @@ -0,0 +1,184 @@ +{ + "review": { + "owner": "Cloud dependency maintainer", + "reviewer": "Codex, maintainer-authorized implementation review", + "date": "2026-09-21", + "rationale": "WP02.05 reconciles the unchanged current lock closure. Registry integrity and declared licence expressions identify build inputs; exact existing artifact profiles, file-level records and complete legal notices remain the redistribution authority. This admission creates no new native capability or broader source reuse permission.", + "inputs": { + ".java-version": "b8481af4c809b46f02fc334825116cbe9e6d6a7bc8e2363511fa77044fca8016", + ".node-version": "73fb1b615e2043a933be1c0895cde4358036acc28d785692509b822aa53c761f", + ".npmrc": "857e18055c0f5d75719d253033954c10511c4b16ae5bd68bc45bb75d93a411bc", + "Directory.Packages.props": "b842214f27a1b95af27bfba82a786df28ed41f0443b545976c4fffc195df4c55", + "Dockerfile": "cbe3e60d8b49be36901370e80b5171832642dd30680af83356431910edb07537", + "NuGet.Config": "cb93c65e28718aa9075fce221e9f9cea9e72d3fe1b30462383448a591f5b3aa1", + "global.json": "67381be18aa807c04218165844967cf58235875477f30495ba98c3648248a9d4", + "package-lock.json": "ffc439bd73191160b61b7f660690291799bad6f7d247d51593114707a25adbbe", + "package.json": "48f40f2eaed6e329a4282cc3f7ee39d58e767984fd4c8000f36315744cf3a6a2", + "src/ArcForges.Cloud/ArcForges.Cloud.csproj": "d2b84581970f81643c43207cb1e24557cd44abb7867e2ddfca6c18b6ed5c7851", + "src/ArcForges.Cloud/packages.lock.json": "cbd7175143f33615d861ed2dc65e7b8cb30671a0e0ce62b81781943df6b2520c", + "tests/ArcForges.Cloud.Consumer/ArcForges.Cloud.Consumer.csproj": "8fe4c5800be3ea425701ac46d4134424a896a00b3d7e7c2bb37ee5c1168d81f4", + "tests/ArcForges.Cloud.Consumer/packages.lock.json": "cd85ca972fa1b8879607189ce2a54de43ba657992d19361a1b68cd9827295192", + "tests/ArcForges.Cloud.Tests/ArcForges.Cloud.Tests.csproj": "f57aefcd844e2a90c36c484b85e3df4f3938a4358c3f60bc2206d7e950c47565", + "tests/ArcForges.Cloud.Tests/packages.lock.json": "22d18c888de531539283b7a38ae536c9843a84811c999d456f85476cf1f2487d", + "tests/kotlin-consumer/build.gradle.kts": "05c1cb296b5f5b66c4f75282c44383a32a8a596c330c14fd782e1912919c8394", + "tests/kotlin-consumer/gradle.lockfile": "0a6640ce98f60bf6e38bf19158fc87e68e33e1934eb3ede2df75b614a6b18c47", + "tests/kotlin-consumer/gradle/verification-metadata.xml": "a3636c4a18cfc8319359129f8c037bf0e2c455512beeff6846414301e8f99639", + "tests/kotlin-consumer/gradle/wrapper/gradle-wrapper.properties": "176fcae7ef9cfcdd82903d41888fe11fe197a674f752e9275aa51d0d8427a2c5", + "tests/kotlin-consumer/settings.gradle.kts": "64675e4ff0bb4d84e56a315bb017e2adac9e58eb1efb86e409fb148806b38a55", + "wrangler.json": "7b22ead0f7b327bc56332ca0692e4ac3f07053063d5daea531c56a6a0206c24e", + "eng/provenance/artifact-profiles/cloud-release-r12.json": "2240b17719fa5131582045b6164735ae79c2880fd79c6c0c4e6479e0d4626321", + "eng/provenance/records/cloud-runtime-notices-r13.json": "3e2f656c04197bdd90f28f2c12e78cd9fb9ab24ce6c4c4407767a223b9d5357d", + "eng/provenance/records/cloud-worker-bundle-r12.json": "04df6106636eda1b201456cca48dc4344b7126aad72f782e6a8b780150ed8665", + "Directory.Build.props": "594fe799ea787c02d4406e14360c4b1902a5aee8679b76c8ac797ae34a9e792c", + "Directory.Build.targets": "fa4bf35487140fecd21b71a2fb524792631a292df2313f9440f8c6e7e90a82d2", + ".github/workflows/ci.yml": "81ec9755c880b522146e6737281c080c77dd8958623dd3a754db3e9c5e89e8a3" + }, + "checks": [ + "locked-restore", + "licence-provenance", + "security", + "class-compilation", + "compatibility", + "sbom", + "framework-posture" + ], + "runtimeAssessment": "No framework version changed. Existing C# Native AOT and JVM verification compiler posture is preserved. Future framework majors require explicit runtime, native, transport and migration assessment. Local runtime/performance coverage runs only for affected behavior supported by the existing environment; none is asserted here.", + "maintenance": "Current exact producer and package locks remain unchanged; dependency review and the existing high-severity audit remain required. Lockfile licence labels are metadata, not replacement file-level redistribution grants. Updates must refresh this reviewed input-bound record and pass applicable existing class checks.", + "previous": null, + "immutableHistory": "Admitted review records are retained in Git history. A dependency change requires a new reviewed source commit and updated input-bound rationale; never amend an already accepted provenance record." + }, + "packages": { + "@arcforges/api-client@1.0.0-ci.74.1": "sha512-G2Gri9QnBPKcVdkOtMpFBS/nYgQ0Ug4xrest5auUxcLZXRRXbq9Q7ueQNeGtmWgDjhA54QZT/R7SMfRinm0g1A==", + "@arcforges/proto@1.0.0-ci.74.1": "sha512-tjGTLa/mCfY7d2kMrnJhGZ7nLgONPb7rM+OSrM68kfeseKEjp/fUPkEASjYq+VKYbh9drZsXVQo1kLw1Ejl09Q==", + "@biomejs/biome@2.5.14": "sha512-0FabLIjd4M/dm8VFI86RMaLLdgepzbdfiAL2R8cr7V81OYYrP1w7Z73KfAwPK5h9SrEBXTzNG2y+mBwPo9xRnw==", + "@biomejs/cli-darwin-arm64@2.5.14": "sha512-UnzaXO65L4tsZimFITFP2M121GyhDcWFrT3pL5ZJ5U4XcS/0L5VHYytVohdCf/gnDUFHgl2I9xnt5bV/J1kxHQ==", + "@biomejs/cli-darwin-x64@2.5.14": "sha512-kiy8qA16K93J7uvFfWi4LgjqDpnRKyePAna6A0Y4jxyUga35SYpIZ2cNWlhy0lsfgqRenCpfymnJWEZ6mgpRgA==", + "@biomejs/cli-linux-arm64@2.5.14": "sha512-vO/9BaU1n30CiFNLx49gMTMtbCAAqlo/EqFoG0BU3deQInTbJrmXSmTQ9e3FoDZIKQnvSLDVNL4lx1ci7y1T1Q==", + "@biomejs/cli-linux-arm64-musl@2.5.14": "sha512-SJ9PrZkBnnH9dHJDnxk34vKs0GB2dbsioaft6/hPhWJ7AHpwYH83Isnhj0FSRpFkGgpVfJ1lds23ApB2czUDLQ==", + "@biomejs/cli-linux-x64@2.5.14": "sha512-VHZRa7CCQBUWKxNwUvHJeuW03WFRgN5NWO//SDGOitc9QIeNyfA42V9zlKm+x82xFSG9Bzi5fi+hbhm9anO8yA==", + "@biomejs/cli-linux-x64-musl@2.5.14": "sha512-2kI5PrMgW5dcEZYrstLPmUmCwkUwZY39rP4BN93Vxbwcs2O57LDQOktUZZYPvvspN5i0mhGr3TJtF5sU26NUWg==", + "@biomejs/cli-win32-arm64@2.5.14": "sha512-pHgAFffmZtaYoxavEsWEYNvcA7NwOIjLyqw2HXyLbt16xYryX0L4fMV2u0G9ag6LNYPIoqWaWqzUcnc6rLGGXg==", + "@biomejs/cli-win32-x64@2.5.14": "sha512-oJWmBhoHsnhUKIke+0gXDX0mltJrWHA1UyHsrTlXwX0TL64ilVZAo+TYZm97baecV0esBdpzy3k96q+09JaZUQ==", + "@bufbuild/protobuf@2.15.0": "sha512-DAheWUkVr/SJTWCc+lg9dhY0eN4SaWlf4+bG1KzHeXbnqt0AfB/NX0Z+VunGlM1ki1B4zVvye27MpKh/svySUA==", + "@cloudflare/containers@0.3.7": "sha512-DM9dm3FnIBSyiSJ1FLavKwl/lk3oAmTaynCzZQ9pZR0ncRPquSxkxd8Nu2MFILxmDDsPkxKsSNEh9mHHMty4Fw==", + "@cloudflare/kv-asset-handler@0.5.0": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==", + "@cloudflare/unenv-preset@2.16.1": "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==", + "@cloudflare/workerd-darwin-64@1.20260918.1": "sha512-H5Em6Wd0jjxaloYh2rp+WLBl2eWbkk7nSP1svGt6K1RSv/rNVqmKdpjZPJTBSavOmeYGa88qvtOWwS+33OHTqQ==", + "@cloudflare/workerd-darwin-arm64@1.20260918.1": "sha512-CR9JRZEQo93fNgBVF4Df2H2/VYO4n7rxSseSwCVv3bJQEb0huADUSCj2FK4ipxar8ToOEB4wawyw0vJo5U/rQQ==", + "@cloudflare/workerd-linux-64@1.20260918.1": "sha512-UQ2nnY3qpXLzQ80frmWO+8HvtqyWaQILe8QYZwpemdjT+sqwCz4Dz+0/WVkFco0v/04kIIqikVeLTY/7gEhmkw==", + "@cloudflare/workerd-linux-arm64@1.20260918.1": "sha512-4rib51MaLNWweUIUxM/Xj558M5QmyZoBSf0ffv+lYah5VTrvwnez3XGxX72pElnBKHROvAPOi5msQ5Ts8JSI0A==", + "@cloudflare/workerd-windows-64@1.20260918.1": "sha512-sATrMx5ShYYgmgUGrcTmvsFSJBFuN95NEkX3xwb1qk8w1A6h5N11sea7yN2IeibwPyPmXKjWNjXOno0hZAM71Q==", + "@cloudflare/workers-types@5.20260918.1": "sha512-bUGc9gIdooYPi6lAUoB/eBXmy/ev9ok0XvDLzfJZQVCT8WCEQwv9f6smz6XeE83JzpX6ZSVi9CG1aDORnErYRQ==", + "@connectrpc/connect@2.2.0": "sha512-M63OQ1ZFcPUm85CuewJ9G9CMV8LjzGR9935xOnXNQGSazAbwMb3x2W7vXBYM1zqrP7XFD8uxp/dUAhirclgwnQ==", + "@connectrpc/connect-web@2.2.0": "sha512-uuBUcBTYfb/r1o98LzCCZk1H90yx0vmZ5m21dpw/q4EUwsKwkCDGI8H0aEdjcZld+Q2jJ5A5ADvPqfb6lzQ/sg==", + "@cspotcode/source-map-support@0.8.1": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "@emnapi/runtime@1.11.3": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "@esbuild/aix-ppc64@0.28.1": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "@esbuild/android-arm@0.28.1": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "@esbuild/android-arm64@0.28.1": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "@esbuild/android-x64@0.28.1": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "@esbuild/darwin-arm64@0.28.1": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "@esbuild/darwin-x64@0.28.1": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "@esbuild/freebsd-arm64@0.28.1": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "@esbuild/freebsd-x64@0.28.1": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "@esbuild/linux-arm@0.28.1": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "@esbuild/linux-arm64@0.28.1": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "@esbuild/linux-ia32@0.28.1": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "@esbuild/linux-loong64@0.28.1": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "@esbuild/linux-mips64el@0.28.1": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "@esbuild/linux-ppc64@0.28.1": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "@esbuild/linux-riscv64@0.28.1": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "@esbuild/linux-s390x@0.28.1": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "@esbuild/linux-x64@0.28.1": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "@esbuild/netbsd-arm64@0.28.1": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "@esbuild/netbsd-x64@0.28.1": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "@esbuild/openbsd-arm64@0.28.1": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "@esbuild/openbsd-x64@0.28.1": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "@esbuild/openharmony-arm64@0.28.1": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "@esbuild/sunos-x64@0.28.1": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "@esbuild/win32-arm64@0.28.1": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "@esbuild/win32-ia32@0.28.1": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "@esbuild/win32-x64@0.28.1": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "@img/colour@1.1.0": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "@img/sharp-darwin-arm64@0.35.4": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", + "@img/sharp-darwin-x64@0.35.4": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", + "@img/sharp-freebsd-wasm32@0.35.4": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "@img/sharp-libvips-darwin-arm64@1.3.3": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", + "@img/sharp-libvips-darwin-x64@1.3.3": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", + "@img/sharp-libvips-linux-arm@1.3.3": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", + "@img/sharp-libvips-linux-arm64@1.3.3": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", + "@img/sharp-libvips-linux-ppc64@1.3.3": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", + "@img/sharp-libvips-linux-riscv64@1.3.3": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", + "@img/sharp-libvips-linux-s390x@1.3.3": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", + "@img/sharp-libvips-linux-x64@1.3.3": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", + "@img/sharp-libvips-linuxmusl-arm64@1.3.3": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", + "@img/sharp-libvips-linuxmusl-x64@1.3.3": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", + "@img/sharp-linux-arm@0.35.4": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", + "@img/sharp-linux-arm64@0.35.4": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", + "@img/sharp-linux-ppc64@0.35.4": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", + "@img/sharp-linux-riscv64@0.35.4": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", + "@img/sharp-linux-s390x@0.35.4": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", + "@img/sharp-linux-x64@0.35.4": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", + "@img/sharp-linuxmusl-arm64@0.35.4": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", + "@img/sharp-linuxmusl-x64@0.35.4": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", + "@img/sharp-wasm32@0.35.4": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "@img/sharp-webcontainers-wasm32@0.35.4": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", + "@img/sharp-win32-arm64@0.35.4": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", + "@img/sharp-win32-ia32@0.35.4": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", + "@img/sharp-win32-x64@0.35.4": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", + "@jridgewell/resolve-uri@3.1.2": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "@jridgewell/sourcemap-codec@1.6.0": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "@jridgewell/trace-mapping@0.3.9": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "@poppinss/colors@4.1.6": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", + "@poppinss/dumper@0.6.5": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "@poppinss/exception@1.2.3": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", + "@sindresorhus/is@7.2.0": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "@speed-highlight/core@1.2.24": "sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw==", + "@types/node@24.13.5": "sha512-TXyindR+lBr22aJIdMQzCFHPHR6cR4js838mRDCSz5hOKWZvZwsXSSiXDmjRj4iJmgl+sR9O+1mkoVBSMadNug==", + "@typescript/typescript-aix-ppc64@7.0.2": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "@typescript/typescript-darwin-arm64@7.0.2": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "@typescript/typescript-darwin-x64@7.0.2": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "@typescript/typescript-freebsd-arm64@7.0.2": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "@typescript/typescript-freebsd-x64@7.0.2": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "@typescript/typescript-linux-arm@7.0.2": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "@typescript/typescript-linux-arm64@7.0.2": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "@typescript/typescript-linux-loong64@7.0.2": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "@typescript/typescript-linux-mips64el@7.0.2": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "@typescript/typescript-linux-ppc64@7.0.2": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "@typescript/typescript-linux-riscv64@7.0.2": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "@typescript/typescript-linux-s390x@7.0.2": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "@typescript/typescript-linux-x64@7.0.2": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "@typescript/typescript-netbsd-arm64@7.0.2": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "@typescript/typescript-netbsd-x64@7.0.2": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "@typescript/typescript-openbsd-arm64@7.0.2": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "@typescript/typescript-openbsd-x64@7.0.2": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "@typescript/typescript-sunos-x64@7.0.2": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "@typescript/typescript-win32-arm64@7.0.2": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "@typescript/typescript-win32-x64@7.0.2": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "blake3-wasm@2.1.5": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "cookie@1.1.1": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "detect-libc@2.1.2": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "error-stack-parser-es@1.0.5": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "esbuild@0.28.1": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "fsevents@2.3.3": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "kleur@4.1.5": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "miniflare@5.20260918.0-alpha": "sha512-vyIes7yW/OTzHtz4GhcBCTohZfqk2eQNiIkngZ07VRA5Qu24aNgW/TrFwlPkMLMjWDQ8R4JJBBHR/KX+liSDtg==", + "path-to-regexp@6.3.0": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "pathe@2.0.3": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "prettier@3.9.8": "sha512-WRFq3Wn3WId7LLROfMLdH7xaFr2jR62wU8nLO6rQUOLOxNZUviyJQs1M0iIhLexSFy+L+w0ch66wtoO2jRjG0A==", + "semver@7.8.5": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "sharp@0.35.4": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", + "supports-color@10.2.2": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "tslib@2.8.1": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "typescript@7.0.2": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "undici@7.29.0": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "undici-types@7.18.2": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "unenv@2.0.0-rc.24": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "workerd@1.20260918.1": "sha512-NsjfQlBNQ0iEniv/STOy4zbp8s5k60PzL1Ter02Eg44arbDhHtf6UOs03E31XDRmmBFxSIkAZuCyld3RKH1wqA==", + "wrangler@4.135.0": "sha512-WrNBQSfIG6YcILJcodYr5ty8vgkzGsV8YX+kfd+uZ5/Bd8cUW0GnUIRKAVfn5kYKqh1m/BPcji9h1d7mE8euFw==", + "ws@8.21.0": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "youch@4.1.0-beta.10": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "youch-core@0.3.3": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==" + }, + "supersedes": null +} diff --git a/eng/provenance/files.json b/eng/provenance/files.json index d1ddbbb..330d3a0 100644 --- a/eng/provenance/files.json +++ b/eng/provenance/files.json @@ -34,12 +34,15 @@ "biome.json", "docs/bootstrap-plan.md", "docs/build-identity.md", + "docs/dependency-policy.md", "docs/deployment.md", "docs/development.md", "docs/kotlin-hello-plan.md", "docs/licence-boundary.md", "docs/provenance.md", "docs/validation-policy.md", + "eng/policy/dependency-policy.json", + "eng/policy/dependency-reviews/admission-r1.json", "eng/policy/licence-boundary.json", "eng/policy/reuse-policy.json", "eng/provenance/NOTICE.txt", @@ -125,6 +128,8 @@ "tests/worker/toolchain.test.ts", "tooling/build-identity.ts", "tooling/cloudflare.ts", + "tooling/dependency-policy.test.ts", + "tooling/dependency-policy.ts", "tooling/kotlin.ts", "tooling/licence-boundary.ts", "tooling/process.ts", diff --git a/package.json b/package.json index e65a067..5d01522 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "lint": "biome lint --error-on-warnings .", "typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.worker.json", "test": "node --test tests/worker/build-identity.test.ts tests/worker/deadline.test.ts tests/worker/licence-boundary.test.ts tests/worker/provenance.test.ts tests/worker/router.test.ts tests/worker/toolchain.test.ts", - "check": "node tooling/project.ts toolchain && node tooling/project.ts licence && node tooling/project.ts provenance && npm run format:check && npm run lint && npm run typecheck && npm test", + "check": "npm run test:dependencies && node tooling/project.ts toolchain && node tooling/project.ts licence && node tooling/project.ts provenance && npm run format:check && npm run lint && npm run typecheck && npm test", "check:dotnet": "dotnet restore Cloud.slnx --locked-mode && dotnet build Cloud.slnx -c Release --no-restore && dotnet test --solution Cloud.slnx -c Release --no-build && dotnet format Cloud.slnx --no-restore --verify-no-changes", "candidate": "node tooling/project.ts candidate", "verify:candidate": "node tooling/project.ts verify", @@ -32,7 +32,9 @@ "dev": "node tooling/project.ts dev", "deploy": "node tooling/cloudflare.ts deploy", "test:live": "node tooling/cloudflare.ts smoke", - "test:artifact": "node tooling/project.ts prepare-provenance-test && node --test tests/worker/release-provenance.test.ts" + "test:artifact": "node tooling/project.ts prepare-provenance-test && node --test tests/worker/release-provenance.test.ts", + "check:dependencies": "node tooling/dependency-policy.ts", + "test:dependencies": "node --test tooling/dependency-policy.test.ts" }, "dependencies": { "@cloudflare/containers": "0.3.7" diff --git a/tooling/dependency-policy.test.ts b/tooling/dependency-policy.test.ts new file mode 100644 index 0000000..8a0bfa9 --- /dev/null +++ b/tooling/dependency-policy.test.ts @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: AGPL-3.0-only +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import path from "node:path"; +import test from "node:test"; +import { auditDependencies, digest, immutableCoordinates, validateHistoricalCoordinates, validateClosure, validateImports, validatePolicy, type Policy } from "./dependency-policy.ts"; + +const root = process.cwd(); +const baseline = JSON.parse(readFileSync("eng/policy/dependency-policy.json", "utf8")) as Policy; +const lock = JSON.parse(readFileSync("package-lock.json", "utf8")); +test("actual repository admission", () => { assert.equal(auditDependencies(root).result, "passed"); }); +test("forbidden licence", () => { + const packages = structuredClone(lock.packages); + packages[Object.keys(baseline.closure)[0]!].license = "GPL-3.0-only"; + assert.throws(() => validateClosure(baseline, packages), /Forbidden licence/u); +}); +test("floating tag", () => { + const packages = structuredClone(lock.packages); + packages[Object.keys(baseline.closure)[0]!].version = "latest"; + assert.throws(() => validateClosure(baseline, packages), /Floating version/u); +}); +test("same version with altered bytes", () => { + const packages = structuredClone(lock.packages); + packages[Object.keys(baseline.closure)[0]!].integrity = `sha512-${Buffer.alloc(64).toString("base64")}`; + assert.throws(() => validateClosure(baseline, packages), /mutable-version/u); +}); +test("wrong publisher", () => { + const policy = structuredClone(baseline); + policy.firstParty["@arcforges/proto"] = { publisher: "other/Contracts", visibility: "public" }; + assert.throws(() => validatePolicy(policy), /Wrong publisher/u); +}); +test("untrusted registry", () => { + const packages = structuredClone(lock.packages); + packages[Object.keys(baseline.closure)[0]!].resolved = "https://registry.npmjs.org.evil.invalid/p.tgz"; + assert.throws(() => validateClosure(baseline, packages), /Untrusted feed|Wrong publisher artifact/u); +}); +test("upgrade needs input-bound review and framework assessment", () => { + const policy = structuredClone(baseline); + policy.inputs["package-lock.json"] = "0".repeat(64); + assert.throws(() => validatePolicy(policy), /Upgrade review/u); + policy.review.inputs = structuredClone(policy.inputs); + policy.review.runtimeAssessment = ""; + assert.throws(() => validatePolicy(policy), /runtimeAssessment/u); +}); +test("native additions need adoption evidence", () => { + const policy = structuredClone(baseline); + policy.native.mode = "anything-installed"; + assert.throws(() => validatePolicy(policy), /Native adoption/u); +}); +test("public sources reject static, re-export and dynamic internal imports", () => { + for (const source of ['import x from "@arcforges/ai-internal";', 'export * from "@arcforges/proto/internal";', 'void import("@arcforges/storage-internal");', 'const x = require("@arcforges/ai-internal");']) + assert.throws(() => validateImports(root, "src/example.ts", source, baseline), /[Ii]nternal/u); +}); +test("source cannot escape into a sibling repository", () => { + assert.throws(() => validateImports(root, "example.ts", 'import "../Contracts/private.ts";', baseline), /Sibling source/u); + validateImports(root, "src/example.ts", 'import type { X } from "@arcforges/proto";', baseline); +}); +test("stable closure cannot inherit foundation candidates", () => { + const policy = structuredClone(baseline); + policy.channel = "stable"; + assert.throws(() => validateClosure(policy, lock.packages), /Prerelease/u); +}); +test("input hashes are portable, content sensitive and independent of outer metadata", () => { + assert.equal(digest("a\r\n"), digest("a\n")); + assert.notEqual(digest("a\n"), digest("b\n")); + assert(path.isAbsolute(root)); +}); + +test("reviewed successor cannot replace bytes for an admitted coordinate", () => { + assert.throws(() => validateHistoricalCoordinates({ "example@1.0.0": "sha512-original" }, { "example@1.0.0": "sha512-replacement" }), /despite successor review/u); + validateHistoricalCoordinates({ "example@1.0.0": "sha512-original" }, { "example@1.0.1": "sha512-new-version" }); +}); +test("comments and escaped module names do not bypass public import scope", () => { + assert.throws(() => validateImports(root, "src/example.ts", 'import /* comment */ "@arcforges/ai-internal";', baseline), /internal/u); + assert.throws(() => validateImports(root, "src/example.ts", 'void import(`@arcforges/${kind}`);', baseline), /Computed import/u); +}); + +test("duplicate nested coordinates cannot hide different package bytes", () => { + assert.throws(() => immutableCoordinates({ "node_modules/example": { version: "1.0.0", integrity: "sha512-first" }, "node_modules/parent/node_modules/example": { version: "1.0.0", integrity: "sha512-second" } }), /Conflicting integrity/u); +}); diff --git a/tooling/dependency-policy.ts b/tooling/dependency-policy.ts new file mode 100644 index 0000000..1e7b1db --- /dev/null +++ b/tooling/dependency-policy.ts @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: AGPL-3.0-only +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import { execFileSync } from "node:child_process"; +import { readFileSync, realpathSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +type Entry = { version?: string; resolved?: string; integrity?: string; license?: string; link?: boolean; inBundle?: boolean; name?: string }; +type Review = { owner: string; reviewer: string; date: string; rationale: string; inputs: Record; checks: string[]; runtimeAssessment: string; maintenance: string }; +export type Policy = { + schemaVersion: number; repository: string; sourceCommit: string; reviewRecord: string; + manifests: string[]; inputs: Record; review: Review; + closure: Record; foundationCandidates: Record; buildToolPrereleases: Record; + firstParty: Record; + registry: string; channel: string; artifactRecords: string[]; + native: { mode: string; evidence: string[] }; +}; +const gitEnvironment = () => Object.fromEntries(Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith("GIT_"))); +const sections = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]; +const exact = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u; +const requiredChecks = ["locked-restore", "licence-provenance", "security", "class-compilation", "compatibility", "sbom", "framework-posture"]; +export function digest(text: string) { return createHash("sha256").update(text.replaceAll("\r\n", "\n")).digest("hex"); } +export function validatePolicy(policy: Policy) { + assert.equal(policy.schemaVersion, 1); + assert(["Cloud", "AI", "Web"].includes(policy.repository), "Unknown owner"); + assert.match(policy.sourceCommit, /^[a-f0-9]{40}$/u); + assert.equal(policy.registry, "https://registry.npmjs.org/"); + assert(["foundation-candidate", "stable"].includes(policy.channel)); + assert(Object.keys(policy.inputs).length > 0, "Missing admitted input closure"); + assert.deepEqual(policy.review.inputs, policy.inputs, "Upgrade review does not bind admitted inputs"); + for (const field of ["owner", "reviewer", "date", "rationale", "runtimeAssessment", "maintenance"] as const) + assert(policy.review[field]?.trim().length > 8, `Missing upgrade review ${field}`); + for (const check of requiredChecks) assert(policy.review.checks.includes(check), `Missing upgrade gate: ${check}`); + assert(policy.artifactRecords.length > 0, "Missing shipped closure authority"); + assert.equal(policy.native.mode, "existing-artifact-closure-only", "Native adoption requires AD-01 through AD-08"); + assert(policy.native.evidence.length > 0, "Missing native closure evidence"); + for (const [name, entry] of Object.entries(policy.firstParty)) { + assert(["@arcforges/proto", "@arcforges/api-client"].includes(name), `Unadmitted internal/first-party package: ${name}`); + assert.equal(entry.publisher, "ArcForges/Contracts", `Wrong publisher: ${name}`); + assert.equal(entry.visibility, "public", `Internal package: ${name}`); + } +} +export function immutableCoordinates(closure: Record) { + const coordinates: Record = {}; + for (const [key, entry] of Object.entries(closure)) { + if (!entry.integrity) continue; + const coordinate = `${entry.name ?? key.split("node_modules/").at(-1)}@${entry.version}`; + const previous = coordinates[coordinate]; + assert(!previous || previous === entry.integrity, `Conflicting integrity across nested coordinates: ${coordinate}`); + coordinates[coordinate] = entry.integrity; + } + return coordinates; +} +export function validateHistoricalCoordinates(admitted: Record, current: Record) { + for (const [coordinate, integrity] of Object.entries(admitted)) + if (current[coordinate]) assert.equal(current[coordinate], integrity, `Immutable version changed despite successor review: ${coordinate}`); +} +export function validateClosure(policy: Policy, packages: Record) { + const actual = Object.fromEntries(Object.entries(packages).filter(([name, entry]) => name.includes("node_modules/") && !entry.link).map(([name, entry]) => [name, Object.fromEntries(Object.entries(entry).filter(([key]) => ["version", "resolved", "integrity", "license", "inBundle", "name"].includes(key))) as Entry])); + for (const [key, entry] of Object.entries(actual)) { + assert(entry.license && !/(?:^|[ (])(?:GPL-[^ )]+|NOASSERTION|UNKNOWN|UNLICENSED)(?:$|[ )])/u.test(entry.license), `Forbidden licence: ${key}`); + assert(entry.version && exact.test(entry.version), `Floating version: ${key}`); + const name = entry.name ?? key.split("node_modules/").at(-1)!; + if (name.startsWith("@arcforges/")) assert(policy.firstParty[name], `Unadmitted publisher/internal package: ${name}`); + if (entry.version.includes("-")) { + assert.equal(policy.channel, "foundation-candidate", `Prerelease in stable closure: ${name}`); + const admitted = name.startsWith("@arcforges/") ? policy.foundationCandidates : policy.buildToolPrereleases; + assert.equal(admitted[name], entry.version, `Unadmitted prerelease: ${name}`); + if (!name.startsWith("@arcforges/")) assert((packages[key] as Entry & { dev?: boolean }).dev, `Preview package entered runtime class: ${name}`); + } + if (name.startsWith("@arcforges/")) { + const expected = `${policy.registry}${name}/-/${name.split("/").at(-1)}-${entry.version}.tgz`; + assert.equal(entry.resolved, expected, `Wrong publisher artifact coordinate: ${name}`); + } + let current = key; + let artifact = entry; + while (artifact.inBundle) { + if (artifact.resolved || artifact.integrity) registry(artifact, current); + const boundary = current.lastIndexOf("/node_modules/"); + assert(boundary > 0, `Orphan bundled dependency: ${key}`); + current = current.slice(0, boundary); + const parent = packages[current]; + assert(parent && !parent.link, `Unverified bundle ancestor: ${key}`); + artifact = parent; + } + registry(artifact, current); + } + assert.deepEqual(actual, policy.closure, "Unadmitted dependency, licence or mutable-version integrity; review the changed closure"); +} +function registry(entry: Entry, name: string) { + const url = new URL(entry.resolved ?? "invalid:"); + assert(url.origin === "https://registry.npmjs.org" && !url.username && !url.password && !url.search && !url.hash, `Untrusted feed: ${name}`); + assert.match(entry.integrity ?? "", /^sha512-[A-Za-z0-9+/]{86}==$/u, `Missing lock integrity: ${name}`); +} +export function validateImports(root: string, file: string, source: string, policy: Policy) { + const check = (value: string) => { + if (value.startsWith("@arcforges/")) { + const name = value.split("/").slice(0, 2).join("/"); + const workspace = ["@arcforges/web-ui", "@arcforges/web-site"].includes(name) && policy.repository === "Web"; + assert(workspace || policy.firstParty[name]?.visibility === "public", `Forbidden internal import: ${file}: ${value}`); + assert(workspace || value === name, `Internal or unadmitted package subpath: ${value}`); + } + if (value.startsWith(".")) { + const target = path.resolve(root, path.dirname(file), value); + assert(target.startsWith(root + path.sep), `Sibling source import: ${file}: ${value}`); + assert(!/(?:^|[\\/])(?:ai-internal|storage-internal)(?:[\\/]|$)/iu.test(target), `Private generated source: ${file}`); + } + assert(!/^(?:https?:|file:|git\+|[A-Za-z]:[\\/]|\/)/u.test(value), `External source import: ${file}: ${value}`); + }; + // Tokenize comments and strings before inspecting module declarations; fixture text is not executable syntax. + const tokens: { value: string; literal: boolean }[] = []; + const lexical = /\/\*[\s\S]*?\*\/|\/\/[^\r\n]*|"(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|`(?:\\[\s\S]|[^`\\])*`|[A-Za-z_$][\w$]*|[^\s]/gu; + for (const match of source.matchAll(lexical)) { + const raw = match[0]; + if (raw.startsWith("//") || raw.startsWith("/*")) continue; + const literal = ['"', "'", "`"].includes(raw[0]!); + const value = literal ? raw.slice(1, -1).replace(/\\u\{([a-f\d]+)\}|\\u([a-f\d]{4})|\\x([a-f\d]{2})|\\([\s\S])/giu, (_all, wide: string, unicode: string, hex: string, escaped: string) => wide || unicode || hex ? String.fromCodePoint(Number.parseInt(wide || unicode || hex, 16)) : escaped) : raw; + tokens.push({ value, literal }); + } + for (let index = 0; index < tokens.length; index++) { + const token = tokens[index]!; + if (token.literal) continue; + const next = tokens[index + 1]; + if (["import", "require"].includes(token.value) && next?.value === "(") { + const argument = tokens[index + 2]; + assert(argument?.literal && !argument.value.includes("${"), `Computed import needs explicit admission: ${file}`); + check(argument.value); + } else if (["import", "from"].includes(token.value) && next?.literal) check(next.value); + } +} +export function auditDependencies(root: string) { + root = realpathSync(root); + const read = (file: string) => { + const full = realpathSync(path.resolve(root, file)); + assert(full.startsWith(root + path.sep), `Escaped dependency input: ${file}`); + return readFileSync(full, "utf8"); + }; + const policy = JSON.parse(read("eng/policy/dependency-policy.json")) as Policy; + validatePolicy(policy); + const activeReview = JSON.parse(read(policy.reviewRecord)) as { review: Review; packages: Record; supersedes: string | null }; + assert.deepEqual(activeReview.review, policy.review, "Missing reviewed successor receipt"); + const git = (...args: string[]) => execFileSync("git", args, { cwd: root, encoding: "utf8", windowsHide: true, env: gitEnvironment() }).trim(); + const historical = [...new Set(git("log", "HEAD", "--diff-filter=A", "--name-only", "--format=", "--", "eng/policy/dependency-reviews/").split("\n").filter(Boolean))]; + const coordinates = immutableCoordinates(policy.closure); + assert.deepEqual(activeReview.packages, coordinates, "Review does not bind immutable package coordinates"); + for (const file of historical) { + const introduced = git("log", "HEAD", "--diff-filter=A", "--format=%H", "--", file).split("\n").at(-1)!; + const original = git("show", `${introduced}:${file}`); + assert.equal(read(file).trim(), original, `Immutable review modified: ${file}`); + const admitted = JSON.parse(original) as { packages: Record }; + validateHistoricalCoordinates(admitted.packages, coordinates); + } + if (activeReview.supersedes) assert(historical.includes(activeReview.supersedes), "Missing predecessor review"); + else assert(historical.length === 0 || historical.includes(policy.reviewRecord), "Upgrade requires predecessor review"); + const files = execFileSync("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], { cwd: root, encoding: "utf8", windowsHide: true, env: gitEnvironment() }).split("\0").filter(Boolean); + const manifests = files.filter((file) => path.basename(file) === "package.json"); + assert.deepEqual(manifests.sort(), [...policy.manifests].sort(), "Unadmitted workspace manifest"); + const inputNames = new Set(["package.json", "package-lock.json", ".node-version", ".java-version", ".npmrc", "NuGet.Config", "global.json", "Directory.Packages.props", "Dockerfile", "wrangler.json", "wrangler.jsonc", "gradle.lockfile", "verification-metadata.xml", "libs.versions.toml", "settings.gradle.kts", "build.gradle.kts", "gradle-wrapper.properties", "vcpkg.json", "vcpkg-configuration.json"]); + for (const file of files) { + if (inputNames.has(path.basename(file)) || /\.(?:csproj|esproj|props|targets)$/u.test(file) || file.endsWith("packages.lock.json")) + assert(Object.hasOwn(policy.inputs, file), `New dependency input requires admission: ${file}`); + if (/^(?:src|tests)\//u.test(file) && file.endsWith(".cs")) + assert(!/\b(?:using|global::)\s*ArcForges\.Contracts\.(?:Internal|Storage|AIInternal)\b/u.test(read(file)), `Unadmitted private generated C# import: ${file}`); + } + const lock = JSON.parse(read("package-lock.json")) as { packages: Record>; lockfileVersion: number }; + assert.equal(lock.lockfileVersion, 3); + for (const file of policy.manifests) { + const manifest = JSON.parse(read(file)) as Record>; + const entry = lock.packages[file === "package.json" ? "" : path.posix.dirname(file)]; + assert(entry, `Missing workspace lock: ${file}`); + for (const section of sections) { + assert.deepEqual(manifest[section] ?? {}, entry[section] ?? {}, `Manifest/lock drift: ${file}`); + for (const [name, version] of Object.entries(manifest[section] ?? {})) assert(exact.test(version), `Floating selector: ${name}`); + } + } + validateClosure(policy, lock.packages); + for (const [file, expected] of Object.entries(policy.inputs)) assert.equal(digest(read(file)), expected, `Dependency input changed without review: ${file}`); + const inventory = JSON.parse(read("eng/provenance/files.json")) as { artifacts: string[] }; + assert.deepEqual(inventory.artifacts, policy.artifactRecords, "Shipped dependency class changed without admission"); + for (const file of files.filter((file) => /^(?:src|worker|apps|packages)\//u.test(file) && /\.(?:ts|tsx|mjs|js|cts|mts)$/u.test(file))) validateImports(root, file, read(file), policy); + return { result: "passed", repository: policy.repository, dependencies: Object.keys(policy.closure).length, inputs: Object.keys(policy.inputs).length, evidence: "offline dependency admission; existing provenance and candidate gates retain redistribution authority" }; +} +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) console.log(JSON.stringify(auditDependencies(process.cwd()), null, 2)); From 015b35008c2d8f613284c981d3cacbecf4e13b96 Mon Sep 17 00:00:00 2001 From: sammiller Date: Mon, 21 Sep 2026 21:41:27 -0700 Subject: [PATCH 2/3] Fix dependency policy formatting diagnosed by CI --- tooling/dependency-policy.test.ts | 80 +++++-- tooling/dependency-policy.ts | 332 +++++++++++++++++++++++++----- 2 files changed, 348 insertions(+), 64 deletions(-) diff --git a/tooling/dependency-policy.test.ts b/tooling/dependency-policy.test.ts index 8a0bfa9..ba24093 100644 --- a/tooling/dependency-policy.test.ts +++ b/tooling/dependency-policy.test.ts @@ -3,12 +3,23 @@ import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import path from "node:path"; import test from "node:test"; -import { auditDependencies, digest, immutableCoordinates, validateHistoricalCoordinates, validateClosure, validateImports, validatePolicy, type Policy } from "./dependency-policy.ts"; +import { + auditDependencies, + digest, + immutableCoordinates, + validateHistoricalCoordinates, + validateClosure, + validateImports, + validatePolicy, + type Policy, +} from "./dependency-policy.ts"; const root = process.cwd(); const baseline = JSON.parse(readFileSync("eng/policy/dependency-policy.json", "utf8")) as Policy; const lock = JSON.parse(readFileSync("package-lock.json", "utf8")); -test("actual repository admission", () => { assert.equal(auditDependencies(root).result, "passed"); }); +test("actual repository admission", () => { + assert.equal(auditDependencies(root).result, "passed"); +}); test("forbidden licence", () => { const packages = structuredClone(lock.packages); packages[Object.keys(baseline.closure)[0]!].license = "GPL-3.0-only"; @@ -21,7 +32,8 @@ test("floating tag", () => { }); test("same version with altered bytes", () => { const packages = structuredClone(lock.packages); - packages[Object.keys(baseline.closure)[0]!].integrity = `sha512-${Buffer.alloc(64).toString("base64")}`; + packages[Object.keys(baseline.closure)[0]!].integrity = + `sha512-${Buffer.alloc(64).toString("base64")}`; assert.throws(() => validateClosure(baseline, packages), /mutable-version/u); }); test("wrong publisher", () => { @@ -31,8 +43,12 @@ test("wrong publisher", () => { }); test("untrusted registry", () => { const packages = structuredClone(lock.packages); - packages[Object.keys(baseline.closure)[0]!].resolved = "https://registry.npmjs.org.evil.invalid/p.tgz"; - assert.throws(() => validateClosure(baseline, packages), /Untrusted feed|Wrong publisher artifact/u); + packages[Object.keys(baseline.closure)[0]!].resolved = + "https://registry.npmjs.org.evil.invalid/p.tgz"; + assert.throws( + () => validateClosure(baseline, packages), + /Untrusted feed|Wrong publisher artifact/u, + ); }); test("upgrade needs input-bound review and framework assessment", () => { const policy = structuredClone(baseline); @@ -48,11 +64,19 @@ test("native additions need adoption evidence", () => { assert.throws(() => validatePolicy(policy), /Native adoption/u); }); test("public sources reject static, re-export and dynamic internal imports", () => { - for (const source of ['import x from "@arcforges/ai-internal";', 'export * from "@arcforges/proto/internal";', 'void import("@arcforges/storage-internal");', 'const x = require("@arcforges/ai-internal");']) + for (const source of [ + 'import x from "@arcforges/ai-internal";', + 'export * from "@arcforges/proto/internal";', + 'void import("@arcforges/storage-internal");', + 'const x = require("@arcforges/ai-internal");', + ]) assert.throws(() => validateImports(root, "src/example.ts", source, baseline), /[Ii]nternal/u); }); test("source cannot escape into a sibling repository", () => { - assert.throws(() => validateImports(root, "example.ts", 'import "../Contracts/private.ts";', baseline), /Sibling source/u); + assert.throws( + () => validateImports(root, "example.ts", 'import "../Contracts/private.ts";', baseline), + /Sibling source/u, + ); validateImports(root, "src/example.ts", 'import type { X } from "@arcforges/proto";', baseline); }); test("stable closure cannot inherit foundation candidates", () => { @@ -67,14 +91,46 @@ test("input hashes are portable, content sensitive and independent of outer meta }); test("reviewed successor cannot replace bytes for an admitted coordinate", () => { - assert.throws(() => validateHistoricalCoordinates({ "example@1.0.0": "sha512-original" }, { "example@1.0.0": "sha512-replacement" }), /despite successor review/u); - validateHistoricalCoordinates({ "example@1.0.0": "sha512-original" }, { "example@1.0.1": "sha512-new-version" }); + assert.throws( + () => + validateHistoricalCoordinates( + { "example@1.0.0": "sha512-original" }, + { "example@1.0.0": "sha512-replacement" }, + ), + /despite successor review/u, + ); + validateHistoricalCoordinates( + { "example@1.0.0": "sha512-original" }, + { "example@1.0.1": "sha512-new-version" }, + ); }); test("comments and escaped module names do not bypass public import scope", () => { - assert.throws(() => validateImports(root, "src/example.ts", 'import /* comment */ "@arcforges/ai-internal";', baseline), /internal/u); - assert.throws(() => validateImports(root, "src/example.ts", 'void import(`@arcforges/${kind}`);', baseline), /Computed import/u); + assert.throws( + () => + validateImports( + root, + "src/example.ts", + 'import /* comment */ "@arcforges/ai-internal";', + baseline, + ), + /internal/u, + ); + assert.throws( + () => validateImports(root, "src/example.ts", "void import(`@arcforges/${kind}`);", baseline), + /Computed import/u, + ); }); test("duplicate nested coordinates cannot hide different package bytes", () => { - assert.throws(() => immutableCoordinates({ "node_modules/example": { version: "1.0.0", integrity: "sha512-first" }, "node_modules/parent/node_modules/example": { version: "1.0.0", integrity: "sha512-second" } }), /Conflicting integrity/u); + assert.throws( + () => + immutableCoordinates({ + "node_modules/example": { version: "1.0.0", integrity: "sha512-first" }, + "node_modules/parent/node_modules/example": { + version: "1.0.0", + integrity: "sha512-second", + }, + }), + /Conflicting integrity/u, + ); }); diff --git a/tooling/dependency-policy.ts b/tooling/dependency-policy.ts index 1e7b1db..a05e865 100644 --- a/tooling/dependency-policy.ts +++ b/tooling/dependency-policy.ts @@ -6,21 +6,60 @@ import { readFileSync, realpathSync } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; -type Entry = { version?: string; resolved?: string; integrity?: string; license?: string; link?: boolean; inBundle?: boolean; name?: string }; -type Review = { owner: string; reviewer: string; date: string; rationale: string; inputs: Record; checks: string[]; runtimeAssessment: string; maintenance: string }; +type Entry = { + version?: string; + resolved?: string; + integrity?: string; + license?: string; + link?: boolean; + inBundle?: boolean; + name?: string; +}; +type Review = { + owner: string; + reviewer: string; + date: string; + rationale: string; + inputs: Record; + checks: string[]; + runtimeAssessment: string; + maintenance: string; +}; export type Policy = { - schemaVersion: number; repository: string; sourceCommit: string; reviewRecord: string; - manifests: string[]; inputs: Record; review: Review; - closure: Record; foundationCandidates: Record; buildToolPrereleases: Record; + schemaVersion: number; + repository: string; + sourceCommit: string; + reviewRecord: string; + manifests: string[]; + inputs: Record; + review: Review; + closure: Record; + foundationCandidates: Record; + buildToolPrereleases: Record; firstParty: Record; - registry: string; channel: string; artifactRecords: string[]; + registry: string; + channel: string; + artifactRecords: string[]; native: { mode: string; evidence: string[] }; }; -const gitEnvironment = () => Object.fromEntries(Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith("GIT_"))); +const gitEnvironment = () => + Object.fromEntries( + Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith("GIT_")), + ); const sections = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]; const exact = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u; -const requiredChecks = ["locked-restore", "licence-provenance", "security", "class-compilation", "compatibility", "sbom", "framework-posture"]; -export function digest(text: string) { return createHash("sha256").update(text.replaceAll("\r\n", "\n")).digest("hex"); } +const requiredChecks = [ + "locked-restore", + "licence-provenance", + "security", + "class-compilation", + "compatibility", + "sbom", + "framework-posture", +]; +export function digest(text: string) { + return createHash("sha256").update(text.replaceAll("\r\n", "\n")).digest("hex"); +} export function validatePolicy(policy: Policy) { assert.equal(policy.schemaVersion, 1); assert(["Cloud", "AI", "Web"].includes(policy.repository), "Unknown owner"); @@ -28,15 +67,34 @@ export function validatePolicy(policy: Policy) { assert.equal(policy.registry, "https://registry.npmjs.org/"); assert(["foundation-candidate", "stable"].includes(policy.channel)); assert(Object.keys(policy.inputs).length > 0, "Missing admitted input closure"); - assert.deepEqual(policy.review.inputs, policy.inputs, "Upgrade review does not bind admitted inputs"); - for (const field of ["owner", "reviewer", "date", "rationale", "runtimeAssessment", "maintenance"] as const) + assert.deepEqual( + policy.review.inputs, + policy.inputs, + "Upgrade review does not bind admitted inputs", + ); + for (const field of [ + "owner", + "reviewer", + "date", + "rationale", + "runtimeAssessment", + "maintenance", + ] as const) assert(policy.review[field]?.trim().length > 8, `Missing upgrade review ${field}`); - for (const check of requiredChecks) assert(policy.review.checks.includes(check), `Missing upgrade gate: ${check}`); + for (const check of requiredChecks) + assert(policy.review.checks.includes(check), `Missing upgrade gate: ${check}`); assert(policy.artifactRecords.length > 0, "Missing shipped closure authority"); - assert.equal(policy.native.mode, "existing-artifact-closure-only", "Native adoption requires AD-01 through AD-08"); + assert.equal( + policy.native.mode, + "existing-artifact-closure-only", + "Native adoption requires AD-01 through AD-08", + ); assert(policy.native.evidence.length > 0, "Missing native closure evidence"); for (const [name, entry] of Object.entries(policy.firstParty)) { - assert(["@arcforges/proto", "@arcforges/api-client"].includes(name), `Unadmitted internal/first-party package: ${name}`); + assert( + ["@arcforges/proto", "@arcforges/api-client"].includes(name), + `Unadmitted internal/first-party package: ${name}`, + ); assert.equal(entry.publisher, "ArcForges/Contracts", `Wrong publisher: ${name}`); assert.equal(entry.visibility, "public", `Internal package: ${name}`); } @@ -47,27 +105,60 @@ export function immutableCoordinates(closure: Record) { if (!entry.integrity) continue; const coordinate = `${entry.name ?? key.split("node_modules/").at(-1)}@${entry.version}`; const previous = coordinates[coordinate]; - assert(!previous || previous === entry.integrity, `Conflicting integrity across nested coordinates: ${coordinate}`); + assert( + !previous || previous === entry.integrity, + `Conflicting integrity across nested coordinates: ${coordinate}`, + ); coordinates[coordinate] = entry.integrity; } return coordinates; } -export function validateHistoricalCoordinates(admitted: Record, current: Record) { +export function validateHistoricalCoordinates( + admitted: Record, + current: Record, +) { for (const [coordinate, integrity] of Object.entries(admitted)) - if (current[coordinate]) assert.equal(current[coordinate], integrity, `Immutable version changed despite successor review: ${coordinate}`); + if (current[coordinate]) + assert.equal( + current[coordinate], + integrity, + `Immutable version changed despite successor review: ${coordinate}`, + ); } export function validateClosure(policy: Policy, packages: Record) { - const actual = Object.fromEntries(Object.entries(packages).filter(([name, entry]) => name.includes("node_modules/") && !entry.link).map(([name, entry]) => [name, Object.fromEntries(Object.entries(entry).filter(([key]) => ["version", "resolved", "integrity", "license", "inBundle", "name"].includes(key))) as Entry])); + const actual = Object.fromEntries( + Object.entries(packages) + .filter(([name, entry]) => name.includes("node_modules/") && !entry.link) + .map(([name, entry]) => [ + name, + Object.fromEntries( + Object.entries(entry).filter(([key]) => + ["version", "resolved", "integrity", "license", "inBundle", "name"].includes(key), + ), + ) as Entry, + ]), + ); for (const [key, entry] of Object.entries(actual)) { - assert(entry.license && !/(?:^|[ (])(?:GPL-[^ )]+|NOASSERTION|UNKNOWN|UNLICENSED)(?:$|[ )])/u.test(entry.license), `Forbidden licence: ${key}`); + assert( + entry.license && + !/(?:^|[ (])(?:GPL-[^ )]+|NOASSERTION|UNKNOWN|UNLICENSED)(?:$|[ )])/u.test(entry.license), + `Forbidden licence: ${key}`, + ); assert(entry.version && exact.test(entry.version), `Floating version: ${key}`); const name = entry.name ?? key.split("node_modules/").at(-1)!; - if (name.startsWith("@arcforges/")) assert(policy.firstParty[name], `Unadmitted publisher/internal package: ${name}`); + if (name.startsWith("@arcforges/")) + assert(policy.firstParty[name], `Unadmitted publisher/internal package: ${name}`); if (entry.version.includes("-")) { assert.equal(policy.channel, "foundation-candidate", `Prerelease in stable closure: ${name}`); - const admitted = name.startsWith("@arcforges/") ? policy.foundationCandidates : policy.buildToolPrereleases; + const admitted = name.startsWith("@arcforges/") + ? policy.foundationCandidates + : policy.buildToolPrereleases; assert.equal(admitted[name], entry.version, `Unadmitted prerelease: ${name}`); - if (!name.startsWith("@arcforges/")) assert((packages[key] as Entry & { dev?: boolean }).dev, `Preview package entered runtime class: ${name}`); + if (!name.startsWith("@arcforges/")) + assert( + (packages[key] as Entry & { dev?: boolean }).dev, + `Preview package entered runtime class: ${name}`, + ); } if (name.startsWith("@arcforges/")) { const expected = `${policy.registry}${name}/-/${name.split("/").at(-1)}-${entry.version}.tgz`; @@ -86,36 +177,72 @@ export function validateClosure(policy: Policy, packages: Record) } registry(artifact, current); } - assert.deepEqual(actual, policy.closure, "Unadmitted dependency, licence or mutable-version integrity; review the changed closure"); + assert.deepEqual( + actual, + policy.closure, + "Unadmitted dependency, licence or mutable-version integrity; review the changed closure", + ); } function registry(entry: Entry, name: string) { const url = new URL(entry.resolved ?? "invalid:"); - assert(url.origin === "https://registry.npmjs.org" && !url.username && !url.password && !url.search && !url.hash, `Untrusted feed: ${name}`); - assert.match(entry.integrity ?? "", /^sha512-[A-Za-z0-9+/]{86}==$/u, `Missing lock integrity: ${name}`); + assert( + url.origin === "https://registry.npmjs.org" && + !url.username && + !url.password && + !url.search && + !url.hash, + `Untrusted feed: ${name}`, + ); + assert.match( + entry.integrity ?? "", + /^sha512-[A-Za-z0-9+/]{86}==$/u, + `Missing lock integrity: ${name}`, + ); } export function validateImports(root: string, file: string, source: string, policy: Policy) { const check = (value: string) => { if (value.startsWith("@arcforges/")) { const name = value.split("/").slice(0, 2).join("/"); - const workspace = ["@arcforges/web-ui", "@arcforges/web-site"].includes(name) && policy.repository === "Web"; - assert(workspace || policy.firstParty[name]?.visibility === "public", `Forbidden internal import: ${file}: ${value}`); + const workspace = + ["@arcforges/web-ui", "@arcforges/web-site"].includes(name) && policy.repository === "Web"; + assert( + workspace || policy.firstParty[name]?.visibility === "public", + `Forbidden internal import: ${file}: ${value}`, + ); assert(workspace || value === name, `Internal or unadmitted package subpath: ${value}`); } if (value.startsWith(".")) { const target = path.resolve(root, path.dirname(file), value); assert(target.startsWith(root + path.sep), `Sibling source import: ${file}: ${value}`); - assert(!/(?:^|[\\/])(?:ai-internal|storage-internal)(?:[\\/]|$)/iu.test(target), `Private generated source: ${file}`); + assert( + !/(?:^|[\\/])(?:ai-internal|storage-internal)(?:[\\/]|$)/iu.test(target), + `Private generated source: ${file}`, + ); } - assert(!/^(?:https?:|file:|git\+|[A-Za-z]:[\\/]|\/)/u.test(value), `External source import: ${file}: ${value}`); + assert( + !/^(?:https?:|file:|git\+|[A-Za-z]:[\\/]|\/)/u.test(value), + `External source import: ${file}: ${value}`, + ); }; // Tokenize comments and strings before inspecting module declarations; fixture text is not executable syntax. const tokens: { value: string; literal: boolean }[] = []; - const lexical = /\/\*[\s\S]*?\*\/|\/\/[^\r\n]*|"(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|`(?:\\[\s\S]|[^`\\])*`|[A-Za-z_$][\w$]*|[^\s]/gu; + const lexical = + /\/\*[\s\S]*?\*\/|\/\/[^\r\n]*|"(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|`(?:\\[\s\S]|[^`\\])*`|[A-Za-z_$][\w$]*|[^\s]/gu; for (const match of source.matchAll(lexical)) { const raw = match[0]; if (raw.startsWith("//") || raw.startsWith("/*")) continue; const literal = ['"', "'", "`"].includes(raw[0]!); - const value = literal ? raw.slice(1, -1).replace(/\\u\{([a-f\d]+)\}|\\u([a-f\d]{4})|\\x([a-f\d]{2})|\\([\s\S])/giu, (_all, wide: string, unicode: string, hex: string, escaped: string) => wide || unicode || hex ? String.fromCodePoint(Number.parseInt(wide || unicode || hex, 16)) : escaped) : raw; + const value = literal + ? raw + .slice(1, -1) + .replace( + /\\u\{([a-f\d]+)\}|\\u([a-f\d]{4})|\\x([a-f\d]{2})|\\([\s\S])/giu, + (_all, wide: string, unicode: string, hex: string, escaped: string) => + wide || unicode || hex + ? String.fromCodePoint(Number.parseInt(wide || unicode || hex, 16)) + : escaped, + ) + : raw; tokens.push({ value, literal }); } for (let index = 0; index < tokens.length; index++) { @@ -124,7 +251,10 @@ export function validateImports(root: string, file: string, source: string, poli const next = tokens[index + 1]; if (["import", "require"].includes(token.value) && next?.value === "(") { const argument = tokens[index + 2]; - assert(argument?.literal && !argument.value.includes("${"), `Computed import needs explicit admission: ${file}`); + assert( + argument?.literal && !argument.value.includes("${"), + `Computed import needs explicit admission: ${file}`, + ); check(argument.value); } else if (["import", "from"].includes(token.value) && next?.literal) check(next.value); } @@ -138,47 +268,145 @@ export function auditDependencies(root: string) { }; const policy = JSON.parse(read("eng/policy/dependency-policy.json")) as Policy; validatePolicy(policy); - const activeReview = JSON.parse(read(policy.reviewRecord)) as { review: Review; packages: Record; supersedes: string | null }; + const activeReview = JSON.parse(read(policy.reviewRecord)) as { + review: Review; + packages: Record; + supersedes: string | null; + }; assert.deepEqual(activeReview.review, policy.review, "Missing reviewed successor receipt"); - const git = (...args: string[]) => execFileSync("git", args, { cwd: root, encoding: "utf8", windowsHide: true, env: gitEnvironment() }).trim(); - const historical = [...new Set(git("log", "HEAD", "--diff-filter=A", "--name-only", "--format=", "--", "eng/policy/dependency-reviews/").split("\n").filter(Boolean))]; + const git = (...args: string[]) => + execFileSync("git", args, { + cwd: root, + encoding: "utf8", + windowsHide: true, + env: gitEnvironment(), + }).trim(); + const historical = [ + ...new Set( + git( + "log", + "HEAD", + "--diff-filter=A", + "--name-only", + "--format=", + "--", + "eng/policy/dependency-reviews/", + ) + .split("\n") + .filter(Boolean), + ), + ]; const coordinates = immutableCoordinates(policy.closure); - assert.deepEqual(activeReview.packages, coordinates, "Review does not bind immutable package coordinates"); + assert.deepEqual( + activeReview.packages, + coordinates, + "Review does not bind immutable package coordinates", + ); for (const file of historical) { - const introduced = git("log", "HEAD", "--diff-filter=A", "--format=%H", "--", file).split("\n").at(-1)!; + const introduced = git("log", "HEAD", "--diff-filter=A", "--format=%H", "--", file) + .split("\n") + .at(-1)!; const original = git("show", `${introduced}:${file}`); assert.equal(read(file).trim(), original, `Immutable review modified: ${file}`); const admitted = JSON.parse(original) as { packages: Record }; validateHistoricalCoordinates(admitted.packages, coordinates); } - if (activeReview.supersedes) assert(historical.includes(activeReview.supersedes), "Missing predecessor review"); - else assert(historical.length === 0 || historical.includes(policy.reviewRecord), "Upgrade requires predecessor review"); - const files = execFileSync("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], { cwd: root, encoding: "utf8", windowsHide: true, env: gitEnvironment() }).split("\0").filter(Boolean); + if (activeReview.supersedes) + assert(historical.includes(activeReview.supersedes), "Missing predecessor review"); + else + assert( + historical.length === 0 || historical.includes(policy.reviewRecord), + "Upgrade requires predecessor review", + ); + const files = execFileSync( + "git", + ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], + { cwd: root, encoding: "utf8", windowsHide: true, env: gitEnvironment() }, + ) + .split("\0") + .filter(Boolean); const manifests = files.filter((file) => path.basename(file) === "package.json"); assert.deepEqual(manifests.sort(), [...policy.manifests].sort(), "Unadmitted workspace manifest"); - const inputNames = new Set(["package.json", "package-lock.json", ".node-version", ".java-version", ".npmrc", "NuGet.Config", "global.json", "Directory.Packages.props", "Dockerfile", "wrangler.json", "wrangler.jsonc", "gradle.lockfile", "verification-metadata.xml", "libs.versions.toml", "settings.gradle.kts", "build.gradle.kts", "gradle-wrapper.properties", "vcpkg.json", "vcpkg-configuration.json"]); + const inputNames = new Set([ + "package.json", + "package-lock.json", + ".node-version", + ".java-version", + ".npmrc", + "NuGet.Config", + "global.json", + "Directory.Packages.props", + "Dockerfile", + "wrangler.json", + "wrangler.jsonc", + "gradle.lockfile", + "verification-metadata.xml", + "libs.versions.toml", + "settings.gradle.kts", + "build.gradle.kts", + "gradle-wrapper.properties", + "vcpkg.json", + "vcpkg-configuration.json", + ]); for (const file of files) { - if (inputNames.has(path.basename(file)) || /\.(?:csproj|esproj|props|targets)$/u.test(file) || file.endsWith("packages.lock.json")) - assert(Object.hasOwn(policy.inputs, file), `New dependency input requires admission: ${file}`); + if ( + inputNames.has(path.basename(file)) || + /\.(?:csproj|esproj|props|targets)$/u.test(file) || + file.endsWith("packages.lock.json") + ) + assert( + Object.hasOwn(policy.inputs, file), + `New dependency input requires admission: ${file}`, + ); if (/^(?:src|tests)\//u.test(file) && file.endsWith(".cs")) - assert(!/\b(?:using|global::)\s*ArcForges\.Contracts\.(?:Internal|Storage|AIInternal)\b/u.test(read(file)), `Unadmitted private generated C# import: ${file}`); + assert( + !/\b(?:using|global::)\s*ArcForges\.Contracts\.(?:Internal|Storage|AIInternal)\b/u.test( + read(file), + ), + `Unadmitted private generated C# import: ${file}`, + ); } - const lock = JSON.parse(read("package-lock.json")) as { packages: Record>; lockfileVersion: number }; + const lock = JSON.parse(read("package-lock.json")) as { + packages: Record>; + lockfileVersion: number; + }; assert.equal(lock.lockfileVersion, 3); for (const file of policy.manifests) { const manifest = JSON.parse(read(file)) as Record>; const entry = lock.packages[file === "package.json" ? "" : path.posix.dirname(file)]; assert(entry, `Missing workspace lock: ${file}`); for (const section of sections) { - assert.deepEqual(manifest[section] ?? {}, entry[section] ?? {}, `Manifest/lock drift: ${file}`); - for (const [name, version] of Object.entries(manifest[section] ?? {})) assert(exact.test(version), `Floating selector: ${name}`); + assert.deepEqual( + manifest[section] ?? {}, + entry[section] ?? {}, + `Manifest/lock drift: ${file}`, + ); + for (const [name, version] of Object.entries(manifest[section] ?? {})) + assert(exact.test(version), `Floating selector: ${name}`); } } validateClosure(policy, lock.packages); - for (const [file, expected] of Object.entries(policy.inputs)) assert.equal(digest(read(file)), expected, `Dependency input changed without review: ${file}`); + for (const [file, expected] of Object.entries(policy.inputs)) + assert.equal(digest(read(file)), expected, `Dependency input changed without review: ${file}`); const inventory = JSON.parse(read("eng/provenance/files.json")) as { artifacts: string[] }; - assert.deepEqual(inventory.artifacts, policy.artifactRecords, "Shipped dependency class changed without admission"); - for (const file of files.filter((file) => /^(?:src|worker|apps|packages)\//u.test(file) && /\.(?:ts|tsx|mjs|js|cts|mts)$/u.test(file))) validateImports(root, file, read(file), policy); - return { result: "passed", repository: policy.repository, dependencies: Object.keys(policy.closure).length, inputs: Object.keys(policy.inputs).length, evidence: "offline dependency admission; existing provenance and candidate gates retain redistribution authority" }; + assert.deepEqual( + inventory.artifacts, + policy.artifactRecords, + "Shipped dependency class changed without admission", + ); + for (const file of files.filter( + (file) => + /^(?:src|worker|apps|packages)\//u.test(file) && /\.(?:ts|tsx|mjs|js|cts|mts)$/u.test(file), + )) + validateImports(root, file, read(file), policy); + return { + result: "passed", + repository: policy.repository, + dependencies: Object.keys(policy.closure).length, + inputs: Object.keys(policy.inputs).length, + evidence: + "offline dependency admission; existing provenance and candidate gates retain redistribution authority", + }; } -if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) console.log(JSON.stringify(auditDependencies(process.cwd()), null, 2)); +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) + console.log(JSON.stringify(auditDependencies(process.cwd()), null, 2)); From 3f1a778cf9766cb795e9a2671f43a98e155f6108 Mon Sep 17 00:00:00 2001 From: sammiller Date: Mon, 21 Sep 2026 21:47:09 -0700 Subject: [PATCH 3/3] Replace unchecked policy assertions and correct import fixture literal --- tooling/dependency-policy.test.ts | 15 ++++++++------- tooling/dependency-policy.ts | 11 +++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/tooling/dependency-policy.test.ts b/tooling/dependency-policy.test.ts index ba24093..fd62480 100644 --- a/tooling/dependency-policy.test.ts +++ b/tooling/dependency-policy.test.ts @@ -17,23 +17,24 @@ import { const root = process.cwd(); const baseline = JSON.parse(readFileSync("eng/policy/dependency-policy.json", "utf8")) as Policy; const lock = JSON.parse(readFileSync("package-lock.json", "utf8")); +const firstDependency = Object.keys(baseline.closure)[0]; +assert(firstDependency, "Fixture requires an admitted dependency"); test("actual repository admission", () => { assert.equal(auditDependencies(root).result, "passed"); }); test("forbidden licence", () => { const packages = structuredClone(lock.packages); - packages[Object.keys(baseline.closure)[0]!].license = "GPL-3.0-only"; + packages[firstDependency].license = "GPL-3.0-only"; assert.throws(() => validateClosure(baseline, packages), /Forbidden licence/u); }); test("floating tag", () => { const packages = structuredClone(lock.packages); - packages[Object.keys(baseline.closure)[0]!].version = "latest"; + packages[firstDependency].version = "latest"; assert.throws(() => validateClosure(baseline, packages), /Floating version/u); }); test("same version with altered bytes", () => { const packages = structuredClone(lock.packages); - packages[Object.keys(baseline.closure)[0]!].integrity = - `sha512-${Buffer.alloc(64).toString("base64")}`; + packages[firstDependency].integrity = `sha512-${Buffer.alloc(64).toString("base64")}`; assert.throws(() => validateClosure(baseline, packages), /mutable-version/u); }); test("wrong publisher", () => { @@ -43,8 +44,7 @@ test("wrong publisher", () => { }); test("untrusted registry", () => { const packages = structuredClone(lock.packages); - packages[Object.keys(baseline.closure)[0]!].resolved = - "https://registry.npmjs.org.evil.invalid/p.tgz"; + packages[firstDependency].resolved = "https://registry.npmjs.org.evil.invalid/p.tgz"; assert.throws( () => validateClosure(baseline, packages), /Untrusted feed|Wrong publisher artifact/u, @@ -116,7 +116,8 @@ test("comments and escaped module names do not bypass public import scope", () = /internal/u, ); assert.throws( - () => validateImports(root, "src/example.ts", "void import(`@arcforges/${kind}`);", baseline), + () => + validateImports(root, "src/example.ts", `void import(\`@arcforges/\${kind}\`);`, baseline), /Computed import/u, ); }); diff --git a/tooling/dependency-policy.ts b/tooling/dependency-policy.ts index a05e865..9a42ec9 100644 --- a/tooling/dependency-policy.ts +++ b/tooling/dependency-policy.ts @@ -145,7 +145,8 @@ export function validateClosure(policy: Policy, packages: Record) `Forbidden licence: ${key}`, ); assert(entry.version && exact.test(entry.version), `Floating version: ${key}`); - const name = entry.name ?? key.split("node_modules/").at(-1)!; + const name = entry.name ?? key.split("node_modules/").at(-1); + assert(name, `Missing dependency identity: ${key}`); if (name.startsWith("@arcforges/")) assert(policy.firstParty[name], `Unadmitted publisher/internal package: ${name}`); if (entry.version.includes("-")) { @@ -231,7 +232,7 @@ export function validateImports(root: string, file: string, source: string, poli for (const match of source.matchAll(lexical)) { const raw = match[0]; if (raw.startsWith("//") || raw.startsWith("/*")) continue; - const literal = ['"', "'", "`"].includes(raw[0]!); + const literal = ['"', "'", "`"].includes(raw.charAt(0)); const value = literal ? raw .slice(1, -1) @@ -246,7 +247,8 @@ export function validateImports(root: string, file: string, source: string, poli tokens.push({ value, literal }); } for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]!; + const token = tokens[index]; + assert(token, "Missing import token"); if (token.literal) continue; const next = tokens[index + 1]; if (["import", "require"].includes(token.value) && next?.value === "(") { @@ -305,7 +307,8 @@ export function auditDependencies(root: string) { for (const file of historical) { const introduced = git("log", "HEAD", "--diff-filter=A", "--format=%H", "--", file) .split("\n") - .at(-1)!; + .at(-1); + assert(introduced, `Missing original review commit: ${file}`); const original = git("show", `${introduced}:${file}`); assert.equal(read(file).trim(), original, `Immutable review modified: ${file}`); const admitted = JSON.parse(original) as { packages: Record };