ci: advisory lockfile supply-chain audit (no install-script changes) (#5604)
* ci: add advisory lockfile supply-chain audit Adds a fast, focused workflow that scans every checked-in npm and cargo lockfile on PRs touching one. Default behaviour is advisory: only public indicator-of-compromise strings, versions on the public known-malicious list, and structurally broken lockfiles fail the build. Structural anomalies (missing integrity hashes, non-default registry, etc.) surface as :⚠️: annotations without gating merges, so reviewers see the audit result inline on every PR without changing the existing install behaviour. Also commits the two missing npm lockfiles the audit needs: studio/package-lock.json (Tauri CLI holder for desktop release) and studio/backend/core/data_recipe/oxc-validator/package-lock.json (oxc-parser runtime for the data-recipe validator). studio/setup.sh, studio/setup.ps1, build.sh, and pyproject.toml are intentionally left alone so the existing install path keeps working unchanged. Audit script behaviour: default mode -> exits 1 only on blocked-known-malicious, known-ioc-string, malformed-lockfile, missing-lockfile, unreadable-lockfile, or missing-toml-parser --strict -> promotes every finding to blocking (opt-in) Adds a try/except around lockfile reads so a permissions error prints a finding instead of crashing CI with a raw traceback. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * test(security): update cargo regression test for advisory mode `scripts/lockfile_supply_chain_audit.py` now classifies `non-registry-cargo-source` as an advisory finding by default (returns exit 0 with a `:⚠️:` annotation) rather than unconditionally blocking with exit 1. Update the existing `test_malicious_cargo_lockfile_refused` to pass --strict so it keeps verifying the "refuse to install" behavior it is named for, and add a second test that pins the default-mode behavior: advisory finding emitted, exit code 0. * audit: escape Finding for GH Actions annotations `:⚠️:` and `::error::` workflow commands truncate the annotation message at the first newline unless the message is %-encoded per the workflow-commands spec. Since `Finding.__str__` returns three lines (kind+path, package, detail), the package and detail fields were being dropped from the GitHub Actions UI. Add a `_gha_escape()` helper that applies the spec'd escapes (`%` -> `%25`, then `\r` -> `%0D`, then `\n` -> `%0A`; the `%` replacement must happen first so the subsequent escapes are not double-encoded), wrap every Finding rendered into a workflow command with it, and pin both the helper and the end-to-end single-line emission with two new regression tests. Caught by gemini-code-assist on PR #5604. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
d1681ea158
commit
dd0b557794
7 changed files with 1384 additions and 12 deletions
79
.github/workflows/lockfile-audit.yml
vendored
Normal file
79
.github/workflows/lockfile-audit.yml
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved.
|
||||
#
|
||||
# Fast, focused supply-chain audit of every checked-in lockfile.
|
||||
#
|
||||
# Runs scripts/lockfile_supply_chain_audit.py on PRs that touch any
|
||||
# npm or cargo lockfile, on push to main, and on a daily schedule so
|
||||
# newly-published IOCs surface even when no PR opens.
|
||||
#
|
||||
# Default behavior is "advisory": only public indicator-of-compromise
|
||||
# strings, known-malicious pinned versions, and structurally broken
|
||||
# lockfiles fail the build. Structural anomalies (missing integrity,
|
||||
# non-default registry, etc.) are emitted as GitHub Actions warnings
|
||||
# but do not block merges. This deliberately keeps the noise floor
|
||||
# low while still failing the moment a checked-in lockfile starts
|
||||
# pointing at known-bad bytes.
|
||||
#
|
||||
# This workflow is intentionally separate from security-audit.yml:
|
||||
# - security-audit.yml is the umbrella job (pip-audit + npm audit +
|
||||
# cargo audit + OSV + Semgrep + secret scanning + SBOM + ...);
|
||||
# it takes ~25 minutes and runs only when dep manifests change.
|
||||
# - lockfile-audit.yml is a ~30 second pure-Python parse + grep on
|
||||
# the lockfiles themselves; it runs on every PR that even nudges
|
||||
# a lockfile so reviewers always see the audit result inline.
|
||||
|
||||
name: Lockfile supply-chain audit
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'studio/frontend/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package-lock.json'
|
||||
- 'studio/package-lock.json'
|
||||
- 'studio/src-tauri/Cargo.lock'
|
||||
- 'scripts/lockfile_supply_chain_audit.py'
|
||||
- '.github/workflows/lockfile-audit.yml'
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'studio/frontend/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package-lock.json'
|
||||
- 'studio/package-lock.json'
|
||||
- 'studio/src-tauri/Cargo.lock'
|
||||
- 'scripts/lockfile_supply_chain_audit.py'
|
||||
- '.github/workflows/lockfile-audit.yml'
|
||||
schedule:
|
||||
- cron: '37 5 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
name: lockfile supply-chain audit
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Verify audit script parses
|
||||
run: python3 -c "import ast; ast.parse(open('scripts/lockfile_supply_chain_audit.py').read())"
|
||||
|
||||
- name: Run lockfile supply-chain audit
|
||||
# Default mode: only known-malicious pinned versions, known IOC
|
||||
# strings, and structurally broken lockfiles fail the build.
|
||||
# Missing-integrity and other structural anomalies are emitted
|
||||
# as ::warning:: annotations and do not gate merges.
|
||||
run: python3 scripts/lockfile_supply_chain_audit.py
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -229,5 +229,9 @@ log.txt
|
|||
setup_leo.sh
|
||||
server.pid
|
||||
*.log
|
||||
# Ignore stray lockfiles; real npm projects opt back in below (npm ci needs them).
|
||||
package-lock.json
|
||||
!studio/frontend/package-lock.json
|
||||
!studio/backend/core/data_recipe/oxc-validator/package-lock.json
|
||||
!studio/package-lock.json
|
||||
llama.cpp/
|
||||
|
|
|
|||
|
|
@ -389,6 +389,18 @@ class Finding:
|
|||
)
|
||||
|
||||
|
||||
def _gha_escape(text: str) -> str:
|
||||
"""Escape a string for use in a GitHub Actions `::warning::` /
|
||||
`::error::` workflow command message. GH Actions truncates
|
||||
annotation messages at the first newline unless `\\n` is
|
||||
escaped as `%0A`; carriage returns and the percent sign need
|
||||
matching escapes per the workflow-commands spec. Order matters:
|
||||
`%` must be replaced first so the subsequent `%0A` / `%0D`
|
||||
sequences are not double-encoded.
|
||||
"""
|
||||
return text.replace("%", "%25").replace("\r", "%0D").replace("\n", "%0A")
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# package-lock.json audit.
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
|
|
@ -397,9 +409,35 @@ class Finding:
|
|||
def audit_npm_lockfile(path: Path) -> list[Finding]:
|
||||
findings: list[Finding] = []
|
||||
if not path.exists():
|
||||
# A missing requested lockfile is a config error, not a clean
|
||||
# audit; surface it so a deleted default cannot pass silently.
|
||||
findings.append(
|
||||
Finding(
|
||||
path = str(path),
|
||||
package = "<root>",
|
||||
kind = "missing-lockfile",
|
||||
detail = (
|
||||
"expected lockfile not found; refusing to silently "
|
||||
"report a clean audit for a path that was not scanned"
|
||||
),
|
||||
)
|
||||
)
|
||||
return findings
|
||||
|
||||
raw = path.read_text(encoding = "utf-8")
|
||||
try:
|
||||
raw = path.read_text(encoding = "utf-8")
|
||||
except OSError as exc:
|
||||
# Permission denied, is-a-directory, broken-pipe etc. -- surface
|
||||
# as a finding instead of crashing CI with a raw traceback.
|
||||
findings.append(
|
||||
Finding(
|
||||
path = str(path),
|
||||
package = "<root>",
|
||||
kind = "unreadable-lockfile",
|
||||
detail = f"could not read file: {exc}",
|
||||
)
|
||||
)
|
||||
return findings
|
||||
try:
|
||||
lock = json.loads(raw)
|
||||
except json.JSONDecodeError as exc:
|
||||
|
|
@ -553,9 +591,32 @@ _PACKAGE_HEADER = re.compile(r"^\[\[package\]\]\s*$")
|
|||
def audit_cargo_lockfile(path: Path) -> list[Finding]:
|
||||
findings: list[Finding] = []
|
||||
if not path.exists():
|
||||
# See audit_npm_lockfile: missing lockfile is a finding.
|
||||
findings.append(
|
||||
Finding(
|
||||
path = str(path),
|
||||
package = "<root>",
|
||||
kind = "missing-lockfile",
|
||||
detail = (
|
||||
"expected lockfile not found; refusing to silently "
|
||||
"report a clean audit for a path that was not scanned"
|
||||
),
|
||||
)
|
||||
)
|
||||
return findings
|
||||
|
||||
raw = path.read_text(encoding = "utf-8")
|
||||
try:
|
||||
raw = path.read_text(encoding = "utf-8")
|
||||
except OSError as exc:
|
||||
findings.append(
|
||||
Finding(
|
||||
path = str(path),
|
||||
package = "<root>",
|
||||
kind = "unreadable-lockfile",
|
||||
detail = f"could not read file: {exc}",
|
||||
)
|
||||
)
|
||||
return findings
|
||||
try:
|
||||
import tomllib # type: ignore[import-not-found]
|
||||
except ImportError:
|
||||
|
|
@ -652,7 +713,31 @@ def audit_cargo_lockfile(path: Path) -> list[Finding]:
|
|||
# ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
DEFAULT_NPM_LOCKFILES = ("studio/frontend/package-lock.json",)
|
||||
# Finding kinds split into BLOCKING vs ADVISORY for the default run mode.
|
||||
# Blocking findings come from public supply-chain attack indicators (a
|
||||
# version we know is malicious, a string an attacker would have to embed
|
||||
# for an attack to work). Advisory findings are structural lockfile
|
||||
# anomalies (missing integrity, non-default registry, etc.) -- they
|
||||
# WARN the maintainer but do not block merges. Pass --strict to make
|
||||
# every finding blocking (PR-5479-style behavior for opt-in adopters).
|
||||
BLOCKING_KINDS: frozenset[str] = frozenset(
|
||||
{
|
||||
"blocked-known-malicious",
|
||||
"known-ioc-string",
|
||||
# Internal-failure kinds: a structurally broken lockfile MIGHT
|
||||
# be hiding a real attack, so we keep these blocking too.
|
||||
"malformed-lockfile",
|
||||
"missing-lockfile",
|
||||
"unreadable-lockfile",
|
||||
"missing-toml-parser",
|
||||
}
|
||||
)
|
||||
|
||||
DEFAULT_NPM_LOCKFILES = (
|
||||
"studio/frontend/package-lock.json",
|
||||
"studio/backend/core/data_recipe/oxc-validator/package-lock.json",
|
||||
"studio/package-lock.json",
|
||||
)
|
||||
DEFAULT_CARGO_LOCKFILES = ("studio/src-tauri/Cargo.lock",)
|
||||
|
||||
|
||||
|
|
@ -671,7 +756,9 @@ def main(argv: list[str] | None = None) -> int:
|
|||
default = None,
|
||||
help = (
|
||||
"Path to a package-lock.json (repeatable). "
|
||||
"Default: studio/frontend/package-lock.json."
|
||||
"Default: studio/frontend/package-lock.json, "
|
||||
"studio/backend/core/data_recipe/oxc-validator/package-lock.json, "
|
||||
"and studio/package-lock.json (Tauri CLI for desktop release)."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
|
|
@ -683,6 +770,18 @@ def main(argv: list[str] | None = None) -> int:
|
|||
"Default: studio/src-tauri/Cargo.lock."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--strict",
|
||||
action = "store_true",
|
||||
help = (
|
||||
"Treat every finding as blocking (exit 1). "
|
||||
"Default mode only blocks on known-malicious versions, "
|
||||
"indicator-of-compromise strings, or structurally broken "
|
||||
"lockfiles; everything else is printed as an advisory "
|
||||
"warning with exit 0. CI should use the default; local "
|
||||
"audits aiming for zero noise can opt in via --strict."
|
||||
),
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
# SF4: require a real justification (e.g. JIRA ticket id) for the
|
||||
|
|
@ -715,8 +814,15 @@ def main(argv: list[str] | None = None) -> int:
|
|||
return 0
|
||||
|
||||
root = Path(args.root).resolve()
|
||||
npm_paths = [root / p for p in (args.npm_lockfile or DEFAULT_NPM_LOCKFILES)]
|
||||
cargo_paths = [root / p for p in (args.cargo_lockfile or DEFAULT_CARGO_LOCKFILES)]
|
||||
# Explicit --npm-lockfile/--cargo-lockfile scopes the scan to those
|
||||
# paths; defaults apply only to the no-args CI invocation.
|
||||
_user_explicit = args.npm_lockfile is not None or args.cargo_lockfile is not None
|
||||
if _user_explicit:
|
||||
npm_paths = [root / p for p in (args.npm_lockfile or ())]
|
||||
cargo_paths = [root / p for p in (args.cargo_lockfile or ())]
|
||||
else:
|
||||
npm_paths = [root / p for p in DEFAULT_NPM_LOCKFILES]
|
||||
cargo_paths = [root / p for p in DEFAULT_CARGO_LOCKFILES]
|
||||
|
||||
all_findings: list[Finding] = []
|
||||
for p in npm_paths:
|
||||
|
|
@ -734,17 +840,57 @@ def main(argv: list[str] | None = None) -> int:
|
|||
)
|
||||
return 0
|
||||
|
||||
# Split findings into blocking (known-malicious / IOC / structurally
|
||||
# broken) and advisory (everything else, e.g. missing integrity on a
|
||||
# registry-published tarball). In default mode advisory findings are
|
||||
# printed but do not change the exit code; --strict treats every
|
||||
# finding as blocking.
|
||||
blocking = [f for f in all_findings if f.kind in BLOCKING_KINDS]
|
||||
advisory = [f for f in all_findings if f.kind not in BLOCKING_KINDS]
|
||||
|
||||
if args.strict:
|
||||
blocking = list(all_findings)
|
||||
advisory = []
|
||||
|
||||
if advisory:
|
||||
print(
|
||||
f"\n[lockfile-audit] {len(advisory)} advisory finding(s) "
|
||||
"(non-blocking; pass --strict to fail the build on these):\n",
|
||||
file = sys.stderr,
|
||||
)
|
||||
for f in advisory:
|
||||
# Surface in GitHub Actions UI as a warning annotation when run
|
||||
# under Actions; harmless prefix elsewhere. GH Actions
|
||||
# truncates annotation messages at the first newline unless
|
||||
# newlines are escaped as `%0A`, so the full multi-line
|
||||
# Finding (kind + path + package + detail) only renders in
|
||||
# the UI after _gha_escape collapses it onto one line.
|
||||
print(f"::warning::{_gha_escape(str(f))}", file = sys.stderr)
|
||||
print(file = sys.stderr)
|
||||
|
||||
if not blocking:
|
||||
print(
|
||||
f"[lockfile-audit] OK: {len(advisory)} advisory finding(s), "
|
||||
"0 blocking. Run with --strict to escalate advisory findings.",
|
||||
flush = True,
|
||||
)
|
||||
return 0
|
||||
|
||||
print(
|
||||
f"\n[lockfile-audit] FAIL: {len(all_findings)} finding(s):\n",
|
||||
f"\n[lockfile-audit] FAIL: {len(blocking)} blocking finding(s):\n",
|
||||
file = sys.stderr,
|
||||
)
|
||||
for f in all_findings:
|
||||
print(str(f), file = sys.stderr)
|
||||
for f in blocking:
|
||||
# Same %-encoding rationale as the advisory branch above: the
|
||||
# GH Actions annotation is truncated at the first newline
|
||||
# unless the message is escaped.
|
||||
print(f"::error::{_gha_escape(str(f))}", file = sys.stderr)
|
||||
print(file = sys.stderr)
|
||||
print(
|
||||
"[lockfile-audit] Refusing to proceed. Each finding above is "
|
||||
"either a structural lockfile anomaly or a public indicator-of-"
|
||||
"compromise. Investigate before running `npm ci` or `cargo fetch`.",
|
||||
"[lockfile-audit] Refusing to proceed. Each blocking finding "
|
||||
"above is either a public indicator-of-compromise, a known-"
|
||||
"malicious pinned version, or a structurally broken lockfile. "
|
||||
"Investigate before running `npm ci` or `cargo fetch`.",
|
||||
file = sys.stderr,
|
||||
)
|
||||
return 1
|
||||
|
|
|
|||
799
studio/backend/core/data_recipe/oxc-validator/package-lock.json
generated
Normal file
799
studio/backend/core/data_recipe/oxc-validator/package-lock.json
generated
Normal file
|
|
@ -0,0 +1,799 @@
|
|||
{
|
||||
"name": "unsloth-oxc-validator-runtime",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "unsloth-oxc-validator-runtime",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"oxc-parser": "^0.123.0",
|
||||
"oxlint": "^1.51.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
|
||||
"integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@emnapi/wasi-threads": "1.2.1",
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/runtime": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
|
||||
"integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/wasi-threads": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
|
||||
"integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
|
||||
"integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@tybys/wasm-util": "^0.10.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emnapi/core": "^1.7.1",
|
||||
"@emnapi/runtime": "^1.7.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-android-arm-eabi": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.123.0.tgz",
|
||||
"integrity": "sha512-EHQ58z+6DbZWokMOKg5AB1KuwrXVgfbBLuuLFfzdc7bI5A4igvdvjKMhUv1VBV+0FABiUCOjNKUmMF7ugprwbQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-android-arm64": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.123.0.tgz",
|
||||
"integrity": "sha512-BK1E0zqNoHf38nTHjnGZ+olKHSKNHh65pChjY06yhaWYP8X7yNDqhQDA4neMPRqnPBgpN4/OW1oSMrdJgDi2aw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-darwin-arm64": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.123.0.tgz",
|
||||
"integrity": "sha512-dkMPbtTbqU+cm+k4YGOBs4zAuq3Xu+wqjbGQvLAuVO7qHhNY4p5LBNudOmOoi0jxS8h1W6Jmlzv8MAKGpK+iDg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-darwin-x64": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.123.0.tgz",
|
||||
"integrity": "sha512-85pic0rCd59DGdM69jI9xE/Snb2KtrfiU48QigjJXjzxUOenGvH4SAFIjFpO/2ZnI3Kz50D8pht4jKN3t2022Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-freebsd-x64": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.123.0.tgz",
|
||||
"integrity": "sha512-mjEiW6z7JtaiHMK/8aJic1lfjkKpzFwK2XFNmm187BFbtDamjGVuKNr2TEyrFEYJyZc217wokR1wrYeZGBQo4Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-linux-arm-gnueabihf": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.123.0.tgz",
|
||||
"integrity": "sha512-mYxigPtGt6SZfhNZBIJfuDM92cLo8XUW08WuKxzHvcmWu6xndLqwLp99Vg4uHke1AXicQEHU3Wri2X9bHF0Vlw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-linux-arm-musleabihf": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.123.0.tgz",
|
||||
"integrity": "sha512-ttWirDC9eUBn0R4Tzz3aeDaLrx9drPdNiLJ8MXeDBFxd6cwLfTIC27qjsdfGpn942tkVIZY3sjWAnvbwDDjX7g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-linux-arm64-gnu": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.123.0.tgz",
|
||||
"integrity": "sha512-apAHyoMNRYT+2G98Y14caZmsr5LD9PsWpGI7nXmSwK26LGiQneCU6HvHQ+d+AX+RJ5TTWZtEb2RD7OLqAC0cYQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-linux-arm64-musl": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.123.0.tgz",
|
||||
"integrity": "sha512-3r99Qa4egjO/iXUBxTlN6Ddt1YkLifG6olzvj8gkoKEK2U/MOW7mQfXRyBmuoMgmZ7O4vk41gO3d21c6VcN3yQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-linux-ppc64-gnu": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.123.0.tgz",
|
||||
"integrity": "sha512-Hr/Z24kUE4pjJs346g80WDwjyJGrxiw6hExJuOiME/76ZFz68y5L11UzprRkW9FN4HxBB7tLZ/fytczV2fEsiA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-linux-riscv64-gnu": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.123.0.tgz",
|
||||
"integrity": "sha512-sxjbhs+8WXeuoLnZ2rBmQ96gPdq3SCmz24reIltsKLUt1EDMgdaQsr7RqwBphw3QAImkMtlPQfAWDWwZyo0xDg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-linux-riscv64-musl": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.123.0.tgz",
|
||||
"integrity": "sha512-d6xHHhqldA/W+VC7v8uHs24zM69Ad3HnHQ45h+uuBhCsbZx3d0E0wL2K3uJ5mYKTR6UPMFk9VMXcHWwvg1PRZQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-linux-s390x-gnu": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.123.0.tgz",
|
||||
"integrity": "sha512-+di9A5wJQlv0VodyhADjJ2rC4geyHY+uhJDl3TFjMgYhhlgLZchi9uHD5mfiUEDWHt1x7/eU2u1ge3LLazZmFw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-linux-x64-gnu": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.123.0.tgz",
|
||||
"integrity": "sha512-sh7pw2g/u6LE1TaRRQsV9Kv9+1y+CywaaNwWWP+3bnEPk/L692oTG0hmEviUlawI8v3OGC+AhbjtAD+HXWQAkg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-linux-x64-musl": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.123.0.tgz",
|
||||
"integrity": "sha512-S+LoD8PiJ639JwIqK1knIeqAyYkeCbLHtAgfapszKX0yVCaYP+aer8dJxL25de9qcDjvYWVrYCkuDZzHmOl2Xw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-openharmony-arm64": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.123.0.tgz",
|
||||
"integrity": "sha512-/65vryK11q1I+k+7ukDlwZOxUFCLYsoZBZPGZHyet5bIP5e3D8mV3uCuvpWZ9Hoe6vUZFw/nAfCrX59MeuJPgw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-wasm32-wasi": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.123.0.tgz",
|
||||
"integrity": "sha512-y4OsMGQiAbZzj2Rq0LEfvhR48rQDvbvqsl/dPdn4tdf+z3H79nZuR+lQ/+KUGjD30vpVGem138sBWHFj9UR+Vg==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@napi-rs/wasm-runtime": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-win32-arm64-msvc": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.123.0.tgz",
|
||||
"integrity": "sha512-9lBqI6AXAkjYavkdpizNU3Q51uoVYfp9FJPx19hnCEdPku1jSgzSnvgmCvhCue0GziIvIvIdWgZ41wXQ3EOoBw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-win32-ia32-msvc": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.123.0.tgz",
|
||||
"integrity": "sha512-zJbqBHwSUB7CyvAONy9ewGtQwcQj+ylOhYGETvUPp3KIYx7lolj4Gayof7iA22SU5eMSjO5COL0c8wYhmn9agA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-parser/binding-win32-x64-msvc": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.123.0.tgz",
|
||||
"integrity": "sha512-q7RZvglQvGo3RX5ljtcGSabu2B2c0oDU/6xC3sBMhsV5KRo0PvyxLdordbEN31NTfuZu4Sgl86C76cAURZIHWA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-project/types": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.123.0.tgz",
|
||||
"integrity": "sha512-YtECP/y8Mj1lSHiUWGSRzy/C6teUKlS87dEfuVKT09LgQbUsBW1rNg+MiJ4buGu3yuADV60gbIvo9/HplA56Ew==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/Boshen"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-android-arm-eabi": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.64.0.tgz",
|
||||
"integrity": "sha512-2r6Nq3XXGLHEXKkSj8JtmJ6N4gDw431DPFOg0ZoJHlNjnG6HVMm/ksQ10m0HJ8WBvwgMe1L50UHPaYZutCRPCw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-android-arm64": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.64.0.tgz",
|
||||
"integrity": "sha512-ePJMpePgg7fBv+L/hVx1xXRU5/5gd5m0obLA6hPEfLXF3GjpR8idIDbY1dhQYhyz1ms2wdTccSboo6KEd2Oxtg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-darwin-arm64": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.64.0.tgz",
|
||||
"integrity": "sha512-U4DMLQd10gJLuoSTLSGbfv3bGjTlUNsScm9Dgb8wwBqmCzidf1pE1pXV4doGNxqwH3KtVng1AGTINA0NvkGLvQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-darwin-x64": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.64.0.tgz",
|
||||
"integrity": "sha512-GoRIL48QWm4/TAvjN8pB1nAG+1/uqc9EdnWT9zqHeb6wsmjZtywj8VRe5aGW47Fdb64YtLOsdLqVxOvQuz98Wg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-freebsd-x64": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.64.0.tgz",
|
||||
"integrity": "sha512-5dFkv4tkg7PxJJGS9/OjrJwjhuHczrd3OQOkRE0wHcLM+ncUnULtzEPWjqGOxTXxZnLWcB91bGiIznx89TVXyQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-arm-gnueabihf": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.64.0.tgz",
|
||||
"integrity": "sha512-jsBqMLl/uOL5+Kq/+BtK9FrmiNGUbx8SiyZXv+WlUxA45KuwcLu9BfiSIL3I3DBDgWM3yZizDITnTK9BcqNBQg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-arm-musleabihf": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.64.0.tgz",
|
||||
"integrity": "sha512-1lrj8At/Uuc9GhjrVFBQo0NEjfBrTkzpmtHIGAhNnIXqn1CAyGL+qrztUsXb2GIluJrpl9Q7qRLJOb/NqydacQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-arm64-gnu": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.64.0.tgz",
|
||||
"integrity": "sha512-HpSQbubwh03mMhAdy2BYtad/fsY8vDFHDAb6bUwuCYg2VD3xCQgn6ArKcO0oZyLCheacKTv4PrF3Mfu5hgoE2g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-arm64-musl": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.64.0.tgz",
|
||||
"integrity": "sha512-00QQ0h0Y7u0G69BgiH3+ky2aaq/QvkDL6DYok8htIuJHxybiux5aQ8jwmg8qIk9wha6UagUP2BAwAzbemcJbpg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-ppc64-gnu": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.64.0.tgz",
|
||||
"integrity": "sha512-2GaimTV6EMW+s5HS0An3oGbQme3BgHswvfVdGk3EB57Xe9+/gyT+Qd7lNVzb3rtir52vbIPzXfaYArzs5b5zcw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-riscv64-gnu": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.64.0.tgz",
|
||||
"integrity": "sha512-H46AtFb9wypjoVwGdlxrm0DsD809NGmtiK9HiyPKTxkSte2YjhC4S+00rOIrwCaxcyPiGid3Y3OMXp5KMAkGZw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-riscv64-musl": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.64.0.tgz",
|
||||
"integrity": "sha512-HEgsidjjvvyzdg82icYkuFCf7REDV7B9JFwbIMbVwrKLBY0MrXX+bku3POn/hduZ2yW91IyVDUMq0Bf02KwXQw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-s390x-gnu": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.64.0.tgz",
|
||||
"integrity": "sha512-Axvm8qryotmKN00P5w4JapaSjvP2LOSbdbBJiX+2SuHd3QzhW7TUc8skqgw+ahQZ5DmzEYeHCqauvW8f32Ns6Q==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-x64-gnu": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.64.0.tgz",
|
||||
"integrity": "sha512-cR60vSd7+m+KRZ3GQGfDxWwahW5RMXg0qlGvAluZr0fTUYvw0H9N9AXAF/M/PMqgytyqvVNmBAkJG9l7U30Y1g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-x64-musl": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.64.0.tgz",
|
||||
"integrity": "sha512-2u/aPZ9pEg7HnvZPDsHxUGNnrpr4qaHi+mCgLgpt+LYRzPrS4Px4wPfkIdRdr2GvKnaYyt+XSlto0Vm5sbStTg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-openharmony-arm64": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.64.0.tgz",
|
||||
"integrity": "sha512-kfhkGfCdoXLSxEkrhDlJrvBYajGmq+ma4EMc53dsOWTq+rIBOlI0vTBmpZNnM5oH2LY/K/w1HAK+UQEgjgpVUg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-win32-arm64-msvc": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.64.0.tgz",
|
||||
"integrity": "sha512-r/cNKBFieONoVu2bb1KkVouq9W+edDUgHumXJGphCRRj+U0xaD4nanrw8ZOqo0IsutPkEM4vCcGBpak6x5aXMg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-win32-ia32-msvc": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.64.0.tgz",
|
||||
"integrity": "sha512-tUw0xUUwEFVZbpJoeCblkv8SJA4Xz3CdXCJbAnBsiNLyxDrk2tLcxEAS6M73Q7hHHDg3OtwI8vZVK3t5RJt4Gw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-win32-x64-msvc": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.64.0.tgz",
|
||||
"integrity": "sha512-9CBR+LO0JVST87fNTzzNxS5I29jIUO5gxT9i9+M3SDHHALElj9sY1Prf12tad3vIRC6OD7Ehtvvh+sn13vSwHw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tybys/wasm-util": {
|
||||
"version": "0.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz",
|
||||
"integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/oxc-parser": {
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.123.0.tgz",
|
||||
"integrity": "sha512-F6ak0tFc01ZGbl5KxvLDQ2K005Z086mp3ByCQBDhUjqXLkapGUkMuJSsYixncdEpkLlcRDcruHR71LD339ADUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@oxc-project/types": "^0.123.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/Boshen"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@oxc-parser/binding-android-arm-eabi": "0.123.0",
|
||||
"@oxc-parser/binding-android-arm64": "0.123.0",
|
||||
"@oxc-parser/binding-darwin-arm64": "0.123.0",
|
||||
"@oxc-parser/binding-darwin-x64": "0.123.0",
|
||||
"@oxc-parser/binding-freebsd-x64": "0.123.0",
|
||||
"@oxc-parser/binding-linux-arm-gnueabihf": "0.123.0",
|
||||
"@oxc-parser/binding-linux-arm-musleabihf": "0.123.0",
|
||||
"@oxc-parser/binding-linux-arm64-gnu": "0.123.0",
|
||||
"@oxc-parser/binding-linux-arm64-musl": "0.123.0",
|
||||
"@oxc-parser/binding-linux-ppc64-gnu": "0.123.0",
|
||||
"@oxc-parser/binding-linux-riscv64-gnu": "0.123.0",
|
||||
"@oxc-parser/binding-linux-riscv64-musl": "0.123.0",
|
||||
"@oxc-parser/binding-linux-s390x-gnu": "0.123.0",
|
||||
"@oxc-parser/binding-linux-x64-gnu": "0.123.0",
|
||||
"@oxc-parser/binding-linux-x64-musl": "0.123.0",
|
||||
"@oxc-parser/binding-openharmony-arm64": "0.123.0",
|
||||
"@oxc-parser/binding-wasm32-wasi": "0.123.0",
|
||||
"@oxc-parser/binding-win32-arm64-msvc": "0.123.0",
|
||||
"@oxc-parser/binding-win32-ia32-msvc": "0.123.0",
|
||||
"@oxc-parser/binding-win32-x64-msvc": "0.123.0"
|
||||
}
|
||||
},
|
||||
"node_modules/oxlint": {
|
||||
"version": "1.64.0",
|
||||
"resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.64.0.tgz",
|
||||
"integrity": "sha512-Star3SNpWPeWFPw7kRXIhXUSn6fdiAl25q15CQzH/9WaOtG6e9CWTc25vNZOCr4PE1yEP1GtKJKIKglhj3OmEQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"oxlint": "bin/oxlint"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/Boshen"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@oxlint/binding-android-arm-eabi": "1.64.0",
|
||||
"@oxlint/binding-android-arm64": "1.64.0",
|
||||
"@oxlint/binding-darwin-arm64": "1.64.0",
|
||||
"@oxlint/binding-darwin-x64": "1.64.0",
|
||||
"@oxlint/binding-freebsd-x64": "1.64.0",
|
||||
"@oxlint/binding-linux-arm-gnueabihf": "1.64.0",
|
||||
"@oxlint/binding-linux-arm-musleabihf": "1.64.0",
|
||||
"@oxlint/binding-linux-arm64-gnu": "1.64.0",
|
||||
"@oxlint/binding-linux-arm64-musl": "1.64.0",
|
||||
"@oxlint/binding-linux-ppc64-gnu": "1.64.0",
|
||||
"@oxlint/binding-linux-riscv64-gnu": "1.64.0",
|
||||
"@oxlint/binding-linux-riscv64-musl": "1.64.0",
|
||||
"@oxlint/binding-linux-s390x-gnu": "1.64.0",
|
||||
"@oxlint/binding-linux-x64-gnu": "1.64.0",
|
||||
"@oxlint/binding-linux-x64-musl": "1.64.0",
|
||||
"@oxlint/binding-openharmony-arm64": "1.64.0",
|
||||
"@oxlint/binding-win32-arm64-msvc": "1.64.0",
|
||||
"@oxlint/binding-win32-ia32-msvc": "1.64.0",
|
||||
"@oxlint/binding-win32-x64-msvc": "1.64.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"oxlint-tsgolint": ">=0.22.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"oxlint-tsgolint": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD",
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
233
studio/package-lock.json
generated
Normal file
233
studio/package-lock.json
generated
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
{
|
||||
"name": "unsloth-studio-tauri-cli",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "unsloth-studio-tauri-cli",
|
||||
"version": "0.0.0",
|
||||
"license": "AGPL-3.0-only",
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "2.10.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.1.tgz",
|
||||
"integrity": "sha512-jQNGF/5quwORdZSSLtTluyKQ+o6SMa/AUICfhf4egCGFdMHqWssApVgYSbg+jmrZoc8e1DscNvjTnXtlHLS11g==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"bin": {
|
||||
"tauri": "tauri.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/tauri"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tauri-apps/cli-darwin-arm64": "2.10.1",
|
||||
"@tauri-apps/cli-darwin-x64": "2.10.1",
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": "2.10.1",
|
||||
"@tauri-apps/cli-linux-arm64-gnu": "2.10.1",
|
||||
"@tauri-apps/cli-linux-arm64-musl": "2.10.1",
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": "2.10.1",
|
||||
"@tauri-apps/cli-linux-x64-gnu": "2.10.1",
|
||||
"@tauri-apps/cli-linux-x64-musl": "2.10.1",
|
||||
"@tauri-apps/cli-win32-arm64-msvc": "2.10.1",
|
||||
"@tauri-apps/cli-win32-ia32-msvc": "2.10.1",
|
||||
"@tauri-apps/cli-win32-x64-msvc": "2.10.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-darwin-arm64": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.1.tgz",
|
||||
"integrity": "sha512-Z2OjCXiZ+fbYZy7PmP3WRnOpM9+Fy+oonKDEmUE6MwN4IGaYqgceTjwHucc/kEEYZos5GICve35f7ZiizgqEnQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-darwin-x64": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.1.tgz",
|
||||
"integrity": "sha512-V/irQVvjPMGOTQqNj55PnQPVuH4VJP8vZCN7ajnj+ZS8Kom1tEM2hR3qbbIRoS3dBKs5mbG8yg1WC+97dq17Pw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.1.tgz",
|
||||
"integrity": "sha512-Hyzwsb4VnCWKGfTw+wSt15Z2pLw2f0JdFBfq2vHBOBhvg7oi6uhKiF87hmbXOBXUZaGkyRDkCHsdzJcIfoJC2w==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.1.tgz",
|
||||
"integrity": "sha512-OyOYs2t5GkBIvyWjA1+h4CZxTcdz1OZPCWAPz5DYEfB0cnWHERTnQ/SLayQzncrT0kwRoSfSz9KxenkyJoTelA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.1.tgz",
|
||||
"integrity": "sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-riscv64-gnu": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.1.tgz",
|
||||
"integrity": "sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.1.tgz",
|
||||
"integrity": "sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-x64-musl": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.1.tgz",
|
||||
"integrity": "sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.1.tgz",
|
||||
"integrity": "sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.1.tgz",
|
||||
"integrity": "sha512-gXyxgEzsFegmnWywYU5pEBURkcFN/Oo45EAwvZrHMh+zUSEAvO5E8TXsgPADYm31d1u7OQU3O3HsYfVBf2moHw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.1.tgz",
|
||||
"integrity": "sha512-6Cn7YpPFwzChy0ERz6djKEmUehWrYlM+xTaNzGPgZocw3BD7OfwfWHKVWxXzdjEW2KfKkHddfdxK1XXTYqBRLg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
studio/package.json
Normal file
10
studio/package.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "unsloth-studio-tauri-cli",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"description": "Lockfile holder for @tauri-apps/cli used by the desktop release workflow. Not a real npm package; `npm ci --prefix studio` resolves the pinned Tauri CLI from this directory's package-lock.json.",
|
||||
"license": "AGPL-3.0-only",
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "2.10.1"
|
||||
}
|
||||
}
|
||||
|
|
@ -27,9 +27,12 @@ def _run_auditor(
|
|||
root: Path,
|
||||
npm_lockfiles: list[Path] | None = None,
|
||||
cargo_lockfiles: list[Path] | None = None,
|
||||
strict: bool = False,
|
||||
timeout: int = 30,
|
||||
) -> subprocess.CompletedProcess:
|
||||
cmd = [sys.executable, str(SCRIPT), "--root", str(root)]
|
||||
if strict:
|
||||
cmd.append("--strict")
|
||||
for p in npm_lockfiles or []:
|
||||
cmd.extend(["--npm-lockfile", str(p)])
|
||||
for p in cargo_lockfiles or []:
|
||||
|
|
@ -170,6 +173,32 @@ checksum = "0000000000000000000000000000000000000000000000000000000000000000"
|
|||
def test_malicious_cargo_lockfile_refused(tmp_path):
|
||||
"""Inline Cargo.lock with `source = "git+https://example.com/..."`
|
||||
must trip the `non-registry-cargo-source` check.
|
||||
|
||||
`non-registry-cargo-source` is an advisory finding kind in the
|
||||
auditor's default mode (per the audit script's BLOCKING_KINDS
|
||||
set). To exercise the historical "refuse to install" behavior we
|
||||
pass --strict here; that promotes every finding to blocking and
|
||||
keeps the test honest about its intent (detection + refusal).
|
||||
"""
|
||||
lockfile = tmp_path / "Cargo.lock"
|
||||
lockfile.write_text(_MALICIOUS_CARGO_LOCK)
|
||||
proc = _run_auditor(
|
||||
root = tmp_path,
|
||||
npm_lockfiles = [FIXTURES / "clean_lockfile.json"],
|
||||
cargo_lockfiles = [lockfile],
|
||||
strict = True,
|
||||
)
|
||||
assert proc.returncode == 1
|
||||
combined = proc.stdout + proc.stderr
|
||||
assert "non-registry-cargo-source" in combined
|
||||
assert "git+https://example.com" in combined
|
||||
|
||||
|
||||
def test_malicious_cargo_lockfile_default_mode_advisory(tmp_path):
|
||||
"""Default (non-strict) mode classifies `non-registry-cargo-source`
|
||||
as advisory: the finding is still emitted as a `::warning::`
|
||||
annotation but the process exits 0 so the build is not gated.
|
||||
Regression test for the advisory/strict split.
|
||||
"""
|
||||
lockfile = tmp_path / "Cargo.lock"
|
||||
lockfile.write_text(_MALICIOUS_CARGO_LOCK)
|
||||
|
|
@ -178,10 +207,13 @@ def test_malicious_cargo_lockfile_refused(tmp_path):
|
|||
npm_lockfiles = [FIXTURES / "clean_lockfile.json"],
|
||||
cargo_lockfiles = [lockfile],
|
||||
)
|
||||
assert proc.returncode == 1
|
||||
assert proc.returncode == 0, (
|
||||
f"expected exit 0 (advisory), got {proc.returncode}\n"
|
||||
f"--- stdout ---\n{proc.stdout}\n--- stderr ---\n{proc.stderr}"
|
||||
)
|
||||
combined = proc.stdout + proc.stderr
|
||||
assert "non-registry-cargo-source" in combined
|
||||
assert "git+https://example.com" in combined
|
||||
assert "advisory finding" in combined
|
||||
|
||||
|
||||
def test_audit_cargo_lockfile_direct_call(tmp_path):
|
||||
|
|
@ -192,6 +224,75 @@ def test_audit_cargo_lockfile_direct_call(tmp_path):
|
|||
assert "non-registry-cargo-source" in kinds
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# GitHub Actions annotation escape: ::warning:: / ::error:: messages
|
||||
# are truncated at the first newline unless escaped, so the multi-line
|
||||
# Finding must be collapsed via the spec'd %0A / %0D / %25 encoding.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_gha_escape_collapses_finding_to_one_line():
|
||||
"""`_gha_escape()` must collapse newlines (`%0A`), carriage
|
||||
returns (`%0D`), and percent signs (`%25`) so that
|
||||
`::warning::<msg>` / `::error::<msg>` render the full finding
|
||||
in the GitHub Actions UI annotation instead of being truncated
|
||||
at the first newline. The `%` replacement must happen first or
|
||||
the subsequent `%0A` / `%0D` escapes get double-encoded.
|
||||
"""
|
||||
assert lsa._gha_escape("a\nb\nc") == "a%0Ab%0Ac"
|
||||
assert lsa._gha_escape("a\rb") == "a%0Db"
|
||||
assert lsa._gha_escape("100%") == "100%25"
|
||||
# Order regression: `%` must escape before `\n` so the literal
|
||||
# text `a%b\nc` becomes `a%25b%0Ac`, not `a%250Ab%0Ac`.
|
||||
assert lsa._gha_escape("a%b\nc") == "a%25b%0Ac"
|
||||
|
||||
f = lsa.Finding(
|
||||
path = "/x/lock.json",
|
||||
package = "node_modules/foo",
|
||||
kind = "missing-integrity-hash",
|
||||
detail = "bad stuff",
|
||||
)
|
||||
escaped = lsa._gha_escape(str(f))
|
||||
assert "\n" not in escaped
|
||||
assert "%0A" in escaped
|
||||
assert "missing-integrity-hash" in escaped
|
||||
assert "node_modules/foo" in escaped
|
||||
assert "bad stuff" in escaped
|
||||
|
||||
|
||||
def test_advisory_finding_emitted_as_single_line_annotation(tmp_path):
|
||||
"""End-to-end check: the `::warning::` line emitted for an
|
||||
advisory finding must be a SINGLE physical line (the rest of
|
||||
the Finding is `%0A`-escaped inside the message). Regression
|
||||
test for the gemini-code-assist review on PR #5604: without
|
||||
`_gha_escape`, GitHub Actions truncates the annotation after
|
||||
`[kind] path` and the package + detail fields never render.
|
||||
"""
|
||||
lockfile = tmp_path / "Cargo.lock"
|
||||
lockfile.write_text(_MALICIOUS_CARGO_LOCK)
|
||||
proc = _run_auditor(
|
||||
root = tmp_path,
|
||||
npm_lockfiles = [FIXTURES / "clean_lockfile.json"],
|
||||
cargo_lockfiles = [lockfile],
|
||||
)
|
||||
warning_lines = [
|
||||
line for line in proc.stderr.splitlines() if line.startswith("::warning::")
|
||||
]
|
||||
assert warning_lines, (
|
||||
"expected at least one ::warning:: annotation; " f"stderr was:\n{proc.stderr}"
|
||||
)
|
||||
for line in warning_lines:
|
||||
# Single physical line: kind, package, detail all present
|
||||
# via %0A escape, not split across stderr lines.
|
||||
assert "%0A" in line, (
|
||||
f"::warning:: line has no %0A escape; multi-line text "
|
||||
f"would be truncated by GH Actions:\n{line}"
|
||||
)
|
||||
assert "non-registry-cargo-source" in line
|
||||
assert "package:" in line
|
||||
assert "detail:" in line
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# SF4: skip env var requires a justification value.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue