From b780882bb0a553a851ce39bca323e8aaff7f66d5 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Wed, 15 Jul 2026 17:34:23 -0300 Subject: [PATCH 1/4] ci: reuse bounded integration artifacts Build target-specific nextest archives once and reuse each extraction across four host workers. Pin prebuilt tools and RISC Zero components, reduce duplicate cache writes, and preserve coverage checks. --- .../build-integration-shard/action.yml | 69 +++ .github/actions/install-risc0/action.yml | 70 ++- .../actions/restore-risc0-runtime/action.yml | 17 + .github/dependabot.yml | 11 + .github/workflows/bench-regression.yml | 20 +- .github/workflows/ci.yml | 412 ++++++++++++------ .github/workflows/publish_images.yml | 22 +- .../src/encryption/shared_key_derivation.rs | 6 +- lez/programs/src/lib.rs | 2 +- 9 files changed, 469 insertions(+), 160 deletions(-) create mode 100644 .github/actions/build-integration-shard/action.yml create mode 100644 .github/actions/restore-risc0-runtime/action.yml create mode 100644 .github/dependabot.yml diff --git a/.github/actions/build-integration-shard/action.yml b/.github/actions/build-integration-shard/action.yml new file mode 100644 index 00000000..3a5bc8e9 --- /dev/null +++ b/.github/actions/build-integration-shard/action.yml @@ -0,0 +1,69 @@ +name: Build integration test shard +description: Builds and uploads one bounded nextest archive +inputs: + shard: + description: Zero-based shard number + required: true +runs: + using: composite + steps: + - name: Build integration test shard ${{ inputs.shard }} + env: + RISC0_DEV_MODE: "1" + SHARD: ${{ inputs.shard }} + run: | + if [[ ! "$SHARD" =~ ^[0-3]$ ]]; then + echo "Invalid integration test shard: $SHARD" >&2 + exit 2 + fi + + shard_dir="$RUNNER_TEMP/integration-test-shards" + filter_file="$shard_dir/$SHARD.filter" + targets_file="$shard_dir/$SHARD.targets" + archive="$shard_dir/integration-tests-$SHARD.tar.zst" + + target_args=() + while IFS= read -r target; do + [[ -n "$target" ]] && target_args+=(--test "$target") + done < "$targets_file" + if (( ${#target_args[@]} == 0 )); then + echo "Shard $SHARD has no integration test targets" >&2 + exit 1 + fi + + cargo nextest archive \ + -p integration_tests \ + "${target_args[@]}" \ + -E "$(cat "$filter_file")" \ + --archive-file "$archive" \ + --no-pager + + archive_bytes="$(stat --format=%s "$archive")" + max_archive_bytes=$((512 * 1024 * 1024)) + if (( archive_bytes > max_archive_bytes )); then + echo "Shard $SHARD archive is larger than the provisional 512 MiB limit" >&2 + exit 1 + fi + + archive_size="$(du -h "$archive" | cut -f1)" + target_count="$(( ${#target_args[@]} / 2 ))" + echo "| $SHARD | $archive_size | $target_count |" >> "$GITHUB_STEP_SUMMARY" + shell: bash + + - name: Upload integration test shard ${{ inputs.shard }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: integration-tests-${{ inputs.shard }} + path: | + ${{ runner.temp }}/integration-test-shards/integration-tests-${{ inputs.shard }}.tar.zst + ${{ runner.temp }}/integration-test-shards/${{ inputs.shard }}.targets + compression-level: 0 + retention-days: 1 + if-no-files-found: error + + - name: Release integration archive disk + if: always() + env: + SHARD: ${{ inputs.shard }} + run: rm -f "$RUNNER_TEMP/integration-test-shards/integration-tests-$SHARD.tar.zst" + shell: bash diff --git a/.github/actions/install-risc0/action.yml b/.github/actions/install-risc0/action.yml index fef3a467..76c7247d 100644 --- a/.github/actions/install-risc0/action.yml +++ b/.github/actions/install-risc0/action.yml @@ -1,10 +1,72 @@ name: Install risc0 -description: Installs risc0 in the environment +description: Installs pinned RISC Zero components in the environment +inputs: + profile: + description: Components to install (build or runtime) + required: false + default: build + save-cache: + description: Save a missing cache from a trusted branch + required: false + default: "false" runs: using: "composite" steps: - - name: Install risc0 + - name: Restore RISC Zero components + id: restore-risc0 + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: ~/.risc0 + key: risc0-${{ runner.os }}-${{ runner.arch }}-${{ inputs.profile }}-rzup-0.5.0-r0vm-3.0.5-rust-1.94.1-cargo-risczero-3.0.5 + + - name: Install pinned RISC Zero components + env: + GITHUB_TOKEN: ${{ github.token }} + RISC0_PROFILE: ${{ inputs.profile }} run: | - curl -L https://risczero.com/install | bash - /home/runner/.risc0/bin/rzup install + risc0_home="${RISC0_HOME:-$HOME/.risc0}" + mkdir -p "$risc0_home/bin" + + rzup="$risc0_home/bin/rzup" + rzup_sha256="7cdc1dd5d4b8ef38ea6170c45bd29ba65d389f0e96b365da61631d1fc5c6c1ca" + if ! echo "$rzup_sha256 $rzup" | sha256sum --check --status; then + rzup_download="$(mktemp)" + trap 'rm -f "$rzup_download"' EXIT + curl --proto '=https' --tlsv1.2 -fsSL \ + https://risc0-artifacts.s3.us-west-2.amazonaws.com/rzup/prod/Linux-X64/rzup \ + -o "$rzup_download" + echo "$rzup_sha256 $rzup_download" | sha256sum --check + install -m 0755 "$rzup_download" "$rzup" + fi + + echo "$risc0_home/bin" >> "$GITHUB_PATH" + test "$("$rzup" --version)" = "rzup 0.5.0" + + case "$RISC0_PROFILE" in + build) + "$rzup" install r0vm 3.0.5 + "$rzup" install rust 1.94.1 + "$rzup" install cargo-risczero 3.0.5 + ;; + runtime) + "$rzup" install r0vm 3.0.5 + ;; + *) + echo "Unsupported RISC Zero profile: $RISC0_PROFILE" >&2 + exit 2 + ;; + esac + + "$rzup" show shell: bash + + - name: Save RISC Zero components + if: >- + steps.restore-risc0.outputs.cache-hit != 'true' && + inputs.save-cache == 'true' && + github.event_name == 'push' && + (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev') + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: ~/.risc0 + key: risc0-${{ runner.os }}-${{ runner.arch }}-${{ inputs.profile }}-rzup-0.5.0-r0vm-3.0.5-rust-1.94.1-cargo-risczero-3.0.5 diff --git a/.github/actions/restore-risc0-runtime/action.yml b/.github/actions/restore-risc0-runtime/action.yml new file mode 100644 index 00000000..5a6880c0 --- /dev/null +++ b/.github/actions/restore-risc0-runtime/action.yml @@ -0,0 +1,17 @@ +name: Restore RISC Zero runtime +description: Restores the producer's pinned r0vm binary +runs: + using: composite + steps: + - name: Download RISC Zero runtime + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: risc0-runtime-3.0.5 + path: ${{ runner.temp }}/risc0-runtime + + - name: Install RISC Zero runtime + run: | + mkdir -p "$HOME/.cargo/bin" + install -m 0755 "$RUNNER_TEMP/risc0-runtime/r0vm" "$HOME/.cargo/bin/r0vm" + test "$(r0vm --version)" = "risc0-r0vm 3.0.5" + shell: bash diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..e38985c1 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 + +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + groups: + github-actions: + patterns: + - "*" diff --git a/.github/workflows/bench-regression.yml b/.github/workflows/bench-regression.yml index d82c0f11..16a57947 100644 --- a/.github/workflows/bench-regression.yml +++ b/.github/workflows/bench-regression.yml @@ -2,8 +2,8 @@ on: pull_request: paths: - "tools/crypto_primitives_bench/**" - - "lez/key_protocol/**" - - "lee/core/**" + - "lee/key_protocol/**" + - "lee/state_machine/core/**" - ".github/workflows/bench-regression.yml" permissions: @@ -12,27 +12,31 @@ permissions: name: bench-regression +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + CARGO_INCREMENTAL: "0" + jobs: crypto-primitives: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} # criterion-compare-action checks out the base branch in a second # working tree, so we need the full history. fetch-depth: 0 - uses: ./.github/actions/install-system-deps - - uses: ./.github/actions/install-risc0 - - name: Install active toolchain - run: rustup install + run: rustup install --profile minimal - name: Run criterion-compare against base branch - uses: boa-dev/criterion-compare-action@v3 + uses: boa-dev/criterion-compare-action@adfd3a94634fe2041ce5613eb7df09d247555b87 # v3.2.4 with: branchName: ${{ github.base_ref }} cwd: tools/crypto_primitives_bench diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 194646f3..fbd3f26c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,3 +1,5 @@ +name: General + on: push: branches: @@ -14,49 +16,55 @@ on: permissions: contents: read - pull-requests: read -name: General +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + CARGO_INCREMENTAL: "0" + CARGO_PROFILE_TEST_DEBUG: "0" + NEXTEST_VERSION: "0.9.140" jobs: fmt-rs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Install nightly toolchain for rustfmt - run: rustup install nightly --profile minimal --component rustfmt + run: rustup install nightly-2026-04-14 --profile minimal --component rustfmt - name: Check Rust files are formatted - run: cargo +nightly fmt --check + run: cargo +nightly-2026-04-14 fmt --check fmt-toml: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Install taplo-cli - run: cargo install --locked taplo-cli + uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2 + with: + tool: taplo-cli@0.10.0 + fallback: none - name: Check TOML files are formatted - run: taplo fmt --check . + run: taplo fmt --check machete: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Install active toolchain - run: rustup install + run: rustup install --profile minimal - name: Install cargo-machete - run: cargo install cargo-machete + uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2 + with: + tool: cargo-machete@0.9.2 + fallback: none - name: Check for unused dependencies run: cargo machete @@ -64,12 +72,13 @@ jobs: deny: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Install cargo-deny - run: cargo install --locked cargo-deny + uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2 + with: + tool: cargo-deny@0.20.2 + fallback: none - name: Check licenses and advisories run: cargo deny check @@ -77,25 +86,20 @@ jobs: lint: runs-on: ubuntu-latest timeout-minutes: 60 - - name: lint steps: - - uses: actions/checkout@v5 - with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: ./.github/actions/install-system-deps - - uses: ./.github/actions/install-risc0 - - name: Install active toolchain - run: rustup install + run: rustup install --profile minimal --component clippy - name: Restore Rust cache - uses: Swatinem/rust-cache@v2 + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 with: shared-key: ci-rust-cache - save-if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' }} + cache-bin: false + save-if: false - name: Lint workspace env: @@ -107,202 +111,344 @@ jobs: RISC0_SKIP_BUILD: "1" run: cargo clippy -p "*program" -- -D warnings + - name: Check rustdoc links + env: + RISC0_SKIP_BUILD: "1" + RUSTDOCFLAGS: -D warnings + run: | + cargo doc \ + --workspace \ + --all-features \ + --no-deps \ + --exclude test_program_guests \ + --exclude test_methods_guests + + for package in test_program_guests test_methods_guests; do + cargo doc \ + -p "$package" \ + --all-features \ + --no-deps \ + --target-dir "$RUNNER_TEMP/rustdoc-$package" + done + unit-tests: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v5 - with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: ./.github/actions/install-system-deps + - name: Install active toolchain + run: rustup install --profile minimal + - uses: ./.github/actions/install-risc0 - - name: Install active toolchain - run: rustup install - - name: Restore Rust cache - uses: Swatinem/rust-cache@v2 + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 with: shared-key: ci-rust-cache - save-if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' }} + cache-bin: false + save-if: false - name: Install nextest - run: cargo install --locked cargo-nextest + uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2 + with: + tool: nextest@${{ env.NEXTEST_VERSION }} + fallback: none - name: Run tests env: RISC0_DEV_MODE: "1" - RUST_LOG: "info" - run: cargo nextest run --workspace --exclude integration_tests --exclude test_fixtures --all-features + RUST_LOG: info + run: cargo nextest run --workspace --exclude integration_tests --exclude test_fixtures --all-features --no-fail-fast test-fixtures-tests: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v5 - with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: ./.github/actions/install-system-deps - - uses: ./.github/actions/install-risc0 - - name: Install active toolchain - run: rustup install + run: rustup install --profile minimal + + - uses: ./.github/actions/install-risc0 + with: + profile: runtime + save-cache: "true" - name: Restore Rust cache - uses: Swatinem/rust-cache@v2 + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 with: shared-key: ci-rust-cache - save-if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' }} + cache-bin: false + save-if: false - name: Install nextest - run: cargo install --locked cargo-nextest + uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2 + with: + tool: nextest@${{ env.NEXTEST_VERSION }} + fallback: none - name: Run test_fixtures tests env: RISC0_DEV_MODE: "1" - RUST_LOG: "info" - run: cargo nextest run -p test_fixtures + RUST_LOG: info + run: cargo nextest run -p test_fixtures --no-fail-fast - integration-tests-prebuild: - runs-on: ubuntu-latest - outputs: - targets: ${{ steps.discover-targets.outputs.targets }} + integration-tests-prepare: + runs-on: ubuntu-24.04 + timeout-minutes: 60 steps: - - uses: actions/checkout@v5 - with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: ./.github/actions/install-system-deps - - uses: ./.github/actions/install-risc0 - - name: Install active toolchain - run: rustup install + run: rustup install --profile minimal + + - uses: ./.github/actions/install-risc0 + with: + save-cache: "true" - name: Restore Rust cache - uses: Swatinem/rust-cache@v2 + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 with: shared-key: ci-rust-cache + cache-bin: false save-if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' }} - name: Install nextest - run: cargo install --locked cargo-nextest - - - name: Build integration test archive - env: - RISC0_DEV_MODE: "1" - run: cargo nextest archive -p integration_tests --archive-file integration-tests.tar.zst --no-pager - - - name: Upload integration test archive - uses: actions/upload-artifact@v4 + uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2 with: - name: integration-tests-archive - path: integration-tests.tar.zst + tool: nextest@${{ env.NEXTEST_VERSION }} + fallback: none - - name: Discover integration test targets from archive - id: discover-targets + - name: Discover and validate integration test shards run: | - cargo nextest list \ - --archive-file integration-tests.tar.zst \ - --list-type binaries-only \ - --message-format json \ - --no-pager > integration-tests-binaries.json + shard_dir="$RUNNER_TEMP/integration-test-shards" + mkdir -p "$shard_dir" - targets_json="$(jq -c '[."rust-binaries" | to_entries[] | select(.value.kind == "test" and .value."binary-name" != "tps") | .value."binary-name"] | sort | unique' integration-tests-binaries.json)" + cargo metadata \ + --no-deps \ + --format-version 1 > "$shard_dir/metadata.json" - if [[ "$targets_json" == "[]" ]]; then - echo "No integration test targets were discovered." >&2 + jq -r ' + [.packages[] + | select(.name == "integration_tests") + | .targets[] + | select(.kind | index("test")) + | select(.name != "tps") + | .name] + | sort + | unique[] + ' "$shard_dir/metadata.json" > "$shard_dir/discovered.targets" + + shard_targets=( + "indexer_ffi_state_consistency keys token indexer_block_batching indexer_test_run_ffi shared_accounts account" + "amm cross_zone_bridge pinata indexer_state_consistency_with_labels indexer_test_run vault program_deployment" + "indexer_ffi_state_consistency_with_labels ata auth_transfer indexer_stall indexer_ffi_block_batching private_pda block_size_limit cross_zone_state_machine" + "cross_zone_verified two_zone bridge indexer_state_consistency cross_zone_ping wallet_ffi config cross_zone_ingress_guard" + ) + + for shard in "${!shard_targets[@]}"; do + targets_file="$shard_dir/$shard.targets" + filter_file="$shard_dir/$shard.filter" + tr ' ' '\n' <<< "${shard_targets[$shard]}" > "$targets_file" + awk ' + { printf "%s%s", separator, "binary(=" $0 ")"; separator = " | " } + END { print "" } + ' "$targets_file" > "$filter_file" + done + + sort "$shard_dir"/[0-3].targets > "$shard_dir/assigned.targets" + if ! diff -u "$shard_dir/discovered.targets" "$shard_dir/assigned.targets"; then + echo "Every non-tps integration binary must belong to exactly one shard." >&2 exit 1 fi - echo "targets=$targets_json" >> "$GITHUB_OUTPUT" - echo "Discovered integration targets: $targets_json" + { + echo "### Integration archive shards" + echo + echo "| Shard | Archive size | Binaries |" + echo "| ---: | ---: | ---: |" + } >> "$GITHUB_STEP_SUMMARY" + + - uses: ./.github/actions/build-integration-shard + with: + shard: "0" + + - uses: ./.github/actions/build-integration-shard + with: + shard: "1" + + - uses: ./.github/actions/build-integration-shard + with: + shard: "2" + + - uses: ./.github/actions/build-integration-shard + with: + shard: "3" + + - name: Stage RISC Zero runtime + run: | + mkdir -p "$RUNNER_TEMP/risc0-runtime" + install -m 0755 "$(command -v r0vm)" "$RUNNER_TEMP/risc0-runtime/r0vm" + + - name: Upload RISC Zero runtime + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: risc0-runtime-3.0.5 + path: ${{ runner.temp }}/risc0-runtime/r0vm + compression-level: 6 + retention-days: 1 + if-no-files-found: error integration-tests: - needs: [test-fixtures-tests, integration-tests-prebuild] - runs-on: ubuntu-latest + needs: + - test-fixtures-tests + - integration-tests-prepare + runs-on: ubuntu-24.04 timeout-minutes: 90 strategy: fail-fast: false + max-parallel: 4 matrix: - target: ${{ fromJson(needs.integration-tests-prebuild.outputs.targets) }} - name: integration-tests (${{ matrix.target }}) + shard: [0, 1, 2, 3] + name: integration-tests (shard ${{ matrix.shard }}) steps: - - uses: actions/checkout@v5 - with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: ./.github/actions/install-system-deps - - - uses: ./.github/actions/install-risc0 - - - name: Install active toolchain - run: rustup install - - - name: Download integration test archive - uses: actions/download-artifact@v4 - with: - name: integration-tests-archive + - uses: ./.github/actions/restore-risc0-runtime - name: Install nextest - run: cargo install --locked cargo-nextest + uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2 + with: + tool: nextest@${{ env.NEXTEST_VERSION }} + fallback: none - - name: Run tests + - name: Download integration test shard + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: integration-tests-${{ matrix.shard }} + path: ${{ runner.temp }}/integration-test-shard + + - name: Run integration test shard env: RISC0_DEV_MODE: "1" - RUST_LOG: "info" - run: cargo nextest run --archive-file integration-tests.tar.zst -E "binary(${{ matrix.target }})" + RUST_LOG: info + run: | + archive="$RUNNER_TEMP/integration-test-shard/integration-tests-${{ matrix.shard }}.tar.zst" + targets="$RUNNER_TEMP/integration-test-shard/${{ matrix.shard }}.targets" + extract_dir="$RUNNER_TEMP/nextest-shard" + mkdir -p "$extract_dir" + cargo-nextest nextest list \ + --archive-file "$archive" \ + --extract-to "$extract_dir" \ + --workspace-remap "$GITHUB_WORKSPACE" \ + --list-type binaries-only \ + --message-format json \ + --no-pager > /dev/null + rm -f "$archive" + + available_kib="$(df --output=avail -k "$RUNNER_TEMP" | tail -n 1 | tr -d ' ')" + minimum_free_kib=$((6 * 1024 * 1024)) + if (( available_kib < minimum_free_kib )); then + echo "Less than 6 GiB remains after shard extraction." >&2 + df -h "$RUNNER_TEMP" >&2 + exit 1 + fi + + common_args=( + --cargo-metadata "$extract_dir/target/nextest/cargo-metadata.json" + --binaries-metadata "$extract_dir/target/nextest/binaries-metadata.json" + --target-dir-remap "$extract_dir/target" + --workspace-remap "$GITHUB_WORKSPACE" + --no-fail-fast + ) + + failed=0 + while IFS= read -r binary; do + echo "::group::integration binary: $binary" + if ! cargo-nextest nextest run "${common_args[@]}" -E "binary(=$binary)"; then + failed=1 + fi + echo "::endgroup::" + done < "$targets" + + exit "$failed" valid-proof-test: - runs-on: ubuntu-latest + needs: integration-tests-prepare + runs-on: ubuntu-24.04 timeout-minutes: 90 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - uses: ./.github/actions/restore-risc0-runtime + + - name: Install nextest + uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2 with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + tool: nextest@${{ env.NEXTEST_VERSION }} + fallback: none - - uses: ./.github/actions/install-system-deps - - - uses: ./.github/actions/install-risc0 - - - name: Install active toolchain - run: rustup install - - - name: Restore Rust cache - uses: Swatinem/rust-cache@v2 + - name: Download integration test shard + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: - shared-key: ci-rust-cache - save-if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' }} + name: integration-tests-2 + path: ${{ runner.temp }}/integration-test-shard - name: Test valid proof env: - RUST_LOG: "info" - run: cargo test -p integration_tests -- --exact private::private_transfer_to_owned_account + RUST_LOG: info + run: | + archive="$RUNNER_TEMP/integration-test-shard/integration-tests-2.tar.zst" + extract_dir="$RUNNER_TEMP/nextest-shard" + mkdir -p "$extract_dir" + cargo-nextest nextest list \ + --archive-file "$archive" \ + --extract-to "$extract_dir" \ + --workspace-remap "$GITHUB_WORKSPACE" \ + --list-type binaries-only \ + --message-format json \ + --no-pager > /dev/null + rm -f "$archive" + + cargo-nextest nextest run \ + --cargo-metadata "$extract_dir/target/nextest/cargo-metadata.json" \ + --binaries-metadata "$extract_dir/target/nextest/binaries-metadata.json" \ + --target-dir-remap "$extract_dir/target" \ + --workspace-remap "$GITHUB_WORKSPACE" \ + -E 'binary(=auth_transfer) & test(=private::private_transfer_to_owned_account)' artifacts: runs-on: ubuntu-latest timeout-minutes: 60 - - name: artifacts steps: - - uses: actions/checkout@v5 - with: - ref: ${{ github.event.pull_request.head.sha || github.head_ref }} + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Install active toolchain + run: rustup install --profile minimal - uses: ./.github/actions/install-risc0 + with: + profile: build - name: Restore Rust cache - uses: Swatinem/rust-cache@v2 + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 with: shared-key: ci-rust-cache - save-if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' }} + cache-bin: false + save-if: false - name: Install just - run: cargo install --locked just + uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2 + with: + tool: just@1.56.0 + fallback: none - name: Build artifacts run: just build-artifacts diff --git a/.github/workflows/publish_images.yml b/.github/workflows/publish_images.yml index 28abb67c..4a3821c9 100644 --- a/.github/workflows/publish_images.yml +++ b/.github/workflows/publish_images.yml @@ -15,20 +15,20 @@ jobs: risc0_base: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - name: Log in to registry - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: registry: ${{ secrets.DOCKER_REGISTRY }} username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push risc0 base image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5 with: context: . file: ./lez/docker/risc0-base.Dockerfile @@ -58,13 +58,13 @@ jobs: dockerfile: ./lez/explorer_service/Dockerfile build_args: "" steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - name: Log in to registry - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: registry: ${{ secrets.DOCKER_REGISTRY }} username: ${{ secrets.DOCKER_USERNAME }} @@ -72,7 +72,7 @@ jobs: - name: Extract metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 with: images: ${{ secrets.DOCKER_REGISTRY }}/${{ github.repository }}/${{ matrix.name }} tags: | @@ -85,7 +85,7 @@ jobs: type=raw,value=latest,enable={{is_default_branch}} - name: Build and push Docker image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5 with: context: . file: ${{ matrix.dockerfile }} @@ -94,5 +94,5 @@ jobs: labels: ${{ steps.meta.outputs.labels }} build-args: ${{ matrix.build_args }} build-contexts: risc0_base=docker-image://${{ secrets.DOCKER_REGISTRY }}/${{ github.repository }}/risc0_base:sha-${{ github.sha }} - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=gha,scope=${{ matrix.name }} + cache-to: type=gha,mode=max,scope=${{ matrix.name }} diff --git a/lee/state_machine/core/src/encryption/shared_key_derivation.rs b/lee/state_machine/core/src/encryption/shared_key_derivation.rs index 3255080b..c8862603 100644 --- a/lee/state_machine/core/src/encryption/shared_key_derivation.rs +++ b/lee/state_machine/core/src/encryption/shared_key_derivation.rs @@ -110,9 +110,9 @@ impl SharedSecretKey { /// Receiver: decapsulate the shared secret from a KEM ciphertext. /// - /// Returns `None` if the `EphemeralPublicKey` is not exactly [`ML_KEM_768_CIPHERTEXT_LEN`] - /// bytes — callers on the wallet scan path should skip the output rather than panic on - /// malformed chain data. + /// Returns `None` if the `EphemeralPublicKey` is not exactly + /// [`crate::ML_KEM_768_CIPHERTEXT_LEN`] bytes — callers on the wallet scan path should skip + /// the output rather than panic on malformed chain data. /// /// `d` and `z` are the two 32-byte halves of the FIPS 203 `ViewingSecretKey` seed. #[must_use] diff --git a/lez/programs/src/lib.rs b/lez/programs/src/lib.rs index fb448038..4d3d72a4 100644 --- a/lez/programs/src/lib.rs +++ b/lez/programs/src/lib.rs @@ -1,4 +1,4 @@ -//! This crate provides [`Program`]s and associated utilities used by LEZ. +//! This crate provides LEZ [`Program`](lee::program::Program) artifacts and related utilities. #[cfg(feature = "artifacts")] pub use inner::*; From 2e28aa6593895dd2911e597c86e3f91d63149d40 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Wed, 15 Jul 2026 19:59:46 -0300 Subject: [PATCH 2/4] ci: restore automatic per-target integration jobs --- .../build-integration-shard/action.yml | 69 - .github/actions/install-risc0/action.yml | 6 +- .../actions/restore-risc0-runtime/action.yml | 5 +- .github/dependabot.yml | 11 - .github/scripts/artifact-client/.gitignore | 1 + .../scripts/artifact-client/package-lock.json | 1892 +++++++++++++++++ .github/scripts/artifact-client/package.json | 11 + .github/scripts/artifact-client/upload.mjs | 65 + .github/workflows/ci.yml | 269 ++- 9 files changed, 2166 insertions(+), 163 deletions(-) delete mode 100644 .github/actions/build-integration-shard/action.yml delete mode 100644 .github/dependabot.yml create mode 100644 .github/scripts/artifact-client/.gitignore create mode 100644 .github/scripts/artifact-client/package-lock.json create mode 100644 .github/scripts/artifact-client/package.json create mode 100644 .github/scripts/artifact-client/upload.mjs diff --git a/.github/actions/build-integration-shard/action.yml b/.github/actions/build-integration-shard/action.yml deleted file mode 100644 index 3a5bc8e9..00000000 --- a/.github/actions/build-integration-shard/action.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Build integration test shard -description: Builds and uploads one bounded nextest archive -inputs: - shard: - description: Zero-based shard number - required: true -runs: - using: composite - steps: - - name: Build integration test shard ${{ inputs.shard }} - env: - RISC0_DEV_MODE: "1" - SHARD: ${{ inputs.shard }} - run: | - if [[ ! "$SHARD" =~ ^[0-3]$ ]]; then - echo "Invalid integration test shard: $SHARD" >&2 - exit 2 - fi - - shard_dir="$RUNNER_TEMP/integration-test-shards" - filter_file="$shard_dir/$SHARD.filter" - targets_file="$shard_dir/$SHARD.targets" - archive="$shard_dir/integration-tests-$SHARD.tar.zst" - - target_args=() - while IFS= read -r target; do - [[ -n "$target" ]] && target_args+=(--test "$target") - done < "$targets_file" - if (( ${#target_args[@]} == 0 )); then - echo "Shard $SHARD has no integration test targets" >&2 - exit 1 - fi - - cargo nextest archive \ - -p integration_tests \ - "${target_args[@]}" \ - -E "$(cat "$filter_file")" \ - --archive-file "$archive" \ - --no-pager - - archive_bytes="$(stat --format=%s "$archive")" - max_archive_bytes=$((512 * 1024 * 1024)) - if (( archive_bytes > max_archive_bytes )); then - echo "Shard $SHARD archive is larger than the provisional 512 MiB limit" >&2 - exit 1 - fi - - archive_size="$(du -h "$archive" | cut -f1)" - target_count="$(( ${#target_args[@]} / 2 ))" - echo "| $SHARD | $archive_size | $target_count |" >> "$GITHUB_STEP_SUMMARY" - shell: bash - - - name: Upload integration test shard ${{ inputs.shard }} - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: integration-tests-${{ inputs.shard }} - path: | - ${{ runner.temp }}/integration-test-shards/integration-tests-${{ inputs.shard }}.tar.zst - ${{ runner.temp }}/integration-test-shards/${{ inputs.shard }}.targets - compression-level: 0 - retention-days: 1 - if-no-files-found: error - - - name: Release integration archive disk - if: always() - env: - SHARD: ${{ inputs.shard }} - run: rm -f "$RUNNER_TEMP/integration-test-shards/integration-tests-$SHARD.tar.zst" - shell: bash diff --git a/.github/actions/install-risc0/action.yml b/.github/actions/install-risc0/action.yml index 76c7247d..ba1b5f34 100644 --- a/.github/actions/install-risc0/action.yml +++ b/.github/actions/install-risc0/action.yml @@ -14,7 +14,7 @@ runs: steps: - name: Restore RISC Zero components id: restore-risc0 - uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ~/.risc0 key: risc0-${{ runner.os }}-${{ runner.arch }}-${{ inputs.profile }}-rzup-0.5.0-r0vm-3.0.5-rust-1.94.1-cargo-risczero-3.0.5 @@ -24,6 +24,8 @@ runs: GITHUB_TOKEN: ${{ github.token }} RISC0_PROFILE: ${{ inputs.profile }} run: | + # Avoid mutable installer defaults: verify rzup itself, then select + # only the exact components required by this workflow profile. risc0_home="${RISC0_HOME:-$HOME/.risc0}" mkdir -p "$risc0_home/bin" @@ -66,7 +68,7 @@ runs: inputs.save-cache == 'true' && github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev') - uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ~/.risc0 key: risc0-${{ runner.os }}-${{ runner.arch }}-${{ inputs.profile }}-rzup-0.5.0-r0vm-3.0.5-rust-1.94.1-cargo-risczero-3.0.5 diff --git a/.github/actions/restore-risc0-runtime/action.yml b/.github/actions/restore-risc0-runtime/action.yml index 5a6880c0..a9de983d 100644 --- a/.github/actions/restore-risc0-runtime/action.yml +++ b/.github/actions/restore-risc0-runtime/action.yml @@ -4,7 +4,7 @@ runs: using: composite steps: - name: Download RISC Zero runtime - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: risc0-runtime-3.0.5 path: ${{ runner.temp }}/risc0-runtime @@ -12,6 +12,7 @@ runs: - name: Install RISC Zero runtime run: | mkdir -p "$HOME/.cargo/bin" - install -m 0755 "$RUNNER_TEMP/risc0-runtime/r0vm" "$HOME/.cargo/bin/r0vm" + mv "$RUNNER_TEMP/risc0-runtime/r0vm" "$HOME/.cargo/bin/r0vm" + chmod 0755 "$HOME/.cargo/bin/r0vm" test "$(r0vm --version)" = "risc0-r0vm 3.0.5" shell: bash diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index e38985c1..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: weekly - groups: - github-actions: - patterns: - - "*" diff --git a/.github/scripts/artifact-client/.gitignore b/.github/scripts/artifact-client/.gitignore new file mode 100644 index 00000000..c2658d7d --- /dev/null +++ b/.github/scripts/artifact-client/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/.github/scripts/artifact-client/package-lock.json b/.github/scripts/artifact-client/package-lock.json new file mode 100644 index 00000000..a3f78451 --- /dev/null +++ b/.github/scripts/artifact-client/package-lock.json @@ -0,0 +1,1892 @@ +{ + "name": "logos-execution-zone-ci-artifact-client", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "logos-execution-zone-ci-artifact-client", + "dependencies": { + "@actions/artifact": "6.2.1" + }, + "engines": { + "node": ">=24" + } + }, + "node_modules/@actions/artifact": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-6.2.1.tgz", + "integrity": "sha512-sJGH0mhEbEjBCw7o6SaLhUU66u27aFW8HTfkIb5Tk2/Wy0caUDc+oYQEgnuFN7a0HCpAbQyK0U6U7XUJDgDWrw==", + "license": "MIT", + "dependencies": { + "@actions/core": "^3.0.0", + "@actions/github": "^9.0.0", + "@actions/http-client": "^4.0.0", + "@azure/storage-blob": "^12.30.0", + "@octokit/core": "^7.0.6", + "@octokit/plugin-request-log": "^6.0.0", + "@octokit/plugin-retry": "^8.0.0", + "@octokit/request": "^10.0.7", + "@octokit/request-error": "^7.1.0", + "@protobuf-ts/plugin": "^2.2.3-alpha.1", + "@protobuf-ts/runtime": "^2.9.4", + "archiver": "^7.0.1", + "jwt-decode": "^4.0.0", + "unzip-stream": "^0.3.1" + } + }, + "node_modules/@actions/core": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-3.0.1.tgz", + "integrity": "sha512-a6d/Nwahm9fliVGRhdhofo40HjHQasUPusmc7vBfyky+7Z+P2A1J68zyFVaNcEclc/Se+eO595oAr5nwEIoIUA==", + "license": "MIT", + "dependencies": { + "@actions/exec": "^3.0.0", + "@actions/http-client": "^4.0.0" + } + }, + "node_modules/@actions/exec": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-3.0.0.tgz", + "integrity": "sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==", + "license": "MIT", + "dependencies": { + "@actions/io": "^3.0.2" + } + }, + "node_modules/@actions/github": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-9.1.1.tgz", + "integrity": "sha512-tL5JbYOBZHc0ngEnCsaDcryUizIUIlQyIMwy1Wkx93H5HzbBJ7TbiPx2PnFjBwZW0Vh05JmfFZhecE6gglYegA==", + "license": "MIT", + "dependencies": { + "@actions/http-client": "^3.0.2", + "@octokit/core": "^7.0.6", + "@octokit/plugin-paginate-rest": "^14.0.0", + "@octokit/plugin-rest-endpoint-methods": "^17.0.0", + "@octokit/request": "^10.0.7", + "@octokit/request-error": "^7.1.0", + "undici": "^6.23.0" + } + }, + "node_modules/@actions/github/node_modules/@actions/http-client": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz", + "integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==", + "license": "MIT", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^6.23.0" + } + }, + "node_modules/@actions/http-client": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-4.0.1.tgz", + "integrity": "sha512-+Nvd1ImaOZBSoPbsUtEhv+1z99H12xzncCkz0a3RuehINE81FZSe2QTj3uvAPTcJX/SCzUQHQ0D1GrPMbrPitg==", + "license": "MIT", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^6.23.0" + } + }, + "node_modules/@actions/io": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-3.0.2.tgz", + "integrity": "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==", + "license": "MIT" + }, + "node_modules/@azure/abort-controller": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.2.0.tgz", + "integrity": "sha512-fNAjWnA/nZ2jz31kxR/AqRaUT8ewHBw/WuBIosK0moMy1C9e5ValbDfFdIxJzVOOYaYkV/b2F1S4H/aHiqfVQg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.11.0.tgz", + "integrity": "sha512-IUZydyTUkDnYdstOW9pFOOUQlBjAepK5teihDE3x6yxsPJs/hsAaaYpeGxdxrgtOiJbBKSjKW7MDk7AEhb4LRg==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.11.0.tgz", + "integrity": "sha512-JjQWO6akOck45PH/XBrxzsQGAiKrfFl4m5iggJ0ItMIz5omRufOXWpqCPpdjKN3vKDzlSUvFjaMb7Zwf0gvAdA==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-http-compat": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.5.0.tgz", + "integrity": "sha512-BoSmXPx2er1Ai+wKlDvj29jIQespCNBwEmKyZVHO2kEFsWbGjAjwMCGzug3DJM5/QYIV3vej0S1zcU5bq9fa8w==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2" + }, + "engines": { + "node": ">=22.0.0" + }, + "peerDependencies": { + "@azure/core-client": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0" + } + }, + "node_modules/@azure/core-lro": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz", + "integrity": "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.2.0", + "@azure/logger": "^1.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-paging": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.7.0.tgz", + "integrity": "sha512-7GEAoIsaoBr6KELNRb8nypowCqvk8dnCHFCYg4XD4lOQGY2GqjQg5IhkRjyBFRO18CGSMq05PaNqSOE9GQro3g==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.25.0.tgz", + "integrity": "sha512-bMs8ekJLjX8wPV+9IPBges1SLPyuDtE9g5gLDWOpxzKcoOFQnpLGkbcT1tdw3FaAmDS1gnPmMmJ6y/T5B96kIA==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.4.0.tgz", + "integrity": "sha512-eGwxD0AtncrxeBM4tG8R55Pc3rdX1hNW2WibJAgYpCVA6E93mvvVH+LcssoVjOBrSKWS55yEIHsk0X8ctHmfOQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.14.0.tgz", + "integrity": "sha512-9n2pWK61veAuN0V20t9lOuoV4CFMdyAZ1ygZzvBGk/pBBJRib/PjL9PLXa/aI2CcPpyHfqVsxxqLCYl6uZlfDw==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-xml": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@azure/core-xml/-/core-xml-1.6.0.tgz", + "integrity": "sha512-e7lX/dk//F6Qf7BB6PTY4+p2yuOQtyOeHGyapYHNwqSp2OnYpwQt49A/Nin2XmKBQ69pwagR4k/lQBq8lbHQkA==", + "license": "MIT", + "dependencies": { + "fast-xml-parser": "^5.5.9", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.4.0.tgz", + "integrity": "sha512-rbAE25KUfjU/s3XHUdJgceoCP5dEOpMx85J04kF+QMdta73XkuG9JGHHinch+XIoKpBdqljin+KqURpJriSzLA==", + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/storage-blob": { + "version": "12.33.0", + "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.33.0.tgz", + "integrity": "sha512-2SX8oP8PyblUcAFZSg39c8Ls+tFjavM6sBeV+qpw33mRzRhI/5hrFJmJ/x0H9xx5l6ECPvgSP8uPxqTeVbHNIA==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.3", + "@azure/core-http-compat": "^2.2.0", + "@azure/core-lro": "^2.2.0", + "@azure/core-paging": "^1.6.2", + "@azure/core-rest-pipeline": "^1.19.1", + "@azure/core-tracing": "^1.2.0", + "@azure/core-util": "^1.11.0", + "@azure/core-xml": "^1.4.5", + "@azure/logger": "^1.1.4", + "@azure/storage-common": "^12.4.1", + "events": "^3.0.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/storage-common": { + "version": "12.4.1", + "resolved": "https://registry.npmjs.org/@azure/storage-common/-/storage-common-12.4.1.tgz", + "integrity": "sha512-t14unw/WofGDUi7TKJrsyXyPsN+NLgRm7hMaq0llxNmTIzt7f257+6LE6FKIJPh88zLj6M7LPvzve0fEYg/L3A==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.9.0", + "@azure/core-http-compat": "^2.2.0", + "@azure/core-rest-pipeline": "^1.24.0", + "@azure/core-tracing": "^1.2.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.1.4", + "events": "^3.3.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.1.tgz", + "integrity": "sha512-BvAMfS6LrgZiryOAZ4pBYucu4wG/Ei/9o9DZ9akbREnMLbPJiom2i8b9C8IsKErQoiKqVhrerzt3kOT/RrzLHg==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@bufbuild/protoplugin": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/@bufbuild/protoplugin/-/protoplugin-2.12.1.tgz", + "integrity": "sha512-PY58KxQVAD1BnnKtStOctsMoegEVGfBnY5AOqVQOIu711nA13oYtTqJM8df5lUQg2J1DR3XxUXptE+fWX5oLdA==", + "license": "Apache-2.0", + "dependencies": { + "@bufbuild/protobuf": "2.12.1", + "@typescript/vfs": "^1.6.2", + "typescript": "5.4.5" + } + }, + "node_modules/@bufbuild/protoplugin/node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nodable/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, + "node_modules/@octokit/auth-token": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", + "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/core": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz", + "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^6.0.0", + "@octokit/graphql": "^9.0.3", + "@octokit/request": "^10.0.6", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "before-after-hook": "^4.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/endpoint": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.3.tgz", + "integrity": "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/graphql": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz", + "integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^10.0.6", + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "27.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz", + "integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz", + "integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz", + "integrity": "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==", + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz", + "integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-8.1.0.tgz", + "integrity": "sha512-O1FZgXeiGb2sowEr/hYTr6YunGdSAFWnr2fyW39Ah85H8O33ELASQxcvOFF5LE6Tjekcyu2ms4qAzJVhSaJxTw==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=7" + } + }, + "node_modules/@octokit/request": { + "version": "10.0.11", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.11.tgz", + "integrity": "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^11.0.3", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "content-type": "^2.0.0", + "json-with-bigint": "^3.5.3", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/request-error": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz", + "integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/types": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz", + "integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^27.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobuf-ts/plugin": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/plugin/-/plugin-2.11.1.tgz", + "integrity": "sha512-HyuprDcw0bEEJqkOWe1rnXUP0gwYLij8YhPuZyZk6cJbIgc/Q0IFgoHQxOXNIXAcXM4Sbehh6kjVnCzasElw1A==", + "license": "Apache-2.0", + "dependencies": { + "@bufbuild/protobuf": "^2.4.0", + "@bufbuild/protoplugin": "^2.4.0", + "@protobuf-ts/protoc": "^2.11.1", + "@protobuf-ts/runtime": "^2.11.1", + "@protobuf-ts/runtime-rpc": "^2.11.1", + "typescript": "^3.9" + }, + "bin": { + "protoc-gen-dump": "bin/protoc-gen-dump", + "protoc-gen-ts": "bin/protoc-gen-ts" + } + }, + "node_modules/@protobuf-ts/protoc": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/protoc/-/protoc-2.11.1.tgz", + "integrity": "sha512-mUZJaV0daGO6HUX90o/atzQ6A7bbN2RSuHtdwo8SSF2Qoe3zHwa4IHyCN1evftTeHfLmdz+45qo47sL+5P8nyg==", + "license": "Apache-2.0", + "bin": { + "protoc": "protoc.js" + } + }, + "node_modules/@protobuf-ts/runtime": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.11.1.tgz", + "integrity": "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@protobuf-ts/runtime-rpc": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime-rpc/-/runtime-rpc-2.11.1.tgz", + "integrity": "sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ==", + "license": "Apache-2.0", + "dependencies": { + "@protobuf-ts/runtime": "^2.11.1" + } + }, + "node_modules/@typescript/vfs": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.4.tgz", + "integrity": "sha512-PJFXFS4ZJKiJ9Qiuix6Dz/OwEIqHD7Dme1UwZhTK11vR+5dqW2ACbdndWQexBzCx+CPuMe5WBYQWCsFyGlQLlQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.7.tgz", + "integrity": "sha512-JVUD8X2tfDMWjcjLs4yVxxVrS8yR5vnh386GAXT9Qj79nBxxXSaHFQZg5FweLmT8HlPQ3kii6noUB+Z9RN7DvQ==", + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anynum": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz", + "integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/archiver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.2", + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "license": "MIT", + "dependencies": { + "glob": "^10.0.0", + "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", + "lazystream": "^1.0.0", + "lodash": "^4.17.15", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.9.1.tgz", + "integrity": "sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==", + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/bare-fs": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.7.4.tgz", + "integrity": "sha512-y1kC+ffIx/tPLdTE693uNjHfzTfr+ravR5tvWlMXe25nELbkqV400S71qHDwbkAQ1FVEZobB1NFRzFbCCcyBCQ==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" + }, + "engines": { + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.1.1.tgz", + "integrity": "sha512-JprUlveX3QjApC1cTpsUOiscADftCGVWkzitbHsRqv84hzYwYHw2mbluddsq5TvI8mH/8Ov1f4BiMAdcB0oYnQ==", + "license": "Apache-2.0" + }, + "node_modules/bare-stream": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.3.tgz", + "integrity": "sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.8.1", + "streamx": "^2.25.0", + "teex": "^1.0.1" + }, + "peerDependencies": { + "bare-abort-controller": "*", + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + }, + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/bare-url": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.5.tgz", + "integrity": "sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ==", + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/before-after-hook": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", + "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", + "license": "Apache-2.0" + }, + "node_modules/binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "license": "MIT", + "dependencies": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "license": "MIT/X11", + "dependencies": { + "traverse": ">=0.3.0 <0.4" + }, + "engines": { + "node": "*" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/compress-commons": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, + "node_modules/fast-xml-builder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.3.0.tgz", + "integrity": "sha512-F74cZEdCvuw9P41GAC3rod4X04jjWGM1JPEv/GWSqFTWLsdyMSBMBMlm9Hk3GLBgLBbdBNY8yee0pQh2RBVESQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.6.2", + "xml-naming": "^0.3.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.10.0.tgz", + "integrity": "sha512-SLhnTEqE5QpJHq/6zl9bsmImEP2adv+y6Wy+cJa7nVTRzQh1OZfCe9k29M5xN74LWnu0xa1zrUrq3KnOKl92Fg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^2.2.0", + "fast-xml-builder": "^1.2.0", + "is-unsafe": "^2.0.0", + "path-expression-matcher": "^1.6.2", + "strnum": "^2.4.1", + "xml-naming": "^0.3.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unsafe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unsafe/-/is-unsafe-2.0.0.tgz", + "integrity": "sha512-2LdV822R+wmI86unXA93WCFpL6g+av8ynWk0nrHyJqGop5VoocYsSLFgN8jrfalT6iGeLNM4KXuVSsULP53kEA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/json-with-bigint": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.10.tgz", + "integrity": "sha512-Vcx+JVNEBts/xfcoCS69sKrOhOk/3TVlvlT+XzUOefVKnnrbYSCKpDCm10pohsJFtsJVYnwa/cXRZ4eElzaM6w==", + "license": "MIT" + }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/path-expression-matcher": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.2.tgz", + "integrity": "sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/streamx": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.28.0.tgz", + "integrity": "sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==", + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "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==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/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==", + "license": "MIT" + }, + "node_modules/string-width-cjs/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strnum": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.1.tgz", + "integrity": "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "anynum": "^1.0.1" + } + }, + "node_modules/tar-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.0.tgz", + "integrity": "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==", + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "bare-fs": "^4.5.5", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "license": "MIT/X11", + "engines": { + "node": "*" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/undici": { + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz", + "integrity": "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "license": "ISC" + }, + "node_modules/unzip-stream": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.4.tgz", + "integrity": "sha512-PyofABPVv+d7fL7GOpusx7eRT9YETY2X04PhwbSipdj6bMxVCFJrr+nm0Mxqbf9hUiTin/UsnuFWBXlDZFy0Cw==", + "license": "MIT", + "dependencies": { + "binary": "^0.3.0", + "mkdirp": "^0.5.1" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "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==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/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==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/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==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/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==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml-naming": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.3.0.tgz", + "integrity": "sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/zip-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + } + } +} diff --git a/.github/scripts/artifact-client/package.json b/.github/scripts/artifact-client/package.json new file mode 100644 index 00000000..f9f1747b --- /dev/null +++ b/.github/scripts/artifact-client/package.json @@ -0,0 +1,11 @@ +{ + "name": "logos-execution-zone-ci-artifact-client", + "private": true, + "type": "module", + "engines": { + "node": ">=24" + }, + "dependencies": { + "@actions/artifact": "6.2.1" + } +} diff --git a/.github/scripts/artifact-client/upload.mjs b/.github/scripts/artifact-client/upload.mjs new file mode 100644 index 00000000..40c86538 --- /dev/null +++ b/.github/scripts/artifact-client/upload.mjs @@ -0,0 +1,65 @@ +import { appendFile, lstat, realpath } from "node:fs/promises"; +import { basename, dirname, resolve } from "node:path"; + +import { DefaultArtifactClient } from "@actions/artifact"; + +const [input, ...extra] = process.argv.slice(2); + +if (!input || extra.length > 0) { + throw new Error("usage: node upload.mjs "); +} + +const archive = await realpath(resolve(input)); +const artifactDirectory = await realpath( + resolve(process.env.INTEGRATION_ARTIFACT_DIR ?? ""), +); +if (dirname(archive) !== artifactDirectory) { + throw new Error(`integration artifact is outside staging: ${archive}`); +} + +const artifactName = basename(archive); +const artifactMatch = /^integration-test-([a-z0-9_]+)\.tar\.zst$/.exec( + artifactName, +); +if (!artifactMatch) { + throw new Error(`invalid integration artifact name: ${artifactName}`); +} + +const archiveStat = await lstat(archive); +if (!archiveStat.isFile()) { + throw new Error(`integration artifact is not a regular file: ${archive}`); +} + +const artifact = new DefaultArtifactClient(); +const { artifacts } = await artifact.listArtifacts({ latest: true }); +if (artifacts.some(({ name }) => name === artifactName)) { + await artifact.deleteArtifact(artifactName); +} + +const { digest, id } = await artifact.uploadArtifact( + artifactName, + [archive], + dirname(archive), + { + retentionDays: 1, + skipArchive: true, + }, +); +if (!digest || !id) { + throw new Error(`artifact upload returned incomplete metadata: ${artifactName}`); +} + +const manifest = resolve(process.env.INTEGRATION_ARTIFACT_MANIFEST ?? ""); +if (dirname(manifest) !== artifactDirectory) { + throw new Error(`integration manifest is outside staging: ${manifest}`); +} +await appendFile( + manifest, + `${JSON.stringify({ + archive: artifactName, + artifact_id: id, + target: artifactMatch[1], + })}\n`, +); + +console.log(`Uploaded ${artifactName} (artifact ${id}, digest ${digest}).`); diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbd3f26c..d6766e64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,6 +116,8 @@ jobs: RISC0_SKIP_BUILD: "1" RUSTDOCFLAGS: -D warnings run: | + # Guest packages generate colliding output names, so document them + # separately below with isolated target directories. cargo doc \ --workspace \ --all-features \ @@ -161,7 +163,7 @@ jobs: env: RISC0_DEV_MODE: "1" RUST_LOG: info - run: cargo nextest run --workspace --exclude integration_tests --exclude test_fixtures --all-features --no-fail-fast + run: cargo nextest run --workspace --exclude integration_tests --exclude test_fixtures --all-features test-fixtures-tests: runs-on: ubuntu-latest @@ -196,11 +198,14 @@ jobs: env: RISC0_DEV_MODE: "1" RUST_LOG: info - run: cargo nextest run -p test_fixtures --no-fail-fast + run: cargo nextest run -p test_fixtures integration-tests-prepare: runs-on: ubuntu-24.04 timeout-minutes: 60 + outputs: + integration-matrix: ${{ steps.publish-matrix.outputs.integration-matrix }} + auth-transfer-artifact-id: ${{ steps.publish-matrix.outputs.auth-transfer-artifact-id }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -226,14 +231,14 @@ jobs: tool: nextest@${{ env.NEXTEST_VERSION }} fallback: none - - name: Discover and validate integration test shards + - name: Discover integration test targets run: | - shard_dir="$RUNNER_TEMP/integration-test-shards" - mkdir -p "$shard_dir" + target_dir="$RUNNER_TEMP/integration-test-targets" + mkdir -p "$target_dir" cargo metadata \ --no-deps \ - --format-version 1 > "$shard_dir/metadata.json" + --format-version 1 > "$target_dir/metadata.json" jq -r ' [.packages[] @@ -244,53 +249,133 @@ jobs: | .name] | sort | unique[] - ' "$shard_dir/metadata.json" > "$shard_dir/discovered.targets" + ' "$target_dir/metadata.json" > "$target_dir/discovered.targets" - shard_targets=( - "indexer_ffi_state_consistency keys token indexer_block_batching indexer_test_run_ffi shared_accounts account" - "amm cross_zone_bridge pinata indexer_state_consistency_with_labels indexer_test_run vault program_deployment" - "indexer_ffi_state_consistency_with_labels ata auth_transfer indexer_stall indexer_ffi_block_batching private_pda block_size_limit cross_zone_state_machine" - "cross_zone_verified two_zone bridge indexer_state_consistency cross_zone_ping wallet_ffi config cross_zone_ingress_guard" - ) + if [[ ! -s "$target_dir/discovered.targets" ]]; then + echo "No non-tps integration test targets were discovered." >&2 + exit 1 + fi - for shard in "${!shard_targets[@]}"; do - targets_file="$shard_dir/$shard.targets" - filter_file="$shard_dir/$shard.filter" - tr ' ' '\n' <<< "${shard_targets[$shard]}" > "$targets_file" - awk ' - { printf "%s%s", separator, "binary(=" $0 ")"; separator = " | " } - END { print "" } - ' "$targets_file" > "$filter_file" - done - - sort "$shard_dir"/[0-3].targets > "$shard_dir/assigned.targets" - if ! diff -u "$shard_dir/discovered.targets" "$shard_dir/assigned.targets"; then - echo "Every non-tps integration binary must belong to exactly one shard." >&2 + target_count="$(wc -l < "$target_dir/discovered.targets")" + if (( target_count > 64 )); then + echo "More than 64 integration targets were discovered." >&2 exit 1 fi { - echo "### Integration archive shards" + echo "### Integration target archives" echo - echo "| Shard | Archive size | Binaries |" - echo "| ---: | ---: | ---: |" + echo "| Target | Archive size |" + echo "| --- | ---: |" } >> "$GITHUB_STEP_SUMMARY" - - uses: ./.github/actions/build-integration-shard + - name: Install Node.js for workflow artifact client + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: - shard: "0" + node-version: 24 - - uses: ./.github/actions/build-integration-shard - with: - shard: "1" + - name: Install workflow artifact client + run: | + npm ci \ + --prefix .github/scripts/artifact-client \ + --ignore-scripts \ + --omit=dev \ + --no-audit \ + --no-fund - - uses: ./.github/actions/build-integration-shard - with: - shard: "2" + - name: Build and upload integration test targets + env: + INTEGRATION_ARTIFACT_DIR: ${{ runner.temp }}/integration-test-targets + INTEGRATION_ARTIFACT_MANIFEST: ${{ runner.temp }}/integration-test-targets/uploaded.jsonl + RISC0_DEV_MODE: "1" + run: | + target_dir="$RUNNER_TEMP/integration-test-targets" + : > "$INTEGRATION_ARTIFACT_MANIFEST" + archive="" + trap '[[ -z "$archive" ]] || rm -f "$archive"' EXIT - - uses: ./.github/actions/build-integration-shard - with: - shard: "3" + target_count=0 + total_archive_bytes=0 + while IFS= read -r target; do + if [[ ! "$target" =~ ^[a-z0-9_]+$ ]]; then + echo "Invalid integration test target: $target" >&2 + exit 2 + fi + + archive="$target_dir/integration-test-$target.tar.zst" + cargo nextest archive \ + -p integration_tests \ + --test "$target" \ + -E "binary(=$target)" \ + --archive-file "$archive" \ + --no-pager + + archive_bytes="$(stat --format=%s "$archive")" + max_archive_bytes=$((128 * 1024 * 1024)) + if (( archive_bytes > max_archive_bytes )); then + echo "Target $target archive is larger than the 128 MiB limit." >&2 + exit 1 + fi + total_archive_bytes=$((total_archive_bytes + archive_bytes)) + max_total_archive_bytes=$((4 * 1024 * 1024 * 1024)) + if (( total_archive_bytes > max_total_archive_bytes )); then + echo "Integration target archives exceed the 4 GiB total limit." >&2 + exit 1 + fi + + archive_size="$(du -h "$archive" | cut -f1)" + echo "| \`$target\` | $archive_size |" >> "$GITHUB_STEP_SUMMARY" + + node .github/scripts/artifact-client/upload.mjs "$archive" + rm -f "$archive" + archive="" + target_count=$((target_count + 1)) + + available_kib="$(df --output=avail -k "$RUNNER_TEMP" | tail -n 1 | tr -d ' ')" + minimum_free_kib=$((6 * 1024 * 1024)) + if (( available_kib < minimum_free_kib )); then + echo "Less than 6 GiB remains while building integration archives." >&2 + df -h "$RUNNER_TEMP" >&2 + exit 1 + fi + done < "$target_dir/discovered.targets" + + echo >> "$GITHUB_STEP_SUMMARY" + echo "Built $target_count integration targets exactly once." \ + >> "$GITHUB_STEP_SUMMARY" + + - name: Publish integration test matrix + id: publish-matrix + run: | + target_dir="$RUNNER_TEMP/integration-test-targets" + jq -r .target "$target_dir/uploaded.jsonl" \ + | sort > "$target_dir/uploaded.targets" + if ! diff -u \ + "$target_dir/discovered.targets" \ + "$target_dir/uploaded.targets"; then + echo "Every discovered integration target must be uploaded exactly once." >&2 + exit 1 + fi + + integration_matrix="$(jq -s -c '{include: .}' \ + "$target_dir/uploaded.jsonl")" + auth_transfer_artifact_id="$(jq -r \ + 'select(.target == "auth_transfer") | .artifact_id' \ + "$target_dir/uploaded.jsonl")" + if [[ ! "$auth_transfer_artifact_id" =~ ^[0-9]+$ ]]; then + echo "The auth_transfer artifact ID is missing or invalid." >&2 + exit 1 + fi + + echo "integration-matrix=$integration_matrix" >> "$GITHUB_OUTPUT" + echo "auth-transfer-artifact-id=$auth_transfer_artifact_id" \ + >> "$GITHUB_OUTPUT" + + - name: Release artifact client and target metadata disk + if: always() + run: | + rm -rf .github/scripts/artifact-client/node_modules + rm -rf "$RUNNER_TEMP/integration-test-targets" - name: Stage RISC Zero runtime run: | @@ -298,13 +383,18 @@ jobs: install -m 0755 "$(command -v r0vm)" "$RUNNER_TEMP/risc0-runtime/r0vm" - name: Upload RISC Zero runtime - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: risc0-runtime-3.0.5 path: ${{ runner.temp }}/risc0-runtime/r0vm compression-level: 6 retention-days: 1 if-no-files-found: error + overwrite: true + + - name: Release staged RISC Zero runtime disk + if: always() + run: rm -f "$RUNNER_TEMP/risc0-runtime/r0vm" integration-tests: needs: @@ -314,10 +404,9 @@ jobs: timeout-minutes: 90 strategy: fail-fast: false - max-parallel: 4 - matrix: - shard: [0, 1, 2, 3] - name: integration-tests (shard ${{ matrix.shard }}) + max-parallel: 30 + matrix: ${{ fromJSON(needs.integration-tests-prepare.outputs.integration-matrix) }} + name: integration-tests (${{ matrix.target }}) steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -329,20 +418,39 @@ jobs: tool: nextest@${{ env.NEXTEST_VERSION }} fallback: none - - name: Download integration test shard - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + - name: Download integration test archive + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: integration-tests-${{ matrix.shard }} - path: ${{ runner.temp }}/integration-test-shard + artifact-ids: ${{ matrix.artifact_id }} + path: ${{ runner.temp }}/integration-test-target + skip-decompress: true - - name: Run integration test shard + - name: Run integration test target env: + ARCHIVE_NAME: ${{ matrix.archive }} RISC0_DEV_MODE: "1" RUST_LOG: info + TARGET: ${{ matrix.target }} run: | - archive="$RUNNER_TEMP/integration-test-shard/integration-tests-${{ matrix.shard }}.tar.zst" - targets="$RUNNER_TEMP/integration-test-shard/${{ matrix.shard }}.targets" - extract_dir="$RUNNER_TEMP/nextest-shard" + if [[ ! "$TARGET" =~ ^[a-z0-9_]+$ ]]; then + echo "Invalid integration test target: $TARGET" >&2 + exit 2 + fi + + expected_archive="integration-test-$TARGET.tar.zst" + if [[ "$ARCHIVE_NAME" != "$expected_archive" ]]; then + echo "Archive $ARCHIVE_NAME does not match target $TARGET." >&2 + exit 2 + fi + + archive="$RUNNER_TEMP/integration-test-target/$ARCHIVE_NAME" + extract_dir="$RUNNER_TEMP/nextest-target" + + echo "::group::Archive and disk usage before extraction" + du -h "$archive" + df -h "$RUNNER_TEMP" + echo "::endgroup::" + mkdir -p "$extract_dir" cargo-nextest nextest list \ --archive-file "$archive" \ @@ -353,32 +461,30 @@ jobs: --no-pager > /dev/null rm -f "$archive" + echo "::group::Disk usage after extraction" + du -sh "$extract_dir" + df -h "$RUNNER_TEMP" + echo "::endgroup::" + available_kib="$(df --output=avail -k "$RUNNER_TEMP" | tail -n 1 | tr -d ' ')" minimum_free_kib=$((6 * 1024 * 1024)) if (( available_kib < minimum_free_kib )); then - echo "Less than 6 GiB remains after shard extraction." >&2 + echo "Less than 6 GiB remains after target extraction." >&2 df -h "$RUNNER_TEMP" >&2 exit 1 fi - common_args=( - --cargo-metadata "$extract_dir/target/nextest/cargo-metadata.json" - --binaries-metadata "$extract_dir/target/nextest/binaries-metadata.json" - --target-dir-remap "$extract_dir/target" - --workspace-remap "$GITHUB_WORKSPACE" - --no-fail-fast - ) - - failed=0 - while IFS= read -r binary; do - echo "::group::integration binary: $binary" - if ! cargo-nextest nextest run "${common_args[@]}" -E "binary(=$binary)"; then - failed=1 - fi - echo "::endgroup::" - done < "$targets" - - exit "$failed" + cargo-nextest nextest run \ + --cargo-metadata "$extract_dir/target/nextest/cargo-metadata.json" \ + --binaries-metadata "$extract_dir/target/nextest/binaries-metadata.json" \ + --target-dir-remap "$extract_dir/target" \ + --workspace-remap "$GITHUB_WORKSPACE" \ + --show-progress none \ + --success-output immediate \ + --status-level all \ + --final-status-level all \ + --no-output-indent \ + -E "binary(=$TARGET)" valid-proof-test: needs: integration-tests-prepare @@ -395,18 +501,20 @@ jobs: tool: nextest@${{ env.NEXTEST_VERSION }} fallback: none - - name: Download integration test shard - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + - name: Download auth_transfer integration test archive + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: integration-tests-2 - path: ${{ runner.temp }}/integration-test-shard + artifact-ids: ${{ needs.integration-tests-prepare.outputs.auth-transfer-artifact-id }} + path: ${{ runner.temp }}/integration-test-target + skip-decompress: true - name: Test valid proof env: - RUST_LOG: info + RISC0_INFO: "1" + RUST_LOG: info,risc0_zkvm::host::client::prove::external=debug,risc0_zkvm::host::server::prove=debug,risc0_zkvm::host::recursion::prove=debug run: | - archive="$RUNNER_TEMP/integration-test-shard/integration-tests-2.tar.zst" - extract_dir="$RUNNER_TEMP/nextest-shard" + archive="$RUNNER_TEMP/integration-test-target/integration-test-auth_transfer.tar.zst" + extract_dir="$RUNNER_TEMP/nextest-target" mkdir -p "$extract_dir" cargo-nextest nextest list \ --archive-file "$archive" \ @@ -417,11 +525,14 @@ jobs: --no-pager > /dev/null rm -f "$archive" + echo "Starting non-development RISC Zero succinct proof." cargo-nextest nextest run \ --cargo-metadata "$extract_dir/target/nextest/cargo-metadata.json" \ --binaries-metadata "$extract_dir/target/nextest/binaries-metadata.json" \ --target-dir-remap "$extract_dir/target" \ --workspace-remap "$GITHUB_WORKSPACE" \ + --no-capture \ + --show-progress none \ -E 'binary(=auth_transfer) & test(=private::private_transfer_to_owned_account)' artifacts: From 35d6907aaa9d3895442205ca8bd2a2edb79c122d Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Wed, 15 Jul 2026 19:59:56 -0300 Subject: [PATCH 3/4] chore(artifacts): refresh privacy circuit binary --- .../privacy_preserving_circuit.bin | Bin 632704 -> 632704 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/artifacts/lee/privacy_preserving_circuit/privacy_preserving_circuit.bin b/artifacts/lee/privacy_preserving_circuit/privacy_preserving_circuit.bin index f54520a81e52737cf7bbe6a694599df12aa125fa..7387656f5e58b039be8849ee8c9aaf490dd7992e 100644 GIT binary patch delta 304 zcmZoTuhsxWEsQNpEzB(}EvzkUE$mx3ER%$d&5cb>EKCf{EsP8d42%sd%nYVqNa9eJ zHr30?Da+L}#HqjpzXE-%Mz3e&6rZk{%rPIU?CoTZY^)L>7fo+S;o!t6D`kMwInxbu zI5f7irgA)26E-q7HZim`u{1R{H8e6Zvoy9an4T!WAw2!V5f1)##U76Bianh1(f|U= BP9p#S delta 305 zcmZoTuhsxWEsQNpEzB(}EvzkUE$mx3ER%#yO-;-V4UH`fP0cJVO^ggp49urrNa9eJ zHr30?Da+L}#HqjpzXE-%Mz3e&6rZk{%rPIU?CoTZY^)L>7fo+S;o!t6D{X+sIf?}w z8r#`YIi9HrTNs&IniyD`8(A0|85#h+Yiu+ Date: Wed, 15 Jul 2026 20:12:56 -0300 Subject: [PATCH 4/4] fix(ci): upload artifacts from action context --- .github/scripts/artifact-client/upload.mjs | 173 ++++++++++++++------- .github/workflows/ci.yml | 65 ++------ 2 files changed, 130 insertions(+), 108 deletions(-) diff --git a/.github/scripts/artifact-client/upload.mjs b/.github/scripts/artifact-client/upload.mjs index 40c86538..0484eb89 100644 --- a/.github/scripts/artifact-client/upload.mjs +++ b/.github/scripts/artifact-client/upload.mjs @@ -1,65 +1,132 @@ -import { appendFile, lstat, realpath } from "node:fs/promises"; -import { basename, dirname, resolve } from "node:path"; +import { + appendFile, + lstat, + readFile, + realpath, + rm, + statfs, + writeFile, +} from "node:fs/promises"; +import { basename, dirname, join, resolve } from "node:path"; import { DefaultArtifactClient } from "@actions/artifact"; -const [input, ...extra] = process.argv.slice(2); +const GIB = 1024 ** 3; +const MIB = 1024 ** 2; -if (!input || extra.length > 0) { - throw new Error("usage: node upload.mjs "); +function humanSize(size) { + if (size >= GIB) return `${(size / GIB).toFixed(2)} GiB`; + return `${(size / MIB).toFixed(2)} MiB`; } -const archive = await realpath(resolve(input)); -const artifactDirectory = await realpath( - resolve(process.env.INTEGRATION_ARTIFACT_DIR ?? ""), -); -if (dirname(archive) !== artifactDirectory) { - throw new Error(`integration artifact is outside staging: ${archive}`); -} +export async function buildAndUploadIntegrationTargets({ core, exec }) { + const artifactDirectory = await realpath( + resolve(process.env.INTEGRATION_ARTIFACT_DIR ?? ""), + ); + const manifest = resolve(process.env.INTEGRATION_ARTIFACT_MANIFEST ?? ""); + const targetsPath = resolve(process.env.INTEGRATION_TARGETS_FILE ?? ""); -const artifactName = basename(archive); -const artifactMatch = /^integration-test-([a-z0-9_]+)\.tar\.zst$/.exec( - artifactName, -); -if (!artifactMatch) { - throw new Error(`invalid integration artifact name: ${artifactName}`); -} + if (dirname(manifest) !== artifactDirectory) { + throw new Error(`integration manifest is outside staging: ${manifest}`); + } + if (dirname(targetsPath) !== artifactDirectory) { + throw new Error(`integration target list is outside staging: ${targetsPath}`); + } + await writeFile(manifest, ""); -const archiveStat = await lstat(archive); -if (!archiveStat.isFile()) { - throw new Error(`integration artifact is not a regular file: ${archive}`); -} + const targets = (await readFile(targetsPath, "utf8")) + .split("\n") + .filter(Boolean); + if (targets.length === 0 || targets.length > 64) { + throw new Error(`invalid integration target count: ${targets.length}`); + } -const artifact = new DefaultArtifactClient(); -const { artifacts } = await artifact.listArtifacts({ latest: true }); -if (artifacts.some(({ name }) => name === artifactName)) { - await artifact.deleteArtifact(artifactName); -} + const artifact = new DefaultArtifactClient(); + let totalArchiveSize = 0; -const { digest, id } = await artifact.uploadArtifact( - artifactName, - [archive], - dirname(archive), - { - retentionDays: 1, - skipArchive: true, - }, -); -if (!digest || !id) { - throw new Error(`artifact upload returned incomplete metadata: ${artifactName}`); -} + for (const target of targets) { + if (!/^[a-z0-9_]+$/.test(target)) { + throw new Error(`invalid integration target: ${target}`); + } -const manifest = resolve(process.env.INTEGRATION_ARTIFACT_MANIFEST ?? ""); -if (dirname(manifest) !== artifactDirectory) { - throw new Error(`integration manifest is outside staging: ${manifest}`); -} -await appendFile( - manifest, - `${JSON.stringify({ - archive: artifactName, - artifact_id: id, - target: artifactMatch[1], - })}\n`, -); + const artifactName = `integration-test-${target}.tar.zst`; + const archive = join(artifactDirectory, artifactName); -console.log(`Uploaded ${artifactName} (artifact ${id}, digest ${digest}).`); + try { + const exitCode = await exec.exec("cargo", [ + "nextest", + "archive", + "-p", + "integration_tests", + "--test", + target, + "-E", + `binary(=${target})`, + "--archive-file", + archive, + "--no-pager", + ]); + if (exitCode !== 0) { + throw new Error(`nextest archive failed for ${target}`); + } + + const archiveStat = await lstat(archive); + if (!archiveStat.isFile()) { + throw new Error(`integration artifact is not a file: ${archive}`); + } + if (archiveStat.size > 128 * MIB) { + throw new Error(`${target} archive exceeds the 128 MiB limit`); + } + + totalArchiveSize += archiveStat.size; + if (totalArchiveSize > 4 * GIB) { + throw new Error("integration archives exceed the 4 GiB total limit"); + } + + await appendFile( + process.env.GITHUB_STEP_SUMMARY, + `| \`${target}\` | ${humanSize(archiveStat.size)} |\n`, + ); + + const { artifacts } = await artifact.listArtifacts({ latest: true }); + if (artifacts.some(({ name }) => name === artifactName)) { + await artifact.deleteArtifact(artifactName); + } + + const { digest, id } = await artifact.uploadArtifact( + artifactName, + [archive], + artifactDirectory, + { + retentionDays: 1, + skipArchive: true, + }, + ); + if (!digest || !id) { + throw new Error(`upload returned incomplete metadata: ${artifactName}`); + } + + await appendFile( + manifest, + `${JSON.stringify({ + archive: artifactName, + artifact_id: id, + target, + })}\n`, + ); + core.info(`Uploaded ${artifactName} (artifact ${id}, digest ${digest}).`); + } finally { + await rm(archive, { force: true }); + } + + const disk = await statfs(artifactDirectory); + if (disk.bavail * disk.bsize < 6 * GIB) { + throw new Error("less than 6 GiB remains while building archives"); + } + } + + await appendFile( + process.env.GITHUB_STEP_SUMMARY, + `\nBuilt ${targets.length} integration targets exactly once.\n`, + ); +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6766e64..b60de542 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -284,65 +284,20 @@ jobs: --no-fund - name: Build and upload integration test targets + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: + ARTIFACT_CLIENT_SCRIPT: ${{ github.workspace }}/.github/scripts/artifact-client/upload.mjs INTEGRATION_ARTIFACT_DIR: ${{ runner.temp }}/integration-test-targets INTEGRATION_ARTIFACT_MANIFEST: ${{ runner.temp }}/integration-test-targets/uploaded.jsonl + INTEGRATION_TARGETS_FILE: ${{ runner.temp }}/integration-test-targets/discovered.targets RISC0_DEV_MODE: "1" - run: | - target_dir="$RUNNER_TEMP/integration-test-targets" - : > "$INTEGRATION_ARTIFACT_MANIFEST" - archive="" - trap '[[ -z "$archive" ]] || rm -f "$archive"' EXIT - - target_count=0 - total_archive_bytes=0 - while IFS= read -r target; do - if [[ ! "$target" =~ ^[a-z0-9_]+$ ]]; then - echo "Invalid integration test target: $target" >&2 - exit 2 - fi - - archive="$target_dir/integration-test-$target.tar.zst" - cargo nextest archive \ - -p integration_tests \ - --test "$target" \ - -E "binary(=$target)" \ - --archive-file "$archive" \ - --no-pager - - archive_bytes="$(stat --format=%s "$archive")" - max_archive_bytes=$((128 * 1024 * 1024)) - if (( archive_bytes > max_archive_bytes )); then - echo "Target $target archive is larger than the 128 MiB limit." >&2 - exit 1 - fi - total_archive_bytes=$((total_archive_bytes + archive_bytes)) - max_total_archive_bytes=$((4 * 1024 * 1024 * 1024)) - if (( total_archive_bytes > max_total_archive_bytes )); then - echo "Integration target archives exceed the 4 GiB total limit." >&2 - exit 1 - fi - - archive_size="$(du -h "$archive" | cut -f1)" - echo "| \`$target\` | $archive_size |" >> "$GITHUB_STEP_SUMMARY" - - node .github/scripts/artifact-client/upload.mjs "$archive" - rm -f "$archive" - archive="" - target_count=$((target_count + 1)) - - available_kib="$(df --output=avail -k "$RUNNER_TEMP" | tail -n 1 | tr -d ' ')" - minimum_free_kib=$((6 * 1024 * 1024)) - if (( available_kib < minimum_free_kib )); then - echo "Less than 6 GiB remains while building integration archives." >&2 - df -h "$RUNNER_TEMP" >&2 - exit 1 - fi - done < "$target_dir/discovered.targets" - - echo >> "$GITHUB_STEP_SUMMARY" - echo "Built $target_count integration targets exactly once." \ - >> "$GITHUB_STEP_SUMMARY" + with: + script: | + const { pathToFileURL } = await import("node:url") + const artifactClient = await import( + pathToFileURL(process.env.ARTIFACT_CLIENT_SCRIPT) + ) + await artifactClient.buildAndUploadIntegrationTargets({ core, exec }) - name: Publish integration test matrix id: publish-matrix