diff --git a/.github/scripts/tests/lockfile-refresh-workflows.test.mjs b/.github/scripts/tests/lockfile-refresh-workflows.test.mjs new file mode 100644 index 0000000000..52fef1f698 --- /dev/null +++ b/.github/scripts/tests/lockfile-refresh-workflows.test.mjs @@ -0,0 +1,24 @@ +import { readFile } from 'node:fs/promises'; +import { test } from 'node:test'; +import assert from 'node:assert/strict'; + +const workflows = [ + '.github/workflows/refresh-lockfile.yml', + '.github/workflows/pr-trusted.yml', + '.github/workflows/docker.yml', +]; + +test('lockfile repair workflows resolve dependencies instead of updating metadata only', async () => { + for (const workflow of workflows) { + const contents = await readFile(workflow, 'utf8'); + const repairCommands = contents + .split('\n') + .filter((line) => line.includes('pnpm install') && line.includes('--no-frozen-lockfile')); + + assert.ok(repairCommands.length > 0, `${workflow} must contain a lockfile repair command`); + for (const command of repairCommands) { + assert.match(command, /--ignore-scripts/); + assert.doesNotMatch(command, /--lockfile-only/); + } + } +}); diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 14b8937abe..5fb9f7e600 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -87,7 +87,7 @@ jobs: - name: Refresh lockfile for Docker build context run: | set -euo pipefail - pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile + pnpm install --ignore-scripts --no-frozen-lockfile changed="$(git status --porcelain)" if [ -z "$changed" ]; then @@ -281,7 +281,7 @@ jobs: - name: Refresh lockfile for Docker build context run: | set -euo pipefail - pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile + pnpm install --ignore-scripts --no-frozen-lockfile changed="$(git status --porcelain)" if [ -z "$changed" ]; then diff --git a/.github/workflows/pr-trusted.yml b/.github/workflows/pr-trusted.yml index 5bc040f992..7bd403aa57 100644 --- a/.github/workflows/pr-trusted.yml +++ b/.github/workflows/pr-trusted.yml @@ -337,7 +337,7 @@ jobs: id: regen_lockfile run: | cp pnpm-lock.yaml "$RUNNER_TEMP/pnpm-lock.before.yaml" - pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile + pnpm install --ignore-scripts --no-frozen-lockfile if cmp -s "$RUNNER_TEMP/pnpm-lock.before.yaml" pnpm-lock.yaml; then echo "regenerated=0" >> "$GITHUB_OUTPUT" else diff --git a/.github/workflows/refresh-lockfile.yml b/.github/workflows/refresh-lockfile.yml index 49ac2176e7..039d21970e 100644 --- a/.github/workflows/refresh-lockfile.yml +++ b/.github/workflows/refresh-lockfile.yml @@ -35,7 +35,7 @@ jobs: cache: pnpm - name: Refresh pnpm lockfile - run: pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile + run: pnpm install --ignore-scripts --no-frozen-lockfile - name: Fail on unexpected file changes run: | diff --git a/.github/workflows/runner-full-stack-e2e.yml b/.github/workflows/runner-full-stack-e2e.yml index 535902a478..22ddb4b04b 100644 --- a/.github/workflows/runner-full-stack-e2e.yml +++ b/.github/workflows/runner-full-stack-e2e.yml @@ -5,6 +5,10 @@ on: - cron: "47 8 * * 0" workflow_dispatch: inputs: + target_branch: + description: "Branch in paperclipai/paperclip to test; the trusted workflow still runs from master" + type: string + required: false all: description: "Run the complete paid matrix when no narrower selector is supplied" type: boolean @@ -38,10 +42,10 @@ permissions: contents: read concurrency: - group: runner-full-stack-e2e-${{ github.ref }} - # Development-only validation refs supersede older runs on the same ref. - # Preserve every protected default-branch campaign for its paid audit trail. - cancel-in-progress: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) }} + group: runner-full-stack-e2e-${{ inputs.target_branch || github.event.repository.default_branch }} + # Development branch campaigns supersede older runs for the same target. + # Preserve every default-branch campaign for its paid audit trail. + cancel-in-progress: ${{ github.event_name == 'workflow_dispatch' && inputs.target_branch != '' && inputs.target_branch != github.event.repository.default_branch }} jobs: authorize: @@ -55,6 +59,7 @@ jobs: test_runner: ${{ steps.runner.outputs.runner }} max_parallel_default: ${{ steps.runner.outputs.max_parallel_default }} max_parallel_limit: ${{ steps.runner.outputs.max_parallel_limit }} + target_sha: ${{ steps.target.outputs.sha }} steps: - name: Require default branch and allowlisted numeric actor IDs env: @@ -89,6 +94,27 @@ jobs: fi done + - name: Resolve requested repository branch to an immutable commit + id: target + env: + GH_TOKEN: ${{ github.token }} + REPOSITORY: ${{ github.repository }} + TARGET_BRANCH: ${{ inputs.target_branch || github.event.repository.default_branch }} + run: | + set -euo pipefail + if [ -z "$TARGET_BRANCH" ] || [[ "$TARGET_BRANCH" == refs/* ]]; then + echo "target_branch must name a branch in this repository without a refs/ prefix." >&2 + exit 1 + fi + encoded_branch="$(jq -rn --arg branch "$TARGET_BRANCH" '$branch | @uri')" + target_sha="$(gh api -X GET "repos/$REPOSITORY/branches/$encoded_branch" --jq .commit.sha)" + if ! [[ "$target_sha" =~ ^[0-9a-f]{40}$ ]]; then + echo "The requested repository branch did not resolve to a commit." >&2 + exit 1 + fi + echo "sha=$target_sha" >> "$GITHUB_OUTPUT" + echo "Resolved the requested repository branch to $target_sha." + - name: Select paid test runner id: runner env: @@ -133,6 +159,9 @@ jobs: daytona_image_content_id: ${{ steps.daytona_image_content.outputs.content_id }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + ref: ${{ needs.authorize.outputs.target_sha }} + persist-credentials: false - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 with: @@ -241,6 +270,9 @@ jobs: content_id: ${{ steps.image.outputs.content_id }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + ref: ${{ needs.authorize.outputs.target_sha }} + persist-credentials: false - name: No Daytona image needed id: local_only @@ -269,6 +301,7 @@ jobs: NEEDS_DAYTONA: ${{ needs.catalog.outputs.needs_daytona }} IMAGE_CONTENT_ID: ${{ needs.catalog.outputs.daytona_image_content_id }} IMAGE_TAG: ghcr.io/paperclipai/paperclip-daytona-runner:e2e-content-${{ needs.catalog.outputs.daytona_image_content_id }} + TARGET_SHA: ${{ needs.authorize.outputs.target_sha }} run: | set -euo pipefail if [ "$NEEDS_DAYTONA" != true ]; then @@ -285,7 +318,7 @@ jobs: docker buildx build \ --platform linux/amd64 \ --build-arg "PAPERCLIP_RUNNER_CONTENT_ID=${IMAGE_CONTENT_ID}" \ - --build-arg "PAPERCLIP_RUNNER_SOURCE_REVISION=${GITHUB_SHA}" \ + --build-arg "PAPERCLIP_RUNNER_SOURCE_REVISION=${TARGET_SHA}" \ --file docker/daytona-runner/Dockerfile \ --tag "$IMAGE_TAG" \ --push \ @@ -558,6 +591,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: + ref: ${{ needs.authorize.outputs.target_sha }} persist-credentials: false - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 @@ -677,7 +711,7 @@ jobs: report: name: Merge and enforce campaign result if: always() && !cancelled() && needs.catalog.result == 'success' - needs: [catalog, daytona_image, test] + needs: [authorize, catalog, daytona_image, test] outputs: history_source_ready: ${{ steps.history_source_ready.outputs.ready }} runs-on: ubuntu-latest @@ -686,6 +720,10 @@ jobs: contents: read steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + # Reporting and sanitization are part of the trusted workflow boundary. + ref: ${{ github.sha }} + persist-credentials: false - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 with: @@ -772,7 +810,7 @@ jobs: publish_history: name: Publish pruned immutable history and landing site - needs: [catalog, report] + needs: [authorize, catalog, report] if: always() && needs.catalog.result == 'success' && needs.report.outputs.history_source_ready == 'true' runs-on: ubuntu-latest timeout-minutes: 15 @@ -786,6 +824,10 @@ jobs: name: runner-e2e-history steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + # Never execute target-controlled publication code with AWS credentials. + ref: ${{ github.sha }} + persist-credentials: false - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 with: diff --git a/packages/paperclip-runner/package.json b/packages/paperclip-runner/package.json index 0598e0636c..f519da4292 100644 --- a/packages/paperclip-runner/package.json +++ b/packages/paperclip-runner/package.json @@ -180,7 +180,7 @@ "@types/node": "^24.0.0", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^4.7.0", + "@vitejs/plugin-react": "^6.1.1", "axe-core": "^4.12.1", "react": "^19.2.7", "react-dom": "^19.2.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a3904c2d24..e2e36cb61a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,7 +50,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) cli: dependencies: @@ -281,7 +281,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages/adapters/hermes-gateway: dependencies: @@ -297,7 +297,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages/adapters/kimi-local: dependencies: @@ -398,7 +398,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages/google-sheets-mcp-server: dependencies: @@ -420,7 +420,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages/kv-demo-mcp-server: dependencies: @@ -439,7 +439,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages/mcp-server: dependencies: @@ -461,7 +461,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages/paperclip-eval-kernel: devDependencies: @@ -515,8 +515,8 @@ importers: specifier: ^19.2.3 version: 19.2.4(@types/react@19.2.18) '@vitejs/plugin-react': - specifier: ^4.7.0 - version: 4.7.0(vite@6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12)) + specifier: ^6.1.1 + version: 6.1.1(vite@6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12)) axe-core: specifier: ^4.12.1 version: 4.13.0 @@ -537,7 +537,7 @@ importers: version: 6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12) vitest: specifier: ^4.1.10 - version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12)) + version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1(@noble/hashes@2.4.0))(vite@6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12)) packages/plugins/create-paperclip-plugin: dependencies: @@ -584,7 +584,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages/plugins/examples/plugin-file-browser-example: dependencies: @@ -702,7 +702,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages/plugins/plugin-llm-wiki: devDependencies: @@ -741,7 +741,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages/plugins/plugin-workspace-diff: dependencies: @@ -775,7 +775,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages/plugins/sdk: dependencies: @@ -829,7 +829,7 @@ importers: version: 7.0.2 vitest: specifier: ^4.1.10 - version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12)) + version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1(@noble/hashes@2.4.0))(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12)) packages/teams-catalog: devDependencies: @@ -840,8 +840,8 @@ importers: server: dependencies: '@aws-sdk/client-s3': - specifier: ^3.1115.0 - version: 3.1115.0 + specifier: ^3.1120.0 + version: 3.1120.0 '@opentelemetry/api': specifier: ^1.9.0 version: 1.9.1 @@ -895,7 +895,7 @@ importers: version: link:../packages/skills-catalog '@vercel/connect': specifier: 0.6.1 - version: 0.6.1(better-auth@1.7.0(@opentelemetry/api@1.9.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))(pg@8.18.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12))) + version: 0.6.1(better-auth@1.7.2(@opentelemetry/api@1.9.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))(pg@8.18.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12))) acpx: specifier: 0.13.1 version: 0.13.1(patch_hash=lzpwjtiaybzoijy455dfycwavu) @@ -906,8 +906,8 @@ importers: specifier: ^3.0.1 version: 3.0.1(ajv@8.20.0) better-auth: - specifier: 1.7.0 - version: 1.7.0(@opentelemetry/api@1.9.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))(pg@8.18.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12)) + specifier: 1.7.2 + version: 1.7.2(@opentelemetry/api@1.9.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))(pg@8.18.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12)) chokidar: specifier: ^5.0.0 version: 5.0.0 @@ -931,7 +931,7 @@ importers: version: 5.2.1 jsdom: specifier: ^30.0.1 - version: 30.0.1(@noble/hashes@2.3.0) + version: 30.0.1(@noble/hashes@2.4.0) multer: specifier: ^2.2.0 version: 2.2.0 @@ -1004,7 +1004,7 @@ importers: version: 8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12) vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) ui: dependencies: @@ -1075,8 +1075,8 @@ importers: specifier: ^0.5.20 version: 0.5.20(tailwindcss@4.3.3) '@tanstack/react-query': - specifier: ^5.101.4 - version: 5.101.4(react@19.2.8) + specifier: ^5.102.8 + version: 5.102.8(react@19.2.8) '@xterm/addon-fit': specifier: ^0.11.0 version: 0.11.0 @@ -1102,8 +1102,8 @@ importers: specifier: ^1.32.0 version: 1.32.0(react@19.2.8) mermaid: - specifier: ^11.16.1 - version: 11.16.1 + specifier: ^11.17.2 + version: 11.17.2 motion: specifier: ^12.42.2 version: 12.43.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -1163,8 +1163,8 @@ importers: specifier: ^19.2.4 version: 19.2.4(@types/react@19.2.18) '@vitejs/plugin-react': - specifier: ^5.2.0 - version: 5.2.0(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12)) + specifier: ^6.1.1 + version: 6.1.1(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12)) storybook: specifier: 10.5.10 version: 10.5.10(@types/react@19.2.18)(react@19.2.8) @@ -1179,7 +1179,7 @@ importers: version: 8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12) vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) packages: @@ -1390,8 +1390,8 @@ packages: resolution: {integrity: sha512-Dtu0gr4dnATZAPwEYbpCsG+MpLM7OAliy2gTepEFQwl1vZ6DL3QMH2FveMa3HLvPsOdhJsPRB3KtxVhph9T75A==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-s3@3.1115.0': - resolution: {integrity: sha512-oeniaXZCRrKMaffnyjOSxp1xJNsuiku2SxyzVI1Bi1Gycpck/dRTVsloSa5E+nBKz1c5y5eMfbK4GAhGUCCC2Q==} + '@aws-sdk/client-s3@3.1120.0': + resolution: {integrity: sha512-UunWgNl/U8wIlxVRyhUPqlozFkUS88UqXjAH50XfPDXaZeK9P7KVYTAh4KREVrLPQTzPxVSbQGog3gHlc/P6vg==} engines: {node: '>=20.0.0'} '@aws-sdk/core@3.977.9': @@ -1492,10 +1492,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.29.7': - resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} - engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.29.7': resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} @@ -1517,18 +1513,6 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-transform-react-jsx-self@7.29.7': - resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-source@7.29.7': - resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/runtime@7.29.7': resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} engines: {node: '>=6.9.0'} @@ -1572,8 +1556,8 @@ packages: '@types/react': optional: true - '@better-auth/core@1.7.0': - resolution: {integrity: sha512-tUYocrJx6vYyf0k9CTAgAYtUFFRZIrcwNIhG3+WSUQGTPrcyl/hbo29Y9ynF2LwOZOwIwWCiis1A6Iqej4jC/g==} + '@better-auth/core@1.7.2': + resolution: {integrity: sha512-j0nM4ygsWbF/fcYRoKtDn8gn8uLXkmC+075HqSqsJEAV828cJR9bvYBCUQ1zmxNyRBk6Iz/qXsA0Zm2oksiOTg==} peerDependencies: '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 @@ -1589,46 +1573,46 @@ packages: '@opentelemetry/api': optional: true - '@better-auth/drizzle-adapter@1.7.0': - resolution: {integrity: sha512-PQ7kT9unMmRFl8u3iwri31Ztx3vluuWL4Lq/SRpOpdU5Y0BMII5zpNLfahY5DOVRg9SHAcnWjs0gcwRxxQMuWQ==} + '@better-auth/drizzle-adapter@1.7.2': + resolution: {integrity: sha512-A5wE10PIv3aS5LGePecEHntQylKy6OOF17B4dqlE0DwJeqU/IOBSd7/LZhMop9cNJ3WFjKMpazVSf91yYM/NFg==} peerDependencies: - '@better-auth/core': ^1.7.0 + '@better-auth/core': ^1.7.2 '@better-auth/utils': 0.4.2 drizzle-orm: ^0.45.2 || >=1.0.0-rc.1 <2.0.0 peerDependenciesMeta: drizzle-orm: optional: true - '@better-auth/kysely-adapter@1.7.0': - resolution: {integrity: sha512-hpLMMJiLGsLF35D6Z0dMRtyax4c1uKMRgCNeHs8v+hBVJr8gh+PuKTPAS4p7P9gAYSz74kqG+i/+Ot/EnBl6xA==} + '@better-auth/kysely-adapter@1.7.2': + resolution: {integrity: sha512-LYdSRLOvZiF+6S0UThu+wE/Qxsq9P2jQs7ZKkY6BIBJqUjYyxVDmi8HFcantBvWWW1/BeQCSsD7YVDG4gICMIQ==} peerDependencies: - '@better-auth/core': ^1.7.0 + '@better-auth/core': ^1.7.2 '@better-auth/utils': 0.4.2 kysely: ^0.28.17 || ^0.29.0 peerDependenciesMeta: kysely: optional: true - '@better-auth/memory-adapter@1.7.0': - resolution: {integrity: sha512-87D5BW931Uh+ap8al7nPZZjLHK3Qje3KuvOJ4cJ9yLkb7n6+CLHJAbwJ8yDTe4RY52smCaMm+uEq3vCtlOmLUw==} + '@better-auth/memory-adapter@1.7.2': + resolution: {integrity: sha512-0q1SXMzm5esH9L0xVuM6IxCk59E4G+3HySX4My9gvEwqtmUobykn+iuc/si3Y4xwUO7JODqQ5o+/pPcLDDMIrA==} peerDependencies: - '@better-auth/core': ^1.7.0 + '@better-auth/core': ^1.7.2 '@better-auth/utils': 0.4.2 - '@better-auth/mongo-adapter@1.7.0': - resolution: {integrity: sha512-2FPZ/gvFnkFWQowXmfcxL+Ae27ZFGmXSsldD7Z29Gneh17tJGPTPpIW22d/ci2J1+744f1bQku+PdCkbZ6j6JA==} + '@better-auth/mongo-adapter@1.7.2': + resolution: {integrity: sha512-4879SmUWHUs0OYlvHoCFbycZ7i1bqytkcgAUdt9RLQMvZ5H3LRMTgax2YVlGZEXgwNjY/X7xAoXOecWLhlQWeA==} peerDependencies: - '@better-auth/core': ^1.7.0 + '@better-auth/core': ^1.7.2 '@better-auth/utils': 0.4.2 mongodb: ^6.0.0 || ^7.0.0 peerDependenciesMeta: mongodb: optional: true - '@better-auth/prisma-adapter@1.7.0': - resolution: {integrity: sha512-LLyyNaXzZrUZ4wLEp58JzpCgbQvuyZFCZqinqd8LTfMwuZG6Z+DEDKIkIsCfUb5wrZjUZ+v2o898EEO0yLHnwQ==} + '@better-auth/prisma-adapter@1.7.2': + resolution: {integrity: sha512-mXTr/83WrNWLrvzIjtgDgdu9iXhOcSG1+qBQOAKlbGSFiOB+z4IMRneQ2wmMOiB8mKY9qGkClVUjKRFXqtHnFQ==} peerDependencies: - '@better-auth/core': ^1.7.0 + '@better-auth/core': ^1.7.2 '@better-auth/utils': 0.4.2 '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 prisma: ^5.0.0 || ^6.0.0 || ^7.0.0 @@ -1638,10 +1622,10 @@ packages: prisma: optional: true - '@better-auth/telemetry@1.7.0': - resolution: {integrity: sha512-sIYgwq/Oc/QlgBGNjWju0gwa1hWlkrrpdTiPd7gGBMS9nzp+6l9zU6k6QFug6wjbDSzUsRHOZIXs2EIn9NcOFQ==} + '@better-auth/telemetry@1.7.2': + resolution: {integrity: sha512-LcWu+O0zrxYDQj8E36vfkJwGPW4k9ZDA/rCo0zST6ihzL+juR7pBowoZIM9E6tK0Vit52mf6412bGT4XM4eTjQ==} peerDependencies: - '@better-auth/core': ^1.7.0 + '@better-auth/core': ^1.7.2 '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 @@ -2904,8 +2888,8 @@ packages: react: ^19.2.8 react-dom: ^19.2.8 - '@mermaid-js/parser@1.2.0': - resolution: {integrity: sha512-oYPyv8A4As1yH5Bx+04iQEQxXuIQDe0GKCNSRgao6z8AM9jixXIfP0vsppRLvGf+nKIOb9/LdpWA4YuJiVvESA==} + '@mermaid-js/parser@1.2.1': + resolution: {integrity: sha512-n12NohV3mrUyUL2o93IgG/ifeW9FTyeJn3zDxkhwa8MJ9Fxg3HQMlA3RiGmD/3UnJvheztkjjQAjA2T4LmUcpw==} '@modelcontextprotocol/sdk@1.30.0': resolution: {integrity: sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==} @@ -2930,16 +2914,16 @@ packages: '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 - '@noble/ciphers@2.3.0': - resolution: {integrity: sha512-Clu/xdfgVTf9o7ngLOURaxePwR0j8sjclKEtVij10/jGulwFsPWCvvRgG/XjUVf8Nei+jLG6uwyXzUTGY1DQrw==} + '@noble/ciphers@2.4.0': + resolution: {integrity: sha512-AnjFn0Jv92laAkvMrghlFZq4qQCIN/4DxFV/eooqtC2YTjB7kBeLMS2T9KJX4Dn+ZVXLOwK0lSgqDtx9gvxtiw==} engines: {node: '>= 20.19.0'} '@noble/hashes@1.8.0': resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} engines: {node: ^14.21.3 || >=16} - '@noble/hashes@2.3.0': - resolution: {integrity: sha512-oN+QwyX7VSHotibwubG3kpzbwKrfnyR6OOO+3Nk/53ADL7FmgHHz4TgrbaYKvvOw09u6QTx0oiH1cNCIOuN0CQ==} + '@noble/hashes@2.4.0': + resolution: {integrity: sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==} engines: {node: '>= 20.19.0'} '@openai/codex@0.148.0': @@ -4236,12 +4220,6 @@ packages: cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-beta.27': - resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} - - '@rolldown/pluginutils@1.0.0-rc.3': - resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} - '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} @@ -4693,11 +4671,11 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 || ^8 - '@tanstack/query-core@5.101.4': - resolution: {integrity: sha512-gNwcvOJcRbLWPOLG/2OBm+zM+Yv+MKsXKEOWC57USuZDEsI71hEErQsiEGx5wX9rzWWkfwM0fVSPoiIFSsxfiw==} + '@tanstack/query-core@5.102.8': + resolution: {integrity: sha512-ZNjkJ33CqvPNec/6lZBnHqLc3EVGPZ9ySLhYahU9TcuRFdmwXewuj0c4hwSWcGHqEUwcSrKeZ+oGcvPBqXcQcg==} - '@tanstack/react-query@5.101.4': - resolution: {integrity: sha512-yRg2pfOCxIs4ZJW3XYYHU/WgtD04FHSnfHlpRT7h7pR77hwkdRG4wxbKe4aq6P0RvXUTBSQpQeadS1SUYUe+KA==} + '@tanstack/react-query@5.102.8': + resolution: {integrity: sha512-TYBea4OuXWD7MhaSHq069TWbFe7rcwWN6kzT7JF0OKi1K6c1gTv2IzD6A6ExJsCMozdkqBWeuIUZmu4KQg0O5A==} peerDependencies: react: ^19.2.8 @@ -4817,8 +4795,8 @@ packages: '@types/d3-selection@3.0.11': resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} - '@types/d3-shape@3.1.8': - resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + '@types/d3-shape@3.2.0': + resolution: {integrity: sha512-kVd74ta9eof3eJOvbNd1vGKS/XERRyQbT26Og63hIsvDO84cjD5gEOhsXf26w3FSoNlPVz84DOFcKv/oou+fMw==} '@types/d3-time-format@4.0.3': resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} @@ -5101,17 +5079,21 @@ packages: resolution: {integrity: sha512-nmVSeQ7tewCkqYBNB/MNL8aPB9sTvtjvqIE6+U17U4IuTyehuWVERDlWrSn0DVfiFAstRlRkGLHBlKHB2FyzbQ==} engines: {node: '>= 20'} - '@vitejs/plugin-react@4.7.0': - resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - - '@vitejs/plugin-react@5.2.0': - resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==} + '@vitejs/plugin-react@6.1.1': + resolution: {integrity: sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + oxc-transform-react: ^0.145.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + oxc-transform-react: + optional: true '@vitest/expect@3.2.4': resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} @@ -5390,8 +5372,8 @@ packages: bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} - better-auth@1.7.0: - resolution: {integrity: sha512-azEG/7e4TLZ25TvvgcsolnzOzLfDFovdIYUb7xKeZQOm0p6Vj+rRKKaIvwE4MvXZCff6NAiIH2dMPl8O5yxI+A==} + better-auth@1.7.2: + resolution: {integrity: sha512-gKapKBEvYIGcMxi74RjQ7EbFLiqyQt58vdoJmL1qAlWSkY1Bc2Vqshl524/3u1NxauiOU03M/Ebh762Brmac9A==} peerDependencies: '@lynx-js/react': '*' '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 @@ -5692,8 +5674,8 @@ packages: peerDependencies: cytoscape: ^3.2.0 - cytoscape@3.34.1: - resolution: {integrity: sha512-Lr0RvH9H75y9ar8h9Toy6u4lxRSCcxUq+hHcQ26sVWo6BnaQp1gwEZOYqwuYTZhyW7npyKnNLP8oJ2p1/3OZ7g==} + cytoscape@3.34.2: + resolution: {integrity: sha512-Cm2jaj1X/PBNlzV9yH8zcfGOxO7U+CJ/+mxSBVPSchLaugdp4jtlGx5qaHtPRZ6tgiZ5P+o1XoRfJA+ba6KM3g==} engines: {node: '>=0.10'} d3-array@2.12.1: @@ -5849,8 +5831,8 @@ packages: dateformat@4.6.3: resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} - dayjs@1.11.21: - resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} + dayjs@1.11.23: + resolution: {integrity: sha512-QDTCU0M0MxR3hQfnlDJfwekQiaanm1ubOD231u73WBckQ/fsamwRLiE2GBz6D3a/xF1NgfiDLJjXBa1hYOYTtQ==} debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} @@ -5944,6 +5926,9 @@ packages: dompurify@3.4.13: resolution: {integrity: sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==} + dompurify@3.4.14: + resolution: {integrity: sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==} + dotenv@17.4.2: resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} engines: {node: '>=12'} @@ -6116,8 +6101,8 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} - es-toolkit@1.50.0: - resolution: {integrity: sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==} + es-toolkit@1.52.0: + resolution: {integrity: sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==} esbuild@0.18.20: resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} @@ -6229,6 +6214,9 @@ packages: fast-wrap-ansi@0.2.2: resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + fastdom@1.0.12: + resolution: {integrity: sha512-LB+xjSTEbjHE1cWsxu+tN2Xqr1kpi+V9aADI7sVM5ZMaXyYGPHULQMzpJMYqOTULK/73pUkWVzzObFRBkPr+hg==} + fault@2.0.1: resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} @@ -6570,12 +6558,12 @@ packages: jose@5.10.0: resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + jose@6.2.10: + resolution: {integrity: sha512-iiW7J9qRFlGxvCOIBDBDxFePQSn7ZMAnrYGhrrOo6siO/MIqwfyilLR27pkfDgUk+raLuzADS8A3S/KLBisc0g==} + jose@6.2.8: resolution: {integrity: sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ==} - jose@6.2.9: - resolution: {integrity: sha512-XrchZOFZUl/T3vTwRe8XK+cJrGtMF4th1ARnDfwbBXFKThGhlsxEE4Zu03AD/bjJSt/9jT/mxrOCkJWOg77aPA==} - joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -6927,8 +6915,8 @@ packages: merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - mermaid@11.16.1: - resolution: {integrity: sha512-TQsq6u22fAn3rek5VOubrhKPo1g5hwC3FXUN9hiyupTckcYiGuuKGkNQrKYwGJkXUxZdojwRG46gsSCFZMDp4g==} + mermaid@11.17.2: + resolution: {integrity: sha512-V6K3C8EBdEsPFZXSKMJe6ppQOENxuHARr9GvHX4hh47lAbhMRD9qf4oEK7LoaRQxULMa80/qt5gHO73aCleBBg==} methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} @@ -7136,8 +7124,8 @@ packages: engines: {node: ^22 || ^24 || >=26} hasBin: true - nanostores@1.5.2: - resolution: {integrity: sha512-B0UbxzK1s0CN8Xht6r+7iT5+xV8PTaRERR1nATeplRv1Rw5YLWfVAid0hkqY3EceqpG4RjTk8GAwIxQY39Rnwg==} + nanostores@1.5.3: + resolution: {integrity: sha512-rQLB6eV4f2AW/n3L0JmwCROpaisYy9EDEADvEFSd1C/qG8hB6O5TPlh9A791JRbJr4CnMQBzptDcvD9OR1+6WA==} engines: {node: ^20.0.0 || >=22.0.0} negotiator@1.0.0: @@ -7545,14 +7533,6 @@ packages: '@types/react': '>=18' react: ^19.2.8 - react-refresh@0.17.0: - resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} - engines: {node: '>=0.10.0'} - - react-refresh@0.18.0: - resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} - engines: {node: '>=0.10.0'} - react-remove-scroll-bar@2.3.8: resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} @@ -7895,6 +7875,9 @@ packages: streamx@2.28.0: resolution: {integrity: sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==} + strictdom@1.0.1: + resolution: {integrity: sha512-cEmp9QeXXRmjj/rVp9oyiqcvyocWab/HaoN4+bwFeZ7QzykJD6L3yD4v12K1x0tHpqRqVpJevN3gW7kyM39Bqg==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -8197,8 +8180,8 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - uuid@14.0.1: - resolution: {integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==} + uuid@14.0.2: + resolution: {integrity: sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==} hasBin: true uvu@0.5.6: @@ -8730,7 +8713,7 @@ snapshots: '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/client-s3@3.1115.0': + '@aws-sdk/client-s3@3.1120.0': dependencies: '@aws-sdk/checksums': 3.1000.29 '@aws-sdk/core': 3.977.9 @@ -8949,8 +8932,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.29.7': {} - '@babel/helper-string-parser@7.29.7': {} '@babel/helper-validator-identifier@7.29.7': {} @@ -8966,16 +8947,6 @@ snapshots: dependencies: '@babel/types': 7.29.8 - '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)': - dependencies: - '@babel/core': 7.29.7 - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)': - dependencies: - '@babel/core': 7.29.7 - '@babel/helper-plugin-utils': 7.29.7 - '@babel/runtime@7.29.7': {} '@babel/template@7.29.7': @@ -9024,62 +8995,62 @@ snapshots: optionalDependencies: '@types/react': 19.2.18 - '@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2)': + '@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3)': dependencies: '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 '@opentelemetry/semantic-conventions': 1.43.0 '@standard-schema/spec': 1.1.0 better-call: 1.4.0(zod@4.4.3) - jose: 6.2.9 + jose: 6.2.10 kysely: 0.29.5 - nanostores: 1.5.2 + nanostores: 1.5.3 zod: 4.4.3 optionalDependencies: '@opentelemetry/api': 1.9.1 - '@better-auth/drizzle-adapter@1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))': + '@better-auth/drizzle-adapter@1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))': dependencies: - '@better-auth/core': 1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2) + '@better-auth/core': 1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3) '@better-auth/utils': 0.4.2 optionalDependencies: drizzle-orm: 0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9) - '@better-auth/kysely-adapter@1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2)(kysely@0.29.5)': + '@better-auth/kysely-adapter@1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(kysely@0.29.5)': dependencies: - '@better-auth/core': 1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2) + '@better-auth/core': 1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3) '@better-auth/utils': 0.4.2 optionalDependencies: kysely: 0.29.5 - '@better-auth/memory-adapter@1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2)': + '@better-auth/memory-adapter@1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)': dependencies: - '@better-auth/core': 1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2) + '@better-auth/core': 1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3) '@better-auth/utils': 0.4.2 - '@better-auth/mongo-adapter@1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2)': + '@better-auth/mongo-adapter@1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)': dependencies: - '@better-auth/core': 1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2) + '@better-auth/core': 1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3) '@better-auth/utils': 0.4.2 - '@better-auth/prisma-adapter@1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2)': + '@better-auth/prisma-adapter@1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)': dependencies: - '@better-auth/core': 1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2) + '@better-auth/core': 1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3) '@better-auth/utils': 0.4.2 - '@better-auth/telemetry@1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)': + '@better-auth/telemetry@1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)': dependencies: - '@better-auth/core': 1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2) + '@better-auth/core': 1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3) '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 '@better-auth/utils@0.4.2': dependencies: - '@noble/hashes': 2.3.0 + '@noble/hashes': 2.4.0 '@better-auth/utils@0.5.0': dependencies: - '@noble/hashes': 2.3.0 + '@noble/hashes': 2.4.0 '@better-fetch/fetch@1.3.1': {} @@ -9775,9 +9746,9 @@ snapshots: '@esbuild/win32-x64@0.28.2': optional: true - '@exodus/bytes@1.15.1(@noble/hashes@2.3.0)': + '@exodus/bytes@1.15.1(@noble/hashes@2.4.0)': optionalDependencies: - '@noble/hashes': 2.3.0 + '@noble/hashes': 2.4.0 '@fastify/busboy@2.1.1': {} @@ -10368,7 +10339,7 @@ snapshots: react: 19.2.8 react-dom: 19.2.8(react@19.2.8) - '@mermaid-js/parser@1.2.0': + '@mermaid-js/parser@1.2.1': dependencies: '@chevrotain/types': 11.1.2 @@ -10411,11 +10382,11 @@ snapshots: '@tybys/wasm-util': 0.10.3 optional: true - '@noble/ciphers@2.3.0': {} + '@noble/ciphers@2.4.0': {} '@noble/hashes@1.8.0': {} - '@noble/hashes@2.3.0': {} + '@noble/hashes@2.4.0': {} '@openai/codex@0.148.0': optionalDependencies: @@ -11570,10 +11541,6 @@ snapshots: '@rolldown/binding-win32-x64-msvc@1.2.5': optional: true - '@rolldown/pluginutils@1.0.0-beta.27': {} - - '@rolldown/pluginutils@1.0.0-rc.3': {} - '@rolldown/pluginutils@1.0.1': {} '@rollup/plugin-node-resolve@16.0.3(rollup@4.63.1)': @@ -11982,11 +11949,11 @@ snapshots: tailwindcss: 4.3.3 vite: 8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12) - '@tanstack/query-core@5.101.4': {} + '@tanstack/query-core@5.102.8': {} - '@tanstack/react-query@5.101.4(react@19.2.8)': + '@tanstack/react-query@5.102.8(react@19.2.8)': dependencies: - '@tanstack/query-core': 5.101.4 + '@tanstack/query-core': 5.102.8 react: 19.2.8 '@testing-library/dom@10.4.1': @@ -12122,7 +12089,7 @@ snapshots: '@types/d3-selection@3.0.11': {} - '@types/d3-shape@3.1.8': + '@types/d3-shape@3.2.0': dependencies: '@types/d3-path': 3.1.1 @@ -12167,7 +12134,7 @@ snapshots: '@types/d3-scale': 4.0.9 '@types/d3-scale-chromatic': 3.1.0 '@types/d3-selection': 3.0.11 - '@types/d3-shape': 3.1.8 + '@types/d3-shape': 3.2.0 '@types/d3-time': 3.0.4 '@types/d3-time-format': 4.0.3 '@types/d3-timer': 3.0.2 @@ -12365,11 +12332,11 @@ snapshots: dependencies: execa: 5.1.1 - '@vercel/connect@0.6.1(better-auth@1.7.0(@opentelemetry/api@1.9.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))(pg@8.18.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12)))': + '@vercel/connect@0.6.1(better-auth@1.7.2(@opentelemetry/api@1.9.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))(pg@8.18.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12)))': dependencies: '@vercel/oidc': 3.8.2 optionalDependencies: - better-auth: 1.7.0(@opentelemetry/api@1.9.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))(pg@8.18.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12)) + better-auth: 1.7.2(@opentelemetry/api@1.9.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))(pg@8.18.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12)) '@vercel/oidc@3.8.2': dependencies: @@ -12377,29 +12344,15 @@ snapshots: '@vercel/cli-exec': 1.0.1 jose: 5.10.0 - '@vitejs/plugin-react@4.7.0(vite@6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12))': + '@vitejs/plugin-react@6.1.1(vite@6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12))': dependencies: - '@babel/core': 7.29.7 - '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7) - '@rolldown/pluginutils': 1.0.0-beta.27 - '@types/babel__core': 7.20.5 - react-refresh: 0.17.0 + '@rolldown/pluginutils': 1.0.1 vite: 6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12) - transitivePeerDependencies: - - supports-color - '@vitejs/plugin-react@5.2.0(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12))': + '@vitejs/plugin-react@6.1.1(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12))': dependencies: - '@babel/core': 7.29.7 - '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7) - '@rolldown/pluginutils': 1.0.0-rc.3 - '@types/babel__core': 7.20.5 - react-refresh: 0.18.0 + '@rolldown/pluginutils': 1.0.1 vite: 8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12) - transitivePeerDependencies: - - supports-color '@vitest/expect@3.2.4': dependencies: @@ -12680,24 +12633,24 @@ snapshots: dependencies: tweetnacl: 0.14.5 - better-auth@1.7.0(@opentelemetry/api@1.9.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))(pg@8.18.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12)): + better-auth@1.7.2(@opentelemetry/api@1.9.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9))(pg@8.18.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12)): dependencies: - '@better-auth/core': 1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2) - '@better-auth/drizzle-adapter': 1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9)) - '@better-auth/kysely-adapter': 1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2)(kysely@0.29.5) - '@better-auth/memory-adapter': 1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2) - '@better-auth/mongo-adapter': 1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2) - '@better-auth/prisma-adapter': 1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2) - '@better-auth/telemetry': 1.7.0(@better-auth/core@1.7.0(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.2))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1) + '@better-auth/core': 1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3) + '@better-auth/drizzle-adapter': 1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(kysely@0.29.5)(pg@8.18.0)(postgres@3.4.9)) + '@better-auth/kysely-adapter': 1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(kysely@0.29.5) + '@better-auth/memory-adapter': 1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2) + '@better-auth/mongo-adapter': 1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2) + '@better-auth/prisma-adapter': 1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2) + '@better-auth/telemetry': 1.7.2(@better-auth/core@1.7.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.10)(kysely@0.29.5)(nanostores@1.5.3))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1) '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 - '@noble/ciphers': 2.3.0 - '@noble/hashes': 2.3.0 + '@noble/ciphers': 2.4.0 + '@noble/hashes': 2.4.0 better-call: 1.4.0(zod@4.4.3) defu: 6.1.7 - jose: 6.2.9 + jose: 6.2.10 kysely: 0.29.5 - nanostores: 1.5.2 + nanostores: 1.5.3 zod: 4.4.3 optionalDependencies: drizzle-kit: 0.31.10 @@ -12705,7 +12658,7 @@ snapshots: pg: 8.18.0 react: 19.2.8 react-dom: 19.2.8(react@19.2.8) - vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12) + vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12) transitivePeerDependencies: - '@cloudflare/workers-types' - '@opentelemetry/api' @@ -12937,17 +12890,17 @@ snapshots: csstype@3.2.3: {} - cytoscape-cose-bilkent@4.1.0(cytoscape@3.34.1): + cytoscape-cose-bilkent@4.1.0(cytoscape@3.34.2): dependencies: cose-base: 1.0.3 - cytoscape: 3.34.1 + cytoscape: 3.34.2 - cytoscape-fcose@2.2.0(cytoscape@3.34.1): + cytoscape-fcose@2.2.0(cytoscape@3.34.2): dependencies: cose-base: 2.2.0 - cytoscape: 3.34.1 + cytoscape: 3.34.2 - cytoscape@3.34.1: {} + cytoscape@3.34.2: {} d3-array@2.12.1: dependencies: @@ -13123,16 +13076,16 @@ snapshots: data-uri-to-buffer@4.0.1: {} - data-urls@7.0.0(@noble/hashes@2.3.0): + data-urls@7.0.0(@noble/hashes@2.4.0): dependencies: whatwg-mimetype: 5.0.0 - whatwg-url: 16.0.1(@noble/hashes@2.3.0) + whatwg-url: 16.0.1(@noble/hashes@2.4.0) transitivePeerDependencies: - '@noble/hashes' dateformat@4.6.3: {} - dayjs@1.11.21: {} + dayjs@1.11.23: {} debug@4.4.3: dependencies: @@ -13202,6 +13155,10 @@ snapshots: optionalDependencies: '@types/trusted-types': 2.0.7 + dompurify@3.4.14: + optionalDependencies: + '@types/trusted-types': 2.0.7 + dotenv@17.4.2: {} downshift@7.6.2(react@19.2.8): @@ -13297,7 +13254,7 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 - es-toolkit@1.50.0: {} + es-toolkit@1.52.0: {} esbuild@0.18.20: optionalDependencies: @@ -13498,6 +13455,10 @@ snapshots: dependencies: fast-string-width: 3.0.2 + fastdom@1.0.12: + dependencies: + strictdom: 1.0.1 + fault@2.0.1: dependencies: format: 0.2.2 @@ -13753,9 +13714,9 @@ snapshots: hono@4.13.2: {} - html-encoding-sniffer@6.0.0(@noble/hashes@2.3.0): + html-encoding-sniffer@6.0.0(@noble/hashes@2.4.0): dependencies: - '@exodus/bytes': 1.15.1(@noble/hashes@2.3.0) + '@exodus/bytes': 1.15.1(@noble/hashes@2.4.0) transitivePeerDependencies: - '@noble/hashes' @@ -13871,9 +13832,9 @@ snapshots: jose@5.10.0: {} - jose@6.2.8: {} + jose@6.2.10: {} - jose@6.2.9: {} + jose@6.2.8: {} joycon@3.1.1: {} @@ -13883,17 +13844,17 @@ snapshots: dependencies: argparse: 2.0.1 - jsdom@30.0.1(@noble/hashes@2.3.0): + jsdom@30.0.1(@noble/hashes@2.4.0): dependencies: '@asamuzakjp/css-color': 6.0.7 '@asamuzakjp/dom-selector': 8.3.2 '@bramus/specificity': 2.4.2 '@csstools/css-syntax-patches-for-csstree': 1.1.8(css-tree@3.2.1) - '@exodus/bytes': 1.15.1(@noble/hashes@2.3.0) + '@exodus/bytes': 1.15.1(@noble/hashes@2.4.0) css-tree: 3.2.1 - data-urls: 7.0.0(@noble/hashes@2.3.0) + data-urls: 7.0.0(@noble/hashes@2.4.0) decimal.js: 10.6.0 - html-encoding-sniffer: 6.0.0(@noble/hashes@2.3.0) + html-encoding-sniffer: 6.0.0(@noble/hashes@2.4.0) is-potential-custom-element-name: 1.0.1 lru-cache: 11.5.2 parse5: 8.0.1 @@ -13904,7 +13865,7 @@ snapshots: w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 - whatwg-url: 17.1.0(@noble/hashes@2.3.0) + whatwg-url: 17.1.0(@noble/hashes@2.4.0) xml-name-validator: 5.0.0 transitivePeerDependencies: - '@noble/hashes' @@ -14299,29 +14260,30 @@ snapshots: merge-stream@2.0.0: {} - mermaid@11.16.1: + mermaid@11.17.2: dependencies: '@braintree/sanitize-url': 7.1.2 '@iconify/utils': 3.1.4 - '@mermaid-js/parser': 1.2.0 + '@mermaid-js/parser': 1.2.1 '@types/d3': 7.4.3 '@upsetjs/venn.js': 2.0.0 - cytoscape: 3.34.1 - cytoscape-cose-bilkent: 4.1.0(cytoscape@3.34.1) - cytoscape-fcose: 2.2.0(cytoscape@3.34.1) + cytoscape: 3.34.2 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.34.2) + cytoscape-fcose: 2.2.0(cytoscape@3.34.2) d3: 7.9.0 d3-sankey: 0.12.3 dagre-d3-es: 7.0.14 - dayjs: 1.11.21 - dompurify: 3.4.13 - es-toolkit: 1.50.0 + dayjs: 1.11.23 + dompurify: 3.4.14 + es-toolkit: 1.52.0 + fastdom: 1.0.12 katex: 0.16.47 khroma: 2.1.0 marked: 16.4.2 roughjs: 4.6.6 stylis: 4.4.0 ts-dedent: 2.3.0 - uuid: 14.0.1 + uuid: 14.0.2 methods@1.1.2: {} @@ -14677,7 +14639,7 @@ snapshots: nanoid@6.0.1: {} - nanostores@1.5.2: {} + nanostores@1.5.3: {} negotiator@1.0.0: {} @@ -15181,10 +15143,6 @@ snapshots: transitivePeerDependencies: - supports-color - react-refresh@0.17.0: {} - - react-refresh@0.18.0: {} - react-remove-scroll-bar@2.3.8(@types/react@19.2.18)(react@19.2.8): dependencies: react: 19.2.8 @@ -15657,6 +15615,8 @@ snapshots: - bare-abort-controller - react-native-b4a + strictdom@1.0.1: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -15977,7 +15937,7 @@ snapshots: util-deprecate@1.0.2: {} - uuid@14.0.1: {} + uuid@14.0.2: {} uvu@0.5.6: dependencies: @@ -16004,7 +15964,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.7) picomatch: 4.0.7 postcss: 8.5.26 - rollup: 4.62.4 + rollup: 4.63.1 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 24.13.3 @@ -16027,7 +15987,7 @@ snapshots: jiti: 2.7.0 tsx: 4.23.12 - vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.3.0))(tsx@4.23.12): + vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1(@noble/hashes@2.4.0))(tsx@4.23.12): dependencies: '@vitest/expect': 4.1.10 '@vitest/mocker': 4.1.10(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12)) @@ -16052,7 +16012,7 @@ snapshots: optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 24.13.3 - jsdom: 30.0.1(@noble/hashes@2.3.0) + jsdom: 30.0.1(@noble/hashes@2.4.0) transitivePeerDependencies: - '@vitejs/devtools' - esbuild @@ -16067,7 +16027,7 @@ snapshots: - tsx - yaml - vitest@4.1.11(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12)): + vitest@4.1.11(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1(@noble/hashes@2.4.0))(vite@6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12)): dependencies: '@vitest/expect': 4.1.11 '@vitest/mocker': 4.1.11(vite@6.4.3(@types/node@24.13.3)(jiti@2.7.0)(lightningcss@1.33.0)(tsx@4.23.12)) @@ -16092,11 +16052,11 @@ snapshots: optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 24.13.3 - jsdom: 30.0.1(@noble/hashes@2.3.0) + jsdom: 30.0.1(@noble/hashes@2.4.0) transitivePeerDependencies: - msw - vitest@4.1.11(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12)): + vitest@4.1.11(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1(@noble/hashes@2.4.0))(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12)): dependencies: '@vitest/expect': 4.1.11 '@vitest/mocker': 4.1.11(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12)) @@ -16121,7 +16081,7 @@ snapshots: optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 24.13.3 - jsdom: 30.0.1(@noble/hashes@2.3.0) + jsdom: 30.0.1(@noble/hashes@2.4.0) transitivePeerDependencies: - msw @@ -16141,17 +16101,17 @@ snapshots: whatwg-mimetype@5.0.0: {} - whatwg-url@16.0.1(@noble/hashes@2.3.0): + whatwg-url@16.0.1(@noble/hashes@2.4.0): dependencies: - '@exodus/bytes': 1.15.1(@noble/hashes@2.3.0) + '@exodus/bytes': 1.15.1(@noble/hashes@2.4.0) tr46: 6.0.0 webidl-conversions: 8.0.1 transitivePeerDependencies: - '@noble/hashes' - whatwg-url@17.1.0(@noble/hashes@2.3.0): + whatwg-url@17.1.0(@noble/hashes@2.4.0): dependencies: - '@exodus/bytes': 1.15.1(@noble/hashes@2.3.0) + '@exodus/bytes': 1.15.1(@noble/hashes@2.4.0) tr46: 6.0.0 webidl-conversions: 8.0.1 transitivePeerDependencies: diff --git a/scripts/__tests__/e2e-shard.test.mjs b/scripts/__tests__/e2e-shard.test.mjs index e1074ea683..691c0b6cc1 100644 --- a/scripts/__tests__/e2e-shard.test.mjs +++ b/scripts/__tests__/e2e-shard.test.mjs @@ -306,8 +306,8 @@ test("the trusted PR workflow regenerates stale stacked lockfiles", () => { ); assert.match( workflow, - /pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile/, - "the policy job must validate the complete merge tree instead of only the current PR layer", + /pnpm install --ignore-scripts --no-frozen-lockfile/, + "the policy job must resolve the complete merge tree instead of only updating lockfile metadata", ); assert.match( workflow, diff --git a/server/package.json b/server/package.json index baecc3805a..498feca490 100644 --- a/server/package.json +++ b/server/package.json @@ -44,7 +44,7 @@ "typecheck": "pnpm run prepare:runner-vendor && pnpm --filter @paperclipai/plugin-sdk ensure-build-deps && tsc --noEmit" }, "dependencies": { - "@aws-sdk/client-s3": "^3.1115.0", + "@aws-sdk/client-s3": "^3.1120.0", "@opentelemetry/api": "^1.9.0", "@paperclipai/adapter-claude-local": "workspace:*", "@paperclipai/adapter-codex-local": "workspace:*", @@ -66,7 +66,7 @@ "acpx": "0.13.1", "ajv": "^8.20.0", "ajv-formats": "^3.0.1", - "better-auth": "1.7.0", + "better-auth": "1.7.2", "chokidar": "^5.0.0", "detect-port": "^2.1.0", "dompurify": "^3.4.13", diff --git a/tests/runner-e2e/README.md b/tests/runner-e2e/README.md index 58ca40b76a..8a718db612 100644 --- a/tests/runner-e2e/README.md +++ b/tests/runner-e2e/README.md @@ -271,13 +271,35 @@ auto-stop/archive/delete values remain as cancellation backstops. ## GitHub Actions `Runner Full-Stack E2E` has only `schedule` and `workflow_dispatch` triggers; it -never runs for a pull request or ordinary push. Because this repository is -public, manual campaigns fail before checkout unless they run from the default -branch and both the original actor and rerun actor have numeric GitHub user IDs -in the non-empty JSON-array repository variable -`RUNNER_E2E_ALLOWED_ACTOR_IDS`. Usernames are intentionally not trusted. -The first scheduled attempt is trusted automation; any human rerun of a -scheduled campaign must pass the triggering-actor allowlist. +never runs for a pull request or ordinary push. Start the trusted workflow from +the default branch. A CODEOWNER can set the optional `target_branch` input to +any branch in `paperclipai/paperclip`. The authorization job resolves that +branch to one immutable commit before any checkout. Catalog, image, and paid +test jobs check out that exact commit. Report sanitization and AWS history +publication explicitly check out the trusted workflow commit. The workflow +definition, runner-group permission, and protected-environment deployment still +come from the default branch. Do not select the target branch in GitHub's **Use +workflow from** control. + +Because this repository is public, manual campaigns fail before checkout unless +the trusted workflow runs from the default branch and both the original actor +and rerun actor have numeric GitHub user IDs in the non-empty JSON-array +repository variable `RUNNER_E2E_ALLOWED_ACTOR_IDS`. Keep this stable-ID list in +sync with the owners of `.github/**` in `.github/CODEOWNERS`. Usernames are +intentionally not trusted. The first scheduled attempt is trusted automation; +any human rerun of a scheduled campaign must pass the triggering-actor +allowlist. + +For example, this command runs one branch cell through the trusted default-branch +workflow: + +```bash +gh workflow run runner-full-stack-e2e.yml \ + --ref master \ + -f target_branch=fix/example \ + -f all=false \ + -f id=core-compatibility.runner-codex.local.message-marker +``` Create a protected `runner-e2e-paid` GitHub environment, restrict it to the default branch, limit environment administration to trusted maintainers, and @@ -307,11 +329,14 @@ it, and require a fresh ephemeral instance for each job so one paid cell cannot leave state for the next. Provider secrets remain protected by the stable-ID authorization checks and the default-branch-only `runner-e2e-paid` environment; the fleet itself is not an authorization boundary. These external fleet controls -are as important as the workflow checks in a public repository. +are as important as the workflow checks in a public repository. A CODEOWNER +dispatch is an explicit authorization to execute the selected repository branch +with the cell's scoped provider credential. -Non-default validation runs share a concurrency key per ref and cancel an older -run when a replacement is dispatched. Protected default-branch paid campaigns -are retained and are never auto-cancelled, preserving their audit trail. +Development branch campaigns share a concurrency key per target branch and +cancel an older run when a replacement is dispatched. Default-branch target +campaigns are retained and are never auto-cancelled, preserving their audit +trail. GitHub Actions artifacts are access-controlled 30-day operational copies, not the permanent public history. They retain packaged PNG/WebM and generated diff --git a/tests/runner-e2e/SECURITY.md b/tests/runner-e2e/SECURITY.md index d23deff204..f4fc612ec8 100644 --- a/tests/runner-e2e/SECURITY.md +++ b/tests/runner-e2e/SECURITY.md @@ -9,15 +9,23 @@ changes. ## GitHub authorization Set `RUNNER_E2E_ALLOWED_ACTOR_IDS` to a non-empty JSON array of numeric GitHub -user IDs, for example `[123456,789012]`. Resolve each ID from the authenticated -CLI and verify the login before adding it: +user IDs. Keep the list equal to the owners of `.github/**` in +`.github/CODEOWNERS`. For example, use `[123456,789012]`. Resolve each ID from +the authenticated CLI and verify the login before adding it: ```bash gh api users/LOGIN --jq '{login,id}' ``` -The paid workflows reject manual dispatches outside the default branch before -checkout. They verify both the original actor and triggering actor for every +The paid workflows reject manual dispatches when the workflow definition does +not come from the default branch. A trusted dispatcher may name any branch in +`paperclipai/paperclip` as the code under test. The authorization job resolves +that branch through the GitHub API and passes only its immutable commit SHA to +the catalog, image, and paid test checkouts. Report sanitization and AWS history +publication explicitly use the trusted workflow commit. Never run the workflow +definition from the target branch. + +The workflows verify both the original actor and triggering actor for every scheduled or manual attempt, including human reruns. Every secret-bearing job repeats this check as its first step so GitHub's partial-job rerun feature cannot bypass a successful predecessor authorization job. The @@ -79,14 +87,23 @@ fresh ephemeral instance for every job, prohibit persistent runner reuse, and disable interactive SSH/debug access unless a separate incident procedure explicitly authorizes it. -Changing the runner does not widen secret access. The paid workflow still has -only schedule and manual triggers, requires the protected default branch and -allowlisted stable actor IDs before checkout, repeats that authorization as the -first matrix step, and receives provider credentials only from the protected +Changing the runner does not widen who can authorize secret access. The paid +workflow still has only schedule and manual triggers, requires its trusted +definition to come from the protected default branch, requires allowlisted +stable actor IDs before checkout, and repeats that authorization as the first +matrix step. Provider credentials come only from the protected `runner-e2e-paid` environment. The fleet selector is an exact workflow literal; -the only repository-controlled input is its boolean rollout switch, so +the only repository-controlled routing input is its boolean rollout switch, so configuration cannot redirect a secret-bearing job to an arbitrary runner. +The optional target branch is code, not workflow authority. A CODEOWNER who +dispatches a target branch explicitly authorizes that branch's selected test +process to receive the cell's scoped provider credential. The workflow resolves +the target only inside the same repository, pins one SHA for the campaign, and +checks it out only after authorization. Target-controlled code cannot replace +the report sanitizer or the AWS history publisher. Fork refs and +target-controlled workflow definitions do not enter this path. + ## AWS OIDC and S3 The AWS role trust policy should accept only GitHub's OIDC audience and the diff --git a/tests/runner-e2e/workflow-security.test.ts b/tests/runner-e2e/workflow-security.test.ts index d727336f22..b3de9fbccb 100644 --- a/tests/runner-e2e/workflow-security.test.ts +++ b/tests/runner-e2e/workflow-security.test.ts @@ -77,6 +77,13 @@ describe("public repository paid workflow security", () => { expect(authorizeJob).toContain( "AWS_PAID_RUNNER_ENABLED: ${{ vars.RUNNER_E2E_AWS_ENABLED }}", ); + expect(authorizeJob).toContain( + "Resolve requested repository branch to an immutable commit", + ); + expect(authorizeJob).toContain( + "repos/$REPOSITORY/branches/$encoded_branch", + ); + expect(authorizeJob).toContain('echo "sha=$target_sha"'); expect(paidJob).toContain( "runs-on: ${{ needs.authorize.outputs.test_runner }}", ); @@ -91,7 +98,34 @@ describe("public repository paid workflow security", () => { '[ "$MAX_PARALLEL" -gt "$MAX_PARALLEL_LIMIT" ]', ); expect(fullStack).toContain( - "cancel-in-progress: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) }}", + "group: runner-full-stack-e2e-${{ inputs.target_branch || github.event.repository.default_branch }}", + ); + expect(fullStack).toContain( + "cancel-in-progress: ${{ github.event_name == 'workflow_dispatch' && inputs.target_branch != '' && inputs.target_branch != github.event.repository.default_branch }}", + ); + expect( + fullStack.match( + /ref: \$\{\{ needs\.authorize\.outputs\.target_sha \}\}/g, + ), + ).toHaveLength(3); + expect(fullStack.match(/ref: \$\{\{ github\.sha \}\}/g)).toHaveLength(2); + expect(fullStack.match(/persist-credentials: false/g)).toHaveLength(5); + expect(fullStack).not.toContain("ref: ${{ inputs.target_branch }}"); + expect(fullStack).toContain( + "PAPERCLIP_RUNNER_SOURCE_REVISION=${TARGET_SHA}", + ); + const reportJob = fullStack.slice( + fullStack.indexOf(" report:"), + fullStack.indexOf(" publish_history:"), + ); + const historyJob = fullStack.slice(fullStack.indexOf(" publish_history:")); + expect(reportJob).toContain("ref: ${{ github.sha }}"); + expect(reportJob).not.toContain( + "ref: ${{ needs.authorize.outputs.target_sha }}", + ); + expect(historyJob).toContain("ref: ${{ github.sha }}"); + expect(historyJob).not.toContain( + "ref: ${{ needs.authorize.outputs.target_sha }}", ); expect(fullStack).toContain( "if: always() && !cancelled() && needs.catalog.result == 'success'", diff --git a/ui/package.json b/ui/package.json index 20ea33f78c..2c467096c9 100644 --- a/ui/package.json +++ b/ui/package.json @@ -51,7 +51,7 @@ "@paperclipai/shared": "workspace:*", "@radix-ui/react-slot": "^1.3.0", "@tailwindcss/typography": "^0.5.20", - "@tanstack/react-query": "^5.101.4", + "@tanstack/react-query": "^5.102.8", "@xterm/addon-fit": "^0.11.0", "@xterm/xterm": "^6.0.0", "class-variance-authority": "^0.7.1", @@ -60,7 +60,7 @@ "i18next": "^26.3.6", "lexical": "0.48.0", "lucide-react": "^1.32.0", - "mermaid": "^11.16.1", + "mermaid": "^11.17.2", "motion": "^12.42.2", "radix-ui": "^1.6.7", "react": "^19.2.8", @@ -82,7 +82,7 @@ "@types/node": "^24.0.0", "@types/react": "^19.2.18", "@types/react-dom": "^19.2.4", - "@vitejs/plugin-react": "^5.2.0", + "@vitejs/plugin-react": "^6.1.1", "storybook": "10.5.10", "tailwindcss": "^4.3.3", "typescript": "^7.0.2",