diff --git a/.deepsec/.gitignore b/.deepsec/.gitignore deleted file mode 100644 index a31b54f3eae4..000000000000 --- a/.deepsec/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -node_modules/ -.env*.local - -# Scan output — regenerated by `deepsec scan` / `process`. INFO.md -# and SETUP.md (manually edited) stay tracked. -data/*/files/ -data/*/runs/ -data/*/reports/ -data/*/debug/ -data/*/project.json -# tech.json embeds an absolute `rootPath` of whoever last scanned; it is -# auto-regenerated by scan/process (only `.tags` is consumed), so keep it -# out of git to avoid leaking local paths. -data/*/tech.json diff --git a/.deepsec/AGENTS.md b/.deepsec/AGENTS.md deleted file mode 100644 index a9970395dfa3..000000000000 --- a/.deepsec/AGENTS.md +++ /dev/null @@ -1,23 +0,0 @@ -# Agent setup - -This is a deepsec scanning workspace. Each registered project has its -own setup prompt at `data//SETUP.md` — open the relevant one when -asked to set a project up. - -## Common tasks - -- **Set up a project for scanning**: read `data//SETUP.md` and - follow it (read `node_modules/deepsec/SKILL.md`, then fill - `data//INFO.md` from the target codebase). -- **Add a new project**: run `deepsec init-project ` — it - scaffolds `data//` and prints/writes the setup prompt for the - new project. -- **Write a custom matcher** (only after a real true-positive shows you - a pattern worth keeping): read - `node_modules/deepsec/dist/docs/writing-matchers.md`. - -## Reference - -The deepsec skill is at `node_modules/deepsec/SKILL.md` (after -`pnpm install`). The full docs ship at -`node_modules/deepsec/dist/docs/`. diff --git a/.deepsec/README.md b/.deepsec/README.md deleted file mode 100644 index 1017bf2926e7..000000000000 --- a/.deepsec/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# deepsec - -This directory holds the [deepsec](https://www.npmjs.com/package/deepsec) -config for the parent repo. Checked into git so teammates inherit -project context (auth shape, threat model, custom matchers); generated -scan output is gitignored. - -Currently configured project: `analytics` (target: `..`). - -## Setup - -1. `pnpm install` — installs deepsec. -2. Add an AI Gateway / Anthropic / OpenAI token to `.env.local`. If - you already have `claude` or `codex` CLI logged in on this - machine, you can skip the token for non-sandbox runs (`process` / - `revalidate` / `triage`); deepsec auto-detects and reuses the - subscription. See - `node_modules/deepsec/dist/docs/vercel-setup.md` after install. -3. Open the parent repo in your coding agent (Claude Code, Cursor, …) - and have it follow `data/analytics/SETUP.md` to fill in - `data/analytics/INFO.md`. - -## Daily commands - -```bash -pnpm deepsec scan -pnpm deepsec process --concurrency 5 -pnpm deepsec revalidate --concurrency 5 # cuts FP rate -pnpm deepsec export --format md-dir --out ./findings -``` - -`--project-id` is auto-resolved while there's only one project in -`deepsec.config.ts`. Once you've added a second project, pass -`--project-id analytics` (or whichever id you want) explicitly. - -`scan` is free (regex only). `process` is the AI stage (≈$0.30/file -on Opus by default). Run state goes to `data/analytics/`. - -## Adding another project - -To scan another codebase from this same `.deepsec/`: - -```bash -pnpm deepsec init-project ../some-other-package # path relative to .deepsec/ -``` - -Appends an entry to `deepsec.config.ts` and writes -`data//{INFO.md,SETUP.md,project.json}`. Open the new SETUP.md -in your agent to fill in INFO.md. - -## Layout - -``` -deepsec.config.ts Project list (one entry per scanned repo) -data/analytics/ - INFO.md Repo context — checked into git, hand-curated - SETUP.md Agent setup prompt — checked in, deletable - project.json Generated (gitignored) - files/ One JSON per scanned source file (gitignored) - runs/ Run metadata (gitignored) - reports/ Generated markdown reports (gitignored) -AGENTS.md Pointer for coding agents -.env.local Tokens (gitignored) -``` - -## Docs - -After `pnpm install`: - -- Skill: `node_modules/deepsec/SKILL.md` -- Full docs: `node_modules/deepsec/dist/docs/{getting-started,configuration,models,writing-matchers,plugins,architecture,data-layout,vercel-setup,faq}.md` - -Or browse on -[GitHub](https://github.com/vercel/deepsec/tree/main/docs). diff --git a/.deepsec/deepsec.config.ts b/.deepsec/deepsec.config.ts deleted file mode 100644 index fe309a709bbf..000000000000 --- a/.deepsec/deepsec.config.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { type DeepsecPlugin, defineConfig } from "deepsec/config"; -import { phoenixPlugModule } from "./matchers/phoenix-plug-module.js"; -import { liveViewMount } from "./matchers/liveview-mount.js"; -import { onEeWithoutElse } from "./matchers/on-ee-without-else.js"; -import { authorizeSiteAccessAllRoles } from "./matchers/authorize-site-access-all-roles.js"; -import { pluginsApiController } from "./matchers/plugins-api-controller.js"; -import { obanWorker } from "./matchers/oban-worker.js"; -import { mixTaskEntrypoint } from "./matchers/mix-task-entrypoint.js"; -import { ssoEntrypoint } from "./matchers/sso-entrypoint.js"; -import { verificationEntrypoint } from "./matchers/verification-entrypoint.js"; -import { liveComponentEvent } from "./matchers/livecomponent-event.js"; -import { liveViewSocketBoundary } from "./matchers/liveview-socket-boundary.js"; -import { authFlowEntrypoint } from "./matchers/auth-flow-entrypoint.js"; -import { ingestionPipelineEntrypoint } from "./matchers/ingestion-pipeline-entrypoint.js"; -import { publicApiScopeEntrypoint } from "./matchers/public-api-scope-entrypoint.js"; -import { csvImportUploadEntrypoint } from "./matchers/csv-import-upload-entrypoint.js"; -import { thirdPartyCallbackEntrypoint } from "./matchers/third-party-callback-entrypoint.js"; - -const plausiblePlugin: DeepsecPlugin = { - name: "plausible-analytics", - matchers: [ - phoenixPlugModule, - liveViewMount, - onEeWithoutElse, - authorizeSiteAccessAllRoles, - pluginsApiController, - obanWorker, - mixTaskEntrypoint, - ssoEntrypoint, - verificationEntrypoint, - liveComponentEvent, - liveViewSocketBoundary, - authFlowEntrypoint, - ingestionPipelineEntrypoint, - publicApiScopeEntrypoint, - csvImportUploadEntrypoint, - thirdPartyCallbackEntrypoint, - ], -}; - -export default defineConfig({ - projects: [ - { - id: "analytics", - root: "..", - // - githubUrl: "https://github.com/plausible/analytics/blob/master", - priorityPaths: [ - "extra/lib/plausible_web/", - "extra/lib/plausible/", - "lib/plausible_web/plugs/", - "lib/plausible/auth/", - "lib/plausible_web/router.ex", - "lib/plausible_web/controllers/", - "lib/plausible_web/live/", - ], - promptAppend: - "This is an Elixir/Phoenix SaaS analytics app. " + - "Auth is plug-based (AuthPlug, RequireAccountPlug, AuthorizeSiteAccess, AuthorizePublicAPI) not decorator-based. " + - "LiveViews are full HTTP+WebSocket entry points — treat mount/3 and handle_event/3 as controller actions. " + - "The `on_ee do ... else ... end` macro compiles two code paths; check both branches. " + - "An absent `else` clause means the CE build silently omits the entire block. " + - "`plug AuthorizeSiteAccess` with no args admits :public role (unauthenticated). " + - '`conn.params["__team"]` is user-supplied; downstream current_team trust is a known risk. ' + - "SSO/SAML, domain verification, Browserless custom-url checks, and LiveComponent phx-target events are high-risk entry points. " + - "The `extra/` directory is EE-only; the CRITICAL finding came from there.", - }, - ], - plugins: [plausiblePlugin], -}); diff --git a/.deepsec/matchers/auth-flow-entrypoint.ts b/.deepsec/matchers/auth-flow-entrypoint.ts deleted file mode 100644 index 15907773f997..000000000000 --- a/.deepsec/matchers/auth-flow-entrypoint.ts +++ /dev/null @@ -1,86 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * Account lifecycle and membership entry points. - * - * The built-in Phoenix matcher reaches the HTTP controller and LiveView edges, - * but many auth, registration, invitation, 2FA, session, and membership bugs - * live in service modules beneath those edges. This matcher keeps the glob set - * to those subsystems and asks the AI to review user-controlled account state - * transitions for rate limits, token/session binding, tenant scope, and role - * checks. - */ -export const authFlowEntrypoint: MatcherPlugin = { - slug: "plausible-auth-flow-entrypoint", - description: - "Login, registration, 2FA, password reset, session, invitation, and membership service boundaries", - noiseTier: "normal", - filePatterns: [ - "lib/plausible_web/controllers/auth_controller.ex", - "lib/plausible_web/controllers/invitation_controller.ex", - "lib/plausible_web/live/register_form.ex", - "lib/plausible_web/live/reset_password_form.ex", - "lib/plausible_web/user_auth.ex", - "lib/plausible_web/two_factor/**/*.ex", - "lib/plausible_web/login_preference.ex", - "lib/plausible/auth/**/*.ex", - "lib/plausible/teams/invitations/**/*.ex", - "lib/plausible/teams/memberships/**/*.ex", - "lib/plausible/teams/sites/transfer.ex", - "lib/plausible/teams/site_transfer.ex", - ], - examples: [ - ' def handle_event("register", %{"user" => params}, socket) do', - " def log_in_user(conn, %Auth.User{} = user, redirect_path) do", - " def verify_password_reset(token) do", - " def accept(invitation_or_transfer_id, user, team \\\\ nil) do", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - if (/\.(test|spec)\.(ex|exs)$/.test(filePath)) return []; - - return regexMatcher( - "plausible-auth-flow-entrypoint", - [ - { - regex: - /^\s*def\s+(?:login|logout|password_reset(?:_request|_form)?|activate|request_activation_code|verify_2fa(?:_setup|_recovery_code)?|delete_me|google_auth_callback|select_team|switch_team)\s*\(/m, - label: "Auth controller account lifecycle action", - }, - { - regex: - /^\s*def\s+handle_event\s*\(\s*"(?:register|validate|set|send-metrics-after)"/m, - label: "Registration/password LiveView event", - }, - { - regex: /^\s*def\s+(?:log_in_user|log_out_user|get_user_session|set_logged_in_cookie)\s*\(/m, - label: "Session/login handoff boundary", - }, - { - regex: - /^\s*def\s+(?:sign|verify)_(?:password_reset|shared_link|oauth_state)\s*\(/m, - label: "Signed token lifecycle", - }, - { - regex: /\bPhoenix\.Token\.(?:sign|verify)\s*\(/, - label: "Phoenix token signing/verification", - }, - { - regex: /^\s*def\s+(?:issue_code|verify_code|create!|remove_by_token)\s*\(/m, - label: "Email/session verification lifecycle", - }, - { - regex: - /^\s*def\s+(?:accept|accept_transfer_no_members|reject|remove|remove_team_invitation|invite|update_role|leave|transfer|delete|create)\s*\(/m, - label: "Invitation, membership, or account mutation service", - }, - { - regex: /\bRepo\.(?:get_by|one|delete_all|transaction)\s*\([^)]*(?:invitation|transfer|token|email|team|membership)/is, - label: "Account/team lookup or mutation keyed by user-controlled identifier", - }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/authorize-site-access-all-roles.ts b/.deepsec/matchers/authorize-site-access-all-roles.ts deleted file mode 100644 index d77568ef9df9..000000000000 --- a/.deepsec/matchers/authorize-site-access-all-roles.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * `plug AuthorizeSiteAccess` with no role restriction. - * - * `PlausibleWeb.Plugs.AuthorizeSiteAccess` called with no args (or `:all_roles`) - * uses @all_roles = [:public, :viewer, :admin, :editor, :super_admin, :owner, :billing] - * as the allowed set — including :public, meaning unauthenticated visitors pass. - * - * Correct for the public stats view; wrong for anything requiring at least :viewer. - * - * Confirmed in router.ex: - * pipeline :internal_stats_api do - * plug PlausibleWeb.Plugs.AuthorizeSiteAccess ← no args, admits :public - * - * Tier: precise — only matches the no-arg / :all_roles form, not - * `plug ..., [:admin, :owner]` or `plug ..., {[:admin], "site_id"}`. - */ -export const authorizeSiteAccessAllRoles: MatcherPlugin = { - slug: "plausible-authorize-all-roles", - description: "AuthorizeSiteAccess with no role restriction — admits :public (unauthenticated) visitors", - noiseTier: "precise", - filePatterns: [ - "lib/plausible_web/**/*.ex", - "extra/lib/plausible_web/**/*.ex", - ], - examples: [ - " plug PlausibleWeb.Plugs.AuthorizeSiteAccess", - " plug PlausibleWeb.Plugs.AuthorizeSiteAccess, :all_roles", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - return regexMatcher( - "plausible-authorize-all-roles", - [ - { - // Matches no-arg and :all_roles forms; does NOT match plug ..., [:admin, ...] - regex: /\bplug\s+PlausibleWeb\.Plugs\.AuthorizeSiteAccess\s*(?:,\s*:all_roles\s*)?(?:#.*)?$/m, - label: "AuthorizeSiteAccess with no role restriction (admits :public)", - }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/csv-import-upload-entrypoint.ts b/.deepsec/matchers/csv-import-upload-entrypoint.ts deleted file mode 100644 index b3f78c260686..000000000000 --- a/.deepsec/matchers/csv-import-upload-entrypoint.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * CSV import and upload boundary. - * - * CSV imports take browser-supplied upload metadata, presign S3 or move local - * files, parse filenames into table/date parameters, and stream content into - * ClickHouse. The LiveView matcher sees the websocket events, but not the file - * handling/import service as its own risky boundary. - */ -export const csvImportUploadEntrypoint: MatcherPlugin = { - slug: "plausible-csv-import-upload-entrypoint", - description: - "CSV import/upload metadata, S3 presigning, local file movement, filename parsing, and ClickHouse import", - noiseTier: "normal", - filePatterns: [ - "lib/plausible_web/live/csv_import.ex", - "lib/plausible_web/live/imports_exports_settings.ex", - "lib/plausible/imported/**/*.ex", - "lib/plausible/s3.ex", - "lib/workers/import_analytics.ex", - "lib/workers/local_import_analytics_cleaner.ex", - ], - examples: [ - " |> allow_upload(:import, upload_opts)", - " uploads = consume_uploaded_entries(socket, :import, upload_consumer)", - " def parse_filename!(filename)", - " File.stream!(local_path, 512_000) |> Stream.into(Ch.stream(conn, statement, params))", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - if (/\.(test|spec)\.(ex|exs)$/.test(filePath)) return []; - - return regexMatcher( - "plausible-csv-import-upload-entrypoint", - [ - { - regex: /\b(?:allow_upload|consume_uploaded_entries|uploaded_entries|cancel_upload)\s*\(/, - label: "LiveView upload lifecycle", - }, - { - regex: /\b(?:entry|upload)\.client_name\b/, - label: "Browser-supplied upload filename", - }, - { - regex: /\b(?:presign_upload|import_presign_upload|ExAws\.S3\.presigned_url)\s*\(/, - label: "Presigned upload URL generation", - }, - { - regex: /\b(?:Path\.basename|Path\.join|Plausible\.File\.mv!|File\.(?:mkdir_p!|stream!|rm))\s*\(/, - label: "Upload path or local file operation", - }, - { - regex: /^\s*def\s+(?:parse_args|import_data|parse_filename!|valid_filename\?|extract_table|date_range|local_dir)\s*\(/m, - label: "CSV import service consumes upload metadata", - }, - { - regex: /\b(?:FROM\s+s3\s*\(|FROM\s+input\s*\(|Ch\.(?:query!|stream)|ClickHouse|Clickhouse)\b/i, - label: "CSV import reaches ClickHouse", - }, - { - regex: /\bOban\.insert!\s*\(\s*Plausible\.Workers\.LocalImportAnalyticsCleaner\.new\b/, - label: "Local upload cleanup worker scheduled from import args", - }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/ingestion-pipeline-entrypoint.ts b/.deepsec/matchers/ingestion-pipeline-entrypoint.ts deleted file mode 100644 index d2bb9d3940f6..000000000000 --- a/.deepsec/matchers/ingestion-pipeline-entrypoint.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * Public tracker event ingestion pipeline. - * - * `/api/event` accepts unauthenticated browser input and passes it through - * request parsing, enrichment, shield checks, tracker script configuration, and - * ClickHouse/session buffers. Generic Phoenix coverage sees the controller but - * not the downstream ingestion pipeline as a single security boundary. - */ -export const ingestionPipelineEntrypoint: MatcherPlugin = { - slug: "plausible-ingestion-pipeline-entrypoint", - description: - "Tracker event ingestion request parsing, enrichment, tracker-script config, and buffering", - noiseTier: "normal", - filePatterns: [ - "lib/plausible_web/controllers/api/external_controller.ex", - "lib/plausible_web/plugs/tracker_plug.ex", - "lib/plausible_web/tracker.ex", - "lib/plausible/ingestion/**/*.ex", - "extra/lib/plausible/ingestion/**/*.ex", - "lib/plausible/event/write_buffer.ex", - "lib/plausible/session/write_buffer.ex", - "lib/plausible/session/balancer*.ex", - ], - examples: [ - " def event(conn, _params) do\n Ingestion.Request.build(conn)", - " def build(%Plug.Conn{} = conn, now \\\\ NaiveDateTime.utc_now()) do", - " def build_and_buffer(%Request{domains: domains} = request, context \\\\ []) do", - ' defp put_props(changeset, %{} = request_body) do\n request_body["props"]', - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - if (/\.(test|spec)\.(ex|exs)$/.test(filePath)) return []; - - return regexMatcher( - "plausible-ingestion-pipeline-entrypoint", - [ - { - regex: /^\s*def\s+event\s*\(\s*conn\s*,/m, - label: "Public tracker event controller action", - }, - { - regex: /\bIngestion\.Request\.build\s*\(\s*conn\s*\)/, - label: "Controller hands Plug.Conn to ingestion request builder", - }, - { - regex: /^\s*def\s+build\s*\(\s*%Plug\.Conn\{\}\s*=\s*conn\b/m, - label: "Ingestion request builder consumes Plug.Conn", - }, - { - regex: /\b(?:Plug\.Conn\.read_body|conn\.body_params|conn\.params|Plug\.Conn\.get_req_header)\b/, - label: "Ingestion reads browser-controlled body, params, or headers", - }, - { - regex: /\brequest_body\s*\[\s*"(?:n|name|u|url|d|domain|r|referrer|m|meta|p|props|sd|e|hashMode)"\s*\]/, - label: "Ingestion maps tracker payload fields", - }, - { - regex: /^\s*def\s+build_and_buffer\s*\(\s*%Request\{/m, - label: "Builds and buffers tracker events", - }, - { - regex: /^\s*defp?\s+(?:pipeline|process_unless_dropped|execute_step|drop_|put_|register_session|validate_clickhouse_event)\b/m, - label: "Event enrichment/drop/persistence pipeline step", - }, - { - regex: /\b(?:ClickhouseEventV2|ClickhouseRepo|Ch\.(?:query|query!|stream)|WriteBuffer\.(?:insert|flush))\b/, - label: "Ingestion writes to ClickHouse or write buffers", - }, - { - regex: /^\s*def\s+(?:get_plausible_main_script|build_script|update_script_configuration|get_or_create_tracker_script_configuration)\s*\(/m, - label: "Tracker script configuration boundary", - }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/livecomponent-event.ts b/.deepsec/matchers/livecomponent-event.ts deleted file mode 100644 index dd2273ead1ea..000000000000 --- a/.deepsec/matchers/livecomponent-event.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * LiveComponent websocket event handlers outside lib/plausible_web/live. - * - * The existing LiveView matcher intentionally scans live/**.ex. Components can - * also receive phx events over the LiveView websocket when rendered with - * phx-target={@myself}, and this repo has component directories outside live/. - * - * Tier: normal — path globs are limited to components, and handle_event/3 is a - * real browser-controlled websocket boundary. - */ -export const liveComponentEvent: MatcherPlugin = { - slug: "plausible-livecomponent-event", - description: "LiveComponent handle_event/3 websocket entry points outside live/ directories", - noiseTier: "normal", - filePatterns: [ - "lib/plausible_web/components/**/*.ex", - "extra/lib/plausible_web/components/**/*.ex", - ], - examples: [ - " use PlausibleWeb, :live_component\n\n def handle_event(\"toggle\", _params, socket) do", - " use Phoenix.LiveComponent\n\n def handle_event(\"save\", params, socket) do", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - if (/\.(test|spec)\.(ex|exs)$/.test(filePath)) return []; - - return regexMatcher( - "plausible-livecomponent-event", - [ - { - regex: /\buse\s+PlausibleWeb\s*,\s*:live_component\b/, - label: "Plausible LiveComponent module", - }, - { - regex: /\buse\s+Phoenix\.LiveComponent\b/, - label: "Phoenix LiveComponent module", - }, - { - regex: /^\s*def\s+handle_event\s*\(\s*"/, - label: "LiveComponent websocket event handler", - }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/liveview-mount.ts b/.deepsec/matchers/liveview-mount.ts deleted file mode 100644 index c3a63082f3f6..000000000000 --- a/.deepsec/matchers/liveview-mount.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * LiveView mount/3 and event handlers — real HTTP+WebSocket entry points. - * - * LiveViews mount twice per page load: once for the HTTP server-render and once - * on WebSocket connect. Auth must be re-checked in mount/3 (or via an on_mount - * hook); the plug pipeline is NOT called on WebSocket reconnect. - * - * Confirmed pattern: team_setup.ex performed a DB write (team rename) in mount - * with no role gate, while the equivalent HTTP controller action had - * `plug AuthorizeTeamAccess, [:owner, :admin]`. - * - * Tier: noisy — every LiveView that defines mount/3 is a legitimate review target. - */ -export const liveViewMount: MatcherPlugin = { - slug: "plausible-liveview-mount", - description: "LiveView mount/3 and event handlers — HTTP+WebSocket entry points", - noiseTier: "noisy", - filePatterns: [ - "lib/plausible_web/live/**/*.ex", - "extra/lib/plausible_web/live/**/*.ex", - ], - examples: [ - " def mount(_params, session, socket) do\n {:ok, socket}\n end", - ' def handle_event("save", params, socket) do', - " def handle_params(params, _uri, socket) do", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - return regexMatcher( - "plausible-liveview-mount", - [ - { regex: /^\s*def\s+mount\s*\(/m, label: "def mount — LiveView HTTP/WS entry point" }, - { regex: /^\s*def\s+handle_event\s*\(\s*"/m, label: "def handle_event — WebSocket state mutation" }, - { regex: /^\s*def\s+handle_params\s*\(/m, label: "def handle_params — URL-param driven state change" }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/liveview-socket-boundary.ts b/.deepsec/matchers/liveview-socket-boundary.ts deleted file mode 100644 index 3dd944347741..000000000000 --- a/.deepsec/matchers/liveview-socket-boundary.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * LiveView websocket/session boundaries. - * - * LiveView reconnects use the socket session and on_mount hooks rather than - * re-running the full Plug pipeline. This matcher covers the socket definition, - * live_session hook wiring, and on_mount context modules that gate websocket - * state. - * - * Tier: normal — tight path globs, but the AI must reason about whether each - * boundary actually re-establishes auth/session/team context safely. - */ -export const liveViewSocketBoundary: MatcherPlugin = { - slug: "plausible-liveview-socket-boundary", - description: "LiveView websocket socket config, live_session hooks, and on_mount auth boundaries", - noiseTier: "normal", - filePatterns: [ - "lib/plausible_web/endpoint.ex", - "lib/plausible_web/router.ex", - "lib/plausible_web/live/**/*context.ex", - "extra/lib/plausible_web/live/**/*context.ex", - ], - examples: [ - ' socket("/live", Phoenix.LiveView.Socket, websocket: [check_origin: true])', - " live_session :settings, on_mount: PlausibleWeb.Live.SettingsContext do", - " def on_mount(:default, _params, session, socket) do", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - if (/\.(test|spec)\.(ex|exs)$/.test(filePath)) return []; - - return regexMatcher( - "plausible-liveview-socket-boundary", - [ - { - regex: /\bsocket\s*\(\s*"\/live"\s*,\s*Phoenix\.LiveView\.Socket\b/, - label: "LiveView websocket endpoint", - }, - { - regex: /\bsession:\s*\{__MODULE__,\s*:runtime_session_opts\b/, - label: "LiveView socket session source", - }, - { - regex: /\blive_session\s+[^,\n]+,\s*on_mount:/, - label: "LiveView live_session on_mount wiring", - }, - { - regex: /^\s*def\s+on_mount\s*\(/, - label: "LiveView on_mount auth/session hook", - }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/mix-task-entrypoint.ts b/.deepsec/matchers/mix-task-entrypoint.ts deleted file mode 100644 index 05078fcc59d1..000000000000 --- a/.deepsec/matchers/mix-task-entrypoint.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * Mix tasks are CLI entry points. Several Plausible tasks take argv values such - * as filenames, ids, URLs, and subscription ids, then call app code or external - * services. Default matchers only accidentally hit a task when another generic - * regex fires. - * - * Tier: normal — `run/1` is broad, but the path glob is limited to first-party - * tasks and the AI can distinguish local maintenance-only tasks from risky - * untrusted-input handling. - */ -export const mixTaskEntrypoint: MatcherPlugin = { - slug: "plausible-mix-task-entrypoint", - description: "Mix task run/1 callbacks — CLI entry points with argv input", - noiseTier: "normal", - filePatterns: ["lib/mix/tasks/**/*.ex"], - examples: [ - "defmodule Mix.Tasks.ImportSomething do\n use Mix.Task\n def run([filename]) do", - " def run(opts) do\n Mix.Task.run(\"app.start\")\n end", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - - return regexMatcher( - "plausible-mix-task-entrypoint", - [ - { regex: /^\s*use\s+Mix\.Task\b/m, label: "Mix task module" }, - { regex: /^\s*def\s+run\s*\(/m, label: "Mix task run/1 CLI entry point" }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/oban-worker.ts b/.deepsec/matchers/oban-worker.ts deleted file mode 100644 index a195e32a9997..000000000000 --- a/.deepsec/matchers/oban-worker.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * Oban workers are queue consumers. Many are scheduled internally, but job - * arguments can also originate from HTTP handlers, imports, third-party - * callbacks, or admin-triggered workflows. The built-in matchers do not cover - * Oban's `perform/1` boundary. - * - * Tier: noisy — every worker perform callback should be reviewed as an async - * entry point for tenant scoping, authorization assumptions, and unsafe use of - * job args. - */ -export const obanWorker: MatcherPlugin = { - slug: "plausible-oban-worker", - description: "Oban worker perform callbacks — async queue entry points", - noiseTier: "noisy", - filePatterns: [ - "lib/workers/**/*.ex", - "extra/lib/**/worker.ex", - "extra/lib/**/*worker*.ex", - ], - examples: [ - " use Oban.Worker, queue: :imports\n\n def perform(%Oban.Job{args: args}) do", - " def perform(%{\"domain\" => domain}) do", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - - return regexMatcher( - "plausible-oban-worker", - [ - { regex: /\buse\s+Oban\.Worker\b/, label: "Oban worker module" }, - { regex: /^\s*def\s+perform\s*\(/m, label: "Oban perform callback entry point" }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/on-ee-without-else.ts b/.deepsec/matchers/on-ee-without-else.ts deleted file mode 100644 index 60c44b1738b4..000000000000 --- a/.deepsec/matchers/on-ee-without-else.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; - -/** - * `on_ee do ... end` blocks without an `else` branch. - * - * The `on_ee` macro compiles two code paths: - * on_ee do - * def super_admin?(%User{id: id}), do: id in @ids # EE path - * else - * def super_admin?(_), do: always(false) # CE path - * end - * - * A missing `else` means the CE build silently omits the entire block. For - * feature display flags this is intentional; for auth checks it can leave - * a CE route unprotected. - * - * Tier: normal — the AI must distinguish "intentional EE-only feature" from - * "missing CE auth fallback". Uses manual line-scanning to track nesting depth - * rather than regexMatcher, since we need to detect the else at exactly depth 1. - */ -export const onEeWithoutElse: MatcherPlugin = { - slug: "plausible-on-ee-no-else", - description: "on_ee do block without else branch — CE build silently omits this block", - noiseTier: "normal", - filePatterns: [ - "lib/plausible_web/**/*.ex", - "lib/plausible/auth/**/*.ex", - "extra/lib/plausible_web/**/*.ex", - ], - examples: [ - " on_ee do\n def super_admin?(nil), do: false\n end", - " on_ee do\n plug :require_admin\n end", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - - const lines = content.split("\n"); - const matches: CandidateMatch[] = []; - - for (let i = 0; i < lines.length; i++) { - if (!/^\s*on_ee\s+do\s*$/.test(lines[i])) continue; - - let depth = 1; - let hasElse = false; - let endLine = i; - - for (let j = i + 1; j < lines.length && j < i + 80; j++) { - const line = lines[j]; - if (/^\s*#/.test(line)) continue; - if (/\bdo\b/.test(line)) depth++; - if (/^\s*end\b/.test(line)) { - depth--; - if (depth === 0) { endLine = j; break; } - } - if (depth === 1 && /^\s*else\s*$/.test(line)) hasElse = true; - } - - if (!hasElse) { - const start = Math.max(0, i - 1); - const end = Math.min(lines.length, endLine + 2); - matches.push({ - vulnSlug: "plausible-on-ee-no-else", - lineNumbers: [i + 1], - snippet: lines.slice(start, Math.min(end, start + 15)).join("\n"), - matchedPattern: "on_ee do without else — CE build omits this block", - }); - } - } - - return matches; - }, -}; diff --git a/.deepsec/matchers/phoenix-plug-module.ts b/.deepsec/matchers/phoenix-plug-module.ts deleted file mode 100644 index 252ce004f4dd..000000000000 --- a/.deepsec/matchers/phoenix-plug-module.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * Phoenix Plug definition modules — the auth/authz layer. - * - * The built-in `ex-phoenix-controller` matcher only fires on `use ..., :controller`, - * route verbs, and `Repo.query`. Plug modules use `import Plug.Conn` instead, making - * all 19 files in lib/plausible_web/plugs/ and 13 files in lib/plausible/auth/ - * invisible to the existing scanner. - * - * Tier: noisy — every plug module in these directories is an authorization boundary - * and should be AI-reviewed. - */ -export const phoenixPlugModule: MatcherPlugin = { - slug: "plausible-plug-module", - description: "Phoenix Plug modules — auth/authz layer invisible to ex-phoenix-controller", - noiseTier: "noisy", - filePatterns: [ - "lib/plausible_web/plugs/**/*.ex", - "lib/plausible/auth/**/*.ex", - "extra/lib/plausible_web/plugs/**/*.ex", - ], - examples: [ - "import Plug.Conn\n def call(conn, _opts) do", - "use Plug.Builder\n plug :check_auth", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - return regexMatcher( - "plausible-plug-module", - [ - { regex: /\bimport\s+Plug\.Conn\b/, label: "import Plug.Conn — plug module entry point" }, - { regex: /\buse\s+Plug\.Builder\b/, label: "use Plug.Builder — plug composition" }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/plugins-api-controller.ts b/.deepsec/matchers/plugins-api-controller.ts deleted file mode 100644 index 236de43591a5..000000000000 --- a/.deepsec/matchers/plugins-api-controller.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * Plausible's Plugins API controllers use `use PlausibleWeb, - * :plugins_api_controller`, which the built-in Phoenix controller matcher does - * not currently recognize. These are public JSON API entry points gated by - * `AuthorizePluginsAPI`, except explicit capability/spec routes. - * - * Tier: noisy — every plugin API controller action is an entry point worth - * review for authz, tenant scoping, schema validation, and mass assignment. - */ -export const pluginsApiController: MatcherPlugin = { - slug: "plausible-plugins-api-controller", - description: "Plugins API controllers using PlausibleWeb :plugins_api_controller", - noiseTier: "noisy", - filePatterns: [ - "lib/plausible_web/plugins/api/controllers/**/*.ex", - "extra/lib/plausible_web/plugins/api/controllers/**/*.ex", - ], - examples: [ - " use PlausibleWeb, :plugins_api_controller\n\n def create(conn, params) do", - " def delete(%{private: %{open_api_spex: %{params: %{id: id}}}} = conn, _params) do", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - - return regexMatcher( - "plausible-plugins-api-controller", - [ - { - regex: /\buse\s+PlausibleWeb\s*,\s*:plugins_api_controller\b/, - label: "Plausible Plugins API controller entry point", - }, - { - regex: - /^\s*def\s+(?:index|get|create|update|delete|delete_bulk|enable|disable)\s*\(/m, - label: "Plugins API action function", - }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/public-api-scope-entrypoint.ts b/.deepsec/matchers/public-api-scope-entrypoint.ts deleted file mode 100644 index e9e9e230454a..000000000000 --- a/.deepsec/matchers/public-api-scope-entrypoint.ts +++ /dev/null @@ -1,78 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * Public API authz and query parsing surface. - * - * Built-in Phoenix coverage catches controllers, and the existing plugin catches - * Plugins API controllers. The service modules that validate API scopes, parse - * stats queries, paginate plugin resources, and apply segment filters need their - * own review path because they are where tenant scoping and request-to-query - * mistakes usually appear. - */ -export const publicApiScopeEntrypoint: MatcherPlugin = { - slug: "plausible-public-api-scope-entrypoint", - description: - "Public API scope checks, OpenAPI body params, stats query parsing, plugin API services, and segment filters", - noiseTier: "normal", - filePatterns: [ - "lib/plausible_web/plugs/authorize_public_api.ex", - "lib/plausible_web/plugs/authorize_plugins_api.ex", - "lib/plausible_web/controllers/api/**/*_controller.ex", - "lib/plausible_web/plugins/api/controllers/**/*.ex", - "extra/lib/plausible_web/plugins/api/controllers/**/*.ex", - "lib/plausible/plugins/api/**/*.ex", - "extra/lib/plausible/plugins/api/**/*.ex", - "lib/plausible/stats/api_query_parser.ex", - "lib/plausible/stats/dashboard/query_parser.ex", - "lib/plausible/stats/query*.ex", - "lib/plausible/stats/filters/**/*.ex", - "lib/plausible/segments/**/*.ex", - ], - examples: [ - ' defp verify_by_scope(conn, api_key, "stats:read:" <> _ = scope) do', - " def parse(params, opts \\\\ []) when is_map(params) do", - " {:ok, paginate(query, params, cursor_fields: [{:id, :desc}])}", - " %{private: %{open_api_spex: %{body_params: body_params}}} = conn", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - if (/\.(test|spec)\.(ex|exs)$/.test(filePath)) return []; - - return regexMatcher( - "plausible-public-api-scope-entrypoint", - [ - { - regex: /\b(?:api_scope|check_scope|verify_by_scope|get_bearer_token|authorization)\b/, - label: "API key scope or bearer-token authorization", - }, - { - regex: /\b(?:conn\.params|conn\.query_params|body_params|open_api_spex|OpenApiSpex)\b/, - label: "Public API params or OpenAPI-validated body", - }, - { - regex: - /^\s*def\s+(?:query|aggregate|breakdown|timeseries|realtime_visitors|create_site|update_site|delete_site|create|update|delete|delete_bulk|enable|disable|index|get)\s*\(/m, - label: "Public API or plugin API action/service function", - }, - { - regex: /\b(?:JSONSchema\.validate|parse\s*\(\s*params|parse_(?:filters|order_by|pagination|metrics|dimensions|include)|Map\.fetch!\s*\(\s*params)\b/, - label: "Stats/query API parameter parsing", - }, - { - regex: /\bpaginate\s*\(\s*query\s*,\s*params\b/, - label: "API pagination from query params", - }, - { - regex: /\b(?:segment_id|site_id|team_id|authorized_site|current_team|current_user)\b/, - label: "Tenant, team, site, or segment scoping value", - }, - { - regex: /\b(?:Clickhouse|ClickhouseRepo|Ch\.(?:query|query!|stream)|QueryRunner|QueryBuilder)\b/, - label: "Stats API request reaches query execution/building", - }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/sso-entrypoint.ts b/.deepsec/matchers/sso-entrypoint.ts deleted file mode 100644 index 5b9498e422bc..000000000000 --- a/.deepsec/matchers/sso-entrypoint.ts +++ /dev/null @@ -1,83 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * Plausible SSO boundary coverage. - * - * SSO spans normal controllers, SAML adapters, LiveView management events, - * force-SSO plugs, domain ownership verification, and a queue worker. Generic - * Phoenix matchers see some of these in isolation, but not as one sensitive - * identity boundary. - * - * Tier: normal — the path globs are SSO-specific, and the AI should review the - * matched boundary for relay-state, cookie, ownership, role, and team scoping. - */ -export const ssoEntrypoint: MatcherPlugin = { - slug: "plausible-sso-entrypoint", - description: "SSO/SAML login, policy, domain verification, and force-SSO entry points", - noiseTier: "normal", - filePatterns: [ - "extra/lib/plausible/auth/sso/**/*.ex", - "extra/lib/plausible_web/controllers/sso_controller.ex", - "extra/lib/plausible_web/live/sso_management.ex", - "extra/lib/plausible_web/live/customer_support/team/components/sso.ex", - "extra/lib/plausible_web/plugs/secure_sso.ex", - "extra/lib/plausible_web/sso/**/*.ex", - "lib/plausible_web/plugs/sso_team_access.ex", - "lib/plausible_web/user_auth.ex", - ], - examples: [ - " def saml_consume(conn, params) do\n saml_adapter().consume(conn, params)\n end", - ' def handle_event("toggle-force-sso", _params, socket) do', - " def set_force_sso(team, mode) do", - " def perform(%{args: %{\"domain\" => domain}}) do", - " def log_in_user(conn, %Auth.SSO.Identity{} = identity, redirect_path) do", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - if (/\.(test|spec)\.(ex|exs|js|ts|tsx)$/.test(filePath)) return []; - - const patterns = [ - { - regex: /^\s*def\s+(?:login|saml_signin|saml_consume|signin|consume)\s*\(/, - label: "SSO/SAML HTTP login boundary", - }, - { - regex: - /^\s*def\s+handle_event\s*\(\s*"(?:init-sso|update-integration|add-domain|verify-domain(?:-submit)?|cancel-verify-domain|remove-domain|toggle-force-sso|update-policy|remove-sso-[^"]+|deprovision-sso-user)"/, - label: "SSO LiveView event boundary", - }, - { - regex: - /^\s*def\s+(?:initiate_saml_integration|update_integration|provision_user|deprovision_user!|set_force_sso|check_force_sso|remove_integration|start_verification|cancel_verification|verify|remove)\s*\(/, - label: "SSO domain/policy service boundary", - }, - { - regex: /^\s*def\s+perform\s*\(/, - label: "SSO background verification worker boundary", - }, - { - regex: /\bSimpleSaml\.(?:parse_response|verify_and_validate_response)\b/, - label: "SAML response parsing/verification", - }, - { - regex: - /^\s*def\s+log_in_user\s*\(\s*conn\s*,\s*%Auth\.SSO\.Identity\{\}\s*=\s*identity\b/, - label: "SSO identity login handoff", - }, - { - regex: /\bAuth\.SSO\.provision_user\s*\(|\bLoginPreference\.set_sso\s*\(/, - label: "SSO user provisioning/login preference handoff", - }, - ]; - - if (/\/sso\//.test(filePath)) { - patterns.push({ - regex: /\bPlug\.Conn\.(?:put_resp_cookie|fetch_cookies|delete_resp_cookie)\b/, - label: "SSO flow cookie handling", - }); - } - - return regexMatcher("plausible-sso-entrypoint", patterns, content); - }, -}; diff --git a/.deepsec/matchers/third-party-callback-entrypoint.ts b/.deepsec/matchers/third-party-callback-entrypoint.ts deleted file mode 100644 index c32f33f2bf6d..000000000000 --- a/.deepsec/matchers/third-party-callback-entrypoint.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * Third-party callback, webhook, and OAuth handoff boundary. - * - * These flows accept data from Paddle, HelpScout, Google OAuth/API, and support - * iframes. They tend to need signature validation, nonce/state binding, replay - * handling, rate limits, and careful error/log handling. SSO/SAML has a more - * specific matcher already, so this matcher focuses on the non-SAML integrations. - */ -export const thirdPartyCallbackEntrypoint: MatcherPlugin = { - slug: "plausible-third-party-callback-entrypoint", - description: - "Paddle webhook, Google OAuth/API, and HelpScout callback/signature/token handoff boundaries", - noiseTier: "normal", - filePatterns: [ - "lib/plausible_web/controllers/api/paddle_controller.ex", - "lib/plausible/billing/billing.ex", - "lib/plausible/billing/paddle_api.ex", - "lib/plausible/billing/subscription/status.ex", - "lib/plausible_web/controllers/auth_controller.ex", - "lib/plausible/google/**/*.ex", - "extra/lib/plausible_web/controllers/help_scout_controller.ex", - "extra/lib/plausible/help_scout.ex", - ], - examples: [ - ' def webhook(conn, %{"alert_name" => "subscription_created"} = params) do', - ' def google_auth_callback(conn, %{"code" => code, "state" => state} = params) do', - " def validate_signature(conn) do", - ' signature = Base.decode64!(conn.params["p_signature"])', - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - if (/\.(test|spec)\.(ex|exs)$/.test(filePath)) return []; - - return regexMatcher( - "plausible-third-party-callback-entrypoint", - [ - { - regex: /^\s*defp?\s+(?:webhook|callback|google_auth_callback|verify_signature|validate_signature)\s*\(/m, - label: "Webhook, callback, OAuth, or signature validation handler", - }, - { - regex: - /\b(?:Plug\.Conn\.read_body|conn\.body_params|conn\.query_string|conn\.params\s*\[\s*"(?:p_signature|customer-id|conversation-id|customer_id|conversation_id|term|token|state|code|error)"\s*\])/, - label: "Third-party request params/body consumed", - }, - { - regex: /\b(?:Base\.decode64!?|Jason\.decode!?|PhpSerializer\.serialize|:public_key\.verify|Plug\.Crypto\.secure_compare)\s*\(/, - label: "Callback payload decoding or signature comparison", - }, - { - regex: /\b(?:Phoenix\.Token\.(?:sign|verify)|sign_oauth_state|verify_oauth_state|fetch_access_token!|fetch_access_token)\s*\(/, - label: "OAuth state or callback token lifecycle", - }, - { - regex: - /\b(?:Plausible\.Billing\.subscription_\w+\s*\(|Plausible\.Billing\.PaddleApi\.\w+\s*\(|HelpScout\.(?:validate_signature|get_details_for_customer|get_details_for_emails|search_users)\s*\(|Plausible\.HelpScout\.\w+\s*\(|Google\.API\.(?:verify_oauth_state|fetch_access_token!?|fetch_verified_properties|fetch_stats|list_properties|get_property|get_analytics_(?:start|end)_date|maybe_refresh_token)\s*\(|Google\.HTTP\.\w+\s*\()/, - label: "Third-party integration handoff", - }, - { - regex: /\b(?:Sentry\.capture_message|Logger\.(?:error|warning|debug))\s*\([^)]*(?:params|reason|error|details|body)/is, - label: "Callback error/log path includes third-party data", - }, - ], - content, - ); - }, -}; diff --git a/.deepsec/matchers/verification-entrypoint.ts b/.deepsec/matchers/verification-entrypoint.ts deleted file mode 100644 index 50e5e5f4b8aa..000000000000 --- a/.deepsec/matchers/verification-entrypoint.ts +++ /dev/null @@ -1,76 +0,0 @@ -import type { CandidateMatch, MatcherPlugin } from "deepsec/config"; -import { regexMatcher } from "deepsec/config"; - -/** - * Installation and domain verification entry points. - * - * These flows take customer-controlled domains/URLs, run DNS and HTTP checks, - * and in EE call Browserless/Puppeteer against the target URL. The default - * matchers catch some generic SSRF or JS patterns but miss the subsystem as a - * review unit. - * - * Tier: normal — every matched boundary should be reviewed for SSRF, redirect, - * DNS rebinding, rate limiting, and diagnostic leakage. - */ -export const verificationEntrypoint: MatcherPlugin = { - slug: "plausible-verification-entrypoint", - description: "Site and SSO domain verification flows that fetch or browse user-controlled URLs", - noiseTier: "normal", - filePatterns: [ - "extra/lib/plausible/installation_support/**/*.ex", - "extra/lib/plausible/auth/sso/domain/verification.ex", - "extra/lib/plausible/auth/sso/domain/verification/**/*.ex", - "extra/lib/plausible_web/live/verification.ex", - "priv/tracker/installation_support/**/*.js", - "tracker/installation_support/**/*.js", - ], - examples: [ - ' def handle_event("verify-custom-url", %{"custom_url" => custom_url}, socket) do', - " def run(url, data_domain, installation_type, opts \\\\ []) do", - " def perform(%State{url: url} = state, _opts) do", - " const response = await page.goto(url)", - ], - match(content, filePath): CandidateMatch[] { - if (/\/(test|tests)\//.test(filePath)) return []; - if (/\.(test|spec)\.(ex|exs|js|ts|tsx)$/.test(filePath)) return []; - - return regexMatcher( - "plausible-verification-entrypoint", - [ - { - regex: /^\s*def\s+handle_event\s*\(\s*"verify-custom-url"/, - label: "LiveView custom URL verification input", - }, - { - regex: /^\s*def\s+run\s*\(\s*(?:url|sso_domain)\b/, - label: "Verification check runner accepts URL/domain input", - }, - { - regex: /^\s*def\s+perform\s*\(\s*%State\{url:\s*url\}/, - label: "Verification check consumes state.url", - }, - { - regex: /\bpage\.goto\s*\(\s*url\s*\)/, - label: "Browserless/Puppeteer navigation to supplied URL", - }, - { - regex: /\bReq\.post\s*\(\s*BrowserlessConfig\.browserless_function_api_endpoint\(\)/, - label: "Browserless function API call", - }, - { - regex: /\brun_request\s*\(\s*(?:url_override|\S*url)/, - label: "Verification HTTP request to supplied domain/URL", - }, - { - regex: /\b(?:dns_lookup|:inet_res\.lookup)\s*\(/, - label: "Verification DNS lookup", - }, - { - regex: /\bwindow\.fetch\s*=\s*function\s*\(\s*url\b/, - label: "Verifier intercepts page fetch calls", - }, - ], - content, - ); - }, -}; diff --git a/.deepsec/package.json b/.deepsec/package.json deleted file mode 100644 index bc4d7e682c28..000000000000 --- a/.deepsec/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "deepsec-workspace", - "version": "0.1.0", - "private": true, - "description": "deepsec scanning workspace", - "type": "module", - "workspaces": [], - "packageManager": "pnpm@9.15.4", - "dependencies": { - "deepsec": "^2.1.2" - } -} diff --git a/.deepsec/pnpm-lock.yaml b/.deepsec/pnpm-lock.yaml deleted file mode 100644 index 3a6f91098167..000000000000 --- a/.deepsec/pnpm-lock.yaml +++ /dev/null @@ -1,2472 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - deepsec: - specifier: ^2.1.2 - version: 2.1.2(@anthropic-ai/sdk@0.96.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3) - -packages: - - '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.201': - resolution: {integrity: sha512-8Mcb3BDyKUGfJWFFTWwt+at37lbDH3ZwVtUNPWGG1toZ75RDCJry5U4kXRvQ2xokvJQlA0E+eNp6keWe5ZH22Q==} - cpu: [arm64] - os: [darwin] - - '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.201': - resolution: {integrity: sha512-TFR2bu0+ml3RHoMrtsgD0qDK5Oknw8kYGBV7qpQHn+IWmE96gnHhogG1LpJwpHtni08XkJIjfWk1DdlsUYtRkQ==} - cpu: [x64] - os: [darwin] - - '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.201': - resolution: {integrity: sha512-EiqbpfJIpChfkn+8Uj061Qjyw0eaRcOXtdrvVuHANyj8ZErVOr8HlH6op9PSeIUa9TX0m2+tNgKPQvOGseQckA==} - cpu: [arm64] - os: [linux] - - '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.201': - resolution: {integrity: sha512-mShTo3MwF0gkN4dDw78wWJiB6aBDVRkl81cnApvoBofpdyUBYgm9Gw16CCjDTgelMKeBFqN6ErJpwjI3wbP00A==} - cpu: [arm64] - os: [linux] - - '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.201': - resolution: {integrity: sha512-IbxnzO5UCbqbm2TnzCHkSyJorAFw2isdKdIsFCTxJJjSs3ZC+v3LC1QSUiVCx0qi+CV6w3MKx6mLI11mrvhbbQ==} - cpu: [x64] - os: [linux] - - '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.201': - resolution: {integrity: sha512-jrJBrRWrSuoFKIgjyqxHqmfd6Pb3Bs5Bvakg0knXCTC4fbUXGnC9Q6u7gdDwgXohUNP6/DD+s8U7bivvvVv0dg==} - cpu: [x64] - os: [linux] - - '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.201': - resolution: {integrity: sha512-UsoytRJ/037uHpb3ATrIoe+AgwTf+PwKuFLGjddHAV/11wERJs0hlrnSmcnp43kf0PFxoSNinngme96YYASmQg==} - cpu: [arm64] - os: [win32] - - '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.201': - resolution: {integrity: sha512-PhalN/0cWcqDfbx7iwoLNR2gurjTiqhBk1G6K+NRScxEcQjWuu5xKXCcdbX8ePVpT+nbEMmFEFpn2y+8V8hIdA==} - cpu: [x64] - os: [win32] - - '@anthropic-ai/claude-agent-sdk@0.3.201': - resolution: {integrity: sha512-InT1XLmf2QpldWdtznKDWEoGJT4p+sXh24yxbeBQ++lMJCzMrI0W27MEmmmDWx0otpa+ubdHCF5YQ6oiNt7cmg==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@anthropic-ai/sdk': '>=0.93.0' - '@modelcontextprotocol/sdk': ^1.29.0 - zod: ^4.0.0 - - '@anthropic-ai/sdk@0.91.1': - resolution: {integrity: sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==} - hasBin: true - peerDependencies: - zod: ^3.25.0 || ^4.0.0 - peerDependenciesMeta: - zod: - optional: true - - '@anthropic-ai/sdk@0.96.0': - resolution: {integrity: sha512-KlCsODtTyb17bLUVCSDC2HtSvAbJf60sEiPEax9dInF+aDF92vS4TZJ5XD7YCQXNb1/5icYaw8Y7wMjPlIV9Zg==} - hasBin: true - peerDependencies: - zod: ^3.25.0 || ^4.0.0 - peerDependenciesMeta: - zod: - optional: true - - '@aws-crypto/sha256-browser@5.2.0': - resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} - - '@aws-crypto/sha256-js@5.2.0': - resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} - engines: {node: '>=16.0.0'} - - '@aws-crypto/supports-web-crypto@5.2.0': - resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} - - '@aws-crypto/util@5.2.0': - resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - - '@aws-sdk/client-bedrock-runtime@3.1048.0': - resolution: {integrity: sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/core@3.974.27': - resolution: {integrity: sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-env@3.972.53': - resolution: {integrity: sha512-+KDA3uc/HZ1vIneGu5QMQb0gAXDYrm2vOE60+BJ7lS0YinMQ5i2oV4PR1A16XkF6K1IbSwjEHd1hQIIgMsK48w==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-http@3.972.55': - resolution: {integrity: sha512-1gBfkWY3RWeBlCoB9lIJjXMx45/54wxcgfzv6BY9otTmMrZPcNPi1v+MwZxxaCUg441NV3jsr1efnFNCXiW70g==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-ini@3.972.60': - resolution: {integrity: sha512-CV2md+PXvABwRjApWGhQ0wACy9WSFIhnUGrovLcjnjBCd/46TbuivLADtkF8IWNjtCQmQ+2IagSaxqBYqXBNAQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-login@3.972.59': - resolution: {integrity: sha512-JG4S9yyA1GFzJdJXqLKrUzZbyK+VDp2QIsJD7YOicJHAhqymfHpDJIok2dLnhOdVB0I37RjdC53uOwCMVS00gw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-node@3.972.62': - resolution: {integrity: sha512-S6Slq3Tx7bvFk5yc34XNADyZYTX2HUXvaFAnowGRQnhjBO8J/mP62Fn7lxvJwjaDyYm/7gh9h6HEHaltRyMFXw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-process@3.972.53': - resolution: {integrity: sha512-EhfH+MQlqOMCkXIVa8MMObPzAQqwTTtxA7KhEJiyPeuNVA8PLOOUpgK7nBrgaDaGiIDLN/9LpGdaHuDjomeRTw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-sso@3.972.59': - resolution: {integrity: sha512-h8793pOjcImx0SB+VcLONcaQQ57VAvKVuqyewQMRKqqH+CSXsG2dwOeLMUJPMxLdNvL7dXOM0ueTukyNUnu5mA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-web-identity@3.972.59': - resolution: {integrity: sha512-VoyO9+vl3XVmpZwn4obskrWIkrA/Jf3lSe1E3ZERlaN9u0D4YZ6+HywC3+L98QOXqZesEfedk67gRER8tK8+8w==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/eventstream-handler-node@3.972.25': - resolution: {integrity: sha512-df7HN1ozwMrB9+59re9PM7tSLxLAcheMWc5u/KyfCPCAWtN/vP7y7RTUZOy48uT1K9MESisVeOPPzF3O1AW01A==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-eventstream@3.972.21': - resolution: {integrity: sha512-HvLgDnxBLaHi9E5K++6Vuk+1+qqn7Pmn8zrlzd+NXH3jBzwujnuzZtAR9WHPkbUGPO92FkoQWj/M1IsdxTlBmQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-websocket@3.972.35': - resolution: {integrity: sha512-7/ZAlq5o5A9FnRsQEftZvcct9LVZf1YaYmWR3eOzyJAdKU66YpOKy5ahUVvyBvCTLyO4Ej4yWIk8dllWNXPBsw==} - engines: {node: '>= 14.0.0'} - - '@aws-sdk/nested-clients@3.997.27': - resolution: {integrity: sha512-A8PIePF9NIIOJ/4Lg1rl9xm/+QaKkHGetq+Z9wb5B+3Da31YYXRo8n7IDMh5C+HQI5eyEmjrwkGWVdYtnLtbXQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/signature-v4-multi-region@3.996.38': - resolution: {integrity: sha512-C379Sk+MiFZCfWZphKlMyLHKxV22OjoGM5KJjj5IJNJcOCWL4IGIpnEGzv1FQiRwhYXfq55SJMfxlqPE08JJ9g==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/token-providers@3.1048.0': - resolution: {integrity: sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/token-providers@3.1079.0': - resolution: {integrity: sha512-cbietrLlHPhhmbnMPTuDS4Zj/KNGhY+3vVhn6dwjO6Dqzrwothzg2srtcY34T9mlICsTXn34avDoWLHSntP54A==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/types@3.973.15': - resolution: {integrity: sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-locate-window@3.965.8': - resolution: {integrity: sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/xml-builder@3.972.33': - resolution: {integrity: sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A==} - engines: {node: '>=20.0.0'} - - '@aws/lambda-invoke-store@0.3.0': - resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==} - engines: {node: '>=18.0.0'} - - '@babel/runtime@7.29.7': - resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} - engines: {node: '>=6.9.0'} - - '@earendil-works/pi-agent-core@0.79.10': - resolution: {integrity: sha512-XKxgdjhcPuyjrthCOFSgfzT3xZ1uBrJ1IMVDxci1to6hIN6BIg9J5iY8q0pGXK1DLgATLP23da+1UyZLwA360Q==} - engines: {node: '>=22.19.0'} - - '@earendil-works/pi-ai@0.79.10': - resolution: {integrity: sha512-9jR23tOl0BIUdQMn70Gr72xYBpM7Xgl9Lyv7gAnU1USfkNRuYG/f/edLl+n/Dp/RafDW3JI4DF7y/GhgkORuew==} - engines: {node: '>=22.19.0'} - hasBin: true - - '@earendil-works/pi-coding-agent@0.79.10': - resolution: {integrity: sha512-YxaRhmgyDTvLDdGVbe7YzTHV80oL5mX5odg6EhGHz3w5Wu1Ix8DCw7bhtiOBLGQNFRcknia0zPmVWIj30XP1EA==} - engines: {node: '>=22.19.0'} - hasBin: true - - '@earendil-works/pi-tui@0.79.10': - resolution: {integrity: sha512-FUVOjDn1DVwM1uHD5MNYboXQrXjIDbSt+BQ3py7nQWCY62tKfxgiM1OBMxTcwRWLfSdZHUPpV0hm1loIdUJnPw==} - engines: {node: '>=22.19.0'} - - '@google/genai@1.52.0': - resolution: {integrity: sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==} - engines: {node: '>=20.0.0'} - peerDependencies: - '@modelcontextprotocol/sdk': ^1.25.2 - peerDependenciesMeta: - '@modelcontextprotocol/sdk': - optional: true - - '@hono/node-server@1.19.14': - resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} - engines: {node: '>=18.14.1'} - peerDependencies: - hono: ^4 - - '@isaacs/fs-minipass@4.0.1': - resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} - engines: {node: '>=18.0.0'} - - '@mariozechner/clipboard-darwin-arm64@0.3.9': - resolution: {integrity: sha512-BfgV7vCEWZwJwZJw03r6bP5+tf0iI/ANuQYCxi9RNn7FrWB3yzGuMKCrNLRl6V761vXRdL8+OqZ0wd4TqlsNOQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@mariozechner/clipboard-darwin-universal@0.3.9': - resolution: {integrity: sha512-BGGR4iA9Z2shAjI65eI5xtyb3LYNlDW9X3gxKxDbqtbnREohsrqznov6zpKoIrsRWpzlYVEdKphS7ksJ0/ndSQ==} - engines: {node: '>= 10'} - os: [darwin] - - '@mariozechner/clipboard-darwin-x64@0.3.9': - resolution: {integrity: sha512-4kURmCbS6nt8uYhtmWpUcJWyPHfmAr5dTpXD1nO3pIfa+TSQ9DbrGOYCKH+aEFW47XhQ4Vp8ZTszie+wfFvDKg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@mariozechner/clipboard-linux-arm64-gnu@0.3.9': - resolution: {integrity: sha512-g59OkUGP2DDfCOIKypHeYgv2M55u/cKvXa5dSxFbEJ34XvIQMdcVmpKCkGUro3ZgefXiGVdwguvTMQGpHWzIXw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@mariozechner/clipboard-linux-arm64-musl@0.3.9': - resolution: {integrity: sha512-AGuJdgKsmJdm4Pych7kv3sqe591ERRaAHW3xjLooiFzn8J+PxUyof++7YZrB5Y5tpnTO+K18Og3taj2NpluCRQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@mariozechner/clipboard-linux-riscv64-gnu@0.3.9': - resolution: {integrity: sha512-DXBEAiuMpk7dhS1a9NzNxVAFi1vaKoPu7rQNgY8LIDLGrK3lnIp3nT10DUum+PKVJoJppIP+NAA8IZe4DMNDPw==} - engines: {node: '>= 10'} - cpu: [riscv64] - os: [linux] - - '@mariozechner/clipboard-linux-x64-gnu@0.3.9': - resolution: {integrity: sha512-WORrMLd6EpElEME7JRKfSaY34nW1P5LbdgK5YNCS1ncG2LqmITsSMEJ8nh2mpvxb3TxqbOOKgY7k9eMJYlW9Mw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@mariozechner/clipboard-linux-x64-musl@0.3.9': - resolution: {integrity: sha512-/DHn+1DrfL6oRaPPWXaOKvonFFrni666fxd+zFqiQEfvBH0tsHVWjq9iqBk0oDp0qaPA72lIMy5BptxISBEhZQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@mariozechner/clipboard-win32-arm64-msvc@0.3.9': - resolution: {integrity: sha512-O5FHD3ErkMwMhNzAfu3ggy0ug4z7btZuoQgwwxlzPrwV2bxlD6WDpqBY4NCgICAgZdDKdp+loUEKVAVt8aYnhQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@mariozechner/clipboard-win32-x64-msvc@0.3.9': - resolution: {integrity: sha512-ihQC3EufqEY81vhXBgVBtK4prL+wc62zJsSvxrgz7K1hsdt6OObz6v9p3Rn1OG3GJksTTKMJF0u/guMISHPhSA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@mariozechner/clipboard@0.3.9': - resolution: {integrity: sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA==} - engines: {node: '>= 10'} - - '@mistralai/mistralai@2.2.6': - resolution: {integrity: sha512-W8pX7zHxjJvMIpw8JMxeJEleapXX0Q9NPszdNzqkM3MIEoIGPObdodujj+WHteXEvGfaP/AMwlNyRfEzSY6dQQ==} - peerDependencies: - '@opentelemetry/api': ^1.9.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - - '@modelcontextprotocol/sdk@1.29.0': - resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} - engines: {node: '>=18'} - peerDependencies: - '@cfworker/json-schema': ^4.1.1 - zod: ^3.25 || ^4.0 - peerDependenciesMeta: - '@cfworker/json-schema': - optional: true - - '@openai/codex-sdk@0.125.0': - resolution: {integrity: sha512-1xCIHdSbQVF880nJ2aVWdPIsWZbSpKODwuP9y/gvtChDYhYfYEW0DKp2H8ZlctkzIjlzS/WzYmP6ZZPHIvs2Dg==} - engines: {node: '>=18'} - - '@openai/codex@0.125.0': - resolution: {integrity: sha512-GiE9wlgL95u/5BRirY5d3EaRLU1tu7Y1R09R8lCHHVmcQdSmhS809FdPDWH3gIYHS7ZriAPqXwJ3aLA0WKl40Q==} - engines: {node: '>=16'} - hasBin: true - - '@openai/codex@0.125.0-darwin-arm64': - resolution: {integrity: sha512-Gn2fHiSO0XgyHp1OSd5DWUTm66Bv9UEuipW5pVEj1E+hWZCOrdqnYttllKFWtRGj5yiKefNX3JIxONgh/ZwlOQ==} - engines: {node: '>=16'} - cpu: [arm64] - os: [darwin] - - '@openai/codex@0.125.0-darwin-x64': - resolution: {integrity: sha512-TZ5Lek2X/UXTI9LXFxzarvQaJeuTrqVh4POc7soO/8RclVnCxADnCf15sivxLd5eiFW4t0myGoeVoM4lciRiRg==} - engines: {node: '>=16'} - cpu: [x64] - os: [darwin] - - '@openai/codex@0.125.0-linux-arm64': - resolution: {integrity: sha512-pPnJoJD6rZ2Iin0zNt/up36bO2/EOp2B+1/rPHu/lSq3PJbT3Fmnfut2kJy5LylXb7bGA2XQbtqOogZzIbnlkA==} - engines: {node: '>=16'} - cpu: [arm64] - os: [linux] - - '@openai/codex@0.125.0-linux-x64': - resolution: {integrity: sha512-K2NTTEeBpz/G+N2x17UGWfauRt3So+ir4f+U/60l5PPnYEJB/w3YZrlXo2G9og8Dm9BqtoBAjoPV74sRv9tWWQ==} - engines: {node: '>=16'} - cpu: [x64] - os: [linux] - - '@openai/codex@0.125.0-win32-arm64': - resolution: {integrity: sha512-zxoUakw9oIHIFrAyk400XkkLBJFA6nOym0NDq6sQ/jhdcYraKqNSRCII2nsBwZHk+/4zgUvuk52iuutgysY/rQ==} - engines: {node: '>=16'} - cpu: [arm64] - os: [win32] - - '@openai/codex@0.125.0-win32-x64': - resolution: {integrity: sha512-ofpOK+OWH5QFuUZ9pTM0d/PcXUXiIP5z5DpRcE9MlucJoyOl4Zy4Nu3NcuHF4YzCkZMQb6x3j0tjDEPHKqNQzw==} - engines: {node: '>=16'} - cpu: [x64] - os: [win32] - - '@opentelemetry/api@1.9.0': - resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} - engines: {node: '>=8.0.0'} - - '@opentelemetry/semantic-conventions@1.41.1': - resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==} - engines: {node: '>=14'} - - '@protobufjs/aspromise@1.1.2': - resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} - - '@protobufjs/base64@1.1.2': - resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - - '@protobufjs/codegen@2.0.5': - resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} - - '@protobufjs/eventemitter@1.1.1': - resolution: {integrity: sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==} - - '@protobufjs/fetch@1.1.1': - resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==} - - '@protobufjs/float@1.0.2': - resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - - '@protobufjs/path@1.1.2': - resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} - - '@protobufjs/pool@1.1.0': - resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - - '@protobufjs/utf8@1.1.1': - resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} - - '@silvia-odwyer/photon-node@0.3.4': - resolution: {integrity: sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==} - - '@smithy/core@3.29.1': - resolution: {integrity: sha512-qoiY4nrk5OCu1+eIR1VB8l5DmON/oKiqrd5zZFAhXJXjJlLWQusKEW/SkBDAtGDcPaz86m9kfcE1lngU0GlM6A==} - engines: {node: '>=18.0.0'} - - '@smithy/credential-provider-imds@4.4.6': - resolution: {integrity: sha512-B2WQ/PV/H6Jeg3lrIq6bKUfa6Hy01mtK7CGs6lhjzHA6k4aagldH6T6eEjnzKl4HI0cJnAsxfJ19pgb5PV+CVQ==} - engines: {node: '>=18.0.0'} - - '@smithy/fetch-http-handler@5.6.3': - resolution: {integrity: sha512-CwCc/7SMTj45y97MUnDTbTaxvtAsiNNRm81z3abROIuMbMsC2Iy5EKfkkVdsKrz8WExQAAMx1EJapq+9j4fFTQ==} - engines: {node: '>=18.0.0'} - - '@smithy/is-array-buffer@2.2.0': - resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} - engines: {node: '>=14.0.0'} - - '@smithy/node-http-handler@4.7.3': - resolution: {integrity: sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==} - engines: {node: '>=18.0.0'} - - '@smithy/node-http-handler@4.9.3': - resolution: {integrity: sha512-qZTa4gQFUo8RM02rk6q5UVTDLNrQ1oS20LsepBzqq1QBVc/EHJ03OOUADcqMZiXHArW+Y7+OGY0BpdTwZRq/Yg==} - engines: {node: '>=18.0.0'} - - '@smithy/signature-v4@5.6.2': - resolution: {integrity: sha512-QgHflghMoPxCJ9axiCVh8KZfbC9fuP6vkXXyK//E3cq7nLaSSyyLj0GAoqVWezYeDQmXIZhmlRvLE16jsqDK6g==} - engines: {node: '>=18.0.0'} - - '@smithy/types@4.15.1': - resolution: {integrity: sha512-x3L0XSACF6UYzKpa9biqiRMgvH5+wnFFew9Tm/grFYqgaupPwx/+ojDPpPJM8dZON3S9tjz5U+PQYsCBd1Mw5Q==} - engines: {node: '>=18.0.0'} - - '@smithy/util-buffer-from@2.2.0': - resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} - engines: {node: '>=14.0.0'} - - '@smithy/util-utf8@2.3.0': - resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} - engines: {node: '>=14.0.0'} - - '@stablelib/base64@1.0.1': - resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==} - - '@types/node@26.1.0': - resolution: {integrity: sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==} - - '@types/retry@0.12.0': - resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} - - '@vercel/cli-config@0.2.0': - resolution: {integrity: sha512-fJRRRB7734BDuXZ89yBEaA2ncYhH7bWX30mk04W80J6VAfQc+4iB8lyzAdaGpFV3/vNlkt9VZt+/uoQoWX6UsQ==} - - '@vercel/cli-exec@1.0.0': - resolution: {integrity: sha512-kQF8LGie/Hbdq9/psJxLE7owRTcqMQMhgybU04gCeR7cbQAr5t8OrjefDNColJv1QSSucFt4pLwRiARVmlOnug==} - engines: {node: '>= 18'} - - '@vercel/oidc@3.2.0': - resolution: {integrity: sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug==} - engines: {node: '>= 20'} - - '@vercel/oidc@3.8.0': - resolution: {integrity: sha512-r00laGW6Pv778RoR6M2NxX91ycSj+PBwVo+fOb9Bif+F0IyUKt25zrvBzfEzQpeAzbqOgPZyQibEWDdDFApd+A==} - engines: {node: '>= 20'} - - '@vercel/sandbox@1.10.2': - resolution: {integrity: sha512-rWhYfIyW0Va0gFxtz434LhVirV+eQs+AK0QQWtsOPw2oTvOSA4iogQqemRqvRPPbqI8nfZOz6kbCsytVa20gdw==} - - '@workflow/serde@4.1.0-beta.2': - resolution: {integrity: sha512-8kkeoQKLDaKXefjV5dbhBj2aErfKp1Mc4pb6tj8144cF+Em5SPbyMbyLCHp+BVrFfFVCBluCtMx+jjvaFVZGww==} - - accepts@2.0.0: - resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} - engines: {node: '>= 0.6'} - - agent-base@7.1.4: - resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} - engines: {node: '>= 14'} - - ajv-formats@3.0.1: - resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - - ajv@8.20.0: - resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} - - async-retry@1.3.3: - resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} - - b4a@1.8.1: - resolution: {integrity: sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==} - peerDependencies: - react-native-b4a: '*' - peerDependenciesMeta: - react-native-b4a: - optional: true - - balanced-match@4.0.4: - resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} - engines: {node: 18 || 20 || >=22} - - bare-events@2.9.1: - resolution: {integrity: sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==} - peerDependencies: - bare-abort-controller: '*' - peerDependenciesMeta: - bare-abort-controller: - optional: true - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - bignumber.js@9.3.1: - resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} - - body-parser@2.3.0: - resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} - engines: {node: '>=18'} - - bowser@2.14.1: - resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} - - brace-expansion@5.0.7: - resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==} - engines: {node: 18 || 20 || >=22} - - buffer-equal-constant-time@1.0.1: - resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} - - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} - - chalk@5.6.2: - resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - chownr@3.0.0: - resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} - engines: {node: '>=18'} - - content-disposition@1.1.0: - resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} - engines: {node: '>=18'} - - content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - - content-type@2.0.0: - resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} - engines: {node: '>=18'} - - cookie-signature@1.2.2: - resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} - engines: {node: '>=6.6.0'} - - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} - - cors@2.8.6: - resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} - engines: {node: '>= 0.10'} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - data-uri-to-buffer@4.0.1: - resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} - engines: {node: '>= 12'} - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deepsec@2.1.2: - resolution: {integrity: sha512-UyIjuNJu/UdZVGyQWKPh4sEHjyPekzyNiMBjlD/T5o9uEhmKiHFWQ8m2ziiKRdQ9hvDbyeYHbuncJc1FnKKpFw==} - hasBin: true - - depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - - diff@8.0.4: - resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} - engines: {node: '>=0.3.1'} - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - ecdsa-sig-formatter@1.0.11: - resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} - - ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - - encodeurl@2.0.0: - resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} - engines: {node: '>= 0.8'} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-object-atoms@1.1.2: - resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} - engines: {node: '>= 0.4'} - - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - - etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - - events-universal@1.0.1: - resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} - - eventsource-parser@3.1.0: - resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} - engines: {node: '>=18.0.0'} - - eventsource@3.0.7: - resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} - engines: {node: '>=18.0.0'} - - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - express-rate-limit@8.5.2: - resolution: {integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==} - engines: {node: '>= 16'} - peerDependencies: - express: '>= 4.11' - - express@5.2.1: - resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} - engines: {node: '>= 18'} - - extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-fifo@1.3.2: - resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - - fast-sha256@1.3.0: - resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==} - - fast-uri@3.1.3: - resolution: {integrity: sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==} - - fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} - - finalhandler@2.1.1: - resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} - engines: {node: '>= 18.0.0'} - - formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} - - forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - - fresh@2.0.0: - resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} - engines: {node: '>= 0.8'} - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - gaxios@7.1.5: - resolution: {integrity: sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==} - engines: {node: '>=18'} - - gcp-metadata@8.1.2: - resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} - engines: {node: '>=18'} - - get-east-asian-width@1.6.0: - resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} - engines: {node: '>=18'} - - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - glob@13.0.6: - resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} - engines: {node: 18 || 20 || >=22} - - google-auth-library@10.9.0: - resolution: {integrity: sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg==} - engines: {node: '>=18'} - - google-logging-utils@1.1.3: - resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==} - engines: {node: '>=14'} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - hasown@2.0.4: - resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} - engines: {node: '>= 0.4'} - - highlight.js@10.7.3: - resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} - - hono@4.12.27: - resolution: {integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==} - engines: {node: '>=16.9.0'} - - hosted-git-info@9.0.3: - resolution: {integrity: sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==} - engines: {node: ^20.17.0 || >=22.9.0} - - http-errors@2.0.1: - resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} - engines: {node: '>= 0.8'} - - http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - - https-proxy-agent@7.0.6: - resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} - engines: {node: '>= 14'} - - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - iconv-lite@0.7.3: - resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} - engines: {node: '>=0.10.0'} - - ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} - engines: {node: '>= 4'} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - ip-address@10.2.0: - resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} - engines: {node: '>= 12'} - - ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - - is-promise@4.0.0: - resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - jiti@2.7.0: - resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} - hasBin: true - - jose@5.10.0: - resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} - - jose@6.2.3: - resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} - - json-bigint@1.0.0: - resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} - - json-schema-to-ts@3.1.1: - resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==} - engines: {node: '>=16'} - - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - - json-schema-typed@8.0.2: - resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} - - jsonlines@0.1.1: - resolution: {integrity: sha512-ekDrAGso79Cvf+dtm+mL8OBI2bmAOt3gssYs833De/C9NmIpWDWyUO4zPgB5x2/OhY366dkhgfPMYfwZF7yOZA==} - - jwa@2.0.1: - resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} - - jws@4.0.1: - resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} - - long@5.3.2: - resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} - - lru-cache@11.5.1: - resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} - engines: {node: 20 || >=22} - - marked@18.0.5: - resolution: {integrity: sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==} - engines: {node: '>= 20'} - hasBin: true - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - media-typer@1.1.0: - resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} - engines: {node: '>= 0.8'} - - merge-descriptors@2.0.0: - resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} - engines: {node: '>=18'} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - mime-db@1.54.0: - resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} - engines: {node: '>= 0.6'} - - mime-types@3.0.2: - resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} - engines: {node: '>=18'} - - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - minimatch@10.2.5: - resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} - engines: {node: 18 || 20 || >=22} - - minipass@7.1.3: - resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} - engines: {node: '>=16 || 14 >=14.17'} - - minizlib@3.1.0: - resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} - engines: {node: '>= 18'} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - negotiator@1.0.0: - resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} - engines: {node: '>= 0.6'} - - node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - deprecated: Use your platform's native DOMException instead - - node-fetch@3.3.2: - resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} - - on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - openai@6.26.0: - resolution: {integrity: sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==} - hasBin: true - peerDependencies: - ws: ^8.18.0 - zod: ^3.25 || ^4.0 - peerDependenciesMeta: - ws: - optional: true - zod: - optional: true - - os-paths@4.4.0: - resolution: {integrity: sha512-wrAwOeXp1RRMFfQY8Sy7VaGVmPocaLwSFOYCGKSyo8qmJ+/yaafCl5BCA1IQZWqFSRBrKDYFeR9d/VyQzfH/jg==} - engines: {node: '>= 6.0'} - - p-retry@4.6.2: - resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} - engines: {node: '>=8'} - - parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - - partial-json@0.1.7: - resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-scurry@2.0.2: - resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} - engines: {node: 18 || 20 || >=22} - - path-to-regexp@8.4.2: - resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - pkce-challenge@5.0.1: - resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} - engines: {node: '>=16.20.0'} - - proper-lockfile@4.1.2: - resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} - - protobufjs@7.6.5: - resolution: {integrity: sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==} - engines: {node: '>=12.0.0'} - - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - - qs@6.15.3: - resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} - engines: {node: '>=0.6'} - - range-parser@1.3.0: - resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==} - engines: {node: '>= 0.6'} - - raw-body@3.0.2: - resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} - engines: {node: '>= 0.10'} - - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - - retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - - retry@0.13.1: - resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} - engines: {node: '>= 4'} - - router@2.2.0: - resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} - engines: {node: '>= 18'} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - semver@7.8.0: - resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==} - engines: {node: '>=10'} - hasBin: true - - send@1.2.1: - resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} - engines: {node: '>= 18'} - - serve-static@2.2.1: - resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} - engines: {node: '>= 18'} - - setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - side-channel-list@1.0.1: - resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.1: - resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} - engines: {node: '>= 0.4'} - - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - standardwebhooks@1.0.0: - resolution: {integrity: sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==} - - statuses@2.0.2: - resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} - engines: {node: '>= 0.8'} - - streamx@2.28.0: - resolution: {integrity: sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==} - - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - tar-stream@3.1.7: - resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} - - tar@7.5.19: - resolution: {integrity: sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw==} - engines: {node: '>=18'} - - text-decoder@1.2.7: - resolution: {integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==} - - toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - - ts-algebra@2.0.0: - resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - type-is@2.1.0: - resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} - engines: {node: '>= 18'} - - typebox@1.1.38: - resolution: {integrity: sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==} - - undici-types@8.3.0: - resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} - - undici@7.28.0: - resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} - engines: {node: '>=20.18.1'} - - undici@8.5.0: - resolution: {integrity: sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg==} - engines: {node: '>=22.19.0'} - - unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - - vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - - web-streams-polyfill@3.3.3: - resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} - engines: {node: '>= 8'} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@8.21.0: - resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - xdg-app-paths@5.1.0: - resolution: {integrity: sha512-RAQ3WkPf4KTU1A8RtFx3gWywzVKe00tfOPFfl2NDGqbIFENQO4kqAJp7mhQjNj/33W5x5hiWWUdyfPq/5SU3QA==} - engines: {node: '>=6'} - - xdg-app-paths@5.5.1: - resolution: {integrity: sha512-hI3flOB4PLZIy5prbtTpirobtPE2ZtZ52szO+2mM9Efp6ErM398La+C1lIpNWDfNoQk+6Lsi6nMcCwVB7pxeMQ==} - engines: {node: '>= 6.0'} - - xdg-portable@7.3.0: - resolution: {integrity: sha512-sqMMuL1rc0FmMBOzCpd0yuy9trqF2yTTVe+E9ogwCSWQCdDEtQUwrZPT6AxqtsFGRNxycgncbP/xmOOSPw5ZUw==} - engines: {node: '>= 6.0'} - - yallist@5.0.0: - resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} - engines: {node: '>=18'} - - yaml@2.9.0: - resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} - engines: {node: '>= 14.6'} - hasBin: true - - zod-to-json-schema@3.25.2: - resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} - peerDependencies: - zod: ^3.25.28 || ^4 - - zod@3.24.4: - resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==} - - zod@4.1.11: - resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==} - - zod@4.4.3: - resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} - -snapshots: - - '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.201': - optional: true - - '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.201': - optional: true - - '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.201': - optional: true - - '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.201': - optional: true - - '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.201': - optional: true - - '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.201': - optional: true - - '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.201': - optional: true - - '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.201': - optional: true - - '@anthropic-ai/claude-agent-sdk@0.3.201(@anthropic-ai/sdk@0.96.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)': - dependencies: - '@anthropic-ai/sdk': 0.96.0(zod@4.4.3) - '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) - zod: 4.4.3 - optionalDependencies: - '@anthropic-ai/claude-agent-sdk-darwin-arm64': 0.3.201 - '@anthropic-ai/claude-agent-sdk-darwin-x64': 0.3.201 - '@anthropic-ai/claude-agent-sdk-linux-arm64': 0.3.201 - '@anthropic-ai/claude-agent-sdk-linux-arm64-musl': 0.3.201 - '@anthropic-ai/claude-agent-sdk-linux-x64': 0.3.201 - '@anthropic-ai/claude-agent-sdk-linux-x64-musl': 0.3.201 - '@anthropic-ai/claude-agent-sdk-win32-arm64': 0.3.201 - '@anthropic-ai/claude-agent-sdk-win32-x64': 0.3.201 - - '@anthropic-ai/sdk@0.91.1(zod@4.4.3)': - dependencies: - json-schema-to-ts: 3.1.1 - optionalDependencies: - zod: 4.4.3 - - '@anthropic-ai/sdk@0.96.0(zod@4.4.3)': - dependencies: - json-schema-to-ts: 3.1.1 - standardwebhooks: 1.0.0 - optionalDependencies: - zod: 4.4.3 - - '@aws-crypto/sha256-browser@5.2.0': - dependencies: - '@aws-crypto/sha256-js': 5.2.0 - '@aws-crypto/supports-web-crypto': 5.2.0 - '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.15 - '@aws-sdk/util-locate-window': 3.965.8 - '@smithy/util-utf8': 2.3.0 - tslib: 2.8.1 - - '@aws-crypto/sha256-js@5.2.0': - dependencies: - '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.15 - tslib: 2.8.1 - - '@aws-crypto/supports-web-crypto@5.2.0': - dependencies: - tslib: 2.8.1 - - '@aws-crypto/util@5.2.0': - dependencies: - '@aws-sdk/types': 3.973.15 - '@smithy/util-utf8': 2.3.0 - tslib: 2.8.1 - - '@aws-sdk/client-bedrock-runtime@3.1048.0': - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.27 - '@aws-sdk/credential-provider-node': 3.972.62 - '@aws-sdk/eventstream-handler-node': 3.972.25 - '@aws-sdk/middleware-eventstream': 3.972.21 - '@aws-sdk/middleware-websocket': 3.972.35 - '@aws-sdk/token-providers': 3.1048.0 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/fetch-http-handler': 5.6.3 - '@smithy/node-http-handler': 4.7.3 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/core@3.974.27': - dependencies: - '@aws-sdk/types': 3.973.15 - '@aws-sdk/xml-builder': 3.972.33 - '@aws/lambda-invoke-store': 0.3.0 - '@smithy/core': 3.29.1 - '@smithy/signature-v4': 5.6.2 - '@smithy/types': 4.15.1 - bowser: 2.14.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-env@3.972.53': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-http@3.972.55': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/fetch-http-handler': 5.6.3 - '@smithy/node-http-handler': 4.9.3 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-ini@3.972.60': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/credential-provider-env': 3.972.53 - '@aws-sdk/credential-provider-http': 3.972.55 - '@aws-sdk/credential-provider-login': 3.972.59 - '@aws-sdk/credential-provider-process': 3.972.53 - '@aws-sdk/credential-provider-sso': 3.972.59 - '@aws-sdk/credential-provider-web-identity': 3.972.59 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/credential-provider-imds': 4.4.6 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-login@3.972.59': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-node@3.972.62': - dependencies: - '@aws-sdk/credential-provider-env': 3.972.53 - '@aws-sdk/credential-provider-http': 3.972.55 - '@aws-sdk/credential-provider-ini': 3.972.60 - '@aws-sdk/credential-provider-process': 3.972.53 - '@aws-sdk/credential-provider-sso': 3.972.59 - '@aws-sdk/credential-provider-web-identity': 3.972.59 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/credential-provider-imds': 4.4.6 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-process@3.972.53': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-sso@3.972.59': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/token-providers': 3.1079.0 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-web-identity@3.972.59': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/eventstream-handler-node@3.972.25': - dependencies: - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/middleware-eventstream@3.972.21': - dependencies: - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/middleware-websocket@3.972.35': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/fetch-http-handler': 5.6.3 - '@smithy/signature-v4': 5.6.2 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/nested-clients@3.997.27': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/signature-v4-multi-region': 3.996.38 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/fetch-http-handler': 5.6.3 - '@smithy/node-http-handler': 4.9.3 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/signature-v4-multi-region@3.996.38': - dependencies: - '@aws-sdk/types': 3.973.15 - '@smithy/signature-v4': 5.6.2 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/token-providers@3.1048.0': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/token-providers@3.1079.0': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/types@3.973.15': - dependencies: - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws-sdk/util-locate-window@3.965.8': - dependencies: - tslib: 2.8.1 - - '@aws-sdk/xml-builder@3.972.33': - dependencies: - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@aws/lambda-invoke-store@0.3.0': {} - - '@babel/runtime@7.29.7': {} - - '@earendil-works/pi-agent-core@0.79.10(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3)': - dependencies: - '@earendil-works/pi-ai': 0.79.10(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3) - ignore: 7.0.5 - typebox: 1.1.38 - yaml: 2.9.0 - transitivePeerDependencies: - - '@modelcontextprotocol/sdk' - - bufferutil - - supports-color - - utf-8-validate - - ws - - zod - - '@earendil-works/pi-ai@0.79.10(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3)': - dependencies: - '@anthropic-ai/sdk': 0.91.1(zod@4.4.3) - '@aws-sdk/client-bedrock-runtime': 3.1048.0 - '@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)) - '@mistralai/mistralai': 2.2.6(@opentelemetry/api@1.9.0) - '@opentelemetry/api': 1.9.0 - '@smithy/node-http-handler': 4.7.3 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - openai: 6.26.0(ws@8.21.0)(zod@4.4.3) - partial-json: 0.1.7 - typebox: 1.1.38 - transitivePeerDependencies: - - '@modelcontextprotocol/sdk' - - bufferutil - - supports-color - - utf-8-validate - - ws - - zod - - '@earendil-works/pi-coding-agent@0.79.10(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3)': - dependencies: - '@earendil-works/pi-agent-core': 0.79.10(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3) - '@earendil-works/pi-ai': 0.79.10(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3) - '@earendil-works/pi-tui': 0.79.10 - '@silvia-odwyer/photon-node': 0.3.4 - chalk: 5.6.2 - cross-spawn: 7.0.6 - diff: 8.0.4 - glob: 13.0.6 - highlight.js: 10.7.3 - hosted-git-info: 9.0.3 - ignore: 7.0.5 - jiti: 2.7.0 - minimatch: 10.2.5 - proper-lockfile: 4.1.2 - semver: 7.8.0 - typebox: 1.1.38 - undici: 8.5.0 - yaml: 2.9.0 - optionalDependencies: - '@mariozechner/clipboard': 0.3.9 - transitivePeerDependencies: - - '@modelcontextprotocol/sdk' - - bufferutil - - supports-color - - utf-8-validate - - ws - - zod - - '@earendil-works/pi-tui@0.79.10': - dependencies: - get-east-asian-width: 1.6.0 - marked: 18.0.5 - - '@google/genai@1.52.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))': - dependencies: - google-auth-library: 10.9.0 - p-retry: 4.6.2 - protobufjs: 7.6.5 - ws: 8.21.0 - optionalDependencies: - '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - '@hono/node-server@1.19.14(hono@4.12.27)': - dependencies: - hono: 4.12.27 - - '@isaacs/fs-minipass@4.0.1': - dependencies: - minipass: 7.1.3 - - '@mariozechner/clipboard-darwin-arm64@0.3.9': - optional: true - - '@mariozechner/clipboard-darwin-universal@0.3.9': - optional: true - - '@mariozechner/clipboard-darwin-x64@0.3.9': - optional: true - - '@mariozechner/clipboard-linux-arm64-gnu@0.3.9': - optional: true - - '@mariozechner/clipboard-linux-arm64-musl@0.3.9': - optional: true - - '@mariozechner/clipboard-linux-riscv64-gnu@0.3.9': - optional: true - - '@mariozechner/clipboard-linux-x64-gnu@0.3.9': - optional: true - - '@mariozechner/clipboard-linux-x64-musl@0.3.9': - optional: true - - '@mariozechner/clipboard-win32-arm64-msvc@0.3.9': - optional: true - - '@mariozechner/clipboard-win32-x64-msvc@0.3.9': - optional: true - - '@mariozechner/clipboard@0.3.9': - optionalDependencies: - '@mariozechner/clipboard-darwin-arm64': 0.3.9 - '@mariozechner/clipboard-darwin-universal': 0.3.9 - '@mariozechner/clipboard-darwin-x64': 0.3.9 - '@mariozechner/clipboard-linux-arm64-gnu': 0.3.9 - '@mariozechner/clipboard-linux-arm64-musl': 0.3.9 - '@mariozechner/clipboard-linux-riscv64-gnu': 0.3.9 - '@mariozechner/clipboard-linux-x64-gnu': 0.3.9 - '@mariozechner/clipboard-linux-x64-musl': 0.3.9 - '@mariozechner/clipboard-win32-arm64-msvc': 0.3.9 - '@mariozechner/clipboard-win32-x64-msvc': 0.3.9 - optional: true - - '@mistralai/mistralai@2.2.6(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/semantic-conventions': 1.41.1 - ws: 8.21.0 - zod: 4.4.3 - zod-to-json-schema: 3.25.2(zod@4.4.3) - optionalDependencies: - '@opentelemetry/api': 1.9.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - '@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)': - dependencies: - '@hono/node-server': 1.19.14(hono@4.12.27) - ajv: 8.20.0 - ajv-formats: 3.0.1(ajv@8.20.0) - content-type: 1.0.5 - cors: 2.8.6 - cross-spawn: 7.0.6 - eventsource: 3.0.7 - eventsource-parser: 3.1.0 - express: 5.2.1 - express-rate-limit: 8.5.2(express@5.2.1) - hono: 4.12.27 - jose: 6.2.3 - json-schema-typed: 8.0.2 - pkce-challenge: 5.0.1 - raw-body: 3.0.2 - zod: 4.4.3 - zod-to-json-schema: 3.25.2(zod@4.4.3) - transitivePeerDependencies: - - supports-color - - '@openai/codex-sdk@0.125.0': - dependencies: - '@openai/codex': 0.125.0 - - '@openai/codex@0.125.0': - optionalDependencies: - '@openai/codex-darwin-arm64': '@openai/codex@0.125.0-darwin-arm64' - '@openai/codex-darwin-x64': '@openai/codex@0.125.0-darwin-x64' - '@openai/codex-linux-arm64': '@openai/codex@0.125.0-linux-arm64' - '@openai/codex-linux-x64': '@openai/codex@0.125.0-linux-x64' - '@openai/codex-win32-arm64': '@openai/codex@0.125.0-win32-arm64' - '@openai/codex-win32-x64': '@openai/codex@0.125.0-win32-x64' - - '@openai/codex@0.125.0-darwin-arm64': - optional: true - - '@openai/codex@0.125.0-darwin-x64': - optional: true - - '@openai/codex@0.125.0-linux-arm64': - optional: true - - '@openai/codex@0.125.0-linux-x64': - optional: true - - '@openai/codex@0.125.0-win32-arm64': - optional: true - - '@openai/codex@0.125.0-win32-x64': - optional: true - - '@opentelemetry/api@1.9.0': {} - - '@opentelemetry/semantic-conventions@1.41.1': {} - - '@protobufjs/aspromise@1.1.2': {} - - '@protobufjs/base64@1.1.2': {} - - '@protobufjs/codegen@2.0.5': {} - - '@protobufjs/eventemitter@1.1.1': {} - - '@protobufjs/fetch@1.1.1': - dependencies: - '@protobufjs/aspromise': 1.1.2 - - '@protobufjs/float@1.0.2': {} - - '@protobufjs/path@1.1.2': {} - - '@protobufjs/pool@1.1.0': {} - - '@protobufjs/utf8@1.1.1': {} - - '@silvia-odwyer/photon-node@0.3.4': {} - - '@smithy/core@3.29.1': - dependencies: - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@smithy/credential-provider-imds@4.4.6': - dependencies: - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@smithy/fetch-http-handler@5.6.3': - dependencies: - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@smithy/is-array-buffer@2.2.0': - dependencies: - tslib: 2.8.1 - - '@smithy/node-http-handler@4.7.3': - dependencies: - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@smithy/node-http-handler@4.9.3': - dependencies: - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@smithy/signature-v4@5.6.2': - dependencies: - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 - tslib: 2.8.1 - - '@smithy/types@4.15.1': - dependencies: - tslib: 2.8.1 - - '@smithy/util-buffer-from@2.2.0': - dependencies: - '@smithy/is-array-buffer': 2.2.0 - tslib: 2.8.1 - - '@smithy/util-utf8@2.3.0': - dependencies: - '@smithy/util-buffer-from': 2.2.0 - tslib: 2.8.1 - - '@stablelib/base64@1.0.1': {} - - '@types/node@26.1.0': - dependencies: - undici-types: 8.3.0 - - '@types/retry@0.12.0': {} - - '@vercel/cli-config@0.2.0': - dependencies: - xdg-app-paths: 5.5.1 - zod: 4.1.11 - - '@vercel/cli-exec@1.0.0': - dependencies: - execa: 5.1.1 - - '@vercel/oidc@3.2.0': {} - - '@vercel/oidc@3.8.0': - dependencies: - '@vercel/cli-config': 0.2.0 - '@vercel/cli-exec': 1.0.0 - jose: 5.10.0 - - '@vercel/sandbox@1.10.2': - dependencies: - '@vercel/oidc': 3.2.0 - '@workflow/serde': 4.1.0-beta.2 - async-retry: 1.3.3 - jsonlines: 0.1.1 - ms: 2.1.3 - picocolors: 1.1.1 - tar-stream: 3.1.7 - undici: 7.28.0 - xdg-app-paths: 5.1.0 - zod: 3.24.4 - transitivePeerDependencies: - - bare-abort-controller - - react-native-b4a - - '@workflow/serde@4.1.0-beta.2': {} - - accepts@2.0.0: - dependencies: - mime-types: 3.0.2 - negotiator: 1.0.0 - - agent-base@7.1.4: {} - - ajv-formats@3.0.1(ajv@8.20.0): - optionalDependencies: - ajv: 8.20.0 - - ajv@8.20.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - async-retry@1.3.3: - dependencies: - retry: 0.13.1 - - b4a@1.8.1: {} - - balanced-match@4.0.4: {} - - bare-events@2.9.1: {} - - base64-js@1.5.1: {} - - bignumber.js@9.3.1: {} - - body-parser@2.3.0: - dependencies: - bytes: 3.1.2 - content-type: 2.0.0 - debug: 4.4.3 - http-errors: 2.0.1 - iconv-lite: 0.7.3 - on-finished: 2.4.1 - qs: 6.15.3 - raw-body: 3.0.2 - type-is: 2.1.0 - transitivePeerDependencies: - - supports-color - - bowser@2.14.1: {} - - brace-expansion@5.0.7: - dependencies: - balanced-match: 4.0.4 - - buffer-equal-constant-time@1.0.1: {} - - bytes@3.1.2: {} - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - - chalk@5.6.2: {} - - chownr@3.0.0: {} - - content-disposition@1.1.0: {} - - content-type@1.0.5: {} - - content-type@2.0.0: {} - - cookie-signature@1.2.2: {} - - cookie@0.7.2: {} - - cors@2.8.6: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - data-uri-to-buffer@4.0.1: {} - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - deepsec@2.1.2(@anthropic-ai/sdk@0.96.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3): - dependencies: - '@anthropic-ai/claude-agent-sdk': 0.3.201(@anthropic-ai/sdk@0.96.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) - '@earendil-works/pi-coding-agent': 0.79.10(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3) - '@openai/codex': 0.125.0 - '@openai/codex-sdk': 0.125.0 - '@vercel/oidc': 3.8.0 - '@vercel/sandbox': 1.10.2 - jiti: 2.7.0 - minimatch: 10.2.5 - tar: 7.5.19 - transitivePeerDependencies: - - '@anthropic-ai/sdk' - - '@modelcontextprotocol/sdk' - - bare-abort-controller - - bufferutil - - react-native-b4a - - supports-color - - utf-8-validate - - ws - - zod - - depd@2.0.0: {} - - diff@8.0.4: {} - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - ecdsa-sig-formatter@1.0.11: - dependencies: - safe-buffer: 5.2.1 - - ee-first@1.1.1: {} - - encodeurl@2.0.0: {} - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-object-atoms@1.1.2: - dependencies: - es-errors: 1.3.0 - - escape-html@1.0.3: {} - - etag@1.8.1: {} - - events-universal@1.0.1: - dependencies: - bare-events: 2.9.1 - transitivePeerDependencies: - - bare-abort-controller - - eventsource-parser@3.1.0: {} - - eventsource@3.0.7: - dependencies: - eventsource-parser: 3.1.0 - - execa@5.1.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - express-rate-limit@8.5.2(express@5.2.1): - dependencies: - express: 5.2.1 - ip-address: 10.2.0 - - express@5.2.1: - dependencies: - accepts: 2.0.0 - body-parser: 2.3.0 - content-disposition: 1.1.0 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.2.2 - debug: 4.4.3 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 2.1.1 - fresh: 2.0.0 - http-errors: 2.0.1 - merge-descriptors: 2.0.0 - mime-types: 3.0.2 - on-finished: 2.4.1 - once: 1.4.0 - parseurl: 1.3.3 - proxy-addr: 2.0.7 - qs: 6.15.3 - range-parser: 1.3.0 - router: 2.2.0 - send: 1.2.1 - serve-static: 2.2.1 - statuses: 2.0.2 - type-is: 2.1.0 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - - extend@3.0.2: {} - - fast-deep-equal@3.1.3: {} - - fast-fifo@1.3.2: {} - - fast-sha256@1.3.0: {} - - fast-uri@3.1.3: {} - - fetch-blob@3.2.0: - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.3.3 - - finalhandler@2.1.1: - dependencies: - debug: 4.4.3 - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - - formdata-polyfill@4.0.10: - dependencies: - fetch-blob: 3.2.0 - - forwarded@0.2.0: {} - - fresh@2.0.0: {} - - function-bind@1.1.2: {} - - gaxios@7.1.5: - dependencies: - extend: 3.0.2 - https-proxy-agent: 7.0.6 - node-fetch: 3.3.2 - transitivePeerDependencies: - - supports-color - - gcp-metadata@8.1.2: - dependencies: - gaxios: 7.1.5 - google-logging-utils: 1.1.3 - json-bigint: 1.0.0 - transitivePeerDependencies: - - supports-color - - get-east-asian-width@1.6.0: {} - - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.2 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.4 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.2 - - get-stream@6.0.1: {} - - glob@13.0.6: - dependencies: - minimatch: 10.2.5 - minipass: 7.1.3 - path-scurry: 2.0.2 - - google-auth-library@10.9.0: - dependencies: - base64-js: 1.5.1 - ecdsa-sig-formatter: 1.0.11 - gaxios: 7.1.5 - gcp-metadata: 8.1.2 - google-logging-utils: 1.1.3 - jws: 4.0.1 - transitivePeerDependencies: - - supports-color - - google-logging-utils@1.1.3: {} - - gopd@1.2.0: {} - - graceful-fs@4.2.11: {} - - has-symbols@1.1.0: {} - - hasown@2.0.4: - dependencies: - function-bind: 1.1.2 - - highlight.js@10.7.3: {} - - hono@4.12.27: {} - - hosted-git-info@9.0.3: - dependencies: - lru-cache: 11.5.1 - - http-errors@2.0.1: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.2 - toidentifier: 1.0.1 - - http-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - https-proxy-agent@7.0.6: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - human-signals@2.1.0: {} - - iconv-lite@0.7.3: - dependencies: - safer-buffer: 2.1.2 - - ignore@7.0.5: {} - - inherits@2.0.4: {} - - ip-address@10.2.0: {} - - ipaddr.js@1.9.1: {} - - is-promise@4.0.0: {} - - is-stream@2.0.1: {} - - isexe@2.0.0: {} - - jiti@2.7.0: {} - - jose@5.10.0: {} - - jose@6.2.3: {} - - json-bigint@1.0.0: - dependencies: - bignumber.js: 9.3.1 - - json-schema-to-ts@3.1.1: - dependencies: - '@babel/runtime': 7.29.7 - ts-algebra: 2.0.0 - - json-schema-traverse@1.0.0: {} - - json-schema-typed@8.0.2: {} - - jsonlines@0.1.1: {} - - jwa@2.0.1: - dependencies: - buffer-equal-constant-time: 1.0.1 - ecdsa-sig-formatter: 1.0.11 - safe-buffer: 5.2.1 - - jws@4.0.1: - dependencies: - jwa: 2.0.1 - safe-buffer: 5.2.1 - - long@5.3.2: {} - - lru-cache@11.5.1: {} - - marked@18.0.5: {} - - math-intrinsics@1.1.0: {} - - media-typer@1.1.0: {} - - merge-descriptors@2.0.0: {} - - merge-stream@2.0.0: {} - - mime-db@1.54.0: {} - - mime-types@3.0.2: - dependencies: - mime-db: 1.54.0 - - mimic-fn@2.1.0: {} - - minimatch@10.2.5: - dependencies: - brace-expansion: 5.0.7 - - minipass@7.1.3: {} - - minizlib@3.1.0: - dependencies: - minipass: 7.1.3 - - ms@2.1.3: {} - - negotiator@1.0.0: {} - - node-domexception@1.0.0: {} - - node-fetch@3.3.2: - dependencies: - data-uri-to-buffer: 4.0.1 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - object-assign@4.1.1: {} - - object-inspect@1.13.4: {} - - on-finished@2.4.1: - dependencies: - ee-first: 1.1.1 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - openai@6.26.0(ws@8.21.0)(zod@4.4.3): - optionalDependencies: - ws: 8.21.0 - zod: 4.4.3 - - os-paths@4.4.0: {} - - p-retry@4.6.2: - dependencies: - '@types/retry': 0.12.0 - retry: 0.13.1 - - parseurl@1.3.3: {} - - partial-json@0.1.7: {} - - path-key@3.1.1: {} - - path-scurry@2.0.2: - dependencies: - lru-cache: 11.5.1 - minipass: 7.1.3 - - path-to-regexp@8.4.2: {} - - picocolors@1.1.1: {} - - pkce-challenge@5.0.1: {} - - proper-lockfile@4.1.2: - dependencies: - graceful-fs: 4.2.11 - retry: 0.12.0 - signal-exit: 3.0.7 - - protobufjs@7.6.5: - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.5 - '@protobufjs/eventemitter': 1.1.1 - '@protobufjs/fetch': 1.1.1 - '@protobufjs/float': 1.0.2 - '@protobufjs/path': 1.1.2 - '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.1 - '@types/node': 26.1.0 - long: 5.3.2 - - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - - qs@6.15.3: - dependencies: - es-define-property: 1.0.1 - side-channel: 1.1.1 - - range-parser@1.3.0: {} - - raw-body@3.0.2: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.1 - iconv-lite: 0.7.3 - unpipe: 1.0.0 - - require-from-string@2.0.2: {} - - retry@0.12.0: {} - - retry@0.13.1: {} - - router@2.2.0: - dependencies: - debug: 4.4.3 - depd: 2.0.0 - is-promise: 4.0.0 - parseurl: 1.3.3 - path-to-regexp: 8.4.2 - transitivePeerDependencies: - - supports-color - - safe-buffer@5.2.1: {} - - safer-buffer@2.1.2: {} - - semver@7.8.0: {} - - send@1.2.1: - dependencies: - debug: 4.4.3 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 2.0.0 - http-errors: 2.0.1 - mime-types: 3.0.2 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.3.0 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - - serve-static@2.2.1: - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 1.2.1 - transitivePeerDependencies: - - supports-color - - setprototypeof@1.2.0: {} - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - side-channel-list@1.0.1: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.1: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.1 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - signal-exit@3.0.7: {} - - standardwebhooks@1.0.0: - dependencies: - '@stablelib/base64': 1.0.1 - fast-sha256: 1.3.0 - - statuses@2.0.2: {} - - streamx@2.28.0: - dependencies: - events-universal: 1.0.1 - fast-fifo: 1.3.2 - text-decoder: 1.2.7 - transitivePeerDependencies: - - bare-abort-controller - - react-native-b4a - - strip-final-newline@2.0.0: {} - - tar-stream@3.1.7: - dependencies: - b4a: 1.8.1 - fast-fifo: 1.3.2 - streamx: 2.28.0 - transitivePeerDependencies: - - bare-abort-controller - - react-native-b4a - - tar@7.5.19: - dependencies: - '@isaacs/fs-minipass': 4.0.1 - chownr: 3.0.0 - minipass: 7.1.3 - minizlib: 3.1.0 - yallist: 5.0.0 - - text-decoder@1.2.7: - dependencies: - b4a: 1.8.1 - transitivePeerDependencies: - - react-native-b4a - - toidentifier@1.0.1: {} - - ts-algebra@2.0.0: {} - - tslib@2.8.1: {} - - type-is@2.1.0: - dependencies: - content-type: 2.0.0 - media-typer: 1.1.0 - mime-types: 3.0.2 - - typebox@1.1.38: {} - - undici-types@8.3.0: {} - - undici@7.28.0: {} - - undici@8.5.0: {} - - unpipe@1.0.0: {} - - vary@1.1.2: {} - - web-streams-polyfill@3.3.3: {} - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - wrappy@1.0.2: {} - - ws@8.21.0: {} - - xdg-app-paths@5.1.0: - dependencies: - xdg-portable: 7.3.0 - - xdg-app-paths@5.5.1: - dependencies: - os-paths: 4.4.0 - xdg-portable: 7.3.0 - - xdg-portable@7.3.0: - dependencies: - os-paths: 4.4.0 - - yallist@5.0.0: {} - - yaml@2.9.0: {} - - zod-to-json-schema@3.25.2(zod@4.4.3): - dependencies: - zod: 4.4.3 - - zod@3.24.4: {} - - zod@4.1.11: {} - - zod@4.4.3: {} diff --git a/.deepsec/pnpm-workspace.yaml b/.deepsec/pnpm-workspace.yaml deleted file mode 100644 index 3334c0e4395f..000000000000 --- a/.deepsec/pnpm-workspace.yaml +++ /dev/null @@ -1 +0,0 @@ -packages: [] diff --git a/.github/workflows/deepsec.yml b/.github/workflows/deepsec.yml deleted file mode 100644 index 4819e9e389da..000000000000 --- a/.github/workflows/deepsec.yml +++ /dev/null @@ -1,152 +0,0 @@ -name: deepsec - -# AI security/bug review of the PR diff, gated on the `deepsec` label. -# Advisory only: findings are posted as a PR comment and never block merge. -# Runs once when the label is added (re-add the label to re-run). - -on: - pull_request: - types: [labeled] - -permissions: - contents: read - -concurrency: - group: deepsec-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - analyze: - if: >- - github.event.label.name == 'deepsec' && - github.event.pull_request.head.repo.full_name == github.repository - runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: - contents: read - outputs: - has_comment: ${{ steps.deepsec.outputs.has_comment }} - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 # need history so `git diff origin/` resolves - persist-credentials: false # PR code must not inherit the repo token - - - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - with: - # pnpm version comes from `packageManager`, which lives in the - # deepsec workspace's package.json, not the repo root one. - package_json_file: .deepsec/package.json - - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: 24 - cache: pnpm - cache-dependency-path: .deepsec/pnpm-lock.yaml - - - name: Install deepsec - working-directory: .deepsec - run: pnpm install --frozen-lockfile - - - name: Install Claude Code CLI (pinned) - run: npm install -g @anthropic-ai/claude-code@2.1.201 - - - name: Run deepsec on the PR diff - id: deepsec - working-directory: .deepsec - env: - # Direct Anthropic API. The secret holds a plain API key, so it - # must go through ANTHROPIC_API_KEY (x-api-key header) — feeding - # it to the ANTHROPIC_AUTH_TOKEN env var sends `Authorization: - # Bearer`, which api.anthropic.com 401s for non-OAuth keys. - # deepsec forwards ANTHROPIC_API_KEY to the Claude Code SDK. - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_AUTH_TOKEN }} - # Pin the provider endpoint so PR-added env files can't redirect - # provider traffic and exfiltrate the credential. - ANTHROPIC_BASE_URL: https://api.anthropic.com - CLAUDE_CODE_EXECUTABLE: claude - # Env indirection so the ref is never spliced into the shell text - # (ref names may contain `$(...)` — Actions script-injection sink). - PR_BASE_REF: ${{ github.event.pull_request.base.ref }} - run: | - # Drop any PR-supplied env file before it can override the pinned base URL. - rm -f .env.local .env*.local - # Advisory gate: never fail the job on findings (would block merge via - # all-checks-pass). deepsec exit codes overlap, so disambiguate by output: - # 0 -> clean review, no findings - # 1 + comment.md -> net-new findings (post them, stay green) - # 1 + no comment.md -> agent/batch failure (warn, stay green — not a clean pass) - # >1 -> hard runtime error (bad input / missing creds) -> fail - set +e - pnpm deepsec process \ - --agent claude \ - --diff "origin/${PR_BASE_REF}" \ - --project-id analytics \ - --root .. \ - --concurrency 5 \ - --max-turns 30 \ - --comment-out ../comment.md - code=$? - set -e - if [ "$code" -gt 1 ]; then - echo "deepsec exited with runtime error code $code" - exit "$code" - fi - if [ -f ../comment.md ]; then - echo "has_comment=true" >> "$GITHUB_OUTPUT" - else - echo "has_comment=false" >> "$GITHUB_OUTPUT" - if [ "$code" -eq 1 ]; then - echo "::warning title=deepsec::Agent/batch failure (exit 1, no findings emitted) — review was not completed. Re-run by re-applying the label." - fi - fi - - - name: Upload comment artifact - if: steps.deepsec.outputs.has_comment == 'true' - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 - with: - name: deepsec-comment - path: comment.md - retention-days: 1 - - # The PR comment truncates each finding (600-char description / - # 400-char recommendation). Export the full, untruncated findings - # as per-finding markdown and attach them to the run so reviewers - # can read the complete analysis without a local re-run. - - name: Export full findings (untruncated) - if: steps.deepsec.outputs.has_comment == 'true' - working-directory: .deepsec - run: pnpm deepsec export --format md-dir --out ../findings --project-id analytics - - - name: Upload full findings artifact - if: steps.deepsec.outputs.has_comment == 'true' - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 - with: - name: deepsec-findings - path: findings/ - retention-days: 14 - - comment: - needs: analyze - if: needs.analyze.outputs.has_comment == 'true' - runs-on: ubuntu-latest - timeout-minutes: 5 - permissions: - pull-requests: write - steps: - - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - with: - name: deepsec-comment - - - uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 - with: - script: | - const fs = require('fs'); - const body = fs.readFileSync('comment.md', 'utf8'); - const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; - const header = `🔎 **deepsec** reviewed \`${context.payload.pull_request.head.sha}\` · findings below are truncated — [full findings artifact](${runUrl}#artifacts)\n\n`; - await github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: header + body, - });