From bfcb494a92e1533a6b2502549840733ebf3c0dc2 Mon Sep 17 00:00:00 2001
From: slicedearth <47583576+slicedearth@users.noreply.github.com>
Date: Mon, 5 Oct 2026 19:28:56 +1100
Subject: [PATCH 1/9] Repair conservative planning and evidence boundaries
Evaluate browser minimums over reviewed released populations, correct script-policy declaration semantics, preserve complete comparison totals, and classify evidence-policy weakening independently from factual changes. Reject ambiguous exceptions and invalid imports while superseding stale asynchronous work and preserving useful session-only behaviour when storage is unavailable.
Bound authorised collection across repeated headers, cookie reduction, redirect and output budgets, absolute deadlines, and generated identifiers. Retain fixed-origin unauthenticated collection, exact verification identities, local-only evidence, bounded schemas, separate decision lanes, and the static no-account and no-telemetry architecture. Add deterministic transport, process, storage and browser regression coverage without weakening existing gates.
Integrate the preserved dependency maintenance batch with narrow compatible advisory updates and reviewed browser-data refreshes. Retain source history, attribution and licence notices, document contract compatibility and approval-gated hosting choices, and keep optional cross-engine checks local with disposable loopback fixtures.
Verified with npm run verify, npm run test (226 tests across 36 files), npm run test:e2e (28 passed), the serial three-engine smoke suite (3 passed), npm audit --audit-level=high (0 vulnerabilities), npm audit signatures (406 signatures and 138 attestations verified), generation and schema checks, and git diff --cached --check. An earlier combined smoke attempt timed out; the final isolated serial repeat passed without retries. No remote publication or deployment was performed.
---
.github/workflows/codeql.yml | 4 +-
.github/workflows/pages.yml | 2 +-
README.md | 4 +-
data/change-events.json | 617 +++++
data/selected-bcd.json | 244 +-
data/source-history.json | 26 +
docs/attested-evidence.md | 12 +
docs/authorised-collection.md | 17 +-
docs/data-contract.md | 31 +-
docs/deployment-security.md | 48 +
docs/engineering-case-study.md | 2 +-
docs/methodology.md | 24 +-
docs/policy-as-code.md | 23 +
e2e/audit-boundaries.spec.ts | 409 +++
e2e/site.spec.ts | 15 +-
examples/evidence-policy.json | 4 +-
package-lock.json | 2369 ++++++++---------
package.json | 32 +-
playwright.config.ts | 23 +-
.../browser-policy-evaluation.schema.json | 2 +-
public/schemas/decision-packet.schema.json | 18 +-
.../evidence-policy-evaluation.schema.json | 8 +-
.../reduced-evidence-report.schema.json | 8 +-
src/assurance.ts | 61 +-
src/catalogue.ts | 4 +-
src/ci-output.ts | 66 +-
src/collector.ts | 39 +-
src/components/EvidenceBundleInspector.astro | 121 +-
src/components/MinimumPlanner.astro | 5 +-
src/components/Planner.astro | 236 +-
src/contracts.ts | 46 +-
src/decision-packet.ts | 31 +-
src/decision-report.ts | 2 +-
src/evaluate.ts | 76 +-
src/evaluation-storage.ts | 8 +-
src/evidence-bundle.ts | 74 +-
src/evidence-model.ts | 2 +-
src/evidence-policy-comparison.ts | 86 +
src/local-state.ts | 56 +
src/minimums.ts | 50 +-
src/policy-comparison.ts | 8 +-
src/profile-storage.ts | 8 +-
tests/audit-regressions.test.ts | 506 ++++
tests/ci-output.test.ts | 29 +
tests/cli-process.test.ts | 176 ++
tests/collector-network.test.ts | 69 +
tests/collector.test.ts | 92 +
tests/evidence-attestation-sigstore.test.ts | 6 +-
tests/evidence-bundle.test.ts | 2 +-
tests/evidence-policy.test.ts | 2 +-
tests/minimums.test.ts | 36 +
tests/workflow-boundaries.test.ts | 16 +
tools/cli.ts | 6 +-
tools/collector-network.ts | 171 +-
tools/serve-dist.ts | 49 +-
55 files changed, 4410 insertions(+), 1671 deletions(-)
create mode 100644 e2e/audit-boundaries.spec.ts
create mode 100644 src/evidence-policy-comparison.ts
create mode 100644 src/local-state.ts
create mode 100644 tests/audit-regressions.test.ts
create mode 100644 tests/cli-process.test.ts
create mode 100644 tests/workflow-boundaries.test.ts
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 7bb3d3c..1334e7f 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -24,9 +24,9 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Initialise CodeQL
- uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
+ uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
languages: javascript-typescript
- name: Analyse source
- uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
+ uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 98591bf..3b7aff9 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -66,4 +66,4 @@ jobs:
steps:
- name: Deploy Pages artifact
id: deployment
- uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
+ uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
diff --git a/README.md b/README.md
index 3bd5b76..f41ead2 100644
--- a/README.md
+++ b/README.md
@@ -130,8 +130,8 @@ boundary.
The current selected dataset is generated from:
-- `@mdn/browser-compat-data` 8.0.8;
-- `web-features` 3.34.2; and
+- `@mdn/browser-compat-data` 8.1.4;
+- `web-features` 3.40.1; and
- exact Web Platform Tests suite paths pinned to revision
`af38980d2fcd74af19a226f5f651051cc15940ed`.
diff --git a/data/change-events.json b/data/change-events.json
index fc1f428..665af87 100644
--- a/data/change-events.json
+++ b/data/change-events.json
@@ -2538,5 +2538,622 @@
"sourceTimestamp": "2026-07-24T16:06:32.098Z",
"summary": "Firefox 156 was added to the selected BCD release metadata.",
"type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-10-13",
+ "status": "planned",
+ "version": "158"
+ },
+ "browser": "firefox_android",
+ "id": "037ccdbcfa90e75323c34ee2",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Firefox for Android 158 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "version_added": "70"
+ },
+ "before": {
+ "version_added": false
+ },
+ "browser": "webview_android",
+ "id": "161d55e466686250bfc5ee8a",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "path": "api.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable_static",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "api.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable_static changed for webview_android: {\"version_added\":false} to {\"version_added\":\"70\"}.",
+ "type": "support_version_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-09-22",
+ "status": "nightly",
+ "version": "154"
+ },
+ "browser": "chrome",
+ "id": "1c33691d2753a1895f20e194",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Chrome 154 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "status": "planned",
+ "version": "155"
+ },
+ "browser": "chrome",
+ "id": "29479f8610b07f8ac005c5a7",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Chrome 155 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-09-22",
+ "status": "nightly",
+ "version": "154"
+ },
+ "browser": "webview_android",
+ "id": "2c1e428eb26b72cf1924226e",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "WebView Android 154 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "status": "planned",
+ "version": "155"
+ },
+ "browser": "webview_android",
+ "id": "32853ba9f5c9c13ee1f810d6",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "WebView Android 155 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "version_added": "85"
+ },
+ "before": {
+ "version_added": "88"
+ },
+ "browser": "webview_android",
+ "id": "34a6fe099ee00b009434fb8b",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "path": "http.headers.Permissions-Policy",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "http.headers.Permissions-Policy changed for webview_android: {\"version_added\":\"88\"} to {\"version_added\":\"85\"}.",
+ "type": "support_version_corrected"
+ },
+ {
+ "after": {
+ "version_added": "85"
+ },
+ "before": {
+ "version_added": "88"
+ },
+ "browser": "chrome",
+ "id": "380bcc9d73d6deed5fe8546d",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "path": "http.headers.Permissions-Policy",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "http.headers.Permissions-Policy changed for chrome: {\"version_added\":\"88\"} to {\"version_added\":\"85\"}.",
+ "type": "support_version_corrected"
+ },
+ {
+ "after": {
+ "version_added": "85"
+ },
+ "before": {
+ "version_added": "88"
+ },
+ "browser": "chrome_android",
+ "id": "4bbf22407c2aec2056a2623a",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "path": "http.headers.Permissions-Policy",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "http.headers.Permissions-Policy changed for chrome_android: {\"version_added\":\"88\"} to {\"version_added\":\"85\"}.",
+ "type": "support_version_corrected"
+ },
+ {
+ "after": {
+ "status": "planned",
+ "version": "155"
+ },
+ "browser": "chrome_android",
+ "id": "513f19b97ab02332edc800b9",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Chrome Android 155 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-09-29",
+ "status": "nightly",
+ "version": "157"
+ },
+ "browser": "firefox_android",
+ "id": "5e3f14d2d0526657c479e372",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Firefox for Android 157 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-07-27",
+ "status": "current",
+ "version": "26.6"
+ },
+ "browser": "safari",
+ "id": "7733146a9762d58aa9385380",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Safari 26.6 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "notes": "Conditional mediation (autofill integration) is not supported; isConditionalMediationAvailable() always returns false.",
+ "partial_implementation": true,
+ "version_added": "131"
+ },
+ "before": {
+ "version_added": false
+ },
+ "browser": "webview_android",
+ "id": "7adb2f05248ebfd44b11c0a0",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "path": "api.PublicKeyCredential.isConditionalMediationAvailable_static",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "api.PublicKeyCredential.isConditionalMediationAvailable_static changed for webview_android: {\"version_added\":false} to {\"version_added\":\"131\",\"partial_implementation\":true,\"notes\":\"Conditional mediation (autofill integration) is not sup….",
+ "type": "partial_support_added"
+ },
+ {
+ "after": {
+ "version_added": "14.0"
+ },
+ "before": {
+ "version_added": "15.0"
+ },
+ "browser": "samsunginternet_android",
+ "id": "86c0464bb1e9261c3f6b1a4c",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "path": "http.headers.Permissions-Policy",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "http.headers.Permissions-Policy changed for samsunginternet_android: {\"version_added\":\"15.0\"} to {\"version_added\":\"14.0\"}.",
+ "type": "support_version_corrected"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-09-22",
+ "status": "nightly",
+ "version": "154"
+ },
+ "browser": "chrome_android",
+ "id": "877fca61a9626dfd88f2b969",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Chrome Android 154 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-07-27",
+ "status": "current",
+ "version": "26.6"
+ },
+ "browser": "safari_ios",
+ "id": "9ac921cc8bdd32cf90d48c84",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Safari on iOS 26.6 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-10-08",
+ "status": "planned",
+ "version": "155"
+ },
+ "browser": "edge",
+ "id": "b28d7c6a10e8b39513082cdc",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Edge 155 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-10-13",
+ "status": "planned",
+ "version": "158"
+ },
+ "browser": "firefox",
+ "id": "cb4899dcb14c351ac163d64d",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Firefox 158 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "version_added": "85"
+ },
+ "before": {
+ "version_added": "88"
+ },
+ "browser": "edge",
+ "id": "cc535ec1126dd819d740c43b",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "path": "http.headers.Permissions-Policy",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "http.headers.Permissions-Policy changed for edge: {\"version_added\":\"88\"} to {\"version_added\":\"85\"}.",
+ "type": "support_version_corrected"
+ },
+ {
+ "after": {
+ "version_added": "149"
+ },
+ "before": {
+ "impl_url": "https://bugzil.la/1958716",
+ "version_added": false
+ },
+ "browser": "firefox_android",
+ "id": "cf410e6f346230a9f241b525",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "path": "api.CredentialsContainer.create.publicKey_option.extensions.prf",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "api.CredentialsContainer.create.publicKey_option.extensions.prf changed for firefox_android: {\"version_added\":false,\"impl_url\":\"https://bugzil.la/1958716\"} to {\"version_added\":\"149\"}.",
+ "type": "support_version_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-09-29",
+ "status": "nightly",
+ "version": "157"
+ },
+ "browser": "firefox",
+ "id": "d6bf5e422846117151686980",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Firefox 157 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-09-24",
+ "status": "nightly",
+ "version": "154"
+ },
+ "browser": "edge",
+ "id": "e5592f8181c5392d545dce2a",
+ "observedInBcdVersion": "8.1.0",
+ "observedInWebFeaturesVersion": "3.37.0",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-09-03T15:52:15.027Z",
+ "summary": "Edge 154 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "status": "beta",
+ "version": "27.2"
+ },
+ "browser": "safari_ios",
+ "id": "2317e1d97beed2465d73b1c6",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Safari on iOS 27.2 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-10-20",
+ "status": "nightly",
+ "version": "156"
+ },
+ "browser": "chrome",
+ "id": "24841353064df9d363785d72",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Chrome 156 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-10-22",
+ "status": "nightly",
+ "version": "156"
+ },
+ "browser": "edge",
+ "id": "25982a665bb3c7756647b154",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Edge 156 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-11-10",
+ "status": "planned",
+ "version": "160"
+ },
+ "browser": "firefox_android",
+ "id": "259da8174f9fb1d31fb1bc1f",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Firefox for Android 160 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-05-11",
+ "status": "current",
+ "version": "30.0"
+ },
+ "browser": "samsunginternet_android",
+ "id": "284ee04f14965b191a18674c",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Samsung Browser 30.0 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-10-27",
+ "status": "nightly",
+ "version": "159"
+ },
+ "browser": "firefox_android",
+ "id": "56649cddeb047632af3409a6",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Firefox for Android 159 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-10-27",
+ "status": "nightly",
+ "version": "159"
+ },
+ "browser": "firefox",
+ "id": "72f4af1348e5d5d79dff181a",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Firefox 159 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "status": "planned",
+ "version": "157"
+ },
+ "browser": "chrome",
+ "id": "79122de93b6b6ebca0671bcc",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Chrome 157 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-10-20",
+ "status": "nightly",
+ "version": "156"
+ },
+ "browser": "chrome_android",
+ "id": "7cfca20381dcf2de017679b7",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Chrome Android 156 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-11-10",
+ "status": "planned",
+ "version": "160"
+ },
+ "browser": "firefox",
+ "id": "80c30d4cb1e47e1170f50616",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Firefox 160 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "status": "planned",
+ "version": "157"
+ },
+ "browser": "webview_android",
+ "id": "834eaed7d80c41b50ff7dc19",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "WebView Android 157 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "version_added": "30.0"
+ },
+ "before": {
+ "version_added": false
+ },
+ "browser": "samsunginternet_android",
+ "id": "856f584c27a60a56f7294a5f",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "path": "http.headers.Integrity-Policy",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "http.headers.Integrity-Policy changed for samsunginternet_android: {\"version_added\":false} to {\"version_added\":\"30.0\"}.",
+ "type": "support_version_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-10-20",
+ "status": "nightly",
+ "version": "156"
+ },
+ "browser": "webview_android",
+ "id": "bdbbc0de7057d2921a97d356",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "WebView Android 156 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "status": "beta",
+ "version": "27.2"
+ },
+ "browser": "safari",
+ "id": "c7c2bda6ded4d9c86ef276f7",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Safari 27.2 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "status": "planned",
+ "version": "157"
+ },
+ "browser": "chrome_android",
+ "id": "c7c4d441e9916a04c41ad310",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Chrome Android 157 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
+ },
+ {
+ "after": {
+ "version_added": "30.0"
+ },
+ "before": {
+ "version_added": false
+ },
+ "browser": "samsunginternet_android",
+ "id": "d5c5d41d5c6a5dd21e1f7c33",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "path": "http.headers.Set-Cookie.http_host-http_prefixes",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "http.headers.Set-Cookie.http_host-http_prefixes changed for samsunginternet_android: {\"version_added\":false} to {\"version_added\":\"30.0\"}.",
+ "type": "support_version_added"
+ },
+ {
+ "after": {
+ "version_added": "30.0"
+ },
+ "before": {
+ "version_added": false
+ },
+ "browser": "samsunginternet_android",
+ "id": "f4eed25a2003a719afa9775a",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "path": "http.headers.Integrity-Policy-Report-Only",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "http.headers.Integrity-Policy-Report-Only changed for samsunginternet_android: {\"version_added\":false} to {\"version_added\":\"30.0\"}.",
+ "type": "support_version_added"
+ },
+ {
+ "after": {
+ "releaseDate": "2026-11-05",
+ "status": "planned",
+ "version": "157"
+ },
+ "browser": "edge",
+ "id": "fc51c60d71e976f89f9f784f",
+ "observedInBcdVersion": "8.1.4",
+ "observedInWebFeaturesVersion": "3.40.1",
+ "schemaVersion": 1,
+ "sourceTimestamp": "2026-10-01T10:12:15.059Z",
+ "summary": "Edge 157 was added to the selected BCD release metadata.",
+ "type": "browser_release_added"
}
]
diff --git a/data/selected-bcd.json b/data/selected-bcd.json
index c138556..aca1676 100644
--- a/data/selected-bcd.json
+++ b/data/selected-bcd.json
@@ -1,6 +1,6 @@
{
- "bcdTimestamp": "2026-07-24T16:06:32.098Z",
- "bcdVersion": "8.0.8",
+ "bcdTimestamp": "2026-10-01T10:12:15.059Z",
+ "bcdVersion": "8.1.4",
"browsers": {
"chrome": {
"id": "chrome",
@@ -748,22 +748,42 @@
},
{
"releaseDate": "2026-06-30",
- "status": "current",
+ "status": "retired",
"version": "150"
},
{
"releaseDate": "2026-07-28",
- "status": "beta",
+ "status": "retired",
"version": "151"
},
{
"releaseDate": "2026-08-25",
- "status": "nightly",
+ "status": "retired",
"version": "152"
},
{
- "status": "planned",
+ "releaseDate": "2026-09-08",
+ "status": "retired",
"version": "153"
+ },
+ {
+ "releaseDate": "2026-09-22",
+ "status": "current",
+ "version": "154"
+ },
+ {
+ "releaseDate": "2026-10-06",
+ "status": "beta",
+ "version": "155"
+ },
+ {
+ "releaseDate": "2026-10-20",
+ "status": "nightly",
+ "version": "156"
+ },
+ {
+ "status": "planned",
+ "version": "157"
}
]
},
@@ -1398,22 +1418,42 @@
},
{
"releaseDate": "2026-06-30",
- "status": "current",
+ "status": "retired",
"version": "150"
},
{
"releaseDate": "2026-07-28",
- "status": "beta",
+ "status": "retired",
"version": "151"
},
{
"releaseDate": "2026-08-25",
- "status": "nightly",
+ "status": "retired",
"version": "152"
},
{
- "status": "planned",
+ "releaseDate": "2026-09-08",
+ "status": "retired",
"version": "153"
+ },
+ {
+ "releaseDate": "2026-09-22",
+ "status": "current",
+ "version": "154"
+ },
+ {
+ "releaseDate": "2026-10-06",
+ "status": "beta",
+ "version": "155"
+ },
+ {
+ "releaseDate": "2026-10-20",
+ "status": "nightly",
+ "version": "156"
+ },
+ {
+ "status": "planned",
+ "version": "157"
}
],
"upstream": "chrome"
@@ -1809,23 +1849,43 @@
},
{
"releaseDate": "2026-07-02",
- "status": "current",
+ "status": "retired",
"version": "150"
},
{
- "releaseDate": "2026-07-30",
- "status": "beta",
+ "releaseDate": "2026-07-31",
+ "status": "retired",
"version": "151"
},
{
- "releaseDate": "2026-08-27",
- "status": "nightly",
+ "releaseDate": "2026-08-28",
+ "status": "retired",
"version": "152"
},
{
- "releaseDate": "2026-09-10",
- "status": "planned",
+ "releaseDate": "2026-09-11",
+ "status": "retired",
"version": "153"
+ },
+ {
+ "releaseDate": "2026-09-24",
+ "status": "current",
+ "version": "154"
+ },
+ {
+ "releaseDate": "2026-10-08",
+ "status": "beta",
+ "version": "155"
+ },
+ {
+ "releaseDate": "2026-10-22",
+ "status": "nightly",
+ "version": "156"
+ },
+ {
+ "releaseDate": "2026-11-05",
+ "status": "planned",
+ "version": "157"
}
],
"upstream": "chrome"
@@ -2611,23 +2671,43 @@
},
{
"releaseDate": "2026-07-21",
- "status": "current",
+ "status": "esr",
"version": "153"
},
{
"releaseDate": "2026-08-18",
- "status": "beta",
+ "status": "retired",
"version": "154"
},
{
"releaseDate": "2026-09-01",
- "status": "nightly",
+ "status": "retired",
"version": "155"
},
{
"releaseDate": "2026-09-15",
- "status": "planned",
+ "status": "retired",
"version": "156"
+ },
+ {
+ "releaseDate": "2026-09-29",
+ "status": "current",
+ "version": "157"
+ },
+ {
+ "releaseDate": "2026-10-13",
+ "status": "beta",
+ "version": "158"
+ },
+ {
+ "releaseDate": "2026-10-27",
+ "status": "nightly",
+ "version": "159"
+ },
+ {
+ "releaseDate": "2026-11-10",
+ "status": "planned",
+ "version": "160"
}
]
},
@@ -3317,23 +3397,43 @@
},
{
"releaseDate": "2026-07-21",
- "status": "current",
+ "status": "esr",
"version": "153"
},
{
"releaseDate": "2026-08-18",
- "status": "beta",
+ "status": "retired",
"version": "154"
},
{
"releaseDate": "2026-09-01",
- "status": "nightly",
+ "status": "retired",
"version": "155"
},
{
"releaseDate": "2026-09-15",
- "status": "planned",
+ "status": "retired",
"version": "156"
+ },
+ {
+ "releaseDate": "2026-09-29",
+ "status": "current",
+ "version": "157"
+ },
+ {
+ "releaseDate": "2026-10-13",
+ "status": "beta",
+ "version": "158"
+ },
+ {
+ "releaseDate": "2026-10-27",
+ "status": "nightly",
+ "version": "159"
+ },
+ {
+ "releaseDate": "2026-11-10",
+ "status": "planned",
+ "version": "160"
}
],
"upstream": "firefox"
@@ -3634,12 +3734,22 @@
},
{
"releaseDate": "2026-05-11",
- "status": "current",
+ "status": "retired",
"version": "26.5"
},
{
- "status": "beta",
+ "releaseDate": "2026-07-27",
+ "status": "retired",
+ "version": "26.6"
+ },
+ {
+ "releaseDate": "2026-09-14",
+ "status": "current",
"version": "27"
+ },
+ {
+ "status": "beta",
+ "version": "27.2"
}
]
},
@@ -3924,19 +4034,29 @@
},
{
"releaseDate": "2026-05-11",
- "status": "current",
+ "status": "retired",
"version": "26.5"
},
{
- "status": "beta",
+ "releaseDate": "2026-07-27",
+ "status": "retired",
+ "version": "26.6"
+ },
+ {
+ "releaseDate": "2026-09-14",
+ "status": "current",
"version": "27"
+ },
+ {
+ "status": "beta",
+ "version": "27.2"
}
],
"upstream": "safari"
},
"samsunginternet_android": {
"id": "samsunginternet_android",
- "name": "Samsung Internet",
+ "name": "Samsung Browser",
"releases": [
{
"releaseDate": "2013-04-27",
@@ -4190,8 +4310,13 @@
},
{
"releaseDate": "2025-10-25",
- "status": "current",
+ "status": "retired",
"version": "29.0"
+ },
+ {
+ "releaseDate": "2026-05-11",
+ "status": "current",
+ "version": "30.0"
}
],
"upstream": "chrome_android"
@@ -4802,22 +4927,42 @@
},
{
"releaseDate": "2026-06-30",
- "status": "current",
+ "status": "retired",
"version": "150"
},
{
"releaseDate": "2026-07-28",
- "status": "beta",
+ "status": "retired",
"version": "151"
},
{
"releaseDate": "2026-08-25",
- "status": "nightly",
+ "status": "retired",
"version": "152"
},
{
- "status": "planned",
+ "releaseDate": "2026-09-08",
+ "status": "retired",
"version": "153"
+ },
+ {
+ "releaseDate": "2026-09-22",
+ "status": "current",
+ "version": "154"
+ },
+ {
+ "releaseDate": "2026-10-06",
+ "status": "beta",
+ "version": "155"
+ },
+ {
+ "releaseDate": "2026-10-20",
+ "status": "nightly",
+ "version": "156"
+ },
+ {
+ "status": "planned",
+ "version": "157"
}
],
"upstream": "chrome_android"
@@ -5062,8 +5207,7 @@
],
"firefox_android": [
{
- "impl_url": "https://bugzil.la/1958716",
- "version_added": false
+ "version_added": "149"
}
],
"safari": [
@@ -5222,7 +5366,9 @@
],
"webview_android": [
{
- "version_added": false
+ "notes": "Conditional mediation (autofill integration) is not supported; isConditionalMediationAvailable() always returns false.",
+ "partial_implementation": true,
+ "version_added": "131"
}
]
}
@@ -5300,7 +5446,7 @@
],
"webview_android": [
{
- "version_added": false
+ "version_added": "70"
}
]
}
@@ -6467,7 +6613,7 @@
],
"samsunginternet_android": [
{
- "version_added": false
+ "version_added": "30.0"
}
],
"webview_android": [
@@ -6538,7 +6684,7 @@
],
"samsunginternet_android": [
{
- "version_added": false
+ "version_added": "30.0"
}
],
"webview_android": [
@@ -6629,17 +6775,17 @@
"support": {
"chrome": [
{
- "version_added": "88"
+ "version_added": "85"
}
],
"chrome_android": [
{
- "version_added": "88"
+ "version_added": "85"
}
],
"edge": [
{
- "version_added": "88"
+ "version_added": "85"
}
],
"firefox": [
@@ -6666,12 +6812,12 @@
],
"samsunginternet_android": [
{
- "version_added": "15.0"
+ "version_added": "14.0"
}
],
"webview_android": [
{
- "version_added": "88"
+ "version_added": "85"
}
]
}
@@ -7153,7 +7299,7 @@
],
"samsunginternet_android": [
{
- "version_added": false
+ "version_added": "30.0"
}
],
"webview_android": [
@@ -7547,7 +7693,7 @@
}
}
},
- "schemaFingerprint": "ebad2f9787d9e115700d562ee122e62ba9116b04888263ebdaf922464b36b092",
+ "schemaFingerprint": "55e3832ebde9d4644e72e418bfda3bc9f2104f195a589da318a9fad1cde9a403",
"schemaVersion": 2,
- "webFeaturesVersion": "3.34.2"
+ "webFeaturesVersion": "3.40.1"
}
diff --git a/data/source-history.json b/data/source-history.json
index b9f004c..50d0619 100644
--- a/data/source-history.json
+++ b/data/source-history.json
@@ -51,6 +51,32 @@
"pathCount": 36,
"schemaFingerprint": "ebad2f9787d9e115700d562ee122e62ba9116b04888263ebdaf922464b36b092",
"webFeaturesVersion": "3.34.2"
+ },
+ {
+ "associatedEventCount": 22,
+ "baselineAssociationCount": 28,
+ "bcdTimestamp": "2026-09-03T15:52:15.027Z",
+ "bcdVersion": "8.1.0",
+ "browserCount": 9,
+ "catalogueVersion": "2.2.0",
+ "controlCount": 30,
+ "id": "884691434b0276dad168bd85",
+ "pathCount": 36,
+ "schemaFingerprint": "0faaff2d43d04fb6f962ed22348ce28b9aa8454ce01e70831e0f11cae29b06a9",
+ "webFeaturesVersion": "3.37.0"
+ },
+ {
+ "associatedEventCount": 18,
+ "baselineAssociationCount": 28,
+ "bcdTimestamp": "2026-10-01T10:12:15.059Z",
+ "bcdVersion": "8.1.4",
+ "browserCount": 9,
+ "catalogueVersion": "2.2.0",
+ "controlCount": 30,
+ "id": "2e6b9c3b8aa64649847c2001",
+ "pathCount": 36,
+ "schemaFingerprint": "55e3832ebde9d4644e72e418bfda3bc9f2104f195a589da318a9fad1cde9a403",
+ "webFeaturesVersion": "3.40.1"
}
],
"schemaVersion": 1
diff --git a/docs/attested-evidence.md b/docs/attested-evidence.md
index d720ff4..9e54278 100644
--- a/docs/attested-evidence.md
+++ b/docs/attested-evidence.md
@@ -123,6 +123,18 @@ messages do not enter the reduced policy result.
## Security meaning
+### Compose a verified result without changing its meaning
+
+`verify-evidence --json` produces an envelope with `attestation` and `evidence`.
+For `build-packet`, extract its exact `evidence` member unchanged into a private
+JSON file using a local JSON tool, then pass that file as the evidence input.
+The nested evaluation already carries the verification outcome bound to the
+report fingerprint; do not splice a verification result from another report or
+invent a `verified` value. Retain the original envelope, report and signature
+bundle privately for re-verification. Packet fingerprints prove content binding,
+not independent cryptographic authenticity of a manually edited input. No new
+wrapper or breaking artifact schema is introduced for this composition path.
+
A verified result establishes that:
- the Sigstore bundle passed the configured cryptographic and transparency
diff --git a/docs/authorised-collection.md b/docs/authorised-collection.md
index e3de9b8..a782f5d 100644
--- a/docs/authorised-collection.md
+++ b/docs/authorised-collection.md
@@ -13,7 +13,7 @@ Collection requires all of the following:
- an explicit manifest file;
- one fixed HTTPS origin;
-- one to 32 exact same-origin paths without query strings or fragments;
+- one to 16 exact same-origin paths without query strings or fragments;
- `--confirm-authorised-target`;
- an output path outside the repository or under ignored `private-data/` or
`.private-data/`;
@@ -31,7 +31,12 @@ The collector:
- records a cross-origin redirect relationship but does not follow it;
- performs bounded `GET` requests only;
- caps each response body at 128 KiB;
-- uses a ten-second request timeout;
+- caps retained HTML at 512 KiB in total;
+- reserves one response slot per remaining surface, limiting redirect expansion
+ to the 16-response bundle budget; an exhausted chain remains an explicit
+ redirect observation rather than a successful final response;
+- uses one absolute ten-second deadline per surface, including DNS, headers,
+ response streaming and all redirect hops; trickled bytes do not restart it;
- does not run JavaScript;
- does not submit forms;
- does not use cookies, credentials, browser profiles or authentication state;
@@ -40,6 +45,14 @@ The collector:
bundle;
- discards non-HTML response bodies.
+Repeated response-header values are limited to eight. Overflow produces an
+explicit transport error, never a successful observation of a sliced subset.
+Cookie reduction preserves the most-specific `__Host-Http-`, `__Http-`,
+`__Host-` or `__Secure-` prefix class while removing the actual name and value.
+Derived labels reserve suffix space within 80 characters; the complete opaque
+surface ID remains the association key. Injected transports that exceed the
+body or aggregate budgets fail instead of producing a complete bundle.
+
Loopback HTTP is available only for deliberate local fixture testing with
`--allow-loopback`. It does not permit other private addresses.
diff --git a/docs/data-contract.md b/docs/data-contract.md
index 913db7f..24cfb49 100644
--- a/docs/data-contract.md
+++ b/docs/data-contract.md
@@ -1,5 +1,32 @@
# Data contract
+## Conservative comparison and policy changes
+
+Decision-packet evidence comparison counts the complete event set before its
+512-event display limit. `totalEvents`, `emittedEvents` and `truncated` describe
+that distinction; omitted events still affect regression gates. Reduced-report
+comparisons preserve the underlying comparison totals when wrapped in packets.
+The browser-policy comparison likewise counts before slicing its display list.
+These additive optional summary fields retain the existing schema numbers;
+consumers with strict older schemas must update their schema files. No browser
+storage migration is needed. Evidence analysis is versioned at 5.1.0; comparisons
+across analysis versions are inconclusive, and policies must deliberately review
+their expected version rather than accepting it automatically.
+
+Evidence-policy drift uses `policy:` keys distinct from factual finding keys.
+Removing surfaces or requirements, relaxing a fail rule, introducing/extending
+exceptions, or replacing trust, identity, scope, freshness or expected-version
+constraints requires regression review. Replacements are deliberately conservative:
+even an intended strengthening of a trust boundary requires human review rather
+than being interpreted as a factual fix. Strengthening a result rule and removing
+an exception are resolutions. Adding requirements and role changes are changes.
+An unchanged browser lane cannot conceal weakening in the evidence lane.
+
+Exceptions must name a declared surface and a required evidence/control/composite
+target. Outcomes must be unique and scopes cannot overlap, regardless of expiry
+or ordering. Disjoint outcomes remain permitted. Exceptions cannot target the
+independent trust, identity, freshness or inventory guards and cannot create pass.
+
## Selected snapshot
`data/selected-bcd.json` is a versioned canonical projection, not a source
@@ -90,10 +117,10 @@ normaliser also has explicit behaviour for historic or fixture `true` and
| Reduced evidence export | 512 KiB |
| Reduced comparison events emitted | 512 |
| Collector manifest | 64 KiB |
-| Collector surfaces | 32 |
+| Collector surfaces | 16 |
| Collector response body | 128 KiB |
| Collector redirects | 5 |
-| Collector request timeout | 10 seconds |
+| Collector absolute surface deadline | 10 seconds |
| Evidence-policy exceptions | 128 |
| Evidence-policy findings | 4,096 |
| Browser-policy exceptions | 64 |
diff --git a/docs/deployment-security.md b/docs/deployment-security.md
index 40e26a8..6268316 100644
--- a/docs/deployment-security.md
+++ b/docs/deployment-security.md
@@ -43,6 +43,30 @@ does not alter the checked-out repository or trigger deployment.
## Browser boundary
+### Manual-dispatch parity review
+
+Manual Pages dispatch checks out its exact `github.sha` and runs `npm run verify`.
+It currently bypasses the separate dependency audit and locked browser job that
+automatic publication obtains from CI. This is not complete CI parity. Before
+using manual dispatch, require a successful CI run for that exact SHA or explicitly
+review the bypass. A proposed non-bypass path would make the manual build run
+`npm audit --audit-level=high`, install the locked Chromium build, and run
+`npm run test:e2e` before uploading. Workflow contract tests keep the exact-SHA
+binding and current boundary reviewable. Enabling those additional hosted steps
+or removing an intentional emergency override requires maintainer approval;
+this local repair does not dispatch or change deployment gates.
+
+### Organisation-specific origin review
+
+Use a separate dedicated origin, not a shared project-site path, for sensitive
+local assessment. A header-capable static host should serve the existing
+reviewed `_headers` policy, including response CSP and frame restrictions that
+cannot be supplied by a meta element. Review TLS, origin isolation, resource
+integrity, zero telemetry and cross-origin request behaviour using synthetic
+fixtures before approval. Keep actual evidence on the device and out of build
+artifacts. A host/origin/DNS/account change and any evidence publication need
+separate explicit approval; no such change is performed by local tests.
+
Every generated HTML page carries a restrictive meta Content Security Policy:
- scripts, styles, images, and fonts are limited to the static site's needs;
@@ -152,6 +176,30 @@ CONTROLCURRENT_DEPLOY_TARGET=github-pages npm run audit:public
git diff --check
```
+Optional local cross-engine smoke checks use the locked browser package without
+changing recurring hosted CI or uploading additional artefacts:
+
+```sh
+npx playwright install chromium firefox webkit
+CONTROLCURRENT_BROWSER_SMOKE=1 npx playwright test --grep @smoke
+```
+
+The smoke fixture uses HTTPS with a disposable, locally generated certificate
+because WebKit upgrades loopback subresources under the site's existing CSP.
+It requires local `openssl`; the certificate and key are deleted after reading
+them into the loopback server. Certificate-error checks are disabled in the
+smoke browser context and readiness probe, not pinned to a single certificate.
+This is a local test-only limitation, not production TLS verification; the built
+site's CSP is not weakened.
+
+The cross-engine smoke jobs run serially to avoid local browser resource
+contention. Shared schema validation disables dynamic compilation, including
+the schema library's caught capability probe, instead of allowing `unsafe-eval`.
+
+The smoke scenario checks keyboard use and enlarged text. The complete
+Chromium suite remains the default; a smoke pass is not equivalent to complete
+Firefox or WebKit coverage.
+
After deployment:
1. compare the deployed commit with the reviewed local commit;
diff --git a/docs/engineering-case-study.md b/docs/engineering-case-study.md
index df24f4f..9f2c51c 100644
--- a/docs/engineering-case-study.md
+++ b/docs/engineering-case-study.md
@@ -28,7 +28,7 @@ This creates a reviewable surface:
## Honest unsupported states
-The desired catalogue included CSP nonce and hash sources. BCD 8.0.8 has no
+The desired catalogue included CSP nonce and hash sources. BCD 8.1.4 has no
standalone compatibility statement for either source expression. Mapping both
to the broader `script-src` directive would overstate the evidence, so the
catalogue exposes them with `unsupported_mapping`.
diff --git a/docs/methodology.md b/docs/methodology.md
index 146aa7d..5a184e5 100644
--- a/docs/methodology.md
+++ b/docs/methodology.md
@@ -35,7 +35,7 @@ control definition. Multi-path controls use:
No current catalogue control uses `any`.
Related data is not substituted for a missing feature. CSP nonce and hash
-sources remain unsupported mappings in BCD 8.0.8 because the package does not
+sources remain unsupported mappings in BCD 8.1.4 because the package does not
publish standalone compatibility statements for those source expressions.
## Version comparison
@@ -199,11 +199,31 @@ require that control. A control required nowhere is `not_applicable`; a required
control with insufficient evidence remains missing, invalid, inconclusive,
report-only, or not evaluated.
-Project-authored strict CSP, cross-origin isolation, and cookie attribute
+Project-authored script CSP declaration, cross-origin isolation, and cookie attribute
composites are transparent candidate recipes rather than certification or
policy scores. They are evaluated only for surfaces that explicitly require
them.
+The script CSP declaration candidate (stable ID `strict-csp-candidate`) is not
+a claim about the whole policy being strong. Analysis version 5.1.0 requires
+one enforced policy, `base-uri 'none'` or `base-uri 'self'`, and valid script
+nonce/hash authorisation in both effective element and general script lists.
+A style-only nonce cannot satisfy it. It checks declarations without needing
+HTML; multiple policies remain review-only rather than being guessed equivalent.
+The CSP3 ignored-token rules allow backwards-compatible `unsafe-inline`, host
+and scheme tokens when nonce/hash and `strict-dynamic` make them ineffective.
+Effective broad script allowances and evaluation sources prevent satisfaction.
+Markup correlation and broader style warnings remain separate; unmatched inline
+content or nonce reuse still requires review. Runtime execution and nonce
+unpredictability are not established. See the [CSP3 processing rules](https://www.w3.org/TR/CSP3/#strict-dynamic-usage).
+
+Browser minimums describe the selected release and the later released versions
+recorded in the reviewed source snapshot, not an unlimited future promise.
+Every recorded point in that suffix must retain support. A removal followed by
+reintroduction does not make the earlier minimum valid; unknown or qualified
+points propagate conservatively. Point-release evaluation remains separate.
+This handles the Safari Partitioned-cookie gap without changing source facts.
+
An optional scope inventory can be supplied before the surface manifest. It
contains up to 256 opaque IDs from a declared list, framework manifest,
authorised crawl, or test suite. Included IDs must match assessed surface IDs
diff --git a/docs/policy-as-code.md b/docs/policy-as-code.md
index 3f0b019..61250de 100644
--- a/docs/policy-as-code.md
+++ b/docs/policy-as-code.md
@@ -85,6 +85,14 @@ Browser availability and supplied configuration evidence remain separate
decision lanes. A packet does not prove independent collection, complete
coverage, correct runtime enforcement, or production security.
+Comparison decisions use complete event totals, not the bounded list displayed
+in a report. Truncated lists expose emitted and total counts. JUnit output adds
+an explicit omitted-events case when needed so an adverse event beyond the
+display limit cannot disappear from the CI result. Evidence-policy requirement
+removals and weakened rules are policy regressions, separate from factual
+evidence changes. Changes to pinned trust, identity, scope or freshness contracts
+also require review rather than implying that evidence improved.
+
The command line can build, validate and compare packets. Comparison keeps the
browser-policy and evidence lanes separate, refuses invalid fingerprints, and
classifies incomparable evidence rather than manufacturing a resolution.
@@ -153,6 +161,21 @@ npm run cli -- compare-packets previous-packet.json decision-packet.json \
--format junit
```
+Compare reduced evidence reports with an optional incomparable-result gate:
+
+```sh
+npm run cli -- compare-reports previous-report.json report.json \
+ --fail-regression --fail-incomparable --format junit
+```
+
+`--fail-incomparable` returns exit code `1` when comparison cannot establish a
+like-for-like result. Without that flag, the existing exit-code behaviour is
+unchanged: incomparable results are reported but do not alone fail the command.
+Invalid input still returns `2`. Flags govern the process exit consistently
+across JSON, text, Markdown and JUnit output. Output documents still describe
+all regressions and incomparable results even when an optional exit gate is
+omitted; JUnit may therefore contain failure cases with a non-strict exit `0`.
+
## JSON Schemas
The static site publishes draft 2020-12 schemas for browser policy profiles and
diff --git a/e2e/audit-boundaries.spec.ts b/e2e/audit-boundaries.spec.ts
new file mode 100644
index 0000000..b72901d
--- /dev/null
+++ b/e2e/audit-boundaries.spec.ts
@@ -0,0 +1,409 @@
+import { expect, test, type Page } from "@playwright/test";
+import { readFileSync } from "node:fs";
+import { inspectEvidenceBundle } from "../src/evidence-bundle";
+import { evaluateProfile } from "../src/evaluate";
+import { selectedSnapshotSchema } from "../src/contracts";
+import { evidenceIdentity, evidenceSourceContext } from "../tests/helpers";
+
+const selectedSnapshot = selectedSnapshotSchema.parse(
+ JSON.parse(readFileSync(new URL("../data/selected-bcd.json", import.meta.url), "utf8")) as unknown
+);
+
+async function reportFixture() {
+ return inspectEvidenceBundle(
+ {
+ schemaVersion: 4,
+ name: "Synthetic deferred fixture",
+ identity: evidenceIdentity,
+ surfaces: [
+ {
+ id: "document",
+ role: "document",
+ requiredEvidence: ["response"],
+ requiredControls: ["content-security-policy"],
+ requiredComposites: []
+ }
+ ],
+ responses: [
+ {
+ schemaVersion: 1,
+ name: "Fixture",
+ surfaceId: "document",
+ headers: { "Content-Security-Policy": "default-src 'none'" }
+ }
+ ]
+ },
+ evidenceSourceContext
+ );
+}
+
+async function deferredInputs(page: Page) {
+ await page.addInitScript(() => {
+ const gates: { kind: "file" | "hash"; release: () => Promise; reject: () => void }[] = [];
+ let activeHandlers = 0;
+ const nativeAdd: unknown = Object.getOwnPropertyDescriptor(
+ EventTarget.prototype,
+ "addEventListener"
+ )?.value;
+ if (typeof nativeAdd !== "function") throw new Error("Missing native event registration");
+ const originalAdd = (
+ target: EventTarget,
+ type: string,
+ listener: EventListenerOrEventListenerObject | null,
+ options?: boolean | AddEventListenerOptions
+ ) => {
+ Reflect.apply(nativeAdd, target, [type, listener, options]);
+ };
+ EventTarget.prototype.addEventListener = function (type, listener, options) {
+ if (typeof listener !== "function") {
+ originalAdd(this, type, listener, options);
+ return;
+ }
+ const wrapped: EventListener = function (this: EventTarget, event) {
+ const result: unknown = listener.call(this, event);
+ if (result instanceof Promise) {
+ activeHandlers++;
+ void result.then(
+ () => {
+ activeHandlers--;
+ },
+ () => {
+ activeHandlers--;
+ }
+ );
+ }
+ };
+ originalAdd(this, type, wrapped, options);
+ };
+ const originalText = (file: File) => Blob.prototype.text.call(file);
+ const originalDigest = crypto.subtle.digest.bind(crypto.subtle);
+ let holdHash = false;
+ Object.defineProperty(window, "auditDeferred", {
+ value: {
+ pending: () => gates.map((gate) => gate.kind),
+ activeHandlers: () => activeHandlers,
+ holdHash: (value: boolean) => {
+ holdHash = value;
+ },
+ release: async (index: number, fail = false) => {
+ const gate = gates[index];
+ if (gate) {
+ if (fail) gate.reject();
+ else await gate.release();
+ }
+ }
+ }
+ });
+ File.prototype.text = function () {
+ return new Promise((resolve, reject) =>
+ gates.push({
+ kind: "file",
+ release: () => originalText(this).then(resolve, reject),
+ reject: () => reject(new Error("Stale synthetic file error"))
+ })
+ );
+ };
+ crypto.subtle.digest = function (algorithm, data) {
+ if (!holdHash) return originalDigest(algorithm, data);
+ return new Promise((resolve, reject) =>
+ gates.push({
+ kind: "hash",
+ release: () => originalDigest(algorithm, data).then(resolve, reject),
+ reject: () => reject(new Error("Stale synthetic hash error"))
+ })
+ );
+ };
+ });
+}
+async function gate(
+ page: Page,
+ action: "release" | "holdHash",
+ value: number | boolean,
+ fail = false
+) {
+ await page.evaluate(
+ async ({ action, value, fail }) => {
+ const api = (
+ window as unknown as {
+ auditDeferred: {
+ release(index: number, fail: boolean): Promise;
+ holdHash(value: boolean): void;
+ };
+ }
+ ).auditDeferred;
+ if (action === "release") await api.release(value as number, fail);
+ else api.holdHash(value as boolean);
+ },
+ { action, value, fail }
+ );
+}
+async function pending(page: Page) {
+ return page.evaluate(() =>
+ (window as unknown as { auditDeferred: { pending(): string[] } }).auditDeferred.pending()
+ );
+}
+
+async function settled(page: Page) {
+ // Observe completion of the enclosing async event handlers, not just their
+ // File.text or digest dependency. No arbitrary race delay is involved.
+ await expect
+ .poll(() =>
+ page.evaluate(() =>
+ (
+ window as unknown as { auditDeferred: { activeHandlers(): number } }
+ ).auditDeferred.activeHandlers()
+ )
+ )
+ .toBe(0);
+}
+
+test("profile edits invalidate every derived export, including an empty browser selection", async ({
+ page
+}) => {
+ await page.goto("/planner/");
+ await page.getByRole("button", { name: "Load example" }).click();
+ await page.getByRole("button", { name: "Check support" }).click();
+ await expect(page.locator("#export-profile")).toBeEnabled();
+ await page.getByLabel("Profile name").fill("Edited plan");
+ await expect(page.locator("#export-profile")).toBeDisabled();
+ await expect(page.locator("#profile-results")).toBeHidden();
+ await page.getByRole("button", { name: "Check support" }).click();
+ await expect(page.locator("#export-profile")).toBeEnabled();
+ for (const checkbox of await page.locator('input[name^="include-"]').all())
+ await checkbox.uncheck();
+ await expect(page.locator("#export-profile")).toBeDisabled();
+ await page.getByRole("button", { name: "Check support" }).click();
+ await expect(page.locator("#profile-results")).toBeHidden();
+});
+
+test("rejects an unavailable imported release without substituting the old select value", async ({
+ page
+}) => {
+ await page.goto("/planner/");
+ const prior = await page.locator('select[name="version-chrome"]').inputValue();
+ await page.locator("#import-profile").setInputFiles({
+ name: "invalid-version.json",
+ mimeType: "application/json",
+ buffer: Buffer.from(
+ JSON.stringify({
+ schemaVersion: 1,
+ name: "Unavailable plan",
+ baselines: [{ browser: "chrome", minimumVersion: "999" }]
+ })
+ )
+ });
+ await expect(page.locator("#profile-message")).toContainText("cannot evaluate");
+ await expect(page.locator('select[name="version-chrome"]')).toHaveValue(prior);
+ await expect(page.getByLabel("Profile name")).not.toHaveValue("Unavailable plan");
+});
+
+test("supports session-only evaluation with a throwing storage getter", async ({ page }) => {
+ await page.addInitScript(() =>
+ Object.defineProperty(window, "localStorage", {
+ get() {
+ throw new Error("Synthetic storage denial");
+ }
+ })
+ );
+ await page.goto("/planner/");
+ await expect(page.locator("#profile-message")).toContainText("unavailable");
+ await page.getByRole("button", { name: "Load example" }).click();
+ await page.getByRole("button", { name: "Check support" }).click();
+ await expect(page.locator("#export-profile")).toBeEnabled();
+ await page.getByRole("button", { name: "Save locally" }).click();
+ await expect(page.locator("#profile-message")).toContainText("not saved");
+});
+
+test("clear and replacement supersede deferred evidence-file successes and errors", async ({
+ page
+}) => {
+ await deferredInputs(page);
+ await page.goto("/assess/");
+ await page.locator(".advanced-assessment > summary").click();
+ await page.locator("#bundle-file").setInputFiles({
+ name: "first.json",
+ mimeType: "application/json",
+ buffer: Buffer.from("first")
+ });
+ await expect.poll(() => pending(page)).toEqual(["file"]);
+ await page.getByRole("button", { name: "Clear" }).last().click();
+ await gate(page, "release", 0);
+ await settled(page);
+ await expect(page.locator("#bundle-block")).toHaveValue("");
+ await page
+ .locator("#bundle-file")
+ .setInputFiles({ name: "old.json", mimeType: "application/json", buffer: Buffer.from("old") });
+ await page
+ .locator("#bundle-file")
+ .setInputFiles({ name: "new.json", mimeType: "application/json", buffer: Buffer.from("new") });
+ await expect.poll(() => pending(page)).toEqual(["file", "file", "file"]);
+ await gate(page, "release", 2);
+ await expect(page.locator("#bundle-block")).toHaveValue("new");
+ await gate(page, "release", 1, true);
+ await settled(page);
+ await expect(page.locator("#bundle-block")).toHaveValue("new");
+ await expect(page.locator("#bundle-message")).not.toContainText("Stale synthetic");
+});
+
+test("clear during deferred hashing cannot restore the report or its export", async ({ page }) => {
+ await deferredInputs(page);
+ await page.goto("/assess/");
+ await page.locator(".advanced-assessment > summary").click();
+ await page.getByRole("button", { name: "Load redacted example" }).last().click();
+ await gate(page, "holdHash", true);
+ await page.getByRole("button", { name: "Review evidence file" }).click();
+ await expect.poll(() => pending(page).then((items) => items.length)).toBeGreaterThan(0);
+ await page.getByRole("button", { name: "Clear" }).last().click();
+ await gate(page, "holdHash", false);
+ for (let i = 0; i < (await pending(page)).length; i++) await gate(page, "release", i);
+ await settled(page);
+ await expect(page.locator("#bundle-results")).toBeHidden();
+ await expect(page.locator("#export-bundle")).toBeDisabled();
+ await expect(page.locator("#bundle-form")).toHaveAttribute("aria-busy", "false");
+});
+
+test("a profile edit cancels a deferred import before any form mutation", async ({ page }) => {
+ await deferredInputs(page);
+ await page.goto("/planner/");
+ await page.locator("#import-profile").setInputFiles({
+ name: "old.json",
+ mimeType: "application/json",
+ buffer: Buffer.from(
+ JSON.stringify({
+ schemaVersion: 1,
+ name: "Stale import",
+ baselines: [{ browser: "chrome", minimumVersion: "120" }]
+ })
+ )
+ });
+ await expect.poll(() => pending(page)).toEqual(["file"]);
+ await page.getByLabel("Profile name").fill("Current plan");
+ await gate(page, "release", 0);
+ await settled(page);
+ await expect(page.getByLabel("Profile name")).toHaveValue("Current plan");
+ await expect(page.locator("#export-profile")).toBeDisabled();
+});
+
+test("preserves import-before-evaluation comparison input but clears it on a genuine edit", async ({
+ page
+}) => {
+ await page.goto("/planner/");
+ await page.getByRole("button", { name: "Load example" }).click();
+ const earlier = evaluateProfile(selectedSnapshot, {
+ schemaVersion: 1,
+ name: "Example browser baseline",
+ baselines: [
+ { browser: "chrome", minimumVersion: "120" },
+ { browser: "firefox", minimumVersion: "115" },
+ { browser: "safari", minimumVersion: "17" }
+ ]
+ });
+ await page.locator("#compare-profile").setInputFiles({
+ name: "earlier.json",
+ mimeType: "application/json",
+ buffer: Buffer.from(JSON.stringify(earlier))
+ });
+ await expect(page.locator("#profile-message")).toContainText("Earlier evaluation loaded");
+ await page.getByRole("button", { name: "Check support" }).click();
+ await expect(
+ page.getByRole("heading", { name: "What changed since the earlier result" })
+ ).toBeVisible();
+ await page.getByLabel("Profile name").fill("New plan");
+ await page.getByRole("button", { name: "Check support" }).click();
+ await expect(
+ page.getByRole("heading", { name: "What changed since the earlier result" })
+ ).toBeHidden();
+});
+
+test("clear during deferred comparison hashing cannot restore comparison exports", async ({
+ page
+}) => {
+ await deferredInputs(page);
+ await page.goto("/assess/");
+ await page.locator(".advanced-assessment > summary").click();
+ await page.getByRole("button", { name: "Load redacted example" }).last().click();
+ await page.getByRole("button", { name: "Review evidence file" }).click();
+ await expect(page.locator("#bundle-results")).toBeVisible();
+ await page.getByText("Compare with an earlier report", { exact: true }).click();
+ await page.locator("#previous-report").fill(JSON.stringify(await reportFixture()));
+ await gate(page, "holdHash", true);
+ await page.locator("#compare-report").click();
+ await expect.poll(() => pending(page).then((items) => items.length)).toBeGreaterThan(0);
+ await page.getByRole("button", { name: "Clear" }).last().click();
+ await gate(page, "holdHash", false);
+ for (let i = 0; i < (await pending(page)).length; i++) await gate(page, "release", i);
+ await settled(page);
+ await expect(page.locator("#export-comparison")).toBeDisabled();
+ await expect(page.locator("#bundle-results")).toBeHidden();
+});
+
+test("profile edits supersede deferred attachment validation and packet export", async ({
+ page
+}) => {
+ await deferredInputs(page);
+ await page.goto("/planner/");
+ await page.getByRole("button", { name: "Load example" }).click();
+ await page.getByRole("button", { name: "Check support" }).click();
+ await page
+ .getByText("Turn this result into a reviewable browser policy", { exact: true })
+ .click();
+ await page.getByRole("button", { name: "Check policy" }).click();
+ const report = await reportFixture();
+ await page.getByLabel("Evidence result JSON").setInputFiles({
+ name: "evidence.json",
+ mimeType: "application/json",
+ buffer: Buffer.from(JSON.stringify(report))
+ });
+ await expect.poll(() => pending(page)).toEqual(["file"]);
+ await page.getByLabel("Profile name").fill("Replacement");
+ await gate(page, "release", 0);
+ await settled(page);
+ await expect(page.locator("#export-decision-packet")).toBeDisabled();
+ await page.getByRole("button", { name: "Check support" }).click();
+ await page.getByRole("button", { name: "Check policy" }).click();
+ await page.getByLabel("Evidence result JSON").setInputFiles({
+ name: "evidence2.json",
+ mimeType: "application/json",
+ buffer: Buffer.from(JSON.stringify(report))
+ });
+ await gate(page, "release", 1);
+ await expect(page.locator("#export-decision-packet")).toBeEnabled();
+ const downloads: string[] = [];
+ page.on("download", (download) => downloads.push(download.suggestedFilename()));
+ await gate(page, "holdHash", true);
+ await page.locator("#export-decision-packet").click();
+ await expect.poll(() => pending(page).then((items) => items.length)).toBeGreaterThan(2);
+ await page.getByLabel("Profile name").fill("Cancelled export");
+ await gate(page, "holdHash", false);
+ for (let i = 2; i < (await pending(page)).length; i++) await gate(page, "release", i);
+ await settled(page);
+ await expect(page.locator("#export-decision-packet")).toBeDisabled();
+ expect(downloads).toEqual([]);
+});
+
+test("planner remains keyboard-operable at enlarged text @smoke", async ({ page }) => {
+ const errors: string[] = [];
+ page.on("pageerror", (error) => errors.push(error.message));
+ page.on("console", (message) => {
+ if (/JavaScript eval|unsafe-eval/u.test(message.text())) errors.push(message.text());
+ });
+ await page.goto("/planner/");
+ await page.evaluate(() => {
+ document.documentElement.style.fontSize = "200%";
+ });
+ await page.getByRole("button", { name: "Load example" }).focus();
+ await expect(page.getByRole("button", { name: "Load example" })).toBeFocused();
+ // Exercise native non-submit and submit keyboard actions, without click helpers.
+ await page.keyboard.press("Space");
+ await expect(page.locator('input[name="include-chrome"]')).toBeChecked();
+ await page.getByRole("button", { name: "Check support" }).focus();
+ await page.keyboard.press("Enter");
+ await expect(page.locator("#profile-results")).toBeVisible();
+ await page.setViewportSize({ width: 640, height: 900 });
+ expect(
+ await page.evaluate(
+ () => document.documentElement.scrollWidth <= document.documentElement.clientWidth
+ )
+ ).toBe(true);
+ expect(errors).toEqual([]);
+});
diff --git a/e2e/site.spec.ts b/e2e/site.spec.ts
index e52f760..2e743d4 100644
--- a/e2e/site.spec.ts
+++ b/e2e/site.spec.ts
@@ -19,8 +19,8 @@ test("renders real source provenance and makes no external request", async ({ pa
).toBeVisible();
await expect(
page.getByText("MDN browser data", { exact: true }).first().locator("..")
- ).toContainText("8.0.8");
- await expect(page.getByText("Web feature data").locator("..")).toContainText("3.34.2");
+ ).toContainText("8.1.4");
+ await expect(page.getByText("Web feature data").locator("..")).toContainText("3.40.1");
await expect(page.getByText("Server connection").locator("..")).toContainText("none");
expect(externalRequests).toEqual([]);
@@ -476,7 +476,7 @@ test("reduces a multi-surface evidence bundle without exposing raw inputs", asyn
page.getByRole("heading", { name: "Privacy-reduced evidence report" })
).toBeVisible();
await expect(
- results.getByRole("heading", { name: "Strong Content Security Policy" })
+ results.getByRole("heading", { name: "Script CSP declaration candidate" })
).toBeVisible();
await expect(
results.getByRole("heading", { name: "Cross-origin isolation headers" })
@@ -488,7 +488,7 @@ test("reduces a multi-surface evidence bundle without exposing raw inputs", asyn
results.getByRole("heading", { name: "Requirements for page · sign-in" })
).toBeVisible();
await expect(
- results.getByText("19 of 19 required features found · 3 of 3 combined checks met")
+ results.getByText("18 of 19 required features found · 3 of 3 combined checks met")
).toBeVisible();
await expect(
results.getByText("No declared surface requires this control.").first()
@@ -500,7 +500,7 @@ test("reduces a multi-surface evidence bundle without exposing raw inputs", asyn
"captured 2026-07-20T09:05:00.000Z by example-ci (application_ci)"
);
await expect(results.locator("#bundle-source")).toContainText(
- "analyser 5.0.0 · catalogue 2.2.0 · BCD 8.0.8"
+ "analyser 5.1.0 · catalogue 2.2.0 · BCD 8.1.4"
);
await expect(
results.getByText("Supplied page list · Reviewed application route manifest")
@@ -685,13 +685,14 @@ test("publishes a restrictive meta policy and refuses embedded interaction", asy
expect(policy).toContain("worker-src 'none'");
expect(policy).not.toContain("frame-ancestors");
- await page.route("http://127.0.0.1:4389/__frame-test.html", async (route) => {
+ const fixtureUrl = new URL("/__frame-test.html", page.url()).href;
+ await page.route(fixtureUrl, async (route) => {
await route.fulfill({
body: '',
contentType: "text/html"
});
});
- await page.goto("http://127.0.0.1:4389/__frame-test.html");
+ await page.goto(fixtureUrl);
const embedded = page.frameLocator('iframe[title="Embedded ControlCurrent"]');
await expect(embedded.getByRole("alert")).toContainText("Open ControlCurrent directly");
await expect(embedded.getByLabel("HTTP response headers")).toBeHidden();
diff --git a/examples/evidence-policy.json b/examples/evidence-policy.json
index 69fc3f6..5089ca6 100644
--- a/examples/evidence-policy.json
+++ b/examples/evidence-policy.json
@@ -1,9 +1,9 @@
{
"schemaVersion": 4,
"name": "Release evidence baseline",
- "expectedAnalyserVersion": "5.0.0",
+ "expectedAnalyserVersion": "5.1.0",
"expectedCatalogueVersion": "2.2.0",
- "expectedBcdVersion": "8.0.8",
+ "expectedBcdVersion": "8.1.4",
"attestation": {
"required": false,
"certificateIssuer": "https://token.actions.githubusercontent.com/",
diff --git a/package-lock.json b/package-lock.json
index a1c40d1..373a734 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,31 +9,31 @@
"version": "0.1.0",
"license": "MIT",
"dependencies": {
- "@mdn/browser-compat-data": "8.0.8",
+ "@mdn/browser-compat-data": "8.1.4",
"@sigstore/bundle": "5.0.0",
- "@sigstore/protobuf-specs": "0.5.1",
+ "@sigstore/protobuf-specs": "0.5.2",
"@sigstore/tuf": "5.0.0",
- "@sigstore/verify": "4.1.0",
+ "@sigstore/verify": "4.1.2",
"parse5": "8.0.1",
- "web-features": "3.34.2",
- "zod": "4.4.3"
+ "web-features": "3.40.1",
+ "zod": "4.5.4"
},
"devDependencies": {
- "@astrojs/check": "0.9.9",
- "@astrojs/sitemap": "3.7.3",
- "@axe-core/playwright": "4.12.1",
+ "@astrojs/check": "0.9.10",
+ "@astrojs/sitemap": "3.7.4",
+ "@axe-core/playwright": "4.13.0",
"@eslint/js": "10.0.1",
- "@playwright/test": "1.62.0",
+ "@playwright/test": "1.63.0",
"@types/node": "24.13.3",
- "@vitest/coverage-v8": "4.1.10",
- "astro": "7.1.3",
- "eslint": "10.8.0",
+ "@vitest/coverage-v8": "5.0.0",
+ "astro": "7.3.1",
+ "eslint": "10.10.0",
"prettier": "3.9.6",
"prettier-plugin-astro": "0.14.1",
- "tsx": "4.23.1",
+ "tsx": "4.23.13",
"typescript": "6.0.3",
- "typescript-eslint": "8.65.0",
- "vitest": "4.1.10"
+ "typescript-eslint": "8.69.0",
+ "vitest": "5.0.0"
},
"engines": {
"node": "^24.15.0 || >=26.0.0",
@@ -41,16 +41,16 @@
}
},
"node_modules/@astrojs/check": {
- "version": "0.9.9",
- "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.9.tgz",
- "integrity": "sha512-A5UW8uIuErLWEoRQvzgXpO1gTjUFtK8r7nU2Z7GewAMxUb7bPvpk11qaKKgxqXlHJWlAvaaxy+Xg28A6bmQ1Tg==",
+ "version": "0.9.10",
+ "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.10.tgz",
+ "integrity": "sha512-zgx/UQMozdjOa3bOxjgeCFdtpE3c9rRX6xHwa+2QXvy8z8Akifu2AtubHyv/zzC2znO8dl8fFWL4K+Ba9kS8HQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@astrojs/language-server": "^2.16.7",
"chokidar": "^4.0.3",
"kleur": "^4.1.5",
- "yargs": "^17.7.2"
+ "yargs": "^18.0.0"
},
"bin": {
"astro-check": "bin/astro-check.js"
@@ -67,30 +67,30 @@
"license": "MIT"
},
"node_modules/@astrojs/compiler-binding": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding/-/compiler-binding-0.3.1.tgz",
- "integrity": "sha512-DaAUj29AIBU2XdJ8uwcab8lW5O2pk9pY8AXkcMw0sw77nVa3oeTYRcO+Dvbbpoexf6ThMc0FMWYCQ/wN1/T7oQ==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding/-/compiler-binding-0.4.0.tgz",
+ "integrity": "sha512-x2RjDUuWfwLNtc3mjAdSRInwqh/rqbLar9cm/5FOMbHvmYZB7yfKewzSclAxWjIZsypJDXv1lhaP2WG+P8TK3g==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
- "@astrojs/compiler-binding-darwin-arm64": "0.3.1",
- "@astrojs/compiler-binding-darwin-x64": "0.3.1",
- "@astrojs/compiler-binding-linux-arm64-gnu": "0.3.1",
- "@astrojs/compiler-binding-linux-arm64-musl": "0.3.1",
- "@astrojs/compiler-binding-linux-x64-gnu": "0.3.1",
- "@astrojs/compiler-binding-linux-x64-musl": "0.3.1",
- "@astrojs/compiler-binding-wasm32-wasi": "0.3.1",
- "@astrojs/compiler-binding-win32-arm64-msvc": "0.3.1",
- "@astrojs/compiler-binding-win32-x64-msvc": "0.3.1"
+ "@astrojs/compiler-binding-darwin-arm64": "0.4.0",
+ "@astrojs/compiler-binding-darwin-x64": "0.4.0",
+ "@astrojs/compiler-binding-linux-arm64-gnu": "0.4.0",
+ "@astrojs/compiler-binding-linux-arm64-musl": "0.4.0",
+ "@astrojs/compiler-binding-linux-x64-gnu": "0.4.0",
+ "@astrojs/compiler-binding-linux-x64-musl": "0.4.0",
+ "@astrojs/compiler-binding-wasm32-wasi": "0.4.0",
+ "@astrojs/compiler-binding-win32-arm64-msvc": "0.4.0",
+ "@astrojs/compiler-binding-win32-x64-msvc": "0.4.0"
}
},
"node_modules/@astrojs/compiler-binding-darwin-arm64": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.3.1.tgz",
- "integrity": "sha512-IEmEF2fUIlTHtpeE/isyEGVOB14cEyh/LZOFYt6wn3jNyVpdC8aR5OZ+RzFUR/f+8ZDM1LaMwZKvoA7eMyJeFw==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.4.0.tgz",
+ "integrity": "sha512-ZVUwHundaQyFNjE6uoa0usaC0WOCitDCLS/4mdb4rOiJXwVUuKJBMxI5WMzXLWmamsXtK/Z//ifLXvV5Yeh4Hw==",
"cpu": [
"arm64"
],
@@ -105,9 +105,9 @@
}
},
"node_modules/@astrojs/compiler-binding-darwin-x64": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.3.1.tgz",
- "integrity": "sha512-GF2kIxjpPDLsn94zbZNMsxEmkU828QqnmM7kiQJnaooS3jmI+I7kk6+oI6EpwOsK3femCMdcm+wmOsEqtGrmjQ==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.4.0.tgz",
+ "integrity": "sha512-FI6G8AY8u6fR1SI/QRR5yGMwtvZwP34CDmZpZ5HwJGa50UM1VISTLhqkhV4a476pmgd25X1Aur2dqw6hUnrlKA==",
"cpu": [
"x64"
],
@@ -122,9 +122,9 @@
}
},
"node_modules/@astrojs/compiler-binding-linux-arm64-gnu": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.3.1.tgz",
- "integrity": "sha512-XJL3SDmOtVrqFhCirNcHwE91+IesJqlgNo23I4qW9QUYfwzm/TBZuH61fgqsb1ttgR1mMYz6ooPWs0JDhwMqpQ==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.4.0.tgz",
+ "integrity": "sha512-lB9gLFJK7m82EnjaU8nlRBEfcwGNeHidW3sSjODTUjMNaoewVuUz9fwwdY5M4jiSXIqWLH3yl6TX8FTDKA74Sw==",
"cpu": [
"arm64"
],
@@ -142,9 +142,9 @@
}
},
"node_modules/@astrojs/compiler-binding-linux-arm64-musl": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.3.1.tgz",
- "integrity": "sha512-xqE8BVbDoBueK/B47w30PtkVofUWJKGkwoMVE+EOMLf11rnoANxIAdA9FPqY+rng4oNI5ndHGsri1yPj2k8vZQ==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.4.0.tgz",
+ "integrity": "sha512-HPbvWqbxFxyaoQJhLxCaSjtYBx9KBo7JGVzEFZCmMl968a2PsSH0UfiODYgYPXofTOIsIH2aoCcrHXML0IA3ig==",
"cpu": [
"arm64"
],
@@ -162,9 +162,9 @@
}
},
"node_modules/@astrojs/compiler-binding-linux-x64-gnu": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.3.1.tgz",
- "integrity": "sha512-1y0StU1qiCuDFH3rmbRJXcxdfHxFPrES1Rd+RLffosvUR7I2cH5SF5SFnBN9vXpzpkmyElZm3Yr47iJBPN7vVA==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.4.0.tgz",
+ "integrity": "sha512-tQKolMxoJ/+0AmLWm1PmJ/i+z3i10ZU1bNuVjEDulCf48azEMtUNjTZgHJ5MPtpYRNc7dlETr8QujUfduzoC7Q==",
"cpu": [
"x64"
],
@@ -182,9 +182,9 @@
}
},
"node_modules/@astrojs/compiler-binding-linux-x64-musl": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.3.1.tgz",
- "integrity": "sha512-16q0fYf7kpbmdObZEeZJEup8hQv/whgNwVjrSvT8umrKwLDSnNIWiQpm09lQQu6bweZB0XyIvHwlPitvJhC+hg==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.4.0.tgz",
+ "integrity": "sha512-5v5YymudsxMHp3NBLCS8BUlu5CRqeLtWD9cKS/4nIhIEHCbpz9okmVV6I0HWqmBAPhWYcDa3vw/vltYPrOQCTA==",
"cpu": [
"x64"
],
@@ -202,9 +202,9 @@
}
},
"node_modules/@astrojs/compiler-binding-wasm32-wasi": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.3.1.tgz",
- "integrity": "sha512-cB456shIwDv/PrVT+2QG7LFndpHkVge5HjqADKZgGaAc9JHVktCtjSrcdkRQ+3tbkPazNKaTLRjXLIiz2NIx9g==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.4.0.tgz",
+ "integrity": "sha512-m/phuH3x3PREvv1OnkM44NoPh4MatUadix1fB1u5SvMLCyDTUZykDJbKnWf1cjnYmHdlB8HcjTjl6JrCqAIXcw==",
"cpu": [
"wasm32"
],
@@ -212,16 +212,16 @@
"license": "MIT",
"optional": true,
"dependencies": {
- "@napi-rs/wasm-runtime": "^1.1.6"
+ "@napi-rs/wasm-runtime": "^1.2.2"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@astrojs/compiler-binding-win32-arm64-msvc": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.3.1.tgz",
- "integrity": "sha512-ur/9+If/yTE69mmeX5MqSZndL0HOyx67GeNZUy3N7wVdWpLz9UTJXwyWS4UR2PUQHitghjsM5xoX0Ge56WRVQQ==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.4.0.tgz",
+ "integrity": "sha512-B9zYf3okEY83kM8gydlpH2BHP00w4ifxPqlYlWrgTwuD6wnkrJDCwBlgy1q31cERjCJRXN1lrE2VmkLvFjv/6g==",
"cpu": [
"arm64"
],
@@ -236,9 +236,9 @@
}
},
"node_modules/@astrojs/compiler-binding-win32-x64-msvc": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.3.1.tgz",
- "integrity": "sha512-k0W+kDBzDkNZOqu4kElDvCOIbKw5Ut9S1WZ1Krj3KTgNuBERNKXsMMsRLLcbgfdMdbe7bTekQLshZrrvmYpmwA==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.4.0.tgz",
+ "integrity": "sha512-zB0Nrv0dGc0zZWPGDRmmETTPhDRqyZjAjk+gWMlVrJX5U89obpB3VUUE1ZiHxOCN5LQojeLK6O8L/dnoHolvNQ==",
"cpu": [
"x64"
],
@@ -253,28 +253,28 @@
}
},
"node_modules/@astrojs/compiler-rs": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@astrojs/compiler-rs/-/compiler-rs-0.3.1.tgz",
- "integrity": "sha512-aT7xkgsbNoS6nriY5qKpbihK43slFHO41iqgHCTdOvn1ifaQxLCc5yXy+6GzAtiafoaC1zA7OwVXCXMsvUZOkg==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-rs/-/compiler-rs-0.4.0.tgz",
+ "integrity": "sha512-koVikeon1kreEy+/JzLQRy3vzHHQVOjycs4degg4vFufKApZOwMZvSSAEztYNhmcQVfNVsVZZI4cEge3cexAbQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@astrojs/compiler-binding": "0.3.1"
+ "@astrojs/compiler-binding": "0.4.0"
},
"engines": {
"node": ">=22.12.0"
}
},
"node_modules/@astrojs/internal-helpers": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.1.tgz",
- "integrity": "sha512-5phcroT/vmOOrYuuAxtkbPixy5hePtlz9i8K4OeDv3dNK6/UQRuXPOSRTxIOBbUY5Sonw2UaxjbuVc43Mcir6Q==",
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.11.0.tgz",
+ "integrity": "sha512-3rzxJ+xbo0+8YyqOzLziIN32wmsHdCjEVz2sGOpRxJ+Ben/KiLph4ItxBy1abEL+E8fkRzqjg0rfXmaHJGw9JA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/hast": "^3.0.4",
"@types/mdast": "^4.0.4",
- "js-yaml": "^4.1.1",
+ "js-yaml": "^4.3.0",
"picomatch": "^4.0.4",
"retext-smartypants": "^6.2.0",
"shiki": "^4.0.2",
@@ -283,9 +283,9 @@
}
},
"node_modules/@astrojs/language-server": {
- "version": "2.16.13",
- "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.16.13.tgz",
- "integrity": "sha512-ekOa+CYprEq5n4EJC1qTIAhLk49HZIUQuFwrEuF+3JK/pdMaYnWoREFUI2A0KEPOJiFA2kamBzKzbYljDvUxLg==",
+ "version": "2.16.16",
+ "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.16.16.tgz",
+ "integrity": "sha512-KuS17AOOqH/M5mHXPmKvtp8L+NNteARC7Xjf395+9R9dtJOBndqdStwU4V+OKzYZpgZ+hliV13knzx/oMtFl7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -325,17 +325,16 @@
}
},
"node_modules/@astrojs/markdown-satteri": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.3.4.tgz",
- "integrity": "sha512-6Lvt/bQZEBW+zzdhPblvfZEy5PGEYJaUsUqaCgwHeRPxZJL1gc9I+DRLKWJjjYTWDzVUTzXlMq4WwSK+X34CVw==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.4.0.tgz",
+ "integrity": "sha512-wykOOW9KsUVcZweOpY/CeXpdKcCKZy6fQbdcteWFuI75+sQCiqxYM7VKsGa5b+aGl3cYQscFY37rsbbyal5MRw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@astrojs/internal-helpers": "0.10.1",
+ "@astrojs/internal-helpers": "0.11.0",
"@astrojs/prism": "4.0.2",
"github-slugger": "^2.0.0",
- "hast-util-from-html": "^2.0.3",
- "satteri": "^0.9.1"
+ "satteri": "^0.10.3"
}
},
"node_modules/@astrojs/prism": {
@@ -352,14 +351,13 @@
}
},
"node_modules/@astrojs/sitemap": {
- "version": "3.7.3",
- "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.7.3.tgz",
- "integrity": "sha512-f8euLVsyeAmAkSm/1M2Kb8sL8byQmfgbvBNaHFItCheTj/IpiJYSEWVcqDHZ/yEHxiS7+w87mQkzwZaPHmk5GA==",
+ "version": "3.7.4",
+ "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.7.4.tgz",
+ "integrity": "sha512-LbKNC24bdUWcQf/pThB6qLlSqHojxGjZDURIzFocY8rlWnAn2t74nnhnK6S5x0NHriHoAduLEpVjRykmeGiVvA==",
"dev": true,
"license": "MIT",
"dependencies": {
"sitemap": "^9.0.0",
- "stream-replace-string": "^2.0.0",
"zod": "^4.3.6"
}
},
@@ -390,13 +388,13 @@
}
},
"node_modules/@axe-core/playwright": {
- "version": "4.12.1",
- "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.12.1.tgz",
- "integrity": "sha512-rMd7xriptqKpP+w5265i4Hdkv2X5kbu6uiBi/B2I7uf3hieRBM3qDCfaKPtxfiYb2mKXfF+yLODJwIx+Jv1GDw==",
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.13.0.tgz",
+ "integrity": "sha512-6YLx+kxXu5GJceG4ozFg+33a2EMTdjYwWGloJ3sb9Kta5pp+ZNS53uxGVog5JetIY8s++P5UrtX+cri+u0VAVg==",
"dev": true,
"license": "MPL-2.0",
"dependencies": {
- "axe-core": "~4.12.1"
+ "axe-core": "~4.13.0"
},
"peerDependencies": {
"playwright-core": ">= 1.0.0"
@@ -423,13 +421,13 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
- "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
+ "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.29.7"
+ "@babel/types": "^7.29.8"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -439,9 +437,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
- "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
+ "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -463,9 +461,9 @@
}
},
"node_modules/@bruits/satteri-darwin-arm64": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-arm64/-/satteri-darwin-arm64-0.9.5.tgz",
- "integrity": "sha512-iw4nZgx9v30lWo/MTngQqi1pI78KI0DnkSm+lVJGYdmPLgAyDNJigVhpG42/Iq55A6c1Ll8q66ljyyRiQUxwow==",
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-arm64/-/satteri-darwin-arm64-0.10.5.tgz",
+ "integrity": "sha512-27KTVl4TJkVahMy/ohyA7qd4938G5UNneFUz/PsScYfpIhj0IVAS23mpcJXdPF44sa6nva198lmV/cKIb2YPyA==",
"cpu": [
"arm64"
],
@@ -477,9 +475,9 @@
]
},
"node_modules/@bruits/satteri-darwin-x64": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-x64/-/satteri-darwin-x64-0.9.5.tgz",
- "integrity": "sha512-6T26Z5Kf3cFW2PSlk9p7zT7yVxvuBSiJvYyz9u8KjYwMTqZyIDOj2wDyNpxKV4+6yUVG7rddq2QwvG/8LJA2+Q==",
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-x64/-/satteri-darwin-x64-0.10.5.tgz",
+ "integrity": "sha512-IjnLe3nKspq6qaeqGgjT7MT8VrTV74yWRlaag7ZdNsI8TDAYZ0iPxMCo+9KQZHUk5EyVB+reBI/PFWL5KuFw9Q==",
"cpu": [
"x64"
],
@@ -491,9 +489,9 @@
]
},
"node_modules/@bruits/satteri-linux-arm64-gnu": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-gnu/-/satteri-linux-arm64-gnu-0.9.5.tgz",
- "integrity": "sha512-u51id17uJwNEMK9nBlICsq6U31c+XVqQueVBkwRIzZG+gMpS8TOJctt5h5Wz33Z8xnMdTd+adtACVz0yHgGuOA==",
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-gnu/-/satteri-linux-arm64-gnu-0.10.5.tgz",
+ "integrity": "sha512-glkYXZCJywjP13v67eAyAMSJdF+ncvEbYvgi/wOtffL9tQ27lr/zsyzUfgs+ovjJ9d8JNQKiXeiArJcX8PJL9w==",
"cpu": [
"arm64"
],
@@ -508,9 +506,9 @@
]
},
"node_modules/@bruits/satteri-linux-arm64-musl": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-musl/-/satteri-linux-arm64-musl-0.9.5.tgz",
- "integrity": "sha512-v39HxiwGC5Rqm01HksP6+5Y+xKLPlsuVFgIgpEAo+SiQ22c+mJVhS3u7Z6ePAKdhL5NJoK1xq70kLz3L13AhpQ==",
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-musl/-/satteri-linux-arm64-musl-0.10.5.tgz",
+ "integrity": "sha512-yWdgG1g17Nh2QyGVlFUxGRa3FEFwiMcpZEyMNWkbM3deC94cmVc+/i9OuyFpdKuWo3GkgoCtYVOoxk1uCnCZIA==",
"cpu": [
"arm64"
],
@@ -525,9 +523,9 @@
]
},
"node_modules/@bruits/satteri-linux-x64-gnu": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-gnu/-/satteri-linux-x64-gnu-0.9.5.tgz",
- "integrity": "sha512-F3uO8uFp3pAP5ZGXttwvh57GS7s0lL953tnNdyI2gRyP4kOOkp6pyGojNJzCjkDvWI2Cvb9iNrKok3aqQPauAw==",
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-gnu/-/satteri-linux-x64-gnu-0.10.5.tgz",
+ "integrity": "sha512-FVaLoPT1fBgGl0J+AYebyyXJYBachGl8Oyyrf1lye4RTqCB4S0Gwkj1uM9RJyThUOvx5VUmAT1CnNh1SFHA+kw==",
"cpu": [
"x64"
],
@@ -542,9 +540,9 @@
]
},
"node_modules/@bruits/satteri-linux-x64-musl": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-musl/-/satteri-linux-x64-musl-0.9.5.tgz",
- "integrity": "sha512-bicEqglLlz++mWyADaZoP0JY20s4vDfLjaPYgQqC+NI4zZLTOOg1T4GB8aqtc822Pqji8SQBmSrTb7CrP8i08Q==",
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-musl/-/satteri-linux-x64-musl-0.10.5.tgz",
+ "integrity": "sha512-EHpVAx2bqW3GINHTKkljtxVfQmVDGWIuwOYOP5YghTj+0PkBa2o8oKPRtQ9Kbsr1Fye8jtUcDjhwj2jMNugZKg==",
"cpu": [
"x64"
],
@@ -559,9 +557,9 @@
]
},
"node_modules/@bruits/satteri-wasm32-wasi": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@bruits/satteri-wasm32-wasi/-/satteri-wasm32-wasi-0.9.5.tgz",
- "integrity": "sha512-zauAuMwfPnKPUkd4AFixRFpXdgKwP2mKgxrIIo2gJzW0/ZneF9dbHnLkojSpaBnCCp7VUL1hIi5WWZvB1CqmAQ==",
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-wasm32-wasi/-/satteri-wasm32-wasi-0.10.5.tgz",
+ "integrity": "sha512-ypz8c/Zmipxp4IoeDa228Gstv6TLzVmNs3yC6wKCoNSOjx1iwpgzu87Y3hTkXFdwChVGU85qeUDuOIarGUZQLw==",
"cpu": [
"wasm32"
],
@@ -571,7 +569,7 @@
"dependencies": {
"@emnapi/core": "1.11.1",
"@emnapi/runtime": "1.11.1",
- "@napi-rs/wasm-runtime": "^1.1.6"
+ "@napi-rs/wasm-runtime": "^1.2.3"
},
"engines": {
"node": ">=14.0.0"
@@ -600,10 +598,21 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
+ "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
"node_modules/@bruits/satteri-win32-arm64-msvc": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-arm64-msvc/-/satteri-win32-arm64-msvc-0.9.5.tgz",
- "integrity": "sha512-SrfE7NEsgZjBvU3c+RR6oQRu0ToXY5uVJEbieXEF0YTctIV2zAVlbaMjWLts074QCgh3a+XHWkR/lWh2VH2LUg==",
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-arm64-msvc/-/satteri-win32-arm64-msvc-0.10.5.tgz",
+ "integrity": "sha512-siTV88nb0LRqNpkL2gXboqCwVdq95sLtzMHS1/3eONV2gLbB3NAK46wmSMvCO/yquBvI2lvaFIfd8P12ecsxBw==",
"cpu": [
"arm64"
],
@@ -615,9 +624,9 @@
]
},
"node_modules/@bruits/satteri-win32-x64-msvc": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-x64-msvc/-/satteri-win32-x64-msvc-0.9.5.tgz",
- "integrity": "sha512-5Kw9ZAtTGS8WHizyn+CJhjjfIQrw+7jcZodpmpXJjefnO15M8UexIi6JR2E5thyvsmHyhL6ZDDMUNR4bKJPd4g==",
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-x64-msvc/-/satteri-win32-x64-msvc-0.10.5.tgz",
+ "integrity": "sha512-C3IfPvfvMXmlzBxaMPKFS1XiuV9pu2mC7YqkPk7PSvTgPZ8gbdASIpHpztDLvTTQjqZ0z1Ol8tK5X+V6XXC0wQ==",
"cpu": [
"x64"
],
@@ -628,6 +637,30 @@
"win32"
]
},
+ "node_modules/@cacheable/memory": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz",
+ "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/utils": "^2.5.0",
+ "@keyv/bigmap": "^1.3.1",
+ "hookified": "^1.15.1",
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@cacheable/utils": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz",
+ "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.5.1",
+ "keyv": "^5.6.0"
+ }
+ },
"node_modules/@capsizecss/unpack": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.1.tgz",
@@ -734,22 +767,22 @@
"license": "MIT"
},
"node_modules/@emnapi/core": {
- "version": "1.11.2",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.2.tgz",
- "integrity": "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==",
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz",
+ "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
- "@emnapi/wasi-threads": "1.2.2",
+ "@emnapi/wasi-threads": "1.2.3",
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/runtime": {
- "version": "1.11.2",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz",
- "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==",
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
+ "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -758,20 +791,21 @@
}
},
"node_modules/@emnapi/wasi-threads": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
- "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz",
+ "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==",
"dev": true,
"license": "MIT",
"optional": true,
+ "peer": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
+ "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
"cpu": [
"ppc64"
],
@@ -786,9 +820,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
+ "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
"cpu": [
"arm"
],
@@ -803,9 +837,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
+ "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
"cpu": [
"arm64"
],
@@ -820,9 +854,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
+ "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
"cpu": [
"x64"
],
@@ -837,9 +871,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
+ "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
"cpu": [
"arm64"
],
@@ -854,9 +888,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
+ "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
"cpu": [
"x64"
],
@@ -871,9 +905,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
"cpu": [
"arm64"
],
@@ -888,9 +922,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
+ "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
"cpu": [
"x64"
],
@@ -905,9 +939,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
+ "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
"cpu": [
"arm"
],
@@ -922,9 +956,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
+ "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
"cpu": [
"arm64"
],
@@ -939,9 +973,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
+ "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
"cpu": [
"ia32"
],
@@ -956,9 +990,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
+ "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
"cpu": [
"loong64"
],
@@ -973,9 +1007,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
+ "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
"cpu": [
"mips64el"
],
@@ -990,9 +1024,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
+ "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
"cpu": [
"ppc64"
],
@@ -1007,9 +1041,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
+ "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
"cpu": [
"riscv64"
],
@@ -1024,9 +1058,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
+ "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
"cpu": [
"s390x"
],
@@ -1041,9 +1075,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
+ "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
"cpu": [
"x64"
],
@@ -1058,9 +1092,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
"cpu": [
"arm64"
],
@@ -1075,9 +1109,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
"cpu": [
"x64"
],
@@ -1092,9 +1126,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
"cpu": [
"arm64"
],
@@ -1109,9 +1143,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
"cpu": [
"x64"
],
@@ -1126,9 +1160,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
+ "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
"cpu": [
"arm64"
],
@@ -1143,9 +1177,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
+ "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
"cpu": [
"x64"
],
@@ -1160,9 +1194,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
+ "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
"cpu": [
"arm64"
],
@@ -1177,9 +1211,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
+ "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
"cpu": [
"ia32"
],
@@ -1194,9 +1228,9 @@
}
},
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
+ "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
"cpu": [
"x64"
],
@@ -1325,9 +1359,9 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz",
- "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==",
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz",
+ "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1425,9 +1459,9 @@
}
},
"node_modules/@img/sharp-darwin-arm64": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz",
- "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==",
+ "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==",
"cpu": [
"arm64"
],
@@ -1444,13 +1478,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-darwin-arm64": "1.3.2"
+ "@img/sharp-libvips-darwin-arm64": "1.3.3"
}
},
"node_modules/@img/sharp-darwin-x64": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz",
- "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==",
+ "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==",
"cpu": [
"x64"
],
@@ -1467,13 +1501,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-darwin-x64": "1.3.2"
+ "@img/sharp-libvips-darwin-x64": "1.3.3"
}
},
"node_modules/@img/sharp-freebsd-wasm32": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz",
- "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==",
+ "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==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
@@ -1481,7 +1515,7 @@
"freebsd"
],
"dependencies": {
- "@img/sharp-wasm32": "0.35.3"
+ "@img/sharp-wasm32": "0.35.4"
},
"engines": {
"node": ">=20.9.0"
@@ -1491,9 +1525,9 @@
}
},
"node_modules/@img/sharp-libvips-darwin-arm64": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz",
- "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==",
+ "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==",
"cpu": [
"arm64"
],
@@ -1508,9 +1542,9 @@
}
},
"node_modules/@img/sharp-libvips-darwin-x64": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz",
- "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==",
+ "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==",
"cpu": [
"x64"
],
@@ -1525,9 +1559,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-arm": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz",
- "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==",
+ "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==",
"cpu": [
"arm"
],
@@ -1545,9 +1579,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-arm64": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz",
- "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==",
+ "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==",
"cpu": [
"arm64"
],
@@ -1565,9 +1599,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-ppc64": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz",
- "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==",
+ "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==",
"cpu": [
"ppc64"
],
@@ -1585,9 +1619,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-riscv64": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz",
- "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==",
+ "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==",
"cpu": [
"riscv64"
],
@@ -1605,9 +1639,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-s390x": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz",
- "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==",
+ "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==",
"cpu": [
"s390x"
],
@@ -1625,9 +1659,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-x64": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz",
- "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==",
+ "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==",
"cpu": [
"x64"
],
@@ -1645,9 +1679,9 @@
}
},
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz",
- "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==",
+ "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==",
"cpu": [
"arm64"
],
@@ -1665,9 +1699,9 @@
}
},
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz",
- "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==",
+ "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==",
"cpu": [
"x64"
],
@@ -1685,9 +1719,9 @@
}
},
"node_modules/@img/sharp-linux-arm": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz",
- "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==",
+ "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==",
"cpu": [
"arm"
],
@@ -1707,13 +1741,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-arm": "1.3.2"
+ "@img/sharp-libvips-linux-arm": "1.3.3"
}
},
"node_modules/@img/sharp-linux-arm64": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz",
- "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==",
+ "version": "0.35.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz",
+ "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==",
"cpu": [
"arm64"
],
@@ -1733,13 +1767,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-arm64": "1.3.2"
+ "@img/sharp-libvips-linux-arm64": "1.3.3"
}
},
"node_modules/@img/sharp-linux-ppc64": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz",
- "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==",
+ "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==",
"cpu": [
"ppc64"
],
@@ -1759,13 +1793,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-ppc64": "1.3.2"
+ "@img/sharp-libvips-linux-ppc64": "1.3.3"
}
},
"node_modules/@img/sharp-linux-riscv64": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz",
- "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==",
+ "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==",
"cpu": [
"riscv64"
],
@@ -1785,13 +1819,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-riscv64": "1.3.2"
+ "@img/sharp-libvips-linux-riscv64": "1.3.3"
}
},
"node_modules/@img/sharp-linux-s390x": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz",
- "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==",
+ "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==",
"cpu": [
"s390x"
],
@@ -1811,13 +1845,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-s390x": "1.3.2"
+ "@img/sharp-libvips-linux-s390x": "1.3.3"
}
},
"node_modules/@img/sharp-linux-x64": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz",
- "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==",
+ "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==",
"cpu": [
"x64"
],
@@ -1837,13 +1871,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-x64": "1.3.2"
+ "@img/sharp-libvips-linux-x64": "1.3.3"
}
},
"node_modules/@img/sharp-linuxmusl-arm64": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz",
- "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==",
+ "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==",
"cpu": [
"arm64"
],
@@ -1863,13 +1897,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-arm64": "1.3.2"
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.3"
}
},
"node_modules/@img/sharp-linuxmusl-x64": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz",
- "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==",
+ "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==",
"cpu": [
"x64"
],
@@ -1889,18 +1923,18 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-x64": "1.3.2"
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.3"
}
},
"node_modules/@img/sharp-wasm32": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz",
- "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==",
+ "version": "0.35.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz",
+ "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==",
"dev": true,
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
"optional": true,
"dependencies": {
- "@emnapi/runtime": "^1.11.1"
+ "@emnapi/runtime": "^1.11.3"
},
"engines": {
"node": ">=20.9.0"
@@ -1910,9 +1944,9 @@
}
},
"node_modules/@img/sharp-webcontainers-wasm32": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz",
- "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==",
+ "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==",
"cpu": [
"wasm32"
],
@@ -1920,7 +1954,7 @@
"license": "Apache-2.0",
"optional": true,
"dependencies": {
- "@img/sharp-wasm32": "0.35.3"
+ "@img/sharp-wasm32": "0.35.4"
},
"engines": {
"node": ">=20.9.0"
@@ -1930,9 +1964,9 @@
}
},
"node_modules/@img/sharp-win32-arm64": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz",
- "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==",
+ "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==",
"cpu": [
"arm64"
],
@@ -1950,9 +1984,9 @@
}
},
"node_modules/@img/sharp-win32-ia32": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz",
- "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==",
+ "version": "0.35.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz",
+ "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==",
"cpu": [
"ia32"
],
@@ -1970,9 +2004,9 @@
}
},
"node_modules/@img/sharp-win32-x64": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz",
- "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==",
+ "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==",
"cpu": [
"x64"
],
@@ -2000,9 +2034,9 @@
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
+ "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
"dev": true,
"license": "MIT"
},
@@ -2017,29 +2051,56 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@keyv/bigmap": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz",
+ "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.4.0",
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@keyv/serialize": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz",
+ "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@mdn/browser-compat-data": {
- "version": "8.0.8",
- "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-8.0.8.tgz",
- "integrity": "sha512-Rutrrc3FYOc+um4/QC4WFETNk2fV8NKWoqQl3tQfcVTQ1WFaoJRbsJBasSF34ltitmnYYD6ZsKW1cOQtSj1jbQ==",
+ "version": "8.1.4",
+ "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-8.1.4.tgz",
+ "integrity": "sha512-Cgp3OP3u9x57kT1sZPI115SP5H1IyaBhdDPnvnHRYZ1988kW83wuqcIdcMinLJXlMKOL5Y2cufWHzngh5cVtow==",
"license": "CC0-1.0"
},
"node_modules/@napi-rs/wasm-runtime": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz",
- "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz",
+ "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@tybys/wasm-util": "^0.10.3"
},
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=23.5.0"
+ },
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
},
"peerDependencies": {
- "@emnapi/core": "^1.7.1",
- "@emnapi/runtime": "^1.7.1"
+ "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4",
+ "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4"
}
},
"node_modules/@oslojs/encoding": {
@@ -2050,23 +2111,23 @@
"license": "MIT"
},
"node_modules/@oxc-project/types": {
- "version": "0.139.0",
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz",
- "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==",
+ "version": "0.148.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.148.0.tgz",
+ "integrity": "sha512-Nm4s/jB+4FpFsPhWGEC4h7rzksesmtnMXomo6rCMcg/b8zLQuOziRgkCS1fxDCXOlJB/6Q8oABOZ/OP6RIPj9A==",
"dev": true,
"license": "MIT",
"funding": {
- "url": "https://github.com/sponsors/Boshen"
+ "url": "https://github.com/sponsors/oxc-project"
}
},
"node_modules/@playwright/test": {
- "version": "1.62.0",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.62.0.tgz",
- "integrity": "sha512-9zOJ6ZQRAena31MpOH9VSzIz8Ou3YJ/wtY/eQm5T2uhfhG7/U3COrMS8xOtUrZrp9OgdmzEnIYODye3nY1VqzA==",
+ "version": "1.63.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.63.0.tgz",
+ "integrity": "sha512-oxMK4vllB9RK5NQ2l1pq1IfOf2AvnEuj/vYGDj0H2nMtmtZpKtCwt/l00GEO6xjGfpBNAvjovvYdCm50dRQkpQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright": "1.62.0"
+ "playwright": "1.63.0"
},
"bin": {
"playwright": "cli.js"
@@ -2075,10 +2136,27 @@
"node": ">=20"
}
},
+ "node_modules/@rolldown/binding-android-arm-eabi": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.7.tgz",
+ "integrity": "sha512-EypzgnYCwyVY4NDHKzGmNJT5b+XaQEBniHxsMdeIQLB/tcCzZnhqrzHpZFbX9iaxx+5RiB8caATBtfvZP7zVxQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
"node_modules/@rolldown/binding-android-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz",
- "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.7.tgz",
+ "integrity": "sha512-l17HE9EweWaqJZhuUuNBN/FzM62xw+DECVnJyvMsxn8vJFAGLy5QfLDoYAcronkAN8VxKZHezDpulHDPx95vFw==",
"cpu": [
"arm64"
],
@@ -2093,9 +2171,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz",
- "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.7.tgz",
+ "integrity": "sha512-8ED8ELFvHXc6OCETIn4gXObPiaR6bckM/ipXtbzlPVDRMBfEGjCKgO90F9YtfdpDatVx/ZQw7aZ1vUMf/+T3Mw==",
"cpu": [
"arm64"
],
@@ -2110,9 +2188,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz",
- "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.7.tgz",
+ "integrity": "sha512-/WPripjtiAIZ2tWY7ddijORT0Ujg87wxWW/qcoFVCKAWVDPhtY0xr7Dj0M3GyNGz60jGwTElhro/mkF9dT7dDQ==",
"cpu": [
"x64"
],
@@ -2127,9 +2205,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz",
- "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.7.tgz",
+ "integrity": "sha512-14DI4NcqpvbICxSnGLx3PmtDaWqRP/KGSGb6C+JLLVPeZRl6dKdHba3pGsqT3vpdTqhEYIPG0MMQ8c0xYqoJxA==",
"cpu": [
"x64"
],
@@ -2144,9 +2222,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz",
- "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.7.tgz",
+ "integrity": "sha512-bxrWIRvHWQvbJwi+VIie/kDJmQxcNE6xxWwZdqF/ExVAigtHkv54WTLQPb+QsZdnFy18fg7JPfWGL0RH6vwIlQ==",
"cpu": [
"arm"
],
@@ -2161,9 +2239,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz",
- "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.7.tgz",
+ "integrity": "sha512-toOY2BChBZyuxU7OYX6Tn389di4IzAqPTycVcci0O7FSfBqzRB3RZn+K5Is6ANf4tmgRd/K1yZTsNTXbkXsnLg==",
"cpu": [
"arm64"
],
@@ -2181,9 +2259,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz",
- "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.7.tgz",
+ "integrity": "sha512-lAIXTH/aiLRLxsTgQvfhjo4K1ydWIp00+V0voOr9beb/9ZmkUFrSIb03dXNFRgMNvkE6oGsF10ioQ6UsI+vS5Q==",
"cpu": [
"arm64"
],
@@ -2201,9 +2279,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz",
- "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.7.tgz",
+ "integrity": "sha512-kdnwS28Pkenp/mZMRwjXXXwxQ7pIsm+bF919LUK93BOyhcLsrVKdP2p9fxpiPNPAbNuch8ypQt0pm2P2LYCAGg==",
"cpu": [
"ppc64"
],
@@ -2221,9 +2299,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz",
- "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.7.tgz",
+ "integrity": "sha512-516OdsyLdr5E65paF3yBF55t8mfm9+gmtCsK3xI7XKXIT7EfRlHhxL8K/NR6Hu8BWSgF5+1w74lTL0+nxcc8Qw==",
"cpu": [
"s390x"
],
@@ -2241,9 +2319,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz",
- "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.7.tgz",
+ "integrity": "sha512-r8/z8n7GFaYRln3xmP1Cxy0HH/HLM0uBUPkEuSVEfKGDA89M0FsZRZJRSwe/tJjRx+fpH/gjorfhB8tmEbSFLA==",
"cpu": [
"x64"
],
@@ -2261,9 +2339,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz",
- "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.7.tgz",
+ "integrity": "sha512-pAsE8iiDxUg1xBqdhrTfg45AVDVpirjz00sblEYClGNNcMnDb+e8beQgqIAw6LvauX/APvgxUnwrgun/YYGBhw==",
"cpu": [
"x64"
],
@@ -2281,9 +2359,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz",
- "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.7.tgz",
+ "integrity": "sha512-lTcIYmmnQQA8Or/2DatS6oSqcdLHvendjS+zLu+FwgToynWMRSmQdpM65fTANJgIS4mjbMOo5KT2lnT9SAb96w==",
"cpu": [
"arm64"
],
@@ -2297,52 +2375,10 @@
"node": "^20.19.0 || >=22.12.0"
}
},
- "node_modules/@rolldown/binding-wasm32-wasi": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz",
- "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==",
- "cpu": [
- "wasm32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "1.11.1",
- "@emnapi/runtime": "1.11.1",
- "@napi-rs/wasm-runtime": "^1.1.6"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
- "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/wasi-threads": "1.2.2",
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz",
- "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
"node_modules/@rolldown/binding-win32-arm64-msvc": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz",
- "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.7.tgz",
+ "integrity": "sha512-e3Gu3WxbNk/UqQhxqU7YIYO+9ZBvWNz3U+h/qRFosscMFzdRPbXYSaSWgSnklv2fz1TgzBTcti2z35c/7irsHw==",
"cpu": [
"arm64"
],
@@ -2357,9 +2393,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz",
- "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.7.tgz",
+ "integrity": "sha512-W/jg5qoRSqjsEv0+dZi4e687mcHqmVuU0P4fK6qS/xjetW2Gmc1W8j//z5nAeNcC8Ttm0hV46IjcYeuVwYhuiw==",
"cpu": [
"x64"
],
@@ -2380,47 +2416,17 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@rollup/pluginutils": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz",
- "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/estree": "^1.0.0",
- "estree-walker": "^2.0.2",
- "picomatch": "^4.0.2"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
- },
- "peerDependenciesMeta": {
- "rollup": {
- "optional": true
- }
- }
- },
- "node_modules/@rollup/pluginutils/node_modules/estree-walker": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
- "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@shikijs/core": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.3.1.tgz",
- "integrity": "sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.4.3.tgz",
+ "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@shikijs/primitive": "4.3.1",
- "@shikijs/types": "4.3.1",
+ "@shikijs/primitive": "4.4.3",
+ "@shikijs/types": "4.4.3",
"@shikijs/vscode-textmate": "^10.0.2",
- "@types/hast": "^3.0.4",
+ "@types/hast": "^3.0.5",
"hast-util-to-html": "^9.0.5"
},
"engines": {
@@ -2428,13 +2434,13 @@
}
},
"node_modules/@shikijs/engine-javascript": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.3.1.tgz",
- "integrity": "sha512-JBItcnPuYq7jVJdZo/vMj94r+szT7XEjHFX+mvFDGSEIbVAXAGyHAHzhbWzpGOwYidCZrErJLLgn2PVeiokHnQ==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz",
+ "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@shikijs/types": "4.3.1",
+ "@shikijs/types": "4.4.3",
"@shikijs/vscode-textmate": "^10.0.2",
"oniguruma-to-es": "^4.3.6"
},
@@ -2443,13 +2449,13 @@
}
},
"node_modules/@shikijs/engine-oniguruma": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.3.1.tgz",
- "integrity": "sha512-OXyNMzg0pews+msMj4cHeqT4xiYKKvbnn6VbdAXxfoFl3SSx4fJTc8FadECuc5/H9p3BzhNAoAUXKwAu9rWYhg==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz",
+ "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@shikijs/types": "4.3.1",
+ "@shikijs/types": "4.4.3",
"@shikijs/vscode-textmate": "^10.0.2"
},
"engines": {
@@ -2457,55 +2463,55 @@
}
},
"node_modules/@shikijs/langs": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.3.1.tgz",
- "integrity": "sha512-m0l9nsDqgBHvbZbk7A0/kXz/impK3uB/c6rAn6Gpg/uPtdZRQ+alsN/17MU5thb68XTj/4DxkZAotrM0GGSpDQ==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz",
+ "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@shikijs/types": "4.3.1"
+ "@shikijs/types": "4.4.3"
},
"engines": {
"node": ">=20"
}
},
"node_modules/@shikijs/primitive": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.3.1.tgz",
- "integrity": "sha512-CXQRQOYy1leqQ8ceTeJdmXv/bsUY++6QyLpXJ94LZAAYj5X2SKRdc5ipguv4NPyGVKItB2PPwUpRNe0Sjh5S1A==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.4.3.tgz",
+ "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@shikijs/types": "4.3.1",
+ "@shikijs/types": "4.4.3",
"@shikijs/vscode-textmate": "^10.0.2",
- "@types/hast": "^3.0.4"
+ "@types/hast": "^3.0.5"
},
"engines": {
"node": ">=20"
}
},
"node_modules/@shikijs/themes": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.3.1.tgz",
- "integrity": "sha512-dgpoJ4WqNi2yTmizQHBJ5zcX6j2lE6icN/0yt4l1kkf16jrY/pwPLoTb1ETsWMz0OBLf9ZNvwmxft+cH+N9qSA==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz",
+ "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@shikijs/types": "4.3.1"
+ "@shikijs/types": "4.4.3"
},
"engines": {
"node": ">=20"
}
},
"node_modules/@shikijs/types": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.3.1.tgz",
- "integrity": "sha512-CHFxE0jztBIZRHH6gxXE7DXUCFXjReEGxZ/j0rfSLGKZuwp2xBYycEP14875DSa9KLL/6700oxIq6oO6ef9K2g==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz",
+ "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@shikijs/vscode-textmate": "^10.0.2",
- "@types/hast": "^3.0.4"
+ "@types/hast": "^3.0.5"
},
"engines": {
"node": ">=20"
@@ -2540,9 +2546,9 @@
}
},
"node_modules/@sigstore/protobuf-specs": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.5.1.tgz",
- "integrity": "sha512-/ScWUhhoFasJsSRGTVBwId1loQjjnjAfE4djL6ZhrXRpNCmPTnUKF5Jokd58ILseOMjzET3UrMOtJPS9sYeI0g==",
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.5.2.tgz",
+ "integrity": "sha512-SQqvFMt4V78fdjcDdYX6HbiVSOR4QK3ZgwCa2KOsopAgPIHy1rU5UDUmzLl02r5oyyaYcYHR1hpwDRk/yUe+Mw==",
"license": "Apache-2.0",
"engines": {
"node": "^18.17.0 || >=20.5.0"
@@ -2562,9 +2568,9 @@
}
},
"node_modules/@sigstore/verify": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-4.1.0.tgz",
- "integrity": "sha512-p/s720RiWxLG8XtmfdPfEJOlATA6H/2knFqmtQbFkHKN3IrhWGUwPfpQAf1UnQIEES9IaH6zzhfjkrhTfeSdZw==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-4.1.2.tgz",
+ "integrity": "sha512-BfD9eLrz3A/DG58aSgfgZYmIR6V9Yw96QVN/frtu2bEH7ctSTk2TDvHU12un3JsDPBTqTNkqkIkucjxljpOFqQ==",
"license": "Apache-2.0",
"dependencies": {
"@sigstore/bundle": "^5.0.0",
@@ -2575,13 +2581,6 @@
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
},
- "node_modules/@standard-schema/spec": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
- "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@tufjs/canonical-json": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz",
@@ -2722,17 +2721,17 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.65.0.tgz",
- "integrity": "sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.69.0.tgz",
+ "integrity": "sha512-t5jQTKPIgVW1PE6dR6H6Qz5gm8zjMlX5/2gRaOGd9eO6V7J+tQc6iWKukEe7dY8u9HyYasQ0yfF0/FSSTEO2gA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
- "@typescript-eslint/scope-manager": "8.65.0",
- "@typescript-eslint/type-utils": "8.65.0",
- "@typescript-eslint/utils": "8.65.0",
- "@typescript-eslint/visitor-keys": "8.65.0",
+ "@typescript-eslint/scope-manager": "8.69.0",
+ "@typescript-eslint/type-utils": "8.69.0",
+ "@typescript-eslint/utils": "8.69.0",
+ "@typescript-eslint/visitor-keys": "8.69.0",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0"
@@ -2745,15 +2744,15 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^8.65.0",
+ "@typescript-eslint/parser": "^8.69.0",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz",
- "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==",
+ "version": "7.0.8",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.8.tgz",
+ "integrity": "sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2761,16 +2760,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.65.0.tgz",
- "integrity": "sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.69.0.tgz",
+ "integrity": "sha512-l4b0DhWioGg6Gt2ebGlvfkFMOjRsauxtsnDRwUSRX1qHq3HdTfQHV8wW9zEXeciai6HfeaKOedQn2Zoofx3WBw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.65.0",
- "@typescript-eslint/types": "8.65.0",
- "@typescript-eslint/typescript-estree": "8.65.0",
- "@typescript-eslint/visitor-keys": "8.65.0",
+ "@typescript-eslint/scope-manager": "8.69.0",
+ "@typescript-eslint/types": "8.69.0",
+ "@typescript-eslint/typescript-estree": "8.69.0",
+ "@typescript-eslint/visitor-keys": "8.69.0",
"debug": "^4.4.3"
},
"engines": {
@@ -2786,14 +2785,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.65.0.tgz",
- "integrity": "sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.69.0.tgz",
+ "integrity": "sha512-yi4obFrHMmnsesWehHbkg9zMA7Jt8cXT+mKM08G999pH1yT6nqgsHx7MYm0uY1wAj8CqiBXYRJ7WAT0QdQHQXg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.65.0",
- "@typescript-eslint/types": "^8.65.0",
+ "@typescript-eslint/tsconfig-utils": "^8.69.0",
+ "@typescript-eslint/types": "^8.69.0",
"debug": "^4.4.3"
},
"engines": {
@@ -2808,14 +2807,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.65.0.tgz",
- "integrity": "sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.69.0.tgz",
+ "integrity": "sha512-ewfspqWvSxKSOaplqAUNbaSFO0eB6w1EtQ+esfYFRm3614Ty4uNtExkcbgd6nWsXphbqKyf9ZYdbZdv2xEoWEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.65.0",
- "@typescript-eslint/visitor-keys": "8.65.0"
+ "@typescript-eslint/types": "8.69.0",
+ "@typescript-eslint/visitor-keys": "8.69.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2826,9 +2825,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.65.0.tgz",
- "integrity": "sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.69.0.tgz",
+ "integrity": "sha512-xNqK7YTDZsLniQMV/4rpFR8Z5JlqeRvVjuG1YgF/mdPVH84HSD19L8CczMA0qg2RfwEV231GHH3VnToJDo4MfQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2843,15 +2842,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.65.0.tgz",
- "integrity": "sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.69.0.tgz",
+ "integrity": "sha512-ZfoJAVg3JZndQEpEl9petVlxau3lRuElc4HRMuAlLCf8to04/iHz692RUSNmXKDjEuJmIL+KZ2/BsOcBc16dsA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.65.0",
- "@typescript-eslint/typescript-estree": "8.65.0",
- "@typescript-eslint/utils": "8.65.0",
+ "@typescript-eslint/types": "8.69.0",
+ "@typescript-eslint/typescript-estree": "8.69.0",
+ "@typescript-eslint/utils": "8.69.0",
"debug": "^4.4.3",
"ts-api-utils": "^2.5.0"
},
@@ -2868,9 +2867,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.65.0.tgz",
- "integrity": "sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.69.0.tgz",
+ "integrity": "sha512-K3VrubUPhlo9VDBS6QdI8YB5j7ClpqLRdefcz6PFrhnwicehBweqQ9Evhl4l+FYz0HdDmMqIiSX0aldGRYtDCA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2882,16 +2881,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.65.0.tgz",
- "integrity": "sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.69.0.tgz",
+ "integrity": "sha512-AdFkgqck3Vudb/kWnxlyafU/4aBhHrbQ9locP2N4psXTy5mOBg0SHJumnLvx7r6g1gV4DKvUFwV2nJZBoqOD8w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.65.0",
- "@typescript-eslint/tsconfig-utils": "8.65.0",
- "@typescript-eslint/types": "8.65.0",
- "@typescript-eslint/visitor-keys": "8.65.0",
+ "@typescript-eslint/project-service": "8.69.0",
+ "@typescript-eslint/tsconfig-utils": "8.69.0",
+ "@typescript-eslint/types": "8.69.0",
+ "@typescript-eslint/visitor-keys": "8.69.0",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -2910,16 +2909,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.65.0.tgz",
- "integrity": "sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.69.0.tgz",
+ "integrity": "sha512-tUbx60BBqQa31kXF5MCsOOLL5E/WzUuxIn7YpAvq+eaUlqvk8/NXnXMBNAdLCr0icjkzem7iUA5QqWHe/hJ1aw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.65.0",
- "@typescript-eslint/types": "8.65.0",
- "@typescript-eslint/typescript-estree": "8.65.0"
+ "@typescript-eslint/scope-manager": "8.69.0",
+ "@typescript-eslint/types": "8.69.0",
+ "@typescript-eslint/typescript-estree": "8.69.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2934,13 +2933,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.65.0.tgz",
- "integrity": "sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.69.0.tgz",
+ "integrity": "sha512-+rmdgPA+EXkNgKYvHvFfhrs35utXbwaC5PGpDquSXcoXQDKUA5UjV0LmTucG/4JXkM31BTu4TilHtrN8IVBe8w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.65.0",
+ "@typescript-eslint/types": "8.69.0",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -2952,36 +2951,34 @@
}
},
"node_modules/@ungap/structured-clone": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz",
- "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.4.0.tgz",
+ "integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==",
"dev": true,
"license": "ISC"
},
"node_modules/@vitest/coverage-v8": {
- "version": "4.1.10",
- "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz",
- "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-5.0.0.tgz",
+ "integrity": "sha512-toMg6PZGCIa/lQNCDoASrfb1ly4hsUKXFtFYC9kD4t78o5Y6LyNJU7AENt8eHPr3quYdxaxK7hj2mnbFfUk9NA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@bcoe/v8-coverage": "^1.0.2",
- "@vitest/utils": "4.1.10",
- "ast-v8-to-istanbul": "^1.0.0",
- "istanbul-lib-coverage": "^3.2.2",
- "istanbul-lib-report": "^3.0.1",
- "istanbul-reports": "^3.2.0",
- "magicast": "^0.5.2",
- "obug": "^2.1.1",
- "std-env": "^4.0.0-rc.1",
- "tinyrainbow": "^3.1.0"
+ "@vitest/istanbul-lib-coverage": "^1.0.0",
+ "@vitest/istanbul-lib-report": "^1.0.0",
+ "ast-v8-to-istanbul": "^1.0.5",
+ "magicast": "^0.5.4",
+ "obug": "^2.1.4",
+ "std-env": "^4.2.0",
+ "tinyrainbow": "^3.1.1"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "@vitest/browser": "4.1.10",
- "vitest": "4.1.10"
+ "@vitest/browser": "5.0.0",
+ "vitest": "5.0.0"
},
"peerDependenciesMeta": {
"@vitest/browser": {
@@ -2989,34 +2986,40 @@
}
}
},
- "node_modules/@vitest/expect": {
- "version": "4.1.10",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz",
- "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==",
+ "node_modules/@vitest/istanbul-lib-coverage": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@vitest/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.1.tgz",
+ "integrity": "sha512-k3DJZ8LhMBK9NS4SclF1ASD3OgXEWDorbIcPTRDK0/Zae6fRvu+fJRxtFdLfHsa9Y24beCdPnoNZ4LviTNstfA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/@vitest/istanbul-lib-report": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@vitest/istanbul-lib-report/-/istanbul-lib-report-1.0.1.tgz",
+ "integrity": "sha512-1EOLRfsTMnyAr3+kEAsP4o9dhaDlGPpD7H5iLBBeq//YpNB1VIahkPhB+eRp9N2Dkfw8oySROjE3yf9XDeaIkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@standard-schema/spec": "^1.1.0",
- "@types/chai": "^5.2.2",
- "@vitest/spy": "4.1.10",
- "@vitest/utils": "4.1.10",
- "chai": "^6.2.2",
- "tinyrainbow": "^3.1.0"
+ "@vitest/istanbul-lib-coverage": "1.0.1"
},
- "funding": {
- "url": "https://opencollective.com/vitest"
+ "engines": {
+ "node": ">=22"
}
},
"node_modules/@vitest/mocker": {
- "version": "4.1.10",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz",
- "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.0.tgz",
+ "integrity": "sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "4.1.10",
+ "@jridgewell/trace-mapping": "0.3.31",
+ "@vitest/spy": "5.0.0",
"estree-walker": "^3.0.3",
- "magic-string": "^0.30.21"
+ "magic-string": "^1.2.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
@@ -3034,70 +3037,12 @@
}
}
},
- "node_modules/@vitest/pretty-format": {
- "version": "4.1.10",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz",
- "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tinyrainbow": "^3.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/runner": {
- "version": "4.1.10",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz",
- "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/utils": "4.1.10",
- "pathe": "^2.0.3"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/snapshot": {
- "version": "4.1.10",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz",
- "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/pretty-format": "4.1.10",
- "@vitest/utils": "4.1.10",
- "magic-string": "^0.30.21",
- "pathe": "^2.0.3"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
"node_modules/@vitest/spy": {
- "version": "4.1.10",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz",
- "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/utils": {
- "version": "4.1.10",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz",
- "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.0.tgz",
+ "integrity": "sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@vitest/pretty-format": "4.1.10",
- "convert-source-map": "^2.0.0",
- "tinyrainbow": "^3.1.0"
- },
"funding": {
"url": "https://opencollective.com/vitest"
}
@@ -3208,9 +3153,9 @@
"license": "MIT"
},
"node_modules/acorn": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz",
- "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==",
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
+ "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
"dev": true,
"license": "MIT",
"bin": {
@@ -3261,26 +3206,26 @@
}
},
"node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz",
+ "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
"engines": {
- "node": ">=8"
+ "node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
@@ -3360,20 +3305,19 @@
}
},
"node_modules/astro": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/astro/-/astro-7.1.3.tgz",
- "integrity": "sha512-4dhPyAAXthf3xLEYnG8SeL7yr/nTPPABfY7e9YF0yuO+vK9Xp+8Q5j4xzsmL3GueukQv4oNwGNTBepLOiDGeJA==",
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/astro/-/astro-7.3.1.tgz",
+ "integrity": "sha512-A/bJYHtc6n0UAdROY9W948fW6lX0pnUA+JWKW+IGCXRyDIGN2MsXC0OlS8onZGJjr+sv8htemwOc9W5PBRXCkw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@astrojs/compiler-rs": "^0.3.1",
- "@astrojs/internal-helpers": "0.10.1",
- "@astrojs/markdown-satteri": "0.3.4",
+ "@astrojs/compiler-rs": "^0.4.0",
+ "@astrojs/internal-helpers": "0.11.0",
+ "@astrojs/markdown-satteri": "0.4.0",
"@astrojs/telemetry": "3.3.3",
"@capsizecss/unpack": "^4.0.0",
"@clack/prompts": "^1.1.0",
"@oslojs/encoding": "^1.1.0",
- "@rollup/pluginutils": "^5.3.0",
"am-i-vibing": "^0.4.0",
"aria-query": "^5.3.2",
"axobject-query": "^4.1.0",
@@ -3382,19 +3326,20 @@
"common-ancestor-path": "^2.0.0",
"cookie": "^2.0.1",
"devalue": "^5.8.1",
- "diff": "^8.0.3",
+ "diff": "^9.0.0",
"dset": "^3.1.4",
"es-module-lexer": "^2.0.0",
"esbuild": "^0.28.0",
+ "find-proc": "0.1.0",
"flattie": "^1.1.1",
"fontace": "~0.4.1",
"get-tsconfig": "5.0.0-beta.4",
"github-slugger": "^2.0.0",
"html-escaper": "3.0.3",
"http-cache-semantics": "^4.2.0",
- "js-yaml": "^4.1.1",
+ "js-yaml": "^4.3.0",
"jsonc-parser": "^3.3.1",
- "magic-string": "^0.30.21",
+ "magic-string": "^1.0.0",
"magicast": "^0.5.2",
"mrmime": "^2.0.1",
"neotraverse": "^1.0.1",
@@ -3412,13 +3357,13 @@
"tinyexec": "^1.0.4",
"tinyglobby": "^0.2.15",
"ultrahtml": "^1.6.0",
- "unifont": "~0.7.4",
+ "unifont": "~0.7.5",
"unstorage": "^1.17.5",
"vite": "^8.0.13",
"vitefu": "^1.1.2",
"xxhash-wasm": "^1.1.0",
"yargs-parser": "^22.0.0",
- "zod": "^4.3.6"
+ "zod": "^4.5.4"
},
"bin": {
"astro": "bin/astro.mjs"
@@ -3433,10 +3378,10 @@
"url": "https://opencollective.com/astrodotbuild"
},
"optionalDependencies": {
- "sharp": "^0.34.0 || ^0.35.0"
+ "sharp": "^0.35.4"
},
"peerDependencies": {
- "@astrojs/markdown-remark": "7.2.1"
+ "@astrojs/markdown-remark": "^7.3.0"
},
"peerDependenciesMeta": {
"@astrojs/markdown-remark": {
@@ -3445,9 +3390,9 @@
}
},
"node_modules/axe-core": {
- "version": "4.12.1",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.12.1.tgz",
- "integrity": "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==",
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.13.0.tgz",
+ "integrity": "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==",
"dev": true,
"license": "MPL-2.0",
"engines": {
@@ -3492,9 +3437,9 @@
"license": "ISC"
},
"node_modules/brace-expansion": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz",
- "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
+ "version": "5.0.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
+ "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
@@ -3503,6 +3448,20 @@
"node": "20 || >=22"
}
},
+ "node_modules/cacheable": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz",
+ "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/memory": "^2.2.0",
+ "@cacheable/utils": "^2.5.0",
+ "hookified": "^1.15.0",
+ "keyv": "^5.6.0",
+ "qified": "^0.10.1"
+ }
+ },
"node_modules/ccount": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
@@ -3579,49 +3538,47 @@
}
},
"node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz",
+ "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==",
"dev": true,
"license": "ISC",
"dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
+ "string-width": "^7.2.0",
+ "strip-ansi": "^7.1.0",
+ "wrap-ansi": "^9.0.0"
},
"engines": {
- "node": ">=12"
+ "node": ">=20"
}
},
- "node_modules/clsx": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
- "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "node_modules/cliui/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "color-name": "~1.1.4"
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
},
"engines": {
- "node": ">=7.0.0"
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
},
"node_modules/comma-separated-tokens": {
"version": "2.0.3",
@@ -3654,13 +3611,6 @@
"node": ">= 18"
}
},
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/cookie": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-2.0.1.tgz",
@@ -3708,17 +3658,17 @@
}
},
"node_modules/css-select": {
- "version": "5.2.2",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
- "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-6.0.0.tgz",
+ "integrity": "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0",
- "css-what": "^6.1.0",
- "domhandler": "^5.0.2",
- "domutils": "^3.0.1",
- "nth-check": "^2.0.1"
+ "css-what": "^7.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.2",
+ "nth-check": "^2.1.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
@@ -3739,9 +3689,9 @@
}
},
"node_modules/css-what": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
- "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-7.0.0.tgz",
+ "integrity": "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
@@ -3846,9 +3796,9 @@
}
},
"node_modules/devalue": {
- "version": "5.8.2",
- "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.2.tgz",
- "integrity": "sha512-DObPPAfdtFbXjxLqK8s2Xk9ZuWz5+ZoFEhC7J76es4GU/rEiXwHTmbImoCdyoCOcBH1UF3+Cz6Z2sYD4hyl5TA==",
+ "version": "5.9.4",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.9.4.tgz",
+ "integrity": "sha512-sPAT4pztbu6586/hrhOnMKS17IJrvg12mXiSPSS3W5qDeN2RGgvZ0diZCm31dBbnevfVmujNO3IM2wrS4Y2Rhg==",
"dev": true,
"license": "MIT"
},
@@ -3867,9 +3817,9 @@
}
},
"node_modules/diff": {
- "version": "8.0.4",
- "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz",
- "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==",
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz",
+ "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
@@ -3976,9 +3926,9 @@
}
},
"node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
+ "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
"dev": true,
"license": "MIT"
},
@@ -3995,16 +3945,16 @@
}
},
"node_modules/es-module-lexer": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz",
- "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz",
+ "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==",
"dev": true,
"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==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
+ "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -4015,32 +3965,32 @@
"node": ">=18"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.28.1",
- "@esbuild/android-arm": "0.28.1",
- "@esbuild/android-arm64": "0.28.1",
- "@esbuild/android-x64": "0.28.1",
- "@esbuild/darwin-arm64": "0.28.1",
- "@esbuild/darwin-x64": "0.28.1",
- "@esbuild/freebsd-arm64": "0.28.1",
- "@esbuild/freebsd-x64": "0.28.1",
- "@esbuild/linux-arm": "0.28.1",
- "@esbuild/linux-arm64": "0.28.1",
- "@esbuild/linux-ia32": "0.28.1",
- "@esbuild/linux-loong64": "0.28.1",
- "@esbuild/linux-mips64el": "0.28.1",
- "@esbuild/linux-ppc64": "0.28.1",
- "@esbuild/linux-riscv64": "0.28.1",
- "@esbuild/linux-s390x": "0.28.1",
- "@esbuild/linux-x64": "0.28.1",
- "@esbuild/netbsd-arm64": "0.28.1",
- "@esbuild/netbsd-x64": "0.28.1",
- "@esbuild/openbsd-arm64": "0.28.1",
- "@esbuild/openbsd-x64": "0.28.1",
- "@esbuild/openharmony-arm64": "0.28.1",
- "@esbuild/sunos-x64": "0.28.1",
- "@esbuild/win32-arm64": "0.28.1",
- "@esbuild/win32-ia32": "0.28.1",
- "@esbuild/win32-x64": "0.28.1"
+ "@esbuild/aix-ppc64": "0.28.2",
+ "@esbuild/android-arm": "0.28.2",
+ "@esbuild/android-arm64": "0.28.2",
+ "@esbuild/android-x64": "0.28.2",
+ "@esbuild/darwin-arm64": "0.28.2",
+ "@esbuild/darwin-x64": "0.28.2",
+ "@esbuild/freebsd-arm64": "0.28.2",
+ "@esbuild/freebsd-x64": "0.28.2",
+ "@esbuild/linux-arm": "0.28.2",
+ "@esbuild/linux-arm64": "0.28.2",
+ "@esbuild/linux-ia32": "0.28.2",
+ "@esbuild/linux-loong64": "0.28.2",
+ "@esbuild/linux-mips64el": "0.28.2",
+ "@esbuild/linux-ppc64": "0.28.2",
+ "@esbuild/linux-riscv64": "0.28.2",
+ "@esbuild/linux-s390x": "0.28.2",
+ "@esbuild/linux-x64": "0.28.2",
+ "@esbuild/netbsd-arm64": "0.28.2",
+ "@esbuild/netbsd-x64": "0.28.2",
+ "@esbuild/openbsd-arm64": "0.28.2",
+ "@esbuild/openbsd-x64": "0.28.2",
+ "@esbuild/openharmony-arm64": "0.28.2",
+ "@esbuild/sunos-x64": "0.28.2",
+ "@esbuild/win32-arm64": "0.28.2",
+ "@esbuild/win32-ia32": "0.28.2",
+ "@esbuild/win32-x64": "0.28.2"
}
},
"node_modules/escalade": {
@@ -4067,9 +4017,9 @@
}
},
"node_modules/eslint": {
- "version": "10.8.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.0.tgz",
- "integrity": "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ==",
+ "version": "10.10.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.10.0.tgz",
+ "integrity": "sha512-NPXn6r5zl4uET1DAVPaOwzX3rut4c0wcmw3dWJAfOsTM5+TogXo0DDjz8pwm/hL8cyVNpHqeK4JpN0NjnyFFNw==",
"dev": true,
"license": "MIT",
"workspaces": [
@@ -4081,7 +4031,7 @@
"@eslint/config-array": "^0.23.5",
"@eslint/config-helpers": "^0.7.0",
"@eslint/core": "^1.2.1",
- "@eslint/plugin-kit": "^0.7.2",
+ "@eslint/plugin-kit": "^0.7.3",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
@@ -4096,7 +4046,7 @@
"esquery": "^1.7.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
+ "file-entry-cache": "11.1.5 || >11.1.6 <12",
"find-up": "^5.0.0",
"glob-parent": "^6.0.2",
"ignore": "^5.2.0",
@@ -4294,9 +4244,9 @@
}
},
"node_modules/fast-uri": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz",
- "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==",
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz",
+ "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==",
"dev": true,
"funding": [
{
@@ -4339,16 +4289,23 @@
}
},
"node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "version": "11.1.5",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz",
+ "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flat-cache": "^4.0.0"
- },
+ "flat-cache": "^6.1.23"
+ }
+ },
+ "node_modules/find-proc": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/find-proc/-/find-proc-0.1.0.tgz",
+ "integrity": "sha512-OaOpEYv2PiQ7SQ5LIrl+deA1XaWcxEjnpM6VuWXTUvn+teIXxeFTLDmu18/zDQpFmHN4o3oDBX+BT0AGwEhemg==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=16.0.0"
+ "node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/find-up": {
@@ -4369,23 +4326,21 @@
}
},
"node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "version": "6.1.23",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz",
+ "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
- },
- "engines": {
- "node": ">=16"
+ "cacheable": "^2.5.0",
+ "flatted": "^3.4.2",
+ "hookified": "^1.15.0"
}
},
"node_modules/flatted": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.3.tgz",
- "integrity": "sha512-/zipXxyO6rGvuNGDiULY9MvEGSkb2gaG4GGH4ygMi0ZZzyMHdUZBmntJmx5x1G2VuPytCwGN4xsJP6cw+sK+vQ==",
+ "version": "3.4.4",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz",
+ "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==",
"dev": true,
"license": "ISC"
},
@@ -4423,9 +4378,9 @@
}
},
"node_modules/fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -4447,6 +4402,19 @@
"node": "6.* || 8.* || >= 10.*"
}
},
+ "node_modules/get-east-asian-width": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz",
+ "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/get-tsconfig": {
"version": "5.0.0-beta.4",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.4.tgz",
@@ -4501,94 +4469,17 @@
"uncrypto": "^0.1.3"
}
},
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/hast-util-from-html": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
- "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==",
+ "node_modules/hashery": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz",
+ "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/hast": "^3.0.0",
- "devlop": "^1.1.0",
- "hast-util-from-parse5": "^8.0.0",
- "parse5": "^7.0.0",
- "vfile": "^6.0.0",
- "vfile-message": "^4.0.0"
+ "hookified": "^1.15.0"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html/node_modules/entities": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
- "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
- "dev": true,
- "license": "BSD-2-Clause",
"engines": {
- "node": ">=0.12"
- },
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
- "node_modules/hast-util-from-html/node_modules/parse5": {
- "version": "7.3.0",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
- "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "entities": "^6.0.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
- }
- },
- "node_modules/hast-util-from-parse5": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
- "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/hast": "^3.0.0",
- "@types/unist": "^3.0.0",
- "devlop": "^1.0.0",
- "hastscript": "^9.0.0",
- "property-information": "^7.0.0",
- "vfile": "^6.0.0",
- "vfile-location": "^5.0.0",
- "web-namespaces": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-parse-selector": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz",
- "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/hast": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
+ "node": ">=20"
}
},
"node_modules/hast-util-to-html": {
@@ -4629,23 +4520,12 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/hastscript": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz",
- "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==",
+ "node_modules/hookified": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz",
+ "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/hast": "^3.0.0",
- "comma-separated-tokens": "^2.0.0",
- "hast-util-parse-selector": "^4.0.0",
- "property-information": "^7.0.0",
- "space-separated-tokens": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
+ "license": "MIT"
},
"node_modules/html-escaper": {
"version": "3.0.3",
@@ -4666,9 +4546,9 @@
}
},
"node_modules/http-cache-semantics": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
- "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.3.0.tgz",
+ "integrity": "sha512-M5t5LlJpS1UHMjvwRQVdFHvPISGeLAxNcrWuJkeGh0KxsqCHZ1O3NXZU/8x7cD0BDcGW8kapxMKTvwlqrNkHkA==",
"dev": true,
"license": "BSD-2-Clause"
},
@@ -4728,16 +4608,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -4771,52 +4641,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/istanbul-lib-coverage": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
- "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/istanbul-lib-report": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
- "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "istanbul-lib-coverage": "^3.0.0",
- "make-dir": "^4.0.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/istanbul-reports": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
- "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "html-escaper": "^2.0.0",
- "istanbul-lib-report": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/istanbul-reports/node_modules/html-escaper": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
- "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/js-tokens": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz",
@@ -4825,9 +4649,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
- "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz",
+ "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==",
"dev": true,
"funding": [
{
@@ -4847,13 +4671,6 @@
"js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -4876,13 +4693,13 @@
"license": "MIT"
},
"node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz",
+ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "json-buffer": "3.0.1"
+ "@keyv/serialize": "^1.1.1"
}
},
"node_modules/kleur": {
@@ -5209,9 +5026,9 @@
}
},
"node_modules/magic-string": {
- "version": "0.30.21",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
- "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.2.3.tgz",
+ "integrity": "sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5219,33 +5036,17 @@
}
},
"node_modules/magicast": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz",
- "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==",
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.4.tgz",
+ "integrity": "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.29.3",
- "@babel/types": "^7.29.0",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7",
"source-map-js": "^1.2.1"
}
},
- "node_modules/make-dir": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
- "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "semver": "^7.5.3"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/mdast-util-to-hast": {
"version": "13.2.1",
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
@@ -5370,12 +5171,12 @@
"license": "MIT"
},
"node_modules/minimatch": {
- "version": "10.2.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
- "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "version": "10.2.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz",
+ "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==",
"license": "BlueOak-1.0.0",
"dependencies": {
- "brace-expansion": "^5.0.5"
+ "brace-expansion": "^5.0.8"
},
"engines": {
"node": "18 || 20 || >=22"
@@ -5408,9 +5209,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
- "version": "3.3.16",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz",
- "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==",
+ "version": "3.3.18",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
+ "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"dev": true,
"funding": [
{
@@ -5465,9 +5266,9 @@
"license": "MIT"
},
"node_modules/node-mock-http": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz",
- "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.5.tgz",
+ "integrity": "sha512-KQyt/wLjG3TAc7DOUhpqWzgd4ERxR80JOlTK5VE5R1S12IaPVN5qkj4klBce9HPG1Njuup4Sb5bljaT34lIyjw==",
"dev": true,
"license": "MIT"
},
@@ -5521,9 +5322,9 @@
}
},
"node_modules/ohash": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
- "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==",
+ "version": "2.0.12",
+ "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.12.tgz",
+ "integrity": "sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==",
"dev": true,
"license": "MIT"
},
@@ -5565,9 +5366,9 @@
}
},
"node_modules/p-limit": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.1.tgz",
- "integrity": "sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q==",
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.2.tgz",
+ "integrity": "sha512-Ll0w3fU24vYpXoZmjjZIee6bJQDgG0oAyo1PdmFYI8UDwJJddaHAypxIH9avUu+t+lSsAwKVsb1jDCMIIChliw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5701,13 +5502,6 @@
"node": ">=8"
}
},
- "node_modules/pathe": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
- "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/piccolore": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz",
@@ -5723,9 +5517,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
- "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5736,28 +5530,25 @@
}
},
"node_modules/playwright": {
- "version": "1.62.0",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.0.tgz",
- "integrity": "sha512-Z14dG305dgaLu6foB1TXQagFiW8JfSUIUaUuPaKQ6NtBPKF1P/qXcqfh6c6K/icPqdy37JmjbiBXf6JNg6Sylw==",
+ "version": "1.63.0",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz",
+ "integrity": "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright-core": "1.62.0"
+ "playwright-core": "1.63.0"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=20"
- },
- "optionalDependencies": {
- "fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
- "version": "1.62.0",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.0.tgz",
- "integrity": "sha512-nsNRyq0r2zsG8AcRHWknc9QRA5XCueC7gWMrs+Gx2tlZn9hcl8zudfh00lhJPY1DE7NmZ6bDsT9g2yey8mXljA==",
+ "version": "1.63.0",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.63.0.tgz",
+ "integrity": "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -5768,9 +5559,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.22",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.22.tgz",
- "integrity": "sha512-KBDEIpLrvpv16pp3K0Fw+UCoZfopFjjgeB+0tA/aaThfEE74kKDLrgg603YvOWJyg3+WYtyq3xYsQWsIyZlPqQ==",
+ "version": "8.5.28",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",
+ "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",
"dev": true,
"funding": [
{
@@ -5788,7 +5579,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.16",
+ "nanoid": "^3.3.18",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -5878,6 +5669,26 @@
"node": ">=6"
}
},
+ "node_modules/qified": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz",
+ "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/qified/node_modules/hookified": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz",
+ "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/radix3": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz",
@@ -5933,16 +5744,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@@ -5980,13 +5781,13 @@
}
},
"node_modules/rolldown": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz",
- "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.7.tgz",
+ "integrity": "sha512-g0EtLvBjTUB7jhyV0S/TCup3v/XSVl45vUIGbOGU4QPiyjTenCe4mKuFvW9fEgYmS2Fo42AUssRmNuMziXdrig==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@oxc-project/types": "=0.139.0",
+ "@oxc-project/types": "=0.148.0",
"@rolldown/pluginutils": "^1.0.0"
},
"bin": {
@@ -5996,21 +5797,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
- "@rolldown/binding-android-arm64": "1.1.5",
- "@rolldown/binding-darwin-arm64": "1.1.5",
- "@rolldown/binding-darwin-x64": "1.1.5",
- "@rolldown/binding-freebsd-x64": "1.1.5",
- "@rolldown/binding-linux-arm-gnueabihf": "1.1.5",
- "@rolldown/binding-linux-arm64-gnu": "1.1.5",
- "@rolldown/binding-linux-arm64-musl": "1.1.5",
- "@rolldown/binding-linux-ppc64-gnu": "1.1.5",
- "@rolldown/binding-linux-s390x-gnu": "1.1.5",
- "@rolldown/binding-linux-x64-gnu": "1.1.5",
- "@rolldown/binding-linux-x64-musl": "1.1.5",
- "@rolldown/binding-openharmony-arm64": "1.1.5",
- "@rolldown/binding-wasm32-wasi": "1.1.5",
- "@rolldown/binding-win32-arm64-msvc": "1.1.5",
- "@rolldown/binding-win32-x64-msvc": "1.1.5"
+ "@rolldown/binding-android-arm-eabi": "1.2.7",
+ "@rolldown/binding-android-arm64": "1.2.7",
+ "@rolldown/binding-darwin-arm64": "1.2.7",
+ "@rolldown/binding-darwin-x64": "1.2.7",
+ "@rolldown/binding-freebsd-x64": "1.2.7",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.7",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.7",
+ "@rolldown/binding-linux-arm64-musl": "1.2.7",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.7",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.7",
+ "@rolldown/binding-linux-x64-gnu": "1.2.7",
+ "@rolldown/binding-linux-x64-musl": "1.2.7",
+ "@rolldown/binding-openharmony-arm64": "1.2.7",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.7",
+ "@rolldown/binding-win32-x64-msvc": "1.2.7"
}
},
"node_modules/s.color": {
@@ -6031,33 +5832,33 @@
}
},
"node_modules/satteri": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/satteri/-/satteri-0.9.5.tgz",
- "integrity": "sha512-ZuWVl+vnM64y+/TtX8Kosv2c00W+hLQiiwnEL6H0UKVVrxFqMw4D2CJHHQaouVd89OAhtBBfjWLqhKi3TVUV4w==",
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/satteri/-/satteri-0.10.5.tgz",
+ "integrity": "sha512-Ao1LKpAEa9Wdg0otgbVKViZHEq9ebdXe4DMrp3s9vQAU0HNIuHnFEuMuOcm0ZIXyV0Yzxj91NvhLpvXZJO/5ZQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree-jsx": "^1.0.5",
- "@types/hast": "^3.0.4",
+ "@types/hast": "^3.0.5",
"@types/mdast": "^4.0.4",
"@types/unist": "^3.0.3"
},
"optionalDependencies": {
- "@bruits/satteri-darwin-arm64": "0.9.5",
- "@bruits/satteri-darwin-x64": "0.9.5",
- "@bruits/satteri-linux-arm64-gnu": "0.9.5",
- "@bruits/satteri-linux-arm64-musl": "0.9.5",
- "@bruits/satteri-linux-x64-gnu": "0.9.5",
- "@bruits/satteri-linux-x64-musl": "0.9.5",
- "@bruits/satteri-wasm32-wasi": "0.9.5",
- "@bruits/satteri-win32-arm64-msvc": "0.9.5",
- "@bruits/satteri-win32-x64-msvc": "0.9.5"
+ "@bruits/satteri-darwin-arm64": "0.10.5",
+ "@bruits/satteri-darwin-x64": "0.10.5",
+ "@bruits/satteri-linux-arm64-gnu": "0.10.5",
+ "@bruits/satteri-linux-arm64-musl": "0.10.5",
+ "@bruits/satteri-linux-x64-gnu": "0.10.5",
+ "@bruits/satteri-linux-x64-musl": "0.10.5",
+ "@bruits/satteri-wasm32-wasi": "0.10.5",
+ "@bruits/satteri-win32-arm64-msvc": "0.10.5",
+ "@bruits/satteri-win32-x64-msvc": "0.10.5"
}
},
"node_modules/sax": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
- "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==",
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz",
+ "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
@@ -6078,9 +5879,9 @@
}
},
"node_modules/sharp": {
- "version": "0.35.3",
- "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz",
- "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==",
+ "version": "0.35.4",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz",
+ "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
@@ -6096,31 +5897,31 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-darwin-arm64": "0.35.3",
- "@img/sharp-darwin-x64": "0.35.3",
- "@img/sharp-freebsd-wasm32": "0.35.3",
- "@img/sharp-libvips-darwin-arm64": "1.3.2",
- "@img/sharp-libvips-darwin-x64": "1.3.2",
- "@img/sharp-libvips-linux-arm": "1.3.2",
- "@img/sharp-libvips-linux-arm64": "1.3.2",
- "@img/sharp-libvips-linux-ppc64": "1.3.2",
- "@img/sharp-libvips-linux-riscv64": "1.3.2",
- "@img/sharp-libvips-linux-s390x": "1.3.2",
- "@img/sharp-libvips-linux-x64": "1.3.2",
- "@img/sharp-libvips-linuxmusl-arm64": "1.3.2",
- "@img/sharp-libvips-linuxmusl-x64": "1.3.2",
- "@img/sharp-linux-arm": "0.35.3",
- "@img/sharp-linux-arm64": "0.35.3",
- "@img/sharp-linux-ppc64": "0.35.3",
- "@img/sharp-linux-riscv64": "0.35.3",
- "@img/sharp-linux-s390x": "0.35.3",
- "@img/sharp-linux-x64": "0.35.3",
- "@img/sharp-linuxmusl-arm64": "0.35.3",
- "@img/sharp-linuxmusl-x64": "0.35.3",
- "@img/sharp-webcontainers-wasm32": "0.35.3",
- "@img/sharp-win32-arm64": "0.35.3",
- "@img/sharp-win32-ia32": "0.35.3",
- "@img/sharp-win32-x64": "0.35.3"
+ "@img/sharp-darwin-arm64": "0.35.4",
+ "@img/sharp-darwin-x64": "0.35.4",
+ "@img/sharp-freebsd-wasm32": "0.35.4",
+ "@img/sharp-libvips-darwin-arm64": "1.3.3",
+ "@img/sharp-libvips-darwin-x64": "1.3.3",
+ "@img/sharp-libvips-linux-arm": "1.3.3",
+ "@img/sharp-libvips-linux-arm64": "1.3.3",
+ "@img/sharp-libvips-linux-ppc64": "1.3.3",
+ "@img/sharp-libvips-linux-riscv64": "1.3.3",
+ "@img/sharp-libvips-linux-s390x": "1.3.3",
+ "@img/sharp-libvips-linux-x64": "1.3.3",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.3",
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.3",
+ "@img/sharp-linux-arm": "0.35.4",
+ "@img/sharp-linux-arm64": "0.35.4",
+ "@img/sharp-linux-ppc64": "0.35.4",
+ "@img/sharp-linux-riscv64": "0.35.4",
+ "@img/sharp-linux-s390x": "0.35.4",
+ "@img/sharp-linux-x64": "0.35.4",
+ "@img/sharp-linuxmusl-arm64": "0.35.4",
+ "@img/sharp-linuxmusl-x64": "0.35.4",
+ "@img/sharp-webcontainers-wasm32": "0.35.4",
+ "@img/sharp-win32-arm64": "0.35.4",
+ "@img/sharp-win32-ia32": "0.35.4",
+ "@img/sharp-win32-x64": "0.35.4"
},
"peerDependenciesMeta": {
"@types/node": {
@@ -6152,20 +5953,20 @@
}
},
"node_modules/shiki": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.3.1.tgz",
- "integrity": "sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.4.3.tgz",
+ "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@shikijs/core": "4.3.1",
- "@shikijs/engine-javascript": "4.3.1",
- "@shikijs/engine-oniguruma": "4.3.1",
- "@shikijs/langs": "4.3.1",
- "@shikijs/themes": "4.3.1",
- "@shikijs/types": "4.3.1",
+ "@shikijs/core": "4.4.3",
+ "@shikijs/engine-javascript": "4.4.3",
+ "@shikijs/engine-oniguruma": "4.4.3",
+ "@shikijs/langs": "4.4.3",
+ "@shikijs/themes": "4.4.3",
+ "@shikijs/types": "4.4.3",
"@shikijs/vscode-textmate": "^10.0.2",
- "@types/hast": "^3.0.4"
+ "@types/hast": "^3.0.5"
},
"engines": {
"node": ">=20"
@@ -6206,9 +6007,9 @@
}
},
"node_modules/smol-toml": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.7.0.tgz",
- "integrity": "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==",
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz",
+ "integrity": "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
@@ -6253,26 +6054,21 @@
"dev": true,
"license": "MIT"
},
- "node_modules/stream-replace-string": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz",
- "integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "version": "8.2.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz",
+ "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
+ "get-east-asian-width": "^1.5.0",
+ "strip-ansi": "^7.1.2"
},
"engines": {
- "node": ">=8"
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/stringify-entities": {
@@ -6291,16 +6087,19 @@
}
},
"node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
+ "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ansi-regex": "^5.0.1"
+ "ansi-regex": "^6.2.2"
},
"engines": {
- "node": ">=8"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/suf-log": {
@@ -6313,33 +6112,20 @@
"s.color": "0.0.15"
}
},
- "node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/svgo": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.2.tgz",
- "integrity": "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.1.0.tgz",
+ "integrity": "sha512-bkxnTg1kSU0guhIBmibA6UUhrQmPVA1XsQLN+ylCd+UWzbnLkySOcXpyk1mrl05f+pcaCx2eHb+sp6BgMZWX+Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"commander": "^11.1.0",
- "css-select": "^5.1.0",
+ "css-select": "^6.0.0",
"css-tree": "^3.0.1",
- "css-what": "^6.1.0",
+ "css-what": "^7.0.0",
"csso": "^5.0.5",
"picocolors": "^1.1.1",
- "sax": "^1.5.0"
+ "sax": "1.6.1"
},
"bin": {
"svgo": "bin/svgo.js"
@@ -6360,11 +6146,14 @@
"license": "MIT"
},
"node_modules/tinybench": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
- "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.1.4.tgz",
+ "integrity": "sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.0.0"
+ }
},
"node_modules/tinyclip": {
"version": "0.1.15",
@@ -6377,9 +6166,9 @@
}
},
"node_modules/tinyexec": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz",
- "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz",
+ "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -6404,9 +6193,9 @@
}
},
"node_modules/tinyrainbow": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz",
- "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz",
+ "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -6457,9 +6246,9 @@
"optional": true
},
"node_modules/tsx": {
- "version": "4.23.1",
- "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.1.tgz",
- "integrity": "sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==",
+ "version": "4.23.13",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.13.tgz",
+ "integrity": "sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6475,21 +6264,6 @@
"fsevents": "~2.3.3"
}
},
- "node_modules/tsx/node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
"node_modules/tuf-js": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-6.0.0.tgz",
@@ -6549,16 +6323,16 @@
}
},
"node_modules/typescript-eslint": {
- "version": "8.65.0",
- "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.65.0.tgz",
- "integrity": "sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==",
+ "version": "8.69.0",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.69.0.tgz",
+ "integrity": "sha512-B3MltX0VqjUBNEe3b3sSuiRbfa6XrfHFtBiPamjT5AsW/dfq+y+bc0wyuS9DxAS1LyzCxRp2+rxzpLUvqM2BvA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/eslint-plugin": "8.65.0",
- "@typescript-eslint/parser": "8.65.0",
- "@typescript-eslint/typescript-estree": "8.65.0",
- "@typescript-eslint/utils": "8.65.0"
+ "@typescript-eslint/eslint-plugin": "8.69.0",
+ "@typescript-eslint/parser": "8.69.0",
+ "@typescript-eslint/typescript-estree": "8.69.0",
+ "@typescript-eslint/utils": "8.69.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6593,6 +6367,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/undici": {
+ "version": "8.10.2",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.2.tgz",
+ "integrity": "sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=22.19.0"
+ }
+ },
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
@@ -6621,15 +6405,15 @@
}
},
"node_modules/unifont": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.4.tgz",
- "integrity": "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==",
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.5.tgz",
+ "integrity": "sha512-ULe/Cs+ZIsq+dcFofNkhqielCrUJnb5mr+Yc4EBM2VlL+6OZR6+cjtI2mT1bJvRBrVncqHAbLURxmPLcCXzWMg==",
"dev": true,
"license": "MIT",
"dependencies": {
"css-tree": "^3.1.0",
- "ofetch": "^1.5.1",
- "ohash": "^2.0.11"
+ "ohash": "^2.0.11",
+ "undici": "^8.0.0"
}
},
"node_modules/unist-util-is": {
@@ -6819,9 +6603,9 @@
}
},
"node_modules/unstorage/node_modules/readdirp": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
- "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz",
+ "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -6857,21 +6641,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/vfile-location": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz",
- "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/unist": "^3.0.0",
- "vfile": "^6.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/vfile-message": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
@@ -6888,16 +6657,16 @@
}
},
"node_modules/vite": {
- "version": "8.1.5",
- "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz",
- "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==",
+ "version": "8.2.2",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz",
+ "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "lightningcss": "^1.32.0",
+ "lightningcss": "^1.33.0",
"picomatch": "^4.0.5",
- "postcss": "^8.5.17",
- "rolldown": "~1.1.5",
+ "postcss": "^8.5.26",
+ "rolldown": "~1.2.4",
"tinyglobby": "^0.2.17"
},
"bin": {
@@ -6914,7 +6683,7 @@
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
- "@vitejs/devtools": "^0.3.0",
+ "@vitejs/devtools": "^0.4.0 || ^0.5.0",
"esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
@@ -6965,21 +6734,6 @@
}
}
},
- "node_modules/vite/node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
"node_modules/vitefu": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz",
@@ -7001,38 +6755,31 @@
}
},
"node_modules/vitest": {
- "version": "4.1.10",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz",
- "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.0.tgz",
+ "integrity": "sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/expect": "4.1.10",
- "@vitest/mocker": "4.1.10",
- "@vitest/pretty-format": "4.1.10",
- "@vitest/runner": "4.1.10",
- "@vitest/snapshot": "4.1.10",
- "@vitest/spy": "4.1.10",
- "@vitest/utils": "4.1.10",
- "es-module-lexer": "^2.0.0",
- "expect-type": "^1.3.0",
- "magic-string": "^0.30.21",
- "obug": "^2.1.1",
- "pathe": "^2.0.3",
- "picomatch": "^4.0.3",
- "std-env": "^4.0.0-rc.1",
- "tinybench": "^2.9.0",
- "tinyexec": "^1.0.2",
- "tinyglobby": "^0.2.15",
- "tinyrainbow": "^3.1.0",
- "vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
+ "@types/chai": "^5.2.2",
+ "@vitest/mocker": "5.0.0",
+ "chai": "^6.2.2",
+ "es-module-lexer": "^2.3.2",
+ "expect-type": "^1.4.0",
+ "magic-string": "^1.2.3",
+ "obug": "^2.1.4",
+ "picomatch": "^4.0.7",
+ "std-env": "^4.2.0",
+ "tinybench": "6.1.4",
+ "tinyexec": "1.3.0",
+ "tinyglobby": "^0.2.17",
"why-is-node-running": "^2.3.0"
},
"bin": {
"vitest": "vitest.mjs"
},
"engines": {
- "node": "^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^22.12.0 || ^24.0.0 || >=26.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
@@ -7040,16 +6787,16 @@
"peerDependencies": {
"@edge-runtime/vm": "*",
"@opentelemetry/api": "^1.9.0",
- "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
- "@vitest/browser-playwright": "4.1.10",
- "@vitest/browser-preview": "4.1.10",
- "@vitest/browser-webdriverio": "4.1.10",
- "@vitest/coverage-istanbul": "4.1.10",
- "@vitest/coverage-v8": "4.1.10",
- "@vitest/ui": "4.1.10",
+ "@types/node": "^22.0.0 || >=24.0.0",
+ "@vitest/browser-playwright": "5.0.0",
+ "@vitest/browser-preview": "5.0.0",
+ "@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0",
+ "@vitest/coverage-istanbul": "5.0.0",
+ "@vitest/coverage-v8": "5.0.0",
+ "@vitest/ui": "5.0.0",
"happy-dom": "*",
"jsdom": "*",
- "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ "vite": "^6.4.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"@edge-runtime/vm": {
@@ -7090,6 +6837,16 @@
}
}
},
+ "node_modules/vitest/node_modules/tinyexec": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz",
+ "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/volar-service-css": {
"version": "0.0.71",
"resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.71.tgz",
@@ -7284,9 +7041,9 @@
}
},
"node_modules/vscode-jsonrpc": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-9.0.1.tgz",
- "integrity": "sha512-rfuA6T75H6m5EkbhtEPzre9pT0HPcDI2MMy4+nPFIBks5J8JBAUHD4tRYSgaBOijIEC7SRkC1kKyXTLqbmh9jw==",
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-9.0.2.tgz",
+ "integrity": "sha512-SbQSV9yRemARxeXw6LU5sS6Zq0e9/DgCCX5yelH263ZQWukbTk8EF8fjTrr1dziasf4GwlJbvTwFnTrnQFWZXQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -7307,27 +7064,27 @@
}
},
"node_modules/vscode-languageserver-protocol": {
- "version": "3.18.2",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.18.2.tgz",
- "integrity": "sha512-XRyDbT0Pp3sSNti3JmxVEUMySWCSi1hhM+/KUlCy1hV1zmrqpM1OwO12EAki8blhmLuIMpaJrYbo0OzGVfK2Qg==",
+ "version": "3.18.3",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.18.3.tgz",
+ "integrity": "sha512-DF49+WeV5py4zO5hhobp60jjsDSK0lAqA0OuKBLBvp423HPWQcCbhZz3JgyfIewsEz2f8U+X75xNIFHdiXZm2w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "vscode-jsonrpc": "9.0.1",
- "vscode-languageserver-types": "3.18.0"
+ "vscode-jsonrpc": "9.0.2",
+ "vscode-languageserver-types": "3.18.3"
}
},
"node_modules/vscode-languageserver-textdocument": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz",
- "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==",
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.14.tgz",
+ "integrity": "sha512-EQyqJMi552E4ZTf46izQ4Fj6XquqxCySR3J5ZSD1SisMf6RfpeOWHxGBE8Gr6V0/3GHIGdAzDn8F8+1nTGCnoQ==",
"dev": true,
"license": "MIT"
},
"node_modules/vscode-languageserver-types": {
- "version": "3.18.0",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.0.tgz",
- "integrity": "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g==",
+ "version": "3.18.3",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.3.tgz",
+ "integrity": "sha512-XIlzJ7Qp/jzSI1ds7/FwPAWrPeTZA7pAtlW4hdJ1J6xXWJL6dR9QYnDhJOdLzdKhUQ5Mm6mvUMw+3DcOQQasPw==",
"dev": true,
"license": "MIT"
},
@@ -7367,29 +7124,18 @@
"license": "MIT"
},
"node_modules/vscode-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
- "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.2.0.tgz",
+ "integrity": "sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==",
"dev": true,
"license": "MIT"
},
"node_modules/web-features": {
- "version": "3.34.2",
- "resolved": "https://registry.npmjs.org/web-features/-/web-features-3.34.2.tgz",
- "integrity": "sha512-1/prthzNwl/ITxBgFuKUCJ1ezWxZDM8rhz/VIBCD6zMEv5STMDQxgf05IfYxmJvFBTTLONaTDUk7umPkhUHmpw==",
+ "version": "3.40.1",
+ "resolved": "https://registry.npmjs.org/web-features/-/web-features-3.40.1.tgz",
+ "integrity": "sha512-HRdUYqZRNawtIEI39iKjk6E6g1yO/bct/8bFcD/O+bNGYsbG475PV80+HTrpkYOiZnoEaVSMu5Q/LTVwnBH5ag==",
"license": "Apache-2.0"
},
- "node_modules/web-namespaces": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
- "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -7434,23 +7180,41 @@
}
},
"node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz",
+ "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/wrap-ansi/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/xxhash-wasm": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz",
@@ -7581,22 +7345,21 @@
}
},
"node_modules/yargs": {
- "version": "17.7.3",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
- "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
+ "version": "18.1.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.1.0.tgz",
+ "integrity": "sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "cliui": "^8.0.1",
+ "cliui": "^9.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
+ "string-width": "^8.2.1",
"y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
+ "yargs-parser": "^22.0.0"
},
"engines": {
- "node": ">=12"
+ "node": "^20.19.0 || ^22.12.0 || >=23"
}
},
"node_modules/yargs-parser": {
@@ -7609,16 +7372,6 @@
"node": "^20.19.0 || ^22.12.0 || >=23"
}
},
- "node_modules/yargs/node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/yocto-queue": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz",
@@ -7633,9 +7386,9 @@
}
},
"node_modules/zod": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
- "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.5.4.tgz",
+ "integrity": "sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
diff --git a/package.json b/package.json
index 54a9d75..3193538 100644
--- a/package.json
+++ b/package.json
@@ -37,34 +37,34 @@
"verify": "npm run lint && npm run format:check && npm run typecheck && npm run check && npm test && npm run audit:repository && npm run build && npm run audit:public && npm run audit:language"
},
"dependencies": {
- "@mdn/browser-compat-data": "8.0.8",
+ "@mdn/browser-compat-data": "8.1.4",
"@sigstore/bundle": "5.0.0",
- "@sigstore/protobuf-specs": "0.5.1",
+ "@sigstore/protobuf-specs": "0.5.2",
"@sigstore/tuf": "5.0.0",
- "@sigstore/verify": "4.1.0",
+ "@sigstore/verify": "4.1.2",
"parse5": "8.0.1",
- "web-features": "3.34.2",
- "zod": "4.4.3"
+ "web-features": "3.40.1",
+ "zod": "4.5.4"
},
"devDependencies": {
- "@astrojs/check": "0.9.9",
- "@astrojs/sitemap": "3.7.3",
- "@axe-core/playwright": "4.12.1",
+ "@astrojs/check": "0.9.10",
+ "@astrojs/sitemap": "3.7.4",
+ "@axe-core/playwright": "4.13.0",
"@eslint/js": "10.0.1",
- "@playwright/test": "1.62.0",
+ "@playwright/test": "1.63.0",
"@types/node": "24.13.3",
- "@vitest/coverage-v8": "4.1.10",
- "astro": "7.1.3",
- "eslint": "10.8.0",
+ "@vitest/coverage-v8": "5.0.0",
+ "astro": "7.3.1",
+ "eslint": "10.10.0",
"prettier": "3.9.6",
"prettier-plugin-astro": "0.14.1",
- "tsx": "4.23.1",
+ "tsx": "4.23.13",
"typescript": "6.0.3",
- "typescript-eslint": "8.65.0",
- "vitest": "4.1.10"
+ "typescript-eslint": "8.69.0",
+ "vitest": "5.0.0"
},
"allowScripts": {
- "esbuild@0.28.1": true,
+ "esbuild@0.28.2": true,
"fsevents@2.3.2": false,
"fsevents@2.3.3": false
}
diff --git a/playwright.config.ts b/playwright.config.ts
index cb4b2fd..7934ac7 100644
--- a/playwright.config.ts
+++ b/playwright.config.ts
@@ -1,14 +1,20 @@
import { defineConfig, devices } from "@playwright/test";
+const crossEngineSmoke = process.env.CONTROLCURRENT_BROWSER_SMOKE === "1";
+const fixtureOrigin = `${crossEngineSmoke ? "https" : "http"}://127.0.0.1:4389`;
+
export default defineConfig({
testDir: "e2e",
fullyParallel: false,
forbidOnly: Boolean(process.env.CI),
retries: process.env.CI ? 1 : 0,
- ...(process.env.CI ? { workers: 1 } : {}),
+ ...(process.env.CI || crossEngineSmoke ? { workers: 1 } : {}),
reporter: [["line"]],
use: {
- baseURL: "http://127.0.0.1:4389",
+ baseURL: fixtureOrigin,
+ // Context-wide test-only bypass for the disposable loopback certificate;
+ // this does not verify production TLS or pin a particular certificate.
+ ignoreHTTPSErrors: crossEngineSmoke,
trace: "retain-on-failure",
screenshot: "only-on-failure"
},
@@ -16,11 +22,18 @@ export default defineConfig({
{
name: "chromium",
use: { ...devices["Desktop Chrome"] }
- }
+ },
+ ...(crossEngineSmoke
+ ? [
+ { name: "firefox", use: { ...devices["Desktop Firefox"] }, grep: /@smoke/u },
+ { name: "webkit", use: { ...devices["Desktop Safari"] }, grep: /@smoke/u }
+ ]
+ : [])
],
webServer: {
- command: "npm run build && tsx tools/serve-dist.ts",
- url: "http://127.0.0.1:4389",
+ command: `npm run build && tsx tools/serve-dist.ts${crossEngineSmoke ? " --https-fixture" : ""}`,
+ url: fixtureOrigin,
+ ignoreHTTPSErrors: crossEngineSmoke,
reuseExistingServer: false,
timeout: 60_000
}
diff --git a/public/schemas/browser-policy-evaluation.schema.json b/public/schemas/browser-policy-evaluation.schema.json
index 0396220..aa8048e 100644
--- a/public/schemas/browser-policy-evaluation.schema.json
+++ b/public/schemas/browser-policy-evaluation.schema.json
@@ -6,7 +6,7 @@
"properties": {
"bcdTimestamp": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"bcdVersion": {
diff --git a/public/schemas/decision-packet.schema.json b/public/schemas/decision-packet.schema.json
index 778db4f..8397a06 100644
--- a/public/schemas/decision-packet.schema.json
+++ b/public/schemas/decision-packet.schema.json
@@ -12,7 +12,7 @@
"properties": {
"bcdTimestamp": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"bcdVersion": {
@@ -757,7 +757,7 @@
"properties": {
"completedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"producer": {
@@ -783,7 +783,7 @@
},
"startedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
}
},
@@ -835,7 +835,7 @@
},
"bcdTimestamp": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"bcdVersion": {
@@ -1304,7 +1304,7 @@
},
"generatedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"includedEntries": {
@@ -2358,7 +2358,7 @@
"properties": {
"completedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"producer": {
@@ -2384,7 +2384,7 @@
},
"startedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
}
},
@@ -2431,7 +2431,7 @@
},
"bcdTimestamp": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"bcdVersion": {
@@ -2499,7 +2499,7 @@
},
"generatedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"includedEntries": {
diff --git a/public/schemas/evidence-policy-evaluation.schema.json b/public/schemas/evidence-policy-evaluation.schema.json
index c374026..f5c8538 100644
--- a/public/schemas/evidence-policy-evaluation.schema.json
+++ b/public/schemas/evidence-policy-evaluation.schema.json
@@ -488,7 +488,7 @@
"properties": {
"completedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"producer": {
@@ -514,7 +514,7 @@
},
"startedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
}
},
@@ -561,7 +561,7 @@
},
"bcdTimestamp": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"bcdVersion": {
@@ -629,7 +629,7 @@
},
"generatedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"includedEntries": {
diff --git a/public/schemas/reduced-evidence-report.schema.json b/public/schemas/reduced-evidence-report.schema.json
index 7e04f37..45965f1 100644
--- a/public/schemas/reduced-evidence-report.schema.json
+++ b/public/schemas/reduced-evidence-report.schema.json
@@ -446,7 +446,7 @@
"properties": {
"completedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"producer": {
@@ -472,7 +472,7 @@
},
"startedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
}
},
@@ -524,7 +524,7 @@
},
"bcdTimestamp": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"bcdVersion": {
@@ -993,7 +993,7 @@
},
"generatedAt": {
"format": "date-time",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
"type": "string"
},
"includedEntries": {
diff --git a/src/assurance.ts b/src/assurance.ts
index 3a006d8..f74e19c 100644
--- a/src/assurance.ts
+++ b/src/assurance.ts
@@ -216,7 +216,12 @@ function cspDirectiveFinding(
);
}
const present =
- enforced.state === "present" && enforced.policies.some((policy) => policy.has(directive));
+ enforced.state === "present" &&
+ enforced.policies.some((policy) =>
+ directive === "base-uri"
+ ? ["'none'", "'self'"].includes((policy.get(directive) ?? []).join(" "))
+ : policy.has(directive)
+ );
const reported =
reportOnly.state === "present" && reportOnly.policies.some((policy) => policy.has(directive));
return finding(
@@ -264,6 +269,60 @@ export function cspElementTokens(policy: CspPolicy, kind: "script" | "style"): s
return directive ? (policy.get(directive) ?? []) : [];
}
+/** Count effective broad allowances, respecting CSP3 ignored source expressions. */
+export function effectiveCspBroadSourceCount(
+ tokens: readonly string[],
+ kind: "script" | "style"
+): number {
+ const authorisation = tokens.some(
+ (token) =>
+ parseCspNonceSource(token).state === "valid" || parseCspHashSource(token).metadata.length > 0
+ );
+ const dynamic = kind === "script" && authorisation && tokens.includes("'strict-dynamic'");
+ return tokens.filter((token) => {
+ const lower = token.toLowerCase();
+ if (["'unsafe-eval'", "'wasm-unsafe-eval'"].includes(lower)) return true;
+ if (lower === "'unsafe-inline'") return !authorisation;
+ const location = lower === "*" || lower === "'self'" || !lower.startsWith("'");
+ return location && !dynamic;
+ }).length;
+}
+
+export function scriptCspCandidate(snapshotInput: unknown): "satisfied" | "gap" | "review" {
+ const { enforced } = extractCspEvidence(snapshotInput);
+ if (enforced.state === "invalid") return "review";
+ if (enforced.state !== "present") return "gap";
+ if (enforced.policies.length !== 1) return "review";
+ const policy = enforced.policies[0];
+ if (!policy || !["'none'", "'self'"].includes((policy.get("base-uri") ?? []).join(" ")))
+ return "gap";
+ // Both the element override and the general script list must meet this declaration recipe.
+ const lists = effectiveDirectiveTokens(policy, SCRIPT_SOURCE_CHAINS);
+ if (lists.length !== SCRIPT_SOURCE_CHAINS.length) return "gap";
+ for (const tokens of lists) {
+ if (
+ !tokens.some(
+ (token) =>
+ parseCspNonceSource(token).state === "valid" ||
+ parseCspHashSource(token).metadata.length > 0
+ )
+ )
+ return "gap";
+ if (
+ tokens.some(
+ (token) =>
+ ["invalid", "short"].includes(parseCspNonceSource(token).state) ||
+ parseCspHashSource(token).invalidSupportedTokenCount > 0
+ )
+ )
+ return "review";
+ if (effectiveCspBroadSourceCount(tokens, "script") > 0) return "gap";
+ }
+ const attributes = policy.get("script-src-attr");
+ if (attributes && effectiveCspBroadSourceCount(attributes, "script") > 0) return "gap";
+ return "satisfied";
+}
+
function cspHasToken(
result: CspParseResult,
chains: readonly (readonly string[])[],
diff --git a/src/catalogue.ts b/src/catalogue.ts
index 027d052..9714a3d 100644
--- a/src/catalogue.ts
+++ b/src/catalogue.ts
@@ -64,7 +64,7 @@ export const SECURITY_CONTROLS = [
"Use a carefully scoped CSP and avoid inline script where a nonce deployment cannot be validated.",
mappingState: "unsupported",
mappingNote:
- "BCD 8.0.8 does not publish a standalone compatibility statement for CSP nonce source expressions.",
+ "BCD 8.1.4 does not publish a standalone compatibility statement for CSP nonce source expressions.",
combination: "all",
bcdPaths: [],
specificationUrls: ["https://w3c.github.io/webappsec-csp/#grammardef-nonce-source"]
@@ -87,7 +87,7 @@ export const SECURITY_CONTROLS = [
"Use nonces or external resources under a restrictive CSP when hash maintenance is unsuitable.",
mappingState: "unsupported",
mappingNote:
- "BCD 8.0.8 does not publish a standalone compatibility statement for CSP hash source expressions.",
+ "BCD 8.1.4 does not publish a standalone compatibility statement for CSP hash source expressions.",
combination: "all",
bcdPaths: [],
specificationUrls: ["https://w3c.github.io/webappsec-csp/#grammardef-hash-source"]
diff --git a/src/ci-output.ts b/src/ci-output.ts
index 233ba09..2b6e90e 100644
--- a/src/ci-output.ts
+++ b/src/ci-output.ts
@@ -53,11 +53,13 @@ function junitSuite(
name: string,
cases: readonly string[],
failures: number,
- skipped: number
+ skipped: number,
+ properties = ""
): string {
return [
'',
``,
+ ...(properties ? [properties] : []),
...cases,
"",
""
@@ -172,6 +174,11 @@ export function renderPolicyDriftMarkdown(input: unknown): string {
`- Review: ${String(comparison.summary.review)}`,
`- Information: ${String(comparison.summary.information)}`,
`- Expiring exceptions: ${String(comparison.summary.expiringExceptions)}`,
+ ...(comparison.summary.truncated
+ ? [
+ `- Displayed events: ${String(comparison.summary.emittedEvents)} of ${String(comparison.summary.totalEvents)}; full totals determine the gate.`
+ ]
+ : []),
"",
...(rows.length
? ["| Classification | Change | Summary |", "| --- | --- | --- |", ...rows]
@@ -190,11 +197,26 @@ export function renderPolicyDriftJunit(input: unknown): string {
item.summary
)
);
+ const visibleFailures = comparison.events.filter((item) => item.severity === "regression").length;
+ const visibleReview = comparison.events.filter((item) => item.severity === "review").length;
+ const hiddenFailures = comparison.summary.regressions - visibleFailures;
+ const hiddenReview = comparison.summary.review - visibleReview;
+ const omitted = comparison.summary.truncated === true;
+ if (omitted)
+ cases.push(
+ junitCase(
+ "Omitted bounded events",
+ "browser policy",
+ hiddenFailures > 0 ? "fail" : hiddenReview > 0 ? "review" : "pass",
+ `${String(hiddenFailures)} adverse and ${String(hiddenReview)} review events were omitted; full totals still determine the gate.`
+ )
+ );
return junitSuite(
`${comparison.beforeProfileName} to ${comparison.afterProfileName}`,
cases,
- comparison.summary.regressions,
- comparison.summary.review
+ visibleFailures + (omitted && hiddenFailures > 0 ? 1 : 0),
+ visibleReview + (omitted && hiddenFailures <= 0 && hiddenReview > 0 ? 1 : 0),
+ ``
);
}
@@ -217,6 +239,12 @@ export function renderDecisionPacketComparisonMarkdown(input: unknown): string {
"",
"## Evidence",
"",
+ ...(comparison.evidence.summary.truncated
+ ? [
+ `Showing ${String(comparison.evidence.summary.emittedEvents)} of ${String(comparison.evidence.summary.totalEvents)} evidence events; the totals and gate include omitted events.`,
+ ""
+ ]
+ : []),
...(comparison.evidence.events.length
? comparison.evidence.events.map(
(item) => `- **${markdown(item.type)}** ${markdown(item.summary)}`
@@ -250,10 +278,36 @@ export function renderDecisionPacketComparisonJunit(input: unknown): string {
item.summary
)
);
+ const visibleFailures =
+ comparison.browserPolicy.events.filter((item) => item.severity === "regression").length +
+ comparison.evidence.events.filter((item) => ["regression", "incomparable"].includes(item.type))
+ .length;
+ const visibleReview =
+ comparison.browserPolicy.events.filter((item) => item.severity === "review").length +
+ comparison.evidence.events.filter((item) => item.type === "changed").length;
+ const hiddenFailures =
+ comparison.summary.regressions + comparison.summary.incomparable - visibleFailures;
+ const hiddenReview =
+ comparison.summary.review + comparison.evidence.summary.changed - visibleReview;
+ const omitted =
+ comparison.evidence.summary.truncated === true ||
+ comparison.browserPolicy.summary.truncated === true;
+ const summaryCases = omitted
+ ? [
+ junitCase(
+ "Omitted bounded events",
+ "decision packet",
+ hiddenFailures > 0 ? "fail" : hiddenReview > 0 ? "review" : "pass",
+ `${String(hiddenFailures)} adverse and ${String(hiddenReview)} review events were omitted from the display. Full totals still determine the gate.`
+ )
+ ]
+ : [];
+ const properties = ``;
return junitSuite(
"decision packet comparison",
- [...policyCases, ...evidenceCases],
- comparison.summary.regressions + comparison.summary.incomparable,
- comparison.summary.review + comparison.summary.changed
+ [...policyCases, ...evidenceCases, ...summaryCases],
+ visibleFailures + (omitted && hiddenFailures > 0 ? 1 : 0),
+ visibleReview + (omitted && hiddenFailures <= 0 && hiddenReview > 0 ? 1 : 0),
+ properties
);
}
diff --git a/src/collector.ts b/src/collector.ts
index ac44bb6..d67b463 100644
--- a/src/collector.ts
+++ b/src/collector.ts
@@ -10,6 +10,12 @@ export const MAX_COLLECTOR_MANIFEST_BYTES = 64 * 1_024;
export const MAX_COLLECTOR_BODY_BYTES = 128 * 1_024;
export const MAX_COLLECTOR_REDIRECTS = 5;
export const COLLECTOR_TIMEOUT_MS = 10_000;
+export const MAX_COLLECTOR_RESPONSES = 16;
+export const MAX_COLLECTOR_TOTAL_HTML_BYTES = 512 * 1_024;
+
+function labelledId(id: string, suffix: string): string {
+ return `${id.slice(0, 80 - suffix.length)}${suffix}`;
+}
const opaqueIdSchema = z.string().regex(/^[a-z0-9][a-z0-9._-]{0,79}$/u);
const pathSchema = z
@@ -100,7 +106,7 @@ export const collectorManifestSchema = z
.optional(),
producerId: opaqueIdSchema,
completeness: z.enum(["complete", "unknown"]),
- surfaces: z.array(collectorSurfaceSchema).min(1).max(32)
+ surfaces: z.array(collectorSurfaceSchema).min(1).max(MAX_COLLECTOR_RESPONSES)
})
.strict()
.superRefine((manifest, context) => {
@@ -154,29 +160,35 @@ export async function collectEvidenceBundle(
const startedAt = clock().toISOString();
const responses: EvidenceBundleInput["responses"] = [];
const htmlDocuments: EvidenceBundleInput["htmlDocuments"] = [];
+ let htmlBytes = 0;
- for (const surface of manifest.surfaces) {
+ for (const [index, surface] of manifest.surfaces.entries()) {
+ // Reserve a response slot for each remaining surface before permitting redirects.
+ const slots =
+ MAX_COLLECTOR_RESPONSES - responses.length - (manifest.surfaces.length - index - 1);
const hops = await transport.collect({
baseOrigin: manifest.baseOrigin,
path: surface.path,
- maximumBodyBytes: MAX_COLLECTOR_BODY_BYTES,
- maximumRedirects: MAX_COLLECTOR_REDIRECTS,
+ maximumBodyBytes: surface.requiredEvidence.includes("html")
+ ? Math.min(MAX_COLLECTOR_BODY_BYTES, MAX_COLLECTOR_TOTAL_HTML_BYTES - htmlBytes)
+ : MAX_COLLECTOR_BODY_BYTES,
+ maximumRedirects: Math.min(MAX_COLLECTOR_REDIRECTS, slots - 1),
timeoutMs: COLLECTOR_TIMEOUT_MS
});
- if (hops.length === 0 || hops.length > MAX_COLLECTOR_REDIRECTS + 1) {
+ if (hops.length === 0 || hops.length > Math.min(MAX_COLLECTOR_REDIRECTS + 1, slots)) {
throw new Error(`Collector returned an invalid hop count for ${surface.id}.`);
}
const redirectChainId = hops.some((hop) => hop.outcome === "redirect")
- ? `${surface.id}-redirect`
+ ? labelledId(surface.id, "-redirect")
: undefined;
for (const [sequence, hop] of hops.entries()) {
responses.push({
schemaVersion: 2,
- name: `${surface.id} response ${String(sequence + 1)}`,
+ name: labelledId(surface.id, ` response ${String(sequence + 1)}`),
surfaceId: surface.id,
context: {
schemaVersion: 1,
- variantId: `${surface.id}-${surface.authentication}`,
+ variantId: labelledId(surface.id, `-${surface.authentication}`),
sequence,
outcome: hop.outcome,
status: hop.status,
@@ -195,9 +207,16 @@ export async function collectEvidenceBundle(
hop.body !== undefined &&
surface.requiredEvidence.includes("html")
) {
+ htmlBytes += new TextEncoder().encode(hop.body).byteLength;
+ if (
+ htmlBytes > MAX_COLLECTOR_TOTAL_HTML_BYTES ||
+ new TextEncoder().encode(hop.body).byteLength > MAX_COLLECTOR_BODY_BYTES
+ ) {
+ throw new Error("Collector HTML budget exhausted; no complete bundle was produced.");
+ }
htmlDocuments.push({
schemaVersion: 1,
- name: `${surface.id} document`,
+ name: labelledId(surface.id, " document"),
surfaceId: surface.id,
html: hop.body
});
@@ -228,7 +247,7 @@ export async function collectEvidenceBundle(
},
scopeInventory: {
schemaVersion: 1,
- name: `${manifest.name} collector scope`,
+ name: labelledId(manifest.name, " collector scope"),
kind: "authorised_crawl",
generatedAt: startedAt,
completeness: manifest.completeness,
diff --git a/src/components/EvidenceBundleInspector.astro b/src/components/EvidenceBundleInspector.astro
index 4a0cdcd..ed92df0 100644
--- a/src/components/EvidenceBundleInspector.astro
+++ b/src/components/EvidenceBundleInspector.astro
@@ -103,6 +103,7 @@ import { selectedSnapshot } from "../data";
`
+ }).finding.state
+ ).toBe("observed");
+ for (const inline of [false, true]) {
+ const tokens = [malformed, ...(inline ? ["'unsafe-inline'"] : [])];
+ expect(effectiveCspBroadSourceCount(tokens, "script")).toBe(inline ? 1 : 0);
+ expect(
+ effectiveCspBroadSourceCount([...tokens, "'strict-dynamic'", "https:"], "script")
+ ).toBe(inline ? 2 : 1);
+ const csp = `script-src ${tokens.join(" ")}; base-uri 'none'`;
+ expect(scriptCspCandidate(snapshot(csp))).toBe("gap");
+ for (const html of [undefined, "", "Fixture"]) {
+ const report = await inspect(csp, html);
+ expect(
+ report.composites.find((item) => item.id === "strict-csp-candidate")?.state
+ ).toBe("gap");
+ const evaluation = await evaluateEvidencePolicy(report, policy, "2026-07-23");
+ expect(
+ evaluation.findings.find(
+ (item) =>
+ item.targetKind === "composite" && item.targetId === "strict-csp-candidate"
+ )
+ ).toMatchObject({ outcome: "gap", decision: "fail" });
+ }
+ }
+ }
+ }
+ );
+
+ it.each([
+ [
+ "malformed default fallback",
+ `default-src 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=?x' 'unsafe-inline'; base-uri 'none'`,
+ "gap"
+ ],
+ [
+ "malformed element override",
+ `script-src ${nonce}; script-src-elem 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=?x' 'unsafe-inline'; base-uri 'none'`,
+ "gap"
+ ],
+ [
+ "malformed general override",
+ `script-src-elem ${nonce}; script-src 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=?x' 'unsafe-inline'; base-uri 'none'`,
+ "gap"
+ ],
+ ["style-only nonce", `style-src ${nonce}; script-src 'unsafe-inline'; base-uri 'none'`, "gap"],
+ [
+ "element override",
+ `script-src ${nonce}; script-src-elem 'unsafe-inline'; base-uri 'none'`,
+ "gap"
+ ],
+ [
+ "general override",
+ `script-src-elem ${nonce}; script-src 'unsafe-inline'; base-uri 'none'`,
+ "gap"
+ ],
+ ["default fallback", `default-src ${nonce}; base-uri 'none'`, "satisfied"],
+ ["valid nonce", `script-src ${nonce}; base-uri 'none'`, "satisfied"],
+ [
+ "CSP3 ignored sources",
+ `script-src ${nonce} 'strict-dynamic' 'unsafe-inline' https: 'self'; base-uri 'none'`,
+ "satisfied"
+ ],
+ [
+ "element and general lists",
+ `script-src-elem ${nonce}; script-src ${nonce}; base-uri 'none'`,
+ "satisfied"
+ ],
+ [
+ "unsafe attribute override",
+ `script-src ${nonce}; script-src-attr 'unsafe-inline'; base-uri 'none'`,
+ "gap"
+ ],
+ [
+ "multiple enforced policies",
+ [`script-src ${nonce}; base-uri 'none'`, "default-src 'none'"],
+ "review"
+ ]
+ ] as const)("preserves %s", async (_name, csp, state) => {
+ const input = typeof csp === "string" ? csp : [...csp];
+ expect(scriptCspCandidate(snapshot(input))).toBe(state);
+ for (const html of [undefined, ""]) {
+ const report = await inspect(input, html);
+ expect(report.composites.find((item) => item.id === "strict-csp-candidate")).toMatchObject({
+ name: "Script CSP declaration candidate",
+ state
+ });
+ const evaluation = await evaluateEvidencePolicy(report, policy, "2026-07-23");
+ expect(evaluation.findings.find((item) => item.targetKind === "composite")).toMatchObject({
+ outcome: state,
+ decision: state === "satisfied" ? "pass" : state === "review" ? "review" : "fail"
+ });
+ }
+ });
+
+ it.each(algorithms)(
+ "preserves valid %s fallback and ignored inline sources",
+ async (algorithm, length) => {
+ const hash = `'${algorithm}-${encodeBase64(new Uint8Array(length))}'`;
+ expect(effectiveCspBroadSourceCount([hash, "'unsafe-inline'"], "script")).toBe(0);
+ expect(
+ effectiveCspBroadSourceCount(
+ [hash, "'strict-dynamic'", "https:", "'self'", "'unsafe-inline'"],
+ "script"
+ )
+ ).toBe(0);
+ for (const directive of ["script-src", "default-src"]) {
+ const report = await inspect(`${directive} ${hash} 'unsafe-inline'; base-uri 'none'`);
+ const evaluation = await evaluateEvidencePolicy(report, policy, "2026-07-23");
+ expect(evaluation.findings.find((item) => item.targetKind === "composite")).toMatchObject({
+ outcome: "satisfied",
+ decision: "pass"
+ });
+ }
+ }
+ );
+
+ it("requires the full token even when a regular-expression end anchor precedes a newline", () => {
+ const hash = `'sha256-${encodeBase64(new Uint8Array(32))}'`;
+ for (const suffix of ["\n", "\r\n", " ", "\t"]) {
+ expect(parseCspHashSource(`${hash}${suffix}`)).toEqual({
+ metadata: [],
+ invalidSupportedTokenCount: 1
+ });
+ }
+ });
+
+ it.each([
+ "sha256-AAAA",
+ "'sha256-AAAA'",
+ "'sha256-AAAA' trailing",
+ "'sha256-AAAA extra'",
+ "'sha256-AAAA=== '",
+ "'md5-AAAA'"
+ ])("does not authorise malformed full token %s", (token) => {
+ expect(parseCspHashSource(token).metadata).toHaveLength(0);
+ });
+});
diff --git a/tests/report-cli-process.test.ts b/tests/report-cli-process.test.ts
new file mode 100644
index 0000000..4945661
--- /dev/null
+++ b/tests/report-cli-process.test.ts
@@ -0,0 +1,311 @@
+import { spawnSync } from "node:child_process";
+import { mkdtemp, writeFile, rm } from "node:fs/promises";
+import { tmpdir } from "node:os";
+import { join } from "node:path";
+// XML parser already pinned by the build dependency graph; no new dependency is introduced.
+import { parser } from "sax";
+import { afterAll, beforeAll, describe, expect, it } from "vitest";
+import { SECURITY_CONTROLS } from "../src/catalogue";
+import { type EvidenceBundleReport, type EvidenceReportComparison } from "../src/contracts";
+import { inspectEvidenceBundle } from "../src/evidence-bundle";
+import { compareEvidenceReports } from "../src/evidence-comparison";
+import { fingerprintEvidenceReportBody } from "../src/evidence-report";
+import { evidenceIdentity, evidenceSourceContext } from "./helpers";
+
+async function report(
+ options: {
+ controls?: string[];
+ application?: string;
+ environment?: string;
+ csp?: string;
+ noResponse?: boolean;
+ count?: number;
+ removeControlsFrom?: number;
+ } = {}
+) {
+ const surfaces = Array.from({ length: options.count ?? 1 }, (_, i) => ({
+ id: i === 0 ? "document" : `document-${String(i)}`,
+ role: "document",
+ requiredEvidence: ["response"],
+ requiredControls:
+ i >= (options.removeControlsFrom ?? Infinity)
+ ? []
+ : (options.controls ?? ["content-security-policy"]),
+ requiredComposites: []
+ }));
+ return inspectEvidenceBundle(
+ {
+ schemaVersion: 4,
+ name: "Fixture <&> comparison",
+ identity: {
+ ...evidenceIdentity,
+ subject: {
+ ...evidenceIdentity.subject,
+ applicationId: options.application ?? evidenceIdentity.subject.applicationId,
+ environment: options.environment ?? evidenceIdentity.subject.environment
+ }
+ },
+ surfaces,
+ ...(options.noResponse
+ ? {
+ htmlDocuments: [
+ { schemaVersion: 1, name: "Empty fixture", surfaceId: "document", html: "" }
+ ]
+ }
+ : {
+ responses: surfaces.slice(0, 16).map((surface) => ({
+ schemaVersion: 1,
+ name: "Response",
+ surfaceId: surface.id,
+ headers:
+ options.csp === ""
+ ? {}
+ : { "Content-Security-Policy": options.csp ?? "default-src 'none'" }
+ }))
+ })
+ },
+ evidenceSourceContext
+ );
+}
+
+let root: string;
+let beforePath: string;
+const scenarios = new Map<
+ string,
+ { path: string; comparison: EvidenceReportComparison; strict: number }
+>();
+function run(after: string, ...args: string[]) {
+ return spawnSync(
+ process.execPath,
+ ["--import", "tsx", "tools/cli.ts", "compare-reports", beforePath, after, ...args],
+ {
+ cwd: process.cwd(),
+ encoding: "utf8",
+ timeout: 10_000,
+ maxBuffer: 2 * 1024 * 1024
+ }
+ );
+}
+beforeAll(async () => {
+ root = await mkdtemp(join(tmpdir(), "controlcurrent-report-cli-"));
+ const before = await report();
+ beforePath = join(root, "before.json");
+ await writeFile(beforePath, JSON.stringify(before));
+ const modelBody = { ...before, provenance: { ...before.provenance, analyserVersion: "5.0.0" } };
+ const { reportFingerprint: oldFingerprint, ...body } = modelBody;
+ expect(oldFingerprint).toMatch(/^[a-f0-9]{64}$/u);
+ const model = { ...body, reportFingerprint: await fingerprintEvidenceReportBody(body) };
+ const inputs: [string, EvidenceBundleReport, number][] = [
+ ["unchanged", before, 0],
+ ["regression", await report({ csp: "" }), 1],
+ ["removed requirement", await report({ controls: [] }), 1],
+ ["not evaluated", await report({ noResponse: true }), 1],
+ ["environment", await report({ environment: "production" }), 1],
+ ["application", await report({ application: "other-app" }), 1],
+ ["model", model, 1]
+ ];
+ for (const [name, after, strict] of inputs) {
+ const path = join(root, `${name}.json`);
+ await writeFile(path, JSON.stringify(after));
+ scenarios.set(name, { path, comparison: await compareEvidenceReports(before, after), strict });
+ }
+}, 30_000);
+afterAll(async () => {
+ if (root) await rm(root, { recursive: true, force: true });
+});
+
+function checkOutput(format: string, stdout: string, comparison: EvidenceReportComparison) {
+ const summary = comparison.summary;
+ if (format === "json") expect(JSON.parse(stdout)).toEqual(comparison);
+ else if (format === "junit") {
+ const xml = parser(true);
+ const properties = new Map();
+ let suite: Record = {};
+ let cases = 0,
+ failures = 0;
+ xml.onerror = (error) => {
+ throw error;
+ };
+ xml.onopentag = (tag) => {
+ if (tag.name === "testsuite") suite = tag.attributes;
+ if (tag.name === "testcase") cases++;
+ if (tag.name === "failure") failures++;
+ if (tag.name === "property") {
+ const name = tag.attributes.name;
+ const value = tag.attributes.value;
+ if (typeof name !== "string" || typeof value !== "string")
+ throw new Error("Invalid JUnit property");
+ properties.set(name, value);
+ }
+ };
+ xml.write(stdout).close();
+ expect(suite.name).toBe("Fixture <&> comparison to Fixture <&> comparison");
+ expect(Number(suite.tests)).toBe(cases);
+ expect(Number(suite.failures)).toBe(failures);
+ expect(properties.get("total-regressions")).toBe(String(summary.regressions));
+ expect(properties.get("total-incomparable")).toBe(String(summary.incomparable));
+ expect(properties.get("total-resolutions")).toBe(String(summary.resolutions));
+ expect(properties.get("total-changed")).toBe(String(summary.changed));
+ expect(properties.get("total-events")).toBe(String(summary.totalEvents));
+ expect(properties.get("emitted-events")).toBe(String(summary.emittedEvents));
+ expect(properties.get("truncated")).toBe(String(summary.truncated));
+ expect(failures > 0).toBe(summary.regressions + summary.incomparable > 0);
+ if (summary.truncated) expect(stdout).toContain("Omitted bounded events");
+ } else {
+ expect(stdout).toContain(
+ `${String(summary.totalEvents)} total, ${String(summary.emittedEvents)} emitted, truncated: ${String(summary.truncated)}`
+ );
+ if (format === "markdown") {
+ expect(stdout).toContain(`Regressions: ${String(summary.regressions)}`);
+ expect(stdout).toContain(`Incomparable: ${String(summary.incomparable)}`);
+ expect(stdout).toContain(`Resolutions: ${String(summary.resolutions)}`);
+ expect(stdout).toContain(`Other changes: ${String(summary.changed)}`);
+ } else {
+ expect(stdout).toContain(`${String(summary.regressions)} regressions`);
+ expect(stdout).toContain(`${String(summary.incomparable)} incomparable`);
+ expect(stdout).toContain(`${String(summary.resolutions)} resolutions`);
+ expect(stdout).toContain(`${String(summary.changed)} other changes`);
+ }
+ }
+}
+
+describe("reduced report CLI contract", () => {
+ it("confirms the audit's genuine builder fixture before asserting the strict gate", () => {
+ const comparison = scenarios.get("removed requirement")?.comparison;
+ expect(comparison).toMatchObject({
+ compatible: true,
+ summary: { regressions: 0, incomparable: 2, changed: 1, totalEvents: 3 }
+ });
+ expect(comparison?.events.map((item) => [item.beforeState, item.afterState])).toContainEqual([
+ "observed",
+ "not_applicable"
+ ]);
+ expect(comparison?.events.map((item) => [item.beforeState, item.afterState])).toContainEqual([
+ "observed",
+ "absent"
+ ]);
+ });
+
+ it.each(["text", "json", "markdown", "junit"])(
+ "parses %s output and retains format-independent default and strict exits",
+ (format) => {
+ for (const [name, scenario] of scenarios) {
+ for (const strict of [false, true]) {
+ const result = run(
+ scenario.path,
+ "--format",
+ format,
+ ...(strict ? ["--fail-regression", "--fail-incomparable"] : [])
+ );
+ expect(result.error, name).toBeUndefined();
+ expect(result.signal, name).toBeNull();
+ expect(result.status, name).toBe(strict ? scenario.strict : 0);
+ expect(result.stderr, name).toBe("");
+ checkOutput(format, result.stdout, scenario.comparison);
+ }
+ }
+ },
+ 60_000
+ );
+
+ it("keeps regression and incomparability independently opt-in and preserves --json", () => {
+ const removal = scenarios.get("removed requirement");
+ const regression = scenarios.get("regression");
+ if (!removal || !regression) throw new Error("Missing process fixture");
+ for (const [scenario, flag, status] of [
+ [removal, "--fail-regression", 0],
+ [removal, "--fail-incomparable", 1],
+ [regression, "--fail-regression", 1],
+ [regression, "--fail-incomparable", 0]
+ ] as const) {
+ const result = run(scenario.path, flag, "--json");
+ expect(result.status).toBe(status);
+ expect(result.stderr).toBe("");
+ checkOutput("json", result.stdout, scenario.comparison);
+ }
+ const alias = run(beforePath, "--json", "--format", "json");
+ expect(alias.status).toBe(0);
+ expect(alias.stderr).toBe("");
+ expect(JSON.parse(alias.stdout)).toMatchObject({ summary: { totalEvents: 0 } });
+ }, 30_000);
+
+ it.each([
+ ["--format", "yaml"],
+ ["--format"],
+ ["--format", "--fail-incomparable"],
+ ["--json", "--format", "text"],
+ ["--format", "json", "--format", "junit"]
+ ])("rejects invalid or conflicting options %j", (...args) => {
+ const result = run(beforePath, ...args);
+ expect(result.status).toBe(2);
+ expect(result.stdout).toBe("");
+ expect(result.stderr).toMatch(/format/iu);
+ });
+
+ it.each(["incomparable", "mixed"])(
+ "gates complete %s totals from bounded normal-builder output",
+ async (kind) => {
+ const controls = SECURITY_CONTROLS.map((item) => item.id);
+ const before = await report({
+ count: 32,
+ controls,
+ ...(kind === "mixed"
+ ? {
+ csp: "default-src 'nonce-AAAAAAAAAAAAAAAAAAAAAA==' 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' 'strict-dynamic'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'; upgrade-insecure-requests; require-trusted-types-for 'script'"
+ }
+ : {})
+ });
+ const after = await report(
+ kind === "mixed"
+ ? { count: 32, controls, removeControlsFrom: 16, csp: "" }
+ : { count: 32, controls: [] }
+ );
+ const comparison = await compareEvidenceReports(before, after);
+ expect(comparison.compatible).toBe(true);
+ expect(comparison.summary).toMatchObject({
+ emittedEvents: 512,
+ truncated: true
+ });
+ if (kind === "incomparable") {
+ expect(comparison.summary.incomparable).toBeGreaterThan(512);
+ expect(comparison.summary.regressions).toBe(0);
+ } else {
+ expect(comparison.summary.regressions).toBeGreaterThan(0);
+ expect(comparison.summary.incomparable).toBeGreaterThan(0);
+ const visibleAdverse = comparison.events.filter(
+ (item) =>
+ item.type.endsWith("_regressed") ||
+ item.type === "surface_gap_added" ||
+ item.type === "evidence_became_incomparable"
+ ).length;
+ expect(comparison.summary.regressions + comparison.summary.incomparable).toBeGreaterThan(
+ visibleAdverse
+ );
+ }
+ const previous = beforePath;
+ beforePath = join(root, "bounded-before.json");
+ const afterPath = join(root, "bounded-after.json");
+ await writeFile(beforePath, JSON.stringify(before));
+ await writeFile(afterPath, JSON.stringify(after));
+ try {
+ for (const format of ["text", "json", "markdown", "junit"]) {
+ for (const strict of [false, true]) {
+ const result = run(
+ afterPath,
+ "--format",
+ format,
+ ...(strict ? ["--fail-regression", "--fail-incomparable"] : [])
+ );
+ expect(result.error).toBeUndefined();
+ expect(result.status).toBe(strict ? 1 : 0);
+ expect(result.stderr).toBe("");
+ checkOutput(format, result.stdout, comparison);
+ }
+ }
+ } finally {
+ beforePath = previous;
+ }
+ },
+ 30_000
+ );
+});
diff --git a/tests/workflow-boundaries.test.ts b/tests/workflow-boundaries.test.ts
index c635c1b..8f64a50 100644
--- a/tests/workflow-boundaries.test.ts
+++ b/tests/workflow-boundaries.test.ts
@@ -2,7 +2,7 @@ import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
describe("publication workflow hardening", () => {
- it("restores a separately audited toolchain before any package-manager invocation", () => {
+ it("restores a separately audited toolchain before project installation", () => {
for (const name of ["ci", "pages", "source-review", "update-dry-run"]) {
const workflow = readFileSync(`.github/workflows/${name}.yml`, "utf8");
expect(workflow).not.toContain("npm install --global");
@@ -15,7 +15,10 @@ describe("publication workflow hardening", () => {
expect(readFileSync(".nvmrc", "utf8").trim()).toBe("24");
const guidance = readFileSync("docs/dependency-policy.md", "utf8");
expect(guidance).toContain("outside the application");
- expect(guidance).toContain("never executes the runner's npm");
+ expect(guidance).toContain("does not use runner npm for reconstruction");
+ expect(guidance).toContain("installation, audit or signature verification");
+ expect(guidance).toContain("node, npm and yarn with `--version`");
+ expect(guidance).toContain("disabling package-manager caching does not disable these probes");
expect(guidance).toContain("not enforced by `packageManager` alone");
expect(
readFileSync(".github/workflows/ci.yml", "utf8").match(/run: node tools\/bootstrap-npm.ts/gu)
diff --git a/tools/cli.ts b/tools/cli.ts
index f141147..5ee641d 100644
--- a/tools/cli.ts
+++ b/tools/cli.ts
@@ -7,6 +7,8 @@ import {
type CliOutputFormat,
renderDecisionPacketComparisonJunit,
renderDecisionPacketComparisonMarkdown,
+ renderEvidenceReportComparisonJunit,
+ renderEvidenceReportComparisonMarkdown,
renderEvidenceEvaluationJunit,
renderEvidenceEvaluationMarkdown,
renderPolicyDriftJunit,
@@ -54,7 +56,7 @@ function usage(): never {
npm run cli -- explain [--json]
npm run cli -- inspect-headers [--fail-missing] [--json]
npm run cli -- inspect-bundle [--fail-missing] [--strict-composites] [--json]
- npm run cli -- compare-reports [--fail-regression] [--fail-incomparable] [--json]
+ npm run cli -- compare-reports [--fail-regression] [--fail-incomparable] [--format text|json|markdown|junit] [--json]
npm run cli -- reduce-scope-inventory [--json]
npm run cli -- collect-evidence --output --confirm-authorised-target [--allow-loopback]
npm run cli -- create-attestation-statement
@@ -76,8 +78,18 @@ function optionValue(name: string): string | undefined {
}
function outputFormat(): CliOutputFormat {
- if (process.argv.includes("--json")) return "json";
- const value = optionValue("--format") ?? "text";
+ const indices = process.argv.flatMap((value, index) => (value === "--format" ? [index] : []));
+ if (indices.length > 1) throw new Error("Specify --format only once.");
+ const index = indices[0];
+ const explicit = index === undefined ? undefined : process.argv[index + 1];
+ if (index !== undefined && (!explicit || explicit.startsWith("--"))) {
+ throw new Error("--format requires text, json, markdown or junit.");
+ }
+ const json = process.argv.includes("--json");
+ if (json && explicit !== undefined && explicit !== "json") {
+ throw new Error("--json conflicts with --format; use --format json or omit --json.");
+ }
+ const value = explicit ?? (json ? "json" : "text");
if (!["text", "json", "markdown", "junit"].includes(value)) {
throw new Error(`Unsupported output format: ${value}`);
}
@@ -319,13 +331,23 @@ async function compareReports(): Promise {
);
const failed =
(process.argv.includes("--fail-regression") && comparison.summary.regressions > 0) ||
- (process.argv.includes("--fail-incomparable") && !comparison.compatible);
- if (process.argv.includes("--json")) {
- process.stdout.write(canonicalJson(comparison));
- } else {
+ (process.argv.includes("--fail-incomparable") &&
+ (!comparison.compatible || comparison.summary.incomparable > 0));
+ const format = outputFormat();
+ if (format === "json") process.stdout.write(canonicalJson(comparison));
+ else if (format === "markdown")
+ process.stdout.write(renderEvidenceReportComparisonMarkdown(comparison));
+ else if (format === "junit")
+ process.stdout.write(renderEvidenceReportComparisonJunit(comparison));
+ else {
console.log(
`${comparison.beforeName} to ${comparison.afterName}: ${String(comparison.summary.regressions)} regressions, ${String(comparison.summary.resolutions)} resolutions, ${String(comparison.summary.changed)} other changes, ${String(comparison.summary.incomparable)} incomparable`
);
+ console.log(
+ `Events: ${String(comparison.summary.totalEvents)} total, ${String(comparison.summary.emittedEvents)} emitted, truncated: ${String(comparison.summary.truncated)}; complete totals determine exit gates.`
+ );
+ console.log(`Report context compatible: ${String(comparison.compatible)}`);
+ for (const reason of comparison.compatibilityReasons) console.log(`- ${reason}`);
for (const event of comparison.events) {
console.log(`- ${event.type.toUpperCase()} ${event.key}: ${event.summary}`);
}
From eaf928facc64e565fe300712a91a518e2970c4df Mon Sep 17 00:00:00 2001
From: slicedearth <47583576+slicedearth@users.noreply.github.com>
Date: Sat, 10 Oct 2026 22:15:24 +1100
Subject: [PATCH 8/9] Keep test report text within the XML character contract
Replace XML-forbidden code points and lone surrogates with one display space
before escaping markup. Preserve legal Unicode and supplementary characters,
including legal noncharacters, without changing report bytes, fingerprints,
comparison totals or process exit decisions.
Reproduce both reported noncharacters through normal evidence builders and the
actual command-line output. Validate emitted bytes with a strict browser XML
parser that rejects the original output, and cover all shared test-report
renderers, markup characters, legal Unicode and character-range boundaries.
Document the replacement policy, executed reproduction, retained historical
closures and deferred Markdown and filesystem work. Preserve all dependency
locks, reviewed source data, compatibility holds and workflow controls.
Validate 366 unit tests across 41 files, 33 controlled browser/accessibility
tests, unchanged coverage thresholds, separate application and toolchain audits,
registry provenance and the local publication-target build. Hosted verification
for this correction remains a separate step.
---
docs/policy-as-code.md | 6 ++
docs/pr32-follow-up.md | 138 ++++++++++++++++++++++++
e2e/junit-output.spec.ts | 222 +++++++++++++++++++++++++++++++++++++++
src/ci-output.ts | 13 ++-
tests/ci-output.test.ts | 27 ++++-
5 files changed, 401 insertions(+), 5 deletions(-)
create mode 100644 docs/pr32-follow-up.md
create mode 100644 e2e/junit-output.spec.ts
diff --git a/docs/policy-as-code.md b/docs/policy-as-code.md
index 770112e..8a54395 100644
--- a/docs/policy-as-code.md
+++ b/docs/policy-as-code.md
@@ -181,6 +181,12 @@ across JSON, text, Markdown and JUnit output. Output documents still describe
all regressions and incomparable results even when an optional exit gate is
omitted; JUnit may therefore contain failure cases with a non-strict exit `0`.
+All JUnit renderers replace each character forbidden by XML 1.0 with one ASCII
+space before escaping markup. This includes U+FFFE, U+FFFF and lone UTF-16
+surrogates. Legal Unicode, including supplementary characters, is preserved.
+The replacement affects display text only; source reports, fingerprints,
+comparison totals and exit decisions are unchanged.
+
## JSON Schemas
The static site publishes draft 2020-12 schemas for browser policy profiles and
diff --git a/docs/pr32-follow-up.md b/docs/pr32-follow-up.md
new file mode 100644
index 0000000..cdf919d
--- /dev/null
+++ b/docs/pr32-follow-up.md
@@ -0,0 +1,138 @@
+# PR32 XML output follow-up
+
+This local correction addresses FU01 from the supplied follow-up audit dated
+7 October 2026. The implementation session began on 10 October with a clean
+checkout at `7f16e8b25366a4ccd15ead7af152f92767c33877` on
+`maintenance/security-repairs-and-deployment-hardening`. Existing commits,
+dependency locks, source snapshots and workflow boundaries are preserved.
+
+## Confirmed correction
+
+Accepted bundle names containing U+FFFE or U+FFFF reached JUnit suite attributes
+through `inspectEvidenceBundle`, report fingerprinting, report comparison and the
+actual CLI. Both pre-fix process fixtures produced XML rejected by Chromium's
+XML parser. This is an output interoperability defect; no target collection,
+external request or security exploit is claimed.
+
+The shared XML escaping function now admits exactly the XML 1.0 character set:
+U+0009, U+000A, U+000D, U+0020–U+D7FF, U+E000–U+FFFD and
+U+10000–U+10FFFF. Each forbidden code point is replaced with one ASCII space
+before markup escaping. Lone UTF-16 surrogates are covered at the renderer
+boundary. Legal supplementary characters, including supplementary noncharacters
+permitted by XML 1.0, are retained. Legal U+007F is also retained rather than
+being removed by the previous broader control-character rule.
+
+This changes display text only. JSON reports keep their original names and
+fingerprints, and comparison totals and exit decisions are unchanged. No schema
+restriction, evaluator-version change, dependency addition or output limit change
+is needed.
+
+## Regression evidence
+
+Twelve new unit cases cover forbidden controls, surrogate boundaries, U+FFFE,
+U+FFFF and legal character-range boundaries. Existing markup escaping remains
+covered. The Markdown test description was narrowed to what it actually tests;
+Markdown literal escaping was not implemented.
+
+Five new default Chromium tests use `DOMParser` with `application/xml` on an
+empty page. The oracle first rejects the original illegal literals and accepts
+ordinary Unicode. The previously used `sax` strict parser accepts those literals,
+so it is not used as the character-validity oracle.
+
+Normal bundle builders generate both report-name fixtures. The tests run the
+actual CLI, decode stdout as strict UTF-8, parse the emitted XML, and compare its
+names, full event totals, case/failure counts, process status and stderr with JSON
+output. Unchanged and regressed reports are covered. Positive controls include
+accented and combining text, Japanese, emoji, supplementary range boundaries,
+quotes and markup characters. The other four shared JUnit renderers are also
+parsed; descriptive renderer-contract fields exercise case/message escaping
+without fabricating reduced-report fingerprints.
+
+The initial browser harness attempt failed on conflicting inherited colour
+environment variables before reaching the XML assertion. The CLI subprocess now
+uses an explicit, non-conflicting colour environment and still requires empty
+stderr. The corrected pre-fix reproduction then failed twice on the intended XML
+parse errors. Initial post-fix fixture assertions omitted an existing outcome
+prefix and one preserved space; those expectations and nine new-fixture lint
+errors were corrected. The production character-set correction was unchanged.
+
+## Retained closures and optional work
+
+PR32-1 through PR32-4 and H1 remain addressed in the retained source. H2's parent
+symlink design and H3's concurrent no-overwrite design remain deferred. This
+patch does not extend their filesystem scope.
+
+The fourteen historical closures and nine optional-item dispositions remain as
+recorded in [the earlier local handoff](pr32-local-corrections.md#historical-and-optional-boundaries).
+FU01 is additional output polish; it does not reopen those original defects.
+Markdown literal escaping remains optional, as do broader browser workflows,
+controller extraction, planner source-age display, deterministic export-error
+coverage, bootstrap failure orchestration and maximum-input experiments.
+The default Chromium project is retained; no Firefox/WebKit schedule or hosted
+workflow is added.
+
+If reports from an earlier PR32 revision depended on malformed CSP hashes,
+regenerate them from the original evidence with the corrected evaluator before
+relying on their conclusions. Import and fingerprint validation check report
+bytes and do not rerun the evaluator. This XML display correction does not itself
+change the analyser model or require a migration.
+
+## Local validation on 10 October 2026
+
+The following checks use Node 26.4.0 and the retained reviewed npm 12.2.0
+reconstruction. Package versions remain Astro 7.3.6, TypeScript 6.0.3,
+Vitest 5.0.3, Playwright 1.63.0 and axe 4.13.0. BCD 8.1.4 and WebDX 3.40.1
+remain unchanged. No package-manager bootstrap change or new reconstruction
+was required for this output-only correction.
+
+| Command | Exit | Observed result |
+| ----------------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------------ |
+| `npm ci` | 0 | 414 added, 415 audited; manifests, both locks and source data unchanged. |
+| `npm run test -- --coverage.enabled=false tests/ci-output.test.ts` | 0 | 16 renderer tests passed. |
+| `CONTROLCURRENT_DEPLOY_TARGET= CONTROLCURRENT_BROWSER_SMOKE=0 npm run test:e2e -- e2e/junit-output.spec.ts` | 0 | All 5 focused XML tests passed. |
+| `CONTROLCURRENT_DEPLOY_TARGET=github-pages npm run verify` | 0 | Every verification stage passed; 366 unit tests in 41 files, none skipped. |
+| `npm audit --audit-level=low --json` | 0 | Dedicated application audit: zero vulnerabilities. |
+| `npm audit --audit-level=high` | 0 | Documented application audit gate: zero vulnerabilities. |
+| `npm audit signatures` | 0 | 414 registry signatures and 149 attestations verified. |
+| `npm audit --prefix --audit-level=low --json` | 0 | Separate npm runtime audit: zero vulnerabilities. |
+| `npm audit signatures --prefix ` | 0 | 147 registry signatures and 72 attestations verified. |
+| `CONTROLCURRENT_DEPLOY_TARGET= CONTROLCURRENT_BROWSER_SMOKE=0 npm run test:e2e` | 0 | 33 Chromium/accessibility tests passed; no failures, skips, flakes or retries. |
+| `git diff --cached --check` and `git diff --quiet` | 0 | Staged diff clean and worktree matches the index before commit. |
+
+Coverage is 89.71% statements, 80.00% branches, 94.72% functions and 90.87% lines;
+thresholds and the coverage denominator policy are unchanged. Astro checked
+66 files with zero errors, warnings or hints. The repository audit checked
+187 tracked/unignored paths, 16 bounded public JSON files and five workflows.
+All six schemas and 36 selected paths/30 controls matched. The publication-target
+build produced 45 pages; the public audit passed on 71 files (2,463,189 bytes).
+The language audit passed on 164 authored files, including staged additions.
+
+The final verification is repeated after staging this record, retaining the
+publication-target build. Browser tests use the default controlled loopback
+fixture and an empty page for XML parsing. The test runner printed inherited
+colour-environment warnings; CLI subprocess stderr remained empty. Runtime
+prefixes, exact invocations, machine results and local logs are retained in the
+temporary validation record. Earlier expected reproduction failures and corrected
+fixture/harness failures are recorded above rather than reported as final passes.
+Registry package provenance is separate from application evidence authenticity.
+
+## Evidence boundaries
+
+The supplied follow-up audit reports successful CI run `37619283178` and CodeQL
+run `37619283088`, attempt 1, for synthetic merge
+`842560428f6167b4cedbf7d3bb8c1a0055155922`. It reports 354 unit tests in 41 files,
+28 Chromium tests, the dedicated application audit and CodeQL completion for
+that earlier revision. These are attributed historical observations, not fresh
+remote verification of this local correction. The original 7 October local
+handoff remains a dated record and is not rewritten as current hosted evidence.
+
+The reviewed reconstructed npm 12.2.0 is reused with Node 26.4.0 for this session.
+The separate runtime and application audits are run separately. The exact
+commands, current counts and any failures or unexecuted checks are recorded in
+the final local validation handoff. No claim is made about the exact Node 24
+floor, broader browser matrix, genuine signed evidence flow, current remote
+checks, branch protection, environment approval or release readiness.
+
+This session is authorised for a local commit only. No push, merge, deployment,
+release, hosted workflow dispatch, live target collection or evidence upload is
+part of this correction.
diff --git a/e2e/junit-output.spec.ts b/e2e/junit-output.spec.ts
new file mode 100644
index 0000000..80afd6d
--- /dev/null
+++ b/e2e/junit-output.spec.ts
@@ -0,0 +1,222 @@
+import { expect, test, type Page } from "@playwright/test";
+import { spawnSync } from "node:child_process";
+import { readFileSync } from "node:fs";
+import { mkdtemp, rm, writeFile } from "node:fs/promises";
+import { tmpdir } from "node:os";
+import { join } from "node:path";
+import {
+ renderDecisionPacketComparisonJunit,
+ renderEvidenceEvaluationJunit,
+ renderPolicyDriftJunit,
+ renderPolicyEvaluationJunit
+} from "../src/ci-output";
+import {
+ evidencePolicyProfileSchema,
+ evidenceReportComparisonSchema,
+ selectedSnapshotSchema
+} from "../src/contracts";
+import { buildDecisionPacket, compareDecisionPackets } from "../src/decision-packet";
+import { inspectEvidenceBundle } from "../src/evidence-bundle";
+import { evaluateEvidencePolicy } from "../src/evidence-policy";
+import { evaluatePolicyProfile } from "../src/policy";
+import { comparePolicyEvaluations } from "../src/policy-comparison";
+import { evidenceIdentity, evidenceSourceContext } from "../tests/helpers";
+
+const asOf = "2026-07-24";
+const selectedSnapshot = selectedSnapshotSchema.parse(
+ JSON.parse(readFileSync(new URL("../data/selected-bcd.json", import.meta.url), "utf8")) as unknown
+);
+
+async function report(name: string, csp = "default-src 'none'") {
+ return inspectEvidenceBundle(
+ {
+ schemaVersion: 4,
+ name,
+ identity: evidenceIdentity,
+ surfaces: [
+ {
+ id: "document",
+ role: "document",
+ requiredEvidence: ["response"],
+ requiredControls: ["content-security-policy"],
+ requiredComposites: []
+ }
+ ],
+ responses: [
+ {
+ schemaVersion: 1,
+ name: "Response",
+ surfaceId: "document",
+ headers: csp ? { "Content-Security-Policy": csp } : {}
+ }
+ ]
+ },
+ evidenceSourceContext
+ );
+}
+
+function cli(args: string[], status: number): string {
+ const environment: NodeJS.ProcessEnv = { ...process.env, NO_COLOR: "1" };
+ delete environment.FORCE_COLOR;
+ const result = spawnSync(process.execPath, ["--import", "tsx", "tools/cli.ts", ...args], {
+ cwd: process.cwd(),
+ env: environment,
+ timeout: 10_000,
+ maxBuffer: 2 * 1024 * 1024
+ });
+ expect(result.error).toBeUndefined();
+ expect(result.signal).toBeNull();
+ expect(result.stderr.toString("utf8")).toBe("");
+ expect(result.status).toBe(status);
+ // Validate the emitted bytes before passing the decoded document to the XML parser.
+ return new TextDecoder("utf-8", { fatal: true }).decode(result.stdout);
+}
+
+async function parseXml(page: Page, xml: string) {
+ return page.evaluate((text) => {
+ const document = new DOMParser().parseFromString(text, "application/xml");
+ return {
+ error: document.querySelector("parsererror")?.textContent ?? null,
+ name: document.documentElement.getAttribute("name"),
+ tests: Number(document.documentElement.getAttribute("tests")),
+ failures: Number(document.documentElement.getAttribute("failures")),
+ cases: document.querySelectorAll("testcase").length,
+ failureElements: document.querySelectorAll("failure").length,
+ properties: Object.fromEntries(
+ Array.from(
+ document.querySelectorAll("property"),
+ (item) => [item.getAttribute("name") ?? "", item.getAttribute("value")] as const
+ )
+ ),
+ values: Array.from(document.querySelectorAll("*"), (element) =>
+ Array.from(element.attributes, (attribute) => attribute.value)
+ ).flat()
+ };
+ }, xml);
+}
+
+test("XML oracle rejects the original illegal characters and accepts legal Unicode", async ({
+ page
+}) => {
+ // sax's strict mode accepts these literals; it is not an oracle for XML 1.0 characters.
+ for (const character of ["\uFFFE", "\uFFFF"]) {
+ const parsed = await parseXml(page, ``);
+ expect(parsed.error).not.toBeNull();
+ }
+ expect((await parseXml(page, '')).error).toBeNull();
+});
+
+for (const [label, input, expected] of [
+ ["U+FFFE", "\uFFFE", " "],
+ ["U+FFFF", "\uFFFF", " "],
+ [
+ "legal Unicode",
+ "café 日本語 e\u0301 😀 \u{10000} \u{1FFFE} \u{10FFFF}",
+ "café 日本語 e\u0301 😀 \u{10000} \u{1FFFE} \u{10FFFF}"
+ ]
+] as const) {
+ test(`exports ${label} in genuine report CLI JUnit without changing gates or totals`, async ({
+ page
+ }) => {
+ const name = `Fixture${input} <&> "' suffix`;
+ const expectedName = `Fixture${expected} <&> "' suffix`;
+ const before = await report(name);
+ expect(before.name).toBe(name);
+ const root = await mkdtemp(join(tmpdir(), "controlcurrent-junit-"));
+ try {
+ const beforePath = join(root, "before.json");
+ const afterPath = join(root, "after.json");
+ await writeFile(beforePath, JSON.stringify(before));
+ for (const changed of [false, true]) {
+ await writeFile(afterPath, JSON.stringify(changed ? await report(name, "") : before));
+ const args = [
+ "compare-reports",
+ beforePath,
+ afterPath,
+ "--fail-regression",
+ "--fail-incomparable"
+ ];
+ const status = changed ? 1 : 0;
+ const comparison = evidenceReportComparisonSchema.parse(
+ JSON.parse(cli([...args, "--format", "json"], status)) as unknown
+ );
+ expect(comparison.beforeName).toBe(name);
+ expect(comparison.afterName).toBe(name);
+ const xml = cli([...args, "--format", "junit"], status);
+ const parsed = await parseXml(page, xml);
+ expect(parsed.error).toBeNull();
+ expect(parsed.name).toBe(`${expectedName} to ${expectedName}`);
+ expect(parsed.tests).toBe(parsed.cases);
+ expect(parsed.failures).toBe(parsed.failureElements);
+ expect(parsed.failures).toBe(comparison.summary.regressions);
+ expect(parsed.properties["total-events"]).toBe(String(comparison.summary.totalEvents));
+ expect(parsed.properties["emitted-events"]).toBe(String(comparison.summary.emittedEvents));
+ expect(parsed.properties["total-regressions"]).toBe(String(comparison.summary.regressions));
+ expect(parsed.properties["total-incomparable"]).toBe(
+ String(comparison.summary.incomparable)
+ );
+ expect(parsed.properties.truncated).toBe(String(comparison.summary.truncated));
+ }
+ } finally {
+ await rm(root, { recursive: true, force: true });
+ }
+ });
+}
+
+test("shared JUnit consumers encode names, case attributes and explanations as valid XML", async ({
+ page
+}) => {
+ const name = "Fixture\uFFFE\uFFFF café 😀 <&> \"' suffix";
+ const expectedName = "Fixture café 😀 <&> \"' suffix";
+ const policy = (controls: string[]) =>
+ evaluatePolicyProfile(
+ selectedSnapshot,
+ {
+ schemaVersion: 1,
+ name,
+ baselines: [{ browser: "chrome", minimumVersion: "120" }],
+ requiredControls: controls,
+ rules: { qualifications: "review", unknown: "fail", unsupported: "fail" },
+ exceptions: []
+ },
+ asOf
+ );
+ const before = policy(["content-security-policy"]);
+ const after = policy(["content-security-policy", "csp-nonces"]);
+ const evidence = await report(name);
+ const evidenceProfile = evidencePolicyProfileSchema.parse(
+ JSON.parse(
+ readFileSync(new URL("../examples/evidence-policy.json", import.meta.url), "utf8")
+ ) as unknown
+ );
+ const evaluation = await evaluateEvidencePolicy(evidence, { ...evidenceProfile, name }, asOf);
+ const packets = await compareDecisionPackets(
+ await buildDecisionPacket(before, evidence, asOf),
+ await buildDecisionPacket(after, evidence, asOf),
+ asOf
+ );
+ expect(packets.browserPolicy.events.length).toBeGreaterThan(0);
+ // Exercise accepted descriptive renderer fields; no reduced report fingerprint is fabricated.
+ const outputs = [
+ renderPolicyEvaluationJunit({
+ ...after,
+ findings: after.findings.map((finding) => ({ ...finding, explanation: name }))
+ }),
+ renderEvidenceEvaluationJunit(evaluation),
+ renderPolicyDriftJunit(comparePolicyEvaluations(before, after, asOf)),
+ renderDecisionPacketComparisonJunit({
+ ...packets,
+ browserPolicy: {
+ ...packets.browserPolicy,
+ events: packets.browserPolicy.events.map((item) => ({ ...item, summary: name }))
+ }
+ })
+ ];
+ for (const xml of outputs) {
+ const parsed = await parseXml(page, xml);
+ expect(parsed.error).toBeNull();
+ expect(parsed.values.some((value) => value.includes(expectedName))).toBe(true);
+ expect(parsed.tests).toBe(parsed.cases);
+ expect(parsed.failures).toBe(parsed.failureElements);
+ }
+});
diff --git a/src/ci-output.ts b/src/ci-output.ts
index 5802baf..5e5692a 100644
--- a/src/ci-output.ts
+++ b/src/ci-output.ts
@@ -24,10 +24,15 @@ function xml(value: string): string {
return Array.from(value)
.map((character) => {
const codePoint = character.codePointAt(0);
- return codePoint !== undefined &&
- ((codePoint < 32 && ![9, 10, 13].includes(codePoint)) || codePoint === 127)
- ? " "
- : character;
+ // XML 1.0 Char: replace each forbidden code point (including lone surrogates)
+ // with one space, while preserving legal BMP and supplementary characters.
+ const legal =
+ codePoint !== undefined &&
+ ([9, 10, 13].includes(codePoint) ||
+ (codePoint >= 0x20 && codePoint <= 0xd7ff) ||
+ (codePoint >= 0xe000 && codePoint <= 0xfffd) ||
+ (codePoint >= 0x10000 && codePoint <= 0x10ffff));
+ return legal ? character : " ";
})
.join("")
.replaceAll("&", "&")
diff --git a/tests/ci-output.test.ts b/tests/ci-output.test.ts
index b86c0c3..3a8de13 100644
--- a/tests/ci-output.test.ts
+++ b/tests/ci-output.test.ts
@@ -23,7 +23,7 @@ const evaluation = evaluatePolicyProfile(
);
describe("CI report formats", () => {
- it("renders bounded Markdown without creating active markup", () => {
+ it("renders bounded Markdown with policy totals and caveats", () => {
const report = renderPolicyEvaluationMarkdown(evaluation);
expect(report).toContain("# ");
expect(report).toContain("| fail | csp-nonces |");
@@ -37,6 +37,31 @@ describe("CI report formats", () => {
expect(report).toContain(" {
+ const name = `Fixture${String.fromCodePoint(codePoint)}suffix`;
+ const report = renderPolicyEvaluationJunit({
+ ...evaluation,
+ profile: { ...evaluation.profile, name },
+ findings: evaluation.findings.map((finding) => ({ ...finding, explanation: name }))
+ });
+ expect(report).toContain('name="Fixture suffix"');
+ expect(report).toContain('classname="Fixture suffix"');
+ expect(report).toContain('message="unsupported_mapping: Fixture suffix"');
+ }
+ );
+
+ it("preserves the XML 1.0 legal character boundaries and supplementary Unicode", () => {
+ const name = "A\t\n\r\u0020\u007f\u0085\ud7ff\ue000\ufffd\u{10000}\u{1fffe}\u{10ffff}Z";
+ const report = renderPolicyEvaluationJunit({
+ ...evaluation,
+ profile: { ...evaluation.profile, name }
+ });
+ expect(report).toContain(`name="${name}"`);
+ expect(report).toContain(`classname="${name}"`);
+ });
+
it("renders deterministic policy-drift Markdown and JUnit", () => {
const comparison = comparePolicyEvaluations(evaluation, evaluation, "2026-07-24");
expect(renderPolicyDriftMarkdown(comparison)).toContain("No policy or decision changes");
From fb5a2a468726fdeea07f4e998192cb5557dee764 Mon Sep 17 00:00:00 2001
From: slicedearth <47583576+slicedearth@users.noreply.github.com>
Date: Sat, 10 Oct 2026 23:00:54 +1100
Subject: [PATCH 9/9] Complete deferred local safeguards and workflow coverage
Anchor private evidence output to the checkout and validate destinations before
collection. Publish complete files with an atomic no-replace operation and
cover competing writers, partial writes and output aliases.
Escape supplied report text, retain complete bounded comparison totals and
separate toolchain activation from reconstruction so all verification gates
precede executable publication.
Extract the planning and evidence controllers with typed page controls,
shared downloads, explicit pending states and source-age context. Extend
local browser workflows, collector process diagnostics and measured safety
tool coverage without changing hosted schedules.
Record final local verification and remaining platform, zoom and release
evidence limits.
---
README.md | 4 +
docs/architecture.md | 18 +
docs/authorised-collection.md | 25 +-
docs/dependency-policy.md | 7 +-
docs/deployment-security.md | 22 +
docs/methodology.md | 17 +-
docs/policy-as-code.md | 15 +
docs/pr32-follow-up.md | 4 +
docs/pr32-local-corrections.md | 4 +
docs/pr32-optional-follow-up.md | 216 +++
e2e/audit-boundaries.spec.ts | 189 ++-
e2e/site.spec.ts | 16 +-
playwright.config.ts | 19 +-
src/ci-output.ts | 21 +-
src/components/EvidenceBundleInspector.astro | 711 +---------
src/components/MinimumPlanner.astro | 100 +-
src/components/Planner.astro | 1255 +-----------------
src/components/SourceContext.astro | 19 +
src/contracts.ts | 20 +-
src/controllers/dom.ts | 25 +
src/controllers/download.ts | 19 +
src/controllers/evidence-bundle.ts | 692 ++++++++++
src/controllers/minimum-planner.ts | 94 ++
src/controllers/planner.ts | 1210 +++++++++++++++++
src/source-age.ts | 8 +
tests/ci-output.test.ts | 47 +-
tests/collector-cli-process.test.ts | 122 ++
tests/decision-packet.test.ts | 42 +-
tests/evaluate.test.ts | 26 +
tests/npm-toolchain.test.ts | 58 +
tests/private-output.test.ts | 169 +++
tests/source-age.test.ts | 18 +
tools/bootstrap-npm.ts | 37 +-
tools/cli.ts | 47 +-
tools/private-output.ts | 110 ++
tools/toolchain-activation.ts | 43 +
vitest.config.ts | 12 +-
37 files changed, 3287 insertions(+), 2174 deletions(-)
create mode 100644 docs/pr32-optional-follow-up.md
create mode 100644 src/components/SourceContext.astro
create mode 100644 src/controllers/dom.ts
create mode 100644 src/controllers/download.ts
create mode 100644 src/controllers/evidence-bundle.ts
create mode 100644 src/controllers/minimum-planner.ts
create mode 100644 src/controllers/planner.ts
create mode 100644 src/source-age.ts
create mode 100644 tests/collector-cli-process.test.ts
create mode 100644 tests/private-output.test.ts
create mode 100644 tests/source-age.test.ts
create mode 100644 tools/private-output.ts
create mode 100644 tools/toolchain-activation.ts
diff --git a/README.md b/README.md
index d832ffd..7035230 100644
--- a/README.md
+++ b/README.md
@@ -55,6 +55,8 @@ checker or certification service.
- Save a browser plan locally or export it as JSON.
- Opt in to remembering one result so a later data update can be compared.
- Compare an exported result with a newer result from the same source version.
+- Read exact source versions, package timestamps and local package age beside
+ both planning workflows.
### Record an engineering decision
@@ -233,6 +235,8 @@ with organisation-specific evidence.
## Documentation
+- [PR32 optional follow-up and local validation](docs/pr32-optional-follow-up.md)
+
- [Architecture](docs/architecture.md)
- [Data contract](docs/data-contract.md)
- [Methodology](docs/methodology.md)
diff --git a/docs/architecture.md b/docs/architecture.md
index 990cf88..6ef51d6 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -54,6 +54,24 @@ static Astro build
The browser receives only static HTML, CSS, JavaScript, and the selected data
bundled by the build. There is no runtime source request.
+## Browser controllers
+
+The planner, minimum planner and evidence-bundle components own their static
+markup. Their scripts call explicit initialisers in `src/controllers/`, which
+own DOM references, operation generations, session state, rendering and event
+handlers. Required controls are checked by element type before handlers are
+registered. Shared helpers handle asynchronous event feedback and bounded Blob
+downloads with URL cleanup; model calculations and guarded storage remain in
+independent modules. This extracts the complete controllers without introducing
+a framework or changing opt-in persistence.
+
+The unit coverage denominator includes model modules, the publication gate,
+collector transport, private-output handling and toolchain activation. DOM
+controllers retain real-browser validation separately, as they did when embedded
+in Astro. CLI dispatch and bootstrap reconstruction remain outside the measured
+unit denominator; subprocess and archive tests are separate evidence for those
+paths. Thresholds are unchanged.
+
## Source selection
The catalogue owns every requested BCD path. The generator:
diff --git a/docs/authorised-collection.md b/docs/authorised-collection.md
index a782f5d..34e8a9d 100644
--- a/docs/authorised-collection.md
+++ b/docs/authorised-collection.md
@@ -87,9 +87,28 @@ npm run cli -- collect-evidence private-data/collector/manifest.json \
--confirm-authorised-target
```
-The command refuses to overwrite an existing file. Output directories are
-created with restrictive permissions where the platform supports them, the file
-is written atomically with mode `0600`, and no output is committed or uploaded.
+The repository boundary is the real directory containing this CLI's checkout,
+even when the command is invoked from a different working directory. Relative
+output arguments are still relative to that working directory. Before any target
+request, the command refuses public repository destinations, existing output
+files and symlink parents beneath the repository's private directories. External
+destinations are resolved through their existing parent directory before new
+children are created; an alias back into the publication tree is refused.
+
+Output directories are created with mode `0700` and temporary files with mode
+`0600` where supported. Complete, flushed bytes are published with an atomic
+same-directory hard link. An existing destination makes that operation fail;
+competing writers cannot replace the winner. Temporary files are removed after
+write or publication failures. A filesystem without hard-link support fails
+closed; there is no overwrite-capable rename fallback. No output is committed
+or uploaded.
+
+Use directories controlled by the operator. Parent validation prevents existing
+aliases; it does not provide a sandbox against another local process that can
+rename or replace those directories concurrently. Defending against a malicious
+same-user directory swap would require a reviewed directory-handle strategy and
+platform-specific support. Restrictive file modes alone do not make a public
+publication directory safe.
Inspect the resulting private bundle separately:
diff --git a/docs/dependency-policy.md b/docs/dependency-policy.md
index 0f9a2c8..c4ea44b 100644
--- a/docs/dependency-policy.md
+++ b/docs/dependency-policy.md
@@ -82,7 +82,12 @@ special archive entries, bundled modules and script-bearing runtime packages.
It caps archives, metadata, members, graph size, total downloads, concurrency
and duration. A fresh temporary directory is used for each invocation. The
reconstructed CLI audits that graph at every severity and verifies registry
-signatures before its npm and npx executables are added to workflow PATH.
+signatures before its npm and npx executable links are created or added to
+workflow PATH. Activation uses the reconstructed CLI's absolute path for the
+version, advisory and signature checks. Any failed gate stops activation; the
+entry point removes that invocation's temporary reconstruction. Offline process
+fixtures exercise each failure and confirm that no executable links or PATH
+entry become available.
This is a project-maintained runtime reconstruction, not an unmodified upstream
distribution or an assurance that unknown vulnerabilities cannot exist.
diff --git a/docs/deployment-security.md b/docs/deployment-security.md
index 3c6a154..fef9e07 100644
--- a/docs/deployment-security.md
+++ b/docs/deployment-security.md
@@ -269,6 +269,28 @@ The smoke scenario checks keyboard use and enlarged text. The complete
Chromium suite remains the default; a smoke pass is not equivalent to complete
Firefox or WebKit coverage.
+The broader local workflow selection is separately opt-in:
+
+```sh
+CONTROLCURRENT_DEPLOY_TARGET= CONTROLCURRENT_BROWSER_WORKFLOWS=1 \
+ npm run test:e2e -- --grep '@smoke|@workflow'
+```
+
+It uses the same disposable HTTPS fixture and runs serially across Chromium,
+Firefox and WebKit. It covers profile/policy imports, Blob downloads, denied
+storage, evidence file drop, non-executing markup, pending-operation supersession,
+bounded export failures, source context, restrictive CSP/framing behaviour, axe
+checks and 320-pixel reflow. The original smoke flag still selects only the
+keyboard/enlarged-text smoke for the optional engines. Neither flag changes
+recurring hosted workflows or uploads artefacts.
+
+The reflow fixture uses a 320 CSS-pixel viewport and the keyboard fixture uses
+200% root font size. Neither is native 400% browser zoom. A manual zoom check
+should set a 1280-pixel browser window to 400% in the browser UI, then exercise
+planner inputs, imports, result disclosure, evidence review and downloads while
+checking focus visibility and horizontal scrolling. Record the browser/version
+and actual zoom setting; do not substitute a CSS transform or device scale factor.
+
After deployment:
1. compare the deployed commit with the reviewed local commit;
diff --git a/docs/methodology.md b/docs/methodology.md
index 5a184e5..b62ee96 100644
--- a/docs/methodology.md
+++ b/docs/methodology.md
@@ -32,7 +32,13 @@ control definition. Multi-path controls use:
- `all` when every mapped feature is required;
- `any` only when independent paths each establish the intended capability.
-No current catalogue control uses `any`.
+Integrity Policy uses `any` for its enforcement and report-only source paths;
+the currently bundled paths carry identical support data. An `any` mapping
+requires at least one path to cover the complete reviewed released population
+from the chosen minimum onwards. Complementary intervals across different paths
+do not establish one consistently available implementation. Synthetic tests
+retain this deliberately stronger planning contract, including qualified support;
+the evaluator does not assume an application switches implementations by release.
Related data is not substituted for a missing feature. CSP nonce and hash
sources remain unsupported mappings in BCD 8.1.4 because the package does not
@@ -78,13 +84,20 @@ policy. The planner accepts explicit minimum versions.
The reverse planner searches release entries marked `retired`, `current`, or
`esr` that carry a release date in the selected snapshot. For every requested
browser, it returns the earliest retained release at which all selected
-controls have the required outcome. Source-qualified support is accepted only
+controls have the required outcome throughout the later reviewed released
+population. Source-qualified support is accepted only
when the visitor selects that option.
An unsupported mapping blocks the complete calculation rather than inheriting
a related control. If no retained release satisfies every control, the result
identifies the blockers at the most recent comparable release.
+Both planning forms show the exact bundled package timestamp and source versions.
+Package age is calculated against the device's clock, with an explicit unavailable
+state for a future timestamp or invalid clock. It is the age of package metadata,
+not a review date, freshness guarantee or runtime source check. The displayed
+snapshot may omit later releases and corrections.
+
Profile comparison requires the same BCD and catalogue versions. It distinguishes:
- support gained or lost;
diff --git a/docs/policy-as-code.md b/docs/policy-as-code.md
index 8a54395..6f5dd83 100644
--- a/docs/policy-as-code.md
+++ b/docs/policy-as-code.md
@@ -187,6 +187,21 @@ surrogates. Legal Unicode, including supplementary characters, is preserved.
The replacement affects display text only; source reports, fingerprints,
comparison totals and exit decisions are unchanged.
+CI Markdown renderers escape supplied names, keys and summaries as CommonMark
+text, including image/link delimiters, HTML, formatting, entities and table pipes.
+Control characters become spaces. This prevents supplied Markdown syntax from
+creating images or raw HTML; a viewer can still independently linkify plain URLs.
+No renderer controls a viewer's network or extension policy. JSON and fingerprints
+retain the original values.
+
+Decision-packet comparison keeps complete evidence totals up to 16,384 and combined
+browser/evidence totals up to 20,480 while emitting at most 512 events per lane.
+Two disjoint accepted 4,096-finding evidence-policy inputs can therefore report
+all 8,192 changes without overflowing a category total. The stress fixture uses
+schema-valid inputs and the normal packet builder; it does not claim the bundled
+catalogue evaluator naturally produces that many findings. Input and byte limits
+are unchanged.
+
## JSON Schemas
The static site publishes draft 2020-12 schemas for browser policy profiles and
diff --git a/docs/pr32-follow-up.md b/docs/pr32-follow-up.md
index cdf919d..2a907e0 100644
--- a/docs/pr32-follow-up.md
+++ b/docs/pr32-follow-up.md
@@ -1,5 +1,9 @@
# PR32 XML output follow-up
+Later authorised optional work is recorded in
+[the optional follow-up](pr32-optional-follow-up.md). This file retains the
+validation evidence and deferred choices at the XML correction's revision.
+
This local correction addresses FU01 from the supplied follow-up audit dated
7 October 2026. The implementation session began on 10 October with a clean
checkout at `7f16e8b25366a4ccd15ead7af152f92767c33877` on
diff --git a/docs/pr32-local-corrections.md b/docs/pr32-local-corrections.md
index e2dfcb7..ffd2d4c 100644
--- a/docs/pr32-local-corrections.md
+++ b/docs/pr32-local-corrections.md
@@ -1,5 +1,9 @@
# PR32 local correction and maintenance record
+Later authorised optional work is recorded in
+[the optional follow-up](pr32-optional-follow-up.md). This file retains the
+dated maintenance evidence and choices for the original correction batch.
+
This record accompanies the local correction of the four confirmed PR32 issues
on 7 October 2026 AEDT. The companion source audit dated 6 October was read as
evidence, not additional authority. This record does not establish release
diff --git a/docs/pr32-optional-follow-up.md b/docs/pr32-optional-follow-up.md
new file mode 100644
index 0000000..b70bf92
--- /dev/null
+++ b/docs/pr32-optional-follow-up.md
@@ -0,0 +1,216 @@
+# PR32 optional local follow-up
+
+This session on 10 October 2026 implements the authorised optional and deferred
+local work. It started with a clean tracked, staged and untracked inventory at
+`eaf928facc64e565fe300712a91a518e2970c4df` on
+`maintenance/security-repairs-and-deployment-hardening`. The earlier maintenance,
+dependency/source refresh, four PR32 corrections and XML correction are retained.
+No branch switch, reset, stash, clean, lock replacement or discarded edit occurred.
+All changes in this session belong to this follow-up; no ownership conflict arose.
+
+## Dispositions
+
+| Item | Current disposition |
+| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| PR32-1 | Retained exact generated-lock exclusions and authored-language regressions. |
+| PR32-2 | Retained anchored CSP hash grammar, SRI options and effective-source tests. |
+| PR32-3 | Retained the complete incomparable-summary gate and real-builder process fixture. |
+| PR32-4 | Retained genuine text/JSON/Markdown/JUnit output and format-independent gates. |
+| H1 | Retained accurate setup-node probe wording; provisioning and least privilege unchanged. |
+| H2 | Implemented repository-root anchoring, private-parent link refusal, canonical external destinations and pre-collection preflight. Trusted-parent concurrency boundary documented. |
+| H3 | Implemented atomic no-replace hard-link publication, private modes and temporary-file cleanup. Real competing writers and a deterministic post-preflight claimant are tested. |
+| FU01 | Retained the exact XML 1.0 character boundary and browser XML parser regressions. |
+
+The private-output root follows the CLI's checkout, not the invoking process's
+working directory. A synthetic process test starts elsewhere and verifies that a
+public destination is refused before any loopback request. Existing aliases into
+the publication tree are rejected. Output bytes are flushed and closed before a
+same-directory hard link claims the final filename. Eight competing processes
+produce exactly one winner; a forced claim after preflight cannot be replaced.
+Serialisation and partial-write failures leave no partial final file or temporary
+file. Unsupported hard-link filesystems fail closed. Windows and other filesystem
+implementations were not executed in this session. The design assumes trusted
+parents and does not claim resistance to malicious concurrent directory swaps.
+
+Markdown display fields now escape CommonMark punctuation, including supplied
+image/link/HTML/formatting syntax. Offline parser fixtures preserve literal names
+and refuse active supplied image/HTML/formatting nodes. CommonMark and GFM parsing
+are distinguished: viewers can independently linkify plain URLs after parsing.
+No URL in those fixtures was visited. JSON, fingerprints and classification remain
+unchanged.
+
+The public packet builder accepts the synthetic maximum of 4,096 evidence-policy
+findings per input within its byte bound. Disjoint sets reproduced a failure at
+8,192 changes against the former 4,096 category cap. Category totals now share the
+existing 16,384 whole-evidence bound; combined totals allow that evidence lane
+plus at most 4,096 browser events. The 512-event display limit remains. These are
+accepted builder-contract inputs, not findings naturally emitted by the current
+catalogue evaluator. No ordinary-user failure is inferred from the stress case.
+
+The planner, minimum planner and evidence-bundle inspector now use complete
+TypeScript controllers with explicit initialisers, typed required DOM controls,
+guarded async listeners and shared bounded downloads. Existing generation/storage
+boundaries remain. Replacement evidence disables review until loading finishes;
+replacement comparisons remove old comparison data immediately. Source timestamps,
+versions and device-clock package age appear beside both planning forms. Package
+age is not a review date or a guarantee of current data.
+
+The alternative-feature test preserves the current stronger contract: one mapped
+path must cover the entire reviewed release population. It covers complementary
+support intervals and a qualified whole-population alternative. The current
+Integrity Policy paths still share their bundled support data. The stale
+methodology claim that no control uses `any` is corrected.
+
+Bootstrap activation is measured separately from reconstruction. Version, advisory
+and registry-signature subprocesses must all succeed before executable links or a
+workflow PATH entry are created. Offline failing subprocesses test each gate. The
+real fresh reconstruction is also validated locally; it does not establish that
+the reconstructed code is benign or that evidence collection is truthful.
+
+## Historical closure matrix
+
+These retain the identified closures, not a claim that every historical acceptance
+permutation has been executed again.
+
+| Finding | Retained closure |
+| ------- | ------------------------------------------------------------------------------- |
+| CC01 | Released populations and Safari gaps. |
+| CC02 | CSP hash grammar and effective declaration candidate; runtime caveats retained. |
+| CC03 | Repeated-header fail-closed handling. |
+| CC04 | Most-specific cookie-prefix redaction. |
+| CC05 | Surface, redirect, HTML and label budgets. |
+| CC06 | Absolute collection deadlines. |
+| CC07 | Complete counts before truncation, including wrapped totals. |
+| CC08 | Independent policy-drift decisions. |
+| CC09 | Dirty-state/export invalidation; pending comparisons now clearer. |
+| CC10 | Unavailable-version preflight. |
+| CC11 | Generation supersession; retained across controller extraction. |
+| CC12 | Guarded opt-in storage. |
+| CC13 | Exception-scope rejection. |
+| CC14 | Cache boundaries. |
+
+## Nine optional choices
+
+| Item | Current status |
+| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| 1. Strict incomparable/formats | Completed previously; retained. |
+| 2. Browser/accessibility breadth | Expanded local opt-in workflows across three engines; native 400% browser zoom and a complete cross-engine site suite remain unexecuted. No recurring hosted change. |
+| 3. CLI diagnostics/coverage | Added actual collector process diagnostics. Measured unit coverage now includes transport, private output and activation. CLI dispatch and reconstruction remain outside that denominator. |
+| 4. UI controllers | Complete planner, minimum-planner and evidence-bundle controllers extracted; shared DOM/event/download boundaries added. Other simple page scripts remain in their components. |
+| 5. Source age | Implemented beside both planning forms with exact timestamp/version context and clock caveats. |
+| 6. Hosting boundary | Retained. Sensitive organisational evidence still requires an appropriate dedicated origin; no account or hosting changes authorised. |
+| 7. Manual deployment parity | Source controls retained. Deployment and eventual exact-main verification remain unobserved. |
+| 8. Portable authenticated output | Existing unchanged evidence-member extraction remains documented; no new wrapper or fresh browser attestation claim. |
+| 9. Export error feedback | Deterministic browser tests now exercise the byte-limit error, Blob failure, no-download outcome and successful retry. |
+
+## Validation record
+
+Commands use Node 26.4.0 and the fresh reviewed npm 12.2.0 reconstruction.
+`RUNTIME` below denotes the fresh temporary directory printed by the bootstrap;
+its `executables` directory is first on PATH for all subsequent npm commands.
+The private command record retains that exact path and per-command exit codes.
+Astro is 7.3.6, TypeScript 6.0.3, Vitest 5.0.3, Playwright 1.63.0 and axe 4.13.0.
+The executed engines report Chromium 153.0.8010.12 (revision 1243), Firefox 155.0
+(1543) and WebKit 26.6 (2359).
+
+| Command | Exit | Observed result |
+| -------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------- |
+| `env -u GITHUB_PATH -u GITHUB_ENV node tools/bootstrap-npm.ts` | 0 | Fresh reconstruction, version check, low-severity runtime audit and registry signature verification succeeded before activation. |
+| `npm ci` | 0 | 414 added, 415 audited; zero reported vulnerabilities. Manifests and locks unchanged. |
+| `npm run test -- --coverage.enabled=false tests/collector-cli-process.test.ts tests/private-output.test.ts` | 0 | 15 focused filesystem/process tests passed, including the deterministic late claimant. |
+| `CONTROLCURRENT_DEPLOY_TARGET= CONTROLCURRENT_BROWSER_SMOKE=0 CONTROLCURRENT_BROWSER_WORKFLOWS=0 npm run test:e2e -- e2e/audit-boundaries.spec.ts` | 0 | 15 focused Chromium tests passed. |
+| `CONTROLCURRENT_DEPLOY_TARGET= CONTROLCURRENT_BROWSER_SMOKE=0 CONTROLCURRENT_BROWSER_WORKFLOWS=1 npm run test:e2e -- --grep '@smoke\|@workflow'` | 0 | 60 passed: 20 each in Chromium, Firefox and WebKit; no failures, skips, flakes or retries. |
+| `CONTROLCURRENT_DEPLOY_TARGET=github-pages npm run verify` | 0 | Every stage passed; 396 tests in 44 files, none skipped. Repeated on the final staged tree before commit. |
+| `npm audit --audit-level=low --json` | 0 | Dedicated full application audit: zero vulnerabilities. |
+| `npm audit --audit-level=high` | 0 | Documented application gate: zero vulnerabilities. |
+| `npm audit --omit=dev --audit-level=low --json` | 0 | Production dependency advisory query: zero vulnerabilities. |
+| `npm audit signatures` | 0 | 414 registry signatures and 149 attestations verified. |
+| `npm audit --prefix "$RUNTIME" --audit-level=low --json` | 0 | Separate package-manager runtime audit: zero vulnerabilities. |
+| `npm audit signatures --prefix "$RUNTIME"` | 0 | 147 registry signatures and 72 attestations verified. |
+| `CONTROLCURRENT_DEPLOY_TARGET= CONTROLCURRENT_BROWSER_SMOKE=0 CONTROLCURRENT_BROWSER_WORKFLOWS=0 npm run test:e2e` | 0 | All 38 default Chromium/accessibility tests passed; no failures, skips, flakes or retries. |
+| `git diff --cached --check` and `git diff --quiet` | 0 | Staged patch passes whitespace checks and matches the worktree before commit. |
+
+The complete verification runs lint, formatting, TypeScript, Astro, unit coverage,
+repository audit, generated-data/schema checks, static build, public audit and
+language audit. Astro checks 73 files with zero errors, warnings or hints. Unit
+coverage is 88.82% statements, 79.32% branches, 94.21% functions and 90.48% lines;
+the expanded denominator meets the unchanged thresholds. The repository audit
+checks 200 tracked/unignored paths, 16 bounded public JSON files (480,213 bytes)
+and five workflows. All six schemas and 36 selected paths/30 controls match.
+The publication-target build has 45 pages and 73 public files (2,463,447 bytes).
+The language audit covers 177 authored paths, including the staged additions.
+
+The install count is not substituted for either dedicated audit. Application
+advisory metadata covers 516 lock-graph entries including optional platform
+packages; registry signatures cover the 414 installed packages. The separate
+runtime graph has 147 packages. No dependency or browser download was added by
+the optional engine checks; those engines were already installed locally.
+
+Intermediate failures are retained as development evidence. The first focused
+run had 68 passes and one obsolete Markdown expectation. The next had 35 passes
+and seven failures: the intended maximum-input reproduction, four parser-extension
+expectations, one legacy escaped-text expectation and one incorrect expected
+support state. The next had 95 passes and one incorrect JUnit-property expectation.
+Those fixtures now check the actual retained contracts. The extracted scripts
+initially exposed 377 strict-lint errors, predominantly inherited non-null
+assertions; typed element guards and async handlers resolved them without rule
+suppression. One remaining generic-helper error and the moved base-URL typing were
+also corrected. The new collector process fixture initially had a missing brace
+(11 other tests passed); all 15 then passed after repair. The first complete verify
+stopped at its new environment-variable type annotation, leaving subsequent stages
+unexecuted in that attempt. The corrected complete run and final staged run pass.
+Browser logs contain inherited colour-environment warnings; the tested CLI
+subprocesses have empty stderr on successful commands.
+
+## Changed files
+
+The local commit contains 37 files:
+
+- UI/model: `src/ci-output.ts`, `src/contracts.ts`, `src/source-age.ts`,
+ `src/components/Planner.astro`, `src/components/MinimumPlanner.astro`,
+ `src/components/EvidenceBundleInspector.astro`, `src/components/SourceContext.astro`,
+ `src/controllers/planner.ts`, `src/controllers/minimum-planner.ts`,
+ `src/controllers/evidence-bundle.ts`, `src/controllers/dom.ts`,
+ `src/controllers/download.ts`.
+- Local tooling: `tools/cli.ts`, `tools/private-output.ts`, `tools/bootstrap-npm.ts`,
+ `tools/toolchain-activation.ts`.
+- Verification: `tests/ci-output.test.ts`, `tests/decision-packet.test.ts`,
+ `tests/evaluate.test.ts`, `tests/npm-toolchain.test.ts`, `tests/private-output.test.ts`,
+ `tests/collector-cli-process.test.ts`, `tests/source-age.test.ts`,
+ `e2e/audit-boundaries.spec.ts`, `e2e/site.spec.ts`, `playwright.config.ts`,
+ `vitest.config.ts`.
+- Documentation: `README.md`, `docs/architecture.md`, `docs/authorised-collection.md`,
+ `docs/dependency-policy.md`, `docs/deployment-security.md`, `docs/methodology.md`,
+ `docs/policy-as-code.md`, `docs/pr32-follow-up.md`, `docs/pr32-local-corrections.md`,
+ `docs/pr32-optional-follow-up.md`.
+
+## Maintenance and provenance limits
+
+The current batch changes no package manifest, either lockfile, selected browser
+dataset, source history, WPT revision, workflow, install-script policy or licence
+inventory. The prior dated advisory and source-change evidence remains in
+[the maintenance handoff](pr32-local-corrections.md) and
+[the XML follow-up](pr32-follow-up.md). The original thirteen historical advisory
+items are not newly claimed to have been individually reconciled. Current audit
+results are separate from historical advisory reachability.
+
+BCD 8.1.4, WebDX 3.40.1, TypeScript 6.0.3 and Node types 24.19.1 are retained.
+This session uses Node 26.4.0 and the reviewed reconstructed npm 12.2.0; the Node 24
+floor is not independently exercised. The reconstruction remains a maintained
+distribution, not the unmodified upstream bundle. Hashes, registry signatures and
+attestations do not prove benign code. Compressed download bounds are not expanded
+disk quotas. Registry provenance is separate from authentic application evidence.
+
+The optional browsers use a disposable loopback HTTPS certificate with the
+documented context-wide test-only certificate bypass. This is not production TLS
+verification. No real signed evidence ceremony, native 400% zoom, hostile-directory
+race defence, current hosted run, branch protection, human environment approval or
+exact-main release check is claimed. Full bootstrap reconstruction is outside unit
+coverage even though archive tests and a successful fresh run provide other evidence.
+
+No push, merge, deployment, release, hosted workflow dispatch, live target
+collection, evidence upload, signing ceremony, external message or account change
+is part of this session. The only remote validation is the previously approved
+registry reconstruction, advisory queries and registry signature verification.
+Further publication or hosted runs need separate approval; merge and deployment
+retain their own renewed approval boundary.
diff --git a/e2e/audit-boundaries.spec.ts b/e2e/audit-boundaries.spec.ts
index b72901d..7fb39d3 100644
--- a/e2e/audit-boundaries.spec.ts
+++ b/e2e/audit-boundaries.spec.ts
@@ -1,5 +1,6 @@
import { expect, test, type Page } from "@playwright/test";
import { readFileSync } from "node:fs";
+import { readFile } from "node:fs/promises";
import { inspectEvidenceBundle } from "../src/evidence-bundle";
import { evaluateProfile } from "../src/evaluate";
import { selectedSnapshotSchema } from "../src/contracts";
@@ -157,7 +158,7 @@ async function settled(page: Page) {
.toBe(0);
}
-test("profile edits invalidate every derived export, including an empty browser selection", async ({
+test("profile edits invalidate every derived export, including an empty browser selection @workflow", async ({
page
}) => {
await page.goto("/planner/");
@@ -176,7 +177,7 @@ test("profile edits invalidate every derived export, including an empty browser
await expect(page.locator("#profile-results")).toBeHidden();
});
-test("rejects an unavailable imported release without substituting the old select value", async ({
+test("rejects an unavailable imported release without substituting the old select value @workflow", async ({
page
}) => {
await page.goto("/planner/");
@@ -197,7 +198,9 @@ test("rejects an unavailable imported release without substituting the old selec
await expect(page.getByLabel("Profile name")).not.toHaveValue("Unavailable plan");
});
-test("supports session-only evaluation with a throwing storage getter", async ({ page }) => {
+test("supports session-only evaluation with a throwing storage getter @workflow", async ({
+ page
+}) => {
await page.addInitScript(() =>
Object.defineProperty(window, "localStorage", {
get() {
@@ -214,7 +217,7 @@ test("supports session-only evaluation with a throwing storage getter", async ({
await expect(page.locator("#profile-message")).toContainText("not saved");
});
-test("clear and replacement supersede deferred evidence-file successes and errors", async ({
+test("clear and replacement supersede deferred evidence-file successes and errors @workflow", async ({
page
}) => {
await deferredInputs(page);
@@ -245,7 +248,9 @@ test("clear and replacement supersede deferred evidence-file successes and error
await expect(page.locator("#bundle-message")).not.toContainText("Stale synthetic");
});
-test("clear during deferred hashing cannot restore the report or its export", async ({ page }) => {
+test("clear during deferred hashing cannot restore the report or its export @workflow", async ({
+ page
+}) => {
await deferredInputs(page);
await page.goto("/assess/");
await page.locator(".advanced-assessment > summary").click();
@@ -262,7 +267,9 @@ test("clear during deferred hashing cannot restore the report or its export", as
await expect(page.locator("#bundle-form")).toHaveAttribute("aria-busy", "false");
});
-test("a profile edit cancels a deferred import before any form mutation", async ({ page }) => {
+test("a profile edit cancels a deferred import before any form mutation @workflow", async ({
+ page
+}) => {
await deferredInputs(page);
await page.goto("/planner/");
await page.locator("#import-profile").setInputFiles({
@@ -284,7 +291,7 @@ test("a profile edit cancels a deferred import before any form mutation", async
await expect(page.locator("#export-profile")).toBeDisabled();
});
-test("preserves import-before-evaluation comparison input but clears it on a genuine edit", async ({
+test("preserves import-before-evaluation comparison input but clears it on a genuine edit @workflow", async ({
page
}) => {
await page.goto("/planner/");
@@ -315,7 +322,7 @@ test("preserves import-before-evaluation comparison input but clears it on a gen
).toBeHidden();
});
-test("clear during deferred comparison hashing cannot restore comparison exports", async ({
+test("clear during deferred comparison hashing cannot restore comparison exports @workflow", async ({
page
}) => {
await deferredInputs(page);
@@ -337,7 +344,7 @@ test("clear during deferred comparison hashing cannot restore comparison exports
await expect(page.locator("#bundle-results")).toBeHidden();
});
-test("profile edits supersede deferred attachment validation and packet export", async ({
+test("profile edits supersede deferred attachment validation and packet export @workflow", async ({
page
}) => {
await deferredInputs(page);
@@ -407,3 +414,167 @@ test("planner remains keyboard-operable at enlarged text @smoke", async ({ page
).toBe(true);
expect(errors).toEqual([]);
});
+
+test("a pending replacement disables evidence review until its bytes arrive @workflow", async ({
+ page
+}) => {
+ await deferredInputs(page);
+ await page.goto("/assess/");
+ await page.locator(".advanced-assessment > summary").click();
+ await page.getByRole("button", { name: "Load redacted example" }).last().click();
+ const old = await page.locator("#bundle-block").inputValue();
+ const replacement = old.replace('"Release candidate"', '"Replacement evidence"');
+ await page.locator("#bundle-file").setInputFiles({
+ name: "replacement.json",
+ mimeType: "application/json",
+ buffer: Buffer.from(replacement)
+ });
+ await expect.poll(() => pending(page)).toEqual(["file"]);
+ await expect(page.getByRole("button", { name: "Review evidence file" })).toBeDisabled();
+ await expect(page.locator("#bundle-form")).toHaveAttribute("aria-busy", "true");
+ await expect(page.locator("#bundle-message")).toContainText("Reading evidence");
+ // Exercise the handler guard as well as the native disabled button.
+ await page.locator("#bundle-form").dispatchEvent("submit");
+ await expect(page.locator("#bundle-results")).toBeHidden();
+ await gate(page, "release", 0);
+ await settled(page);
+ await expect(page.locator("#bundle-block")).toHaveValue(replacement);
+ await expect(page.getByRole("button", { name: "Review evidence file" })).toBeEnabled();
+ await page.getByRole("button", { name: "Review evidence file" }).click();
+ await expect(page.locator("#bundle-source")).toContainText("Replacement evidence");
+});
+
+test("a pending comparison hides its predecessor from the visible result and exported report @workflow", async ({
+ page
+}) => {
+ await page.goto("/planner/");
+ await page.getByRole("button", { name: "Load example" }).click();
+ await page.getByRole("button", { name: "Check support" }).click();
+ const earlier = evaluateProfile(selectedSnapshot, {
+ schemaVersion: 1,
+ name: "Earlier snapshot",
+ baselines: [{ browser: "chrome", minimumVersion: "120" }]
+ });
+ await page.locator("#compare-profile").setInputFiles({
+ name: "earlier.json",
+ mimeType: "application/json",
+ buffer: Buffer.from(JSON.stringify(earlier))
+ });
+ await expect(page.locator("#profile-comparison")).toBeVisible();
+ // Delay the next read without navigating away from the retained result.
+ await page.evaluate(() => {
+ File.prototype.text = () =>
+ new Promise(() => {
+ /* Deliberately pending fixture. */
+ });
+ });
+ await page.locator("#compare-profile").setInputFiles({
+ name: "replacement.json",
+ mimeType: "application/json",
+ buffer: Buffer.from(JSON.stringify(earlier))
+ });
+ await expect(page.locator("#profile-message")).toContainText("Reading the earlier evaluation");
+ await expect(page.locator("#profile-comparison")).toBeHidden();
+ const downloading = page.waitForEvent("download");
+ await page.locator("#export-engineering-report").click();
+ const path = await (await downloading).path();
+ if (!path) throw new Error("Missing local report download");
+ expect(await readFile(path, "utf8")).not.toContain("Earlier snapshot");
+});
+
+test("bounded export and Blob failures reach the live status and recover without a download @workflow", async ({
+ page
+}) => {
+ await page.goto("/planner/");
+ await page.getByRole("button", { name: "Load example" }).click();
+ await page.getByRole("button", { name: "Check support" }).click();
+ const downloads: string[] = [];
+ page.on("download", (download) => downloads.push(download.suggestedFilename()));
+ await page.evaluate(() => {
+ const descriptor = Object.getOwnPropertyDescriptor(TextEncoder.prototype, "encode");
+ if (!descriptor) throw new Error("Missing native encoder");
+ TextEncoder.prototype.encode = function () {
+ Object.defineProperty(TextEncoder.prototype, "encode", descriptor);
+ return new Uint8Array(512 * 1024 + 1);
+ };
+ });
+ await page.locator("#export-profile").click();
+ await expect(page.locator("#profile-message")).toHaveAttribute("role", "status");
+ await expect(page.locator("#profile-message")).toContainText("exceeds the 524288-byte limit");
+ expect(downloads).toEqual([]);
+ await page.evaluate(() => {
+ const create = URL.createObjectURL.bind(URL);
+ URL.createObjectURL = () => {
+ URL.createObjectURL = create;
+ throw new Error("Synthetic Blob creation failure");
+ };
+ });
+ await page.locator("#export-profile").click();
+ await expect(page.locator("#profile-message")).toContainText("Synthetic Blob creation failure");
+ expect(downloads).toEqual([]);
+ const downloading = page.waitForEvent("download");
+ await page.locator("#export-profile").click();
+ expect((await downloading).suggestedFilename()).toBe("controlcurrent-profile.json");
+ await expect(page.locator("#profile-message")).toContainText("generated locally");
+});
+
+test("file-drop input stays local and never executes supplied markup @workflow", async ({
+ page
+}) => {
+ const external: string[] = [];
+ await page.route("**/*", async (route) => {
+ if (new URL(route.request().url()).hostname !== "127.0.0.1") {
+ external.push(route.request().url());
+ await route.abort();
+ } else await route.continue();
+ });
+ await page.goto("/assess/");
+ await page.locator(".advanced-assessment > summary").click();
+ await page.getByRole("button", { name: "Load redacted example" }).last().click();
+ const example: unknown = JSON.parse(await page.locator("#bundle-block").inputValue());
+ if (!example || typeof example !== "object") throw new Error("Missing fixture");
+ const fixture = {
+ ...example,
+ htmlDocuments: [
+ {
+ schemaVersion: 1,
+ name: "Synthetic markup",
+ surfaceId: "sign-in",
+ html: '
'
+ }
+ ]
+ };
+ const text = JSON.stringify(fixture);
+ await page.getByRole("button", { name: "Clear" }).last().click();
+ await page.locator("#bundle-drop").evaluate((element, value) => {
+ const transfer = new DataTransfer();
+ transfer.items.add(new File([value], "dropped.json", { type: "application/json" }));
+ element.dispatchEvent(
+ new DragEvent("drop", { bubbles: true, cancelable: true, dataTransfer: transfer })
+ );
+ }, text);
+ await expect(page.locator("#bundle-message")).toContainText("Evidence file loaded");
+ await page.getByRole("button", { name: "Review evidence file" }).click();
+ await expect(page.locator("#bundle-results")).toBeVisible();
+ expect(await page.evaluate(() => "fixtureExecuted" in window)).toBe(false);
+ expect(external).toEqual([]);
+});
+
+test("planning shows exact bundled timestamps and local source age beside both forms @workflow", async ({
+ page
+}) => {
+ await page.clock.setFixedTime(new Date("2026-10-10T12:00:00.000Z"));
+ await page.goto("/planner/");
+ const contexts = page.locator(".source-context");
+ await expect(contexts).toHaveCount(2);
+ for (const context of await contexts.all()) {
+ await expect(context.locator("time")).toHaveAttribute(
+ "datetime",
+ selectedSnapshot.bcdTimestamp
+ );
+ await expect(context).toContainText(`BCD ${selectedSnapshot.bcdVersion}`);
+ await expect(context).toContainText(`Web feature data ${selectedSnapshot.webFeaturesVersion}`);
+ await expect(context).toContainText("Package age on this device:");
+ await expect(context).toContainText("may omit later releases or corrections");
+ }
+});
diff --git a/e2e/site.spec.ts b/e2e/site.spec.ts
index 2e743d4..f722efa 100644
--- a/e2e/site.spec.ts
+++ b/e2e/site.spec.ts
@@ -28,7 +28,7 @@ test("renders real source provenance and makes no external request", async ({ pa
expect(violations.violations).toEqual([]);
});
-test("evaluates, stores, clears, and exports a profile locally", async ({ page }) => {
+test("evaluates, stores, clears, and exports a profile locally @workflow", async ({ page }) => {
await page.goto("/planner/");
await page.getByRole("button", { name: "Load example" }).click();
await page.getByRole("button", { name: "Check support" }).click();
@@ -122,7 +122,9 @@ test("evaluates, stores, clears, and exports a profile locally", async ({ page }
expect(violations.violations).toEqual([]);
});
-test("imports explicit browser minimums and builds a local policy report", async ({ page }) => {
+test("imports explicit browser minimums and builds a local policy report @workflow", async ({
+ page
+}) => {
await page.goto("/planner/");
await page.locator("#import-browser-config").setInputFiles({
name: "package.json",
@@ -309,7 +311,7 @@ test("wraps long browser-data labels without clipping", async ({ page }) => {
await expectLabelsInsideBounds();
});
-test("keeps dense views inside the viewport at 320 pixels", async ({ page }) => {
+test("keeps dense views inside the viewport at 320 pixels @workflow", async ({ page }) => {
await page.setViewportSize({ width: 320, height: 800 });
for (const path of [
"/",
@@ -451,7 +453,9 @@ test("assesses and clears a redacted header snapshot without a network request",
expect(await page.evaluate(() => localStorage.length)).toBe(0);
});
-test("reduces a multi-surface evidence bundle without exposing raw inputs", async ({ page }) => {
+test("reduces a multi-surface evidence bundle without exposing raw inputs @workflow", async ({
+ page
+}) => {
const externalRequests: string[] = [];
page.on("request", (request) => {
const url = new URL(request.url());
@@ -673,7 +677,9 @@ test("does not detect the actual browser or expose a runtime connection surface"
expect(source).not.toContain("userAgentData");
});
-test("publishes a restrictive meta policy and refuses embedded interaction", async ({ page }) => {
+test("publishes a restrictive meta policy and refuses embedded interaction @workflow", async ({
+ page
+}) => {
await page.goto("/assess/");
const policy = await page
.locator('meta[http-equiv="Content-Security-Policy"]')
diff --git a/playwright.config.ts b/playwright.config.ts
index 7934ac7..76e1df9 100644
--- a/playwright.config.ts
+++ b/playwright.config.ts
@@ -1,20 +1,23 @@
import { defineConfig, devices } from "@playwright/test";
const crossEngineSmoke = process.env.CONTROLCURRENT_BROWSER_SMOKE === "1";
-const fixtureOrigin = `${crossEngineSmoke ? "https" : "http"}://127.0.0.1:4389`;
+const crossEngineWorkflows = process.env.CONTROLCURRENT_BROWSER_WORKFLOWS === "1";
+const crossEngine = crossEngineSmoke || crossEngineWorkflows;
+const optionalTests = crossEngineWorkflows ? /@(?:smoke|workflow)/u : /@smoke/u;
+const fixtureOrigin = `${crossEngine ? "https" : "http"}://127.0.0.1:4389`;
export default defineConfig({
testDir: "e2e",
fullyParallel: false,
forbidOnly: Boolean(process.env.CI),
retries: process.env.CI ? 1 : 0,
- ...(process.env.CI || crossEngineSmoke ? { workers: 1 } : {}),
+ ...(process.env.CI || crossEngine ? { workers: 1 } : {}),
reporter: [["line"]],
use: {
baseURL: fixtureOrigin,
// Context-wide test-only bypass for the disposable loopback certificate;
// this does not verify production TLS or pin a particular certificate.
- ignoreHTTPSErrors: crossEngineSmoke,
+ ignoreHTTPSErrors: crossEngine,
trace: "retain-on-failure",
screenshot: "only-on-failure"
},
@@ -23,17 +26,17 @@ export default defineConfig({
name: "chromium",
use: { ...devices["Desktop Chrome"] }
},
- ...(crossEngineSmoke
+ ...(crossEngine
? [
- { name: "firefox", use: { ...devices["Desktop Firefox"] }, grep: /@smoke/u },
- { name: "webkit", use: { ...devices["Desktop Safari"] }, grep: /@smoke/u }
+ { name: "firefox", use: { ...devices["Desktop Firefox"] }, grep: optionalTests },
+ { name: "webkit", use: { ...devices["Desktop Safari"] }, grep: optionalTests }
]
: [])
],
webServer: {
- command: `npm run build && tsx tools/serve-dist.ts${crossEngineSmoke ? " --https-fixture" : ""}`,
+ command: `npm run build && tsx tools/serve-dist.ts${crossEngine ? " --https-fixture" : ""}`,
url: fixtureOrigin,
- ignoreHTTPSErrors: crossEngineSmoke,
+ ignoreHTTPSErrors: crossEngine,
reuseExistingServer: false,
timeout: 60_000
}
diff --git a/src/ci-output.ts b/src/ci-output.ts
index 5e5692a..8dfbd5b 100644
--- a/src/ci-output.ts
+++ b/src/ci-output.ts
@@ -9,15 +9,18 @@ import {
export type CliOutputFormat = "text" | "json" | "markdown" | "junit";
function markdown(value: string): string {
- return Array.from(value)
- .map((character) => {
- const codePoint = character.codePointAt(0);
- return codePoint !== undefined && (codePoint < 32 || codePoint === 127) ? " " : character;
- })
- .join("")
- .replaceAll("\\", "\\\\")
- .replaceAll("|", "\\|")
- .trim();
+ return (
+ Array.from(value)
+ .map((character) => {
+ const codePoint = character.codePointAt(0);
+ return codePoint !== undefined && (codePoint < 32 || codePoint === 127) ? " " : character;
+ })
+ .join("")
+ // Escape all CommonMark punctuation in supplied text, including entities,
+ // HTML, autolinks, images and formatting. Renderer-owned syntax stays intact.
+ .replace(/[!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]/gu, "\\$&")
+ .trim()
+ );
}
function xml(value: string): string {
diff --git a/src/components/EvidenceBundleInspector.astro b/src/components/EvidenceBundleInspector.astro
index 66247b1..ecdf5a5 100644
--- a/src/components/EvidenceBundleInspector.astro
+++ b/src/components/EvidenceBundleInspector.astro
@@ -111,713 +111,6 @@ import { selectedSnapshot } from "../data";
diff --git a/src/components/MinimumPlanner.astro b/src/components/MinimumPlanner.astro
index 2346a87..2018298 100644
--- a/src/components/MinimumPlanner.astro
+++ b/src/components/MinimumPlanner.astro
@@ -2,6 +2,7 @@
import { BROWSER_IDS } from "../browsers";
import { SECURITY_CONTROLS } from "../catalogue";
import { browserNames } from "../format";
+import SourceContext from "./SourceContext.astro";
const defaultControls = new Set([
"content-security-policy",
@@ -26,6 +27,8 @@ const categories = [...new Set(SECURITY_CONTROLS.map((control) => control.catego
+
+