diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index 125473ac34..f9c770cd4b 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -56,8 +56,21 @@ jobs:
run: bun scripts/lint/no-unauth-routes.ts
- name: Check unsafe type casts
run: bun check:casts:strict
- - name: Check types
+ # Two type-check passes, deliberately. `bun check-types` runs a single
+ # root `tsc` over the shared React-Native/web/node program (jsx:
+ # react-native, lib DOM+ESNext). That program structurally CANNOT house
+ # packages with a different global type environment — Cloudflare Workers
+ # packages (packages/mcp: @cloudflare/workers-types, no DOM) and the
+ # @kitajs/html JSX package (packages/consent-ui: global JSX namespace) —
+ # so those, plus osm-db/osm-import/overpass, are excluded from the root
+ # tsconfig. `bun check-types:packages` (turbo) then type-checks EVERY
+ # package under its OWN tsconfig, closing that gap. Both must stay: the
+ # root pass catches cross-package program errors, the turbo pass catches
+ # per-package errors the root program can't see (e.g. MCP, #2533).
+ - name: Check types (root tsc — shared RN/web/node program)
run: bun check-types
+ - name: Check types (per-package — turbo, each tsconfig)
+ run: bun check-types:packages
- name: Run Expo Doctor
run: bunx expo-doctor
working-directory: apps/expo
diff --git a/.gitignore b/.gitignore
index b1dcf6f57f..dad434b0c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,4 +53,7 @@ apps/guides/public/og/
# Git worktrees
.worktrees/
.worktrees
+
+# Cloudflare wrangler local state (dev/test artifacts)
+.wrangler/
.turbo/
diff --git a/CLAUDE.md b/CLAUDE.md
index d66e54c70b..f9303ab88d 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -158,28 +158,33 @@ Sentry.addBreadcrumb({ category: 'feature', message: 'Action started', level: 'i
- **Better Auth errors** (plain objects with `{ message, status, code }`) are not JS Errors. Use `toAuthError` from `expo-app/features/auth/lib/authErrors` to convert them into an `AuthClientError` that carries `status` and `code`. Capture and throw that — do not create a separate synthetic error for Sentry and another for throwing.
- Include `httpStatus` and `errorCode` in `extra` for any HTTP error so they're searchable in Sentry.
-**API / Cloudflare Workers** — use helpers from `@packrat/api/utils/sentry`:
+**API / Cloudflare Workers** — helpers from `@packrat/api/utils/sentry`. There are **three boundaries by where code runs** — match the tier to the situation instead of wrapping everything in try/catch:
-```ts
-import { apiAddBreadcrumb, captureApiException } from '@packrat/api/utils/sentry';
+1. **Route handlers → do nothing.** Elysia's global `.onError` (`src/app.ts`) is the central sink: it reports unexpected errors (skips `VALIDATION`/`PARSE`/`NOT_FOUND`), tagged by the matched **route template** + `request_id`. Let errors propagate — don't add a try/catch *just* to report. Only catch in a route to **translate** an error into a specific response (and then it's a swallow — see tier 3).
-// Breadcrumb before significant async steps
-apiAddBreadcrumb({ category: 'feature', message: 'Fetching external data', level: 'info' });
+2. **Sub-operations you rethrow from → wrap in `record`.** Workflow `step.do` bodies, queue/cron consumers, and services called outside an Elysia request. It opens a Sentry span (OTel-semantic, Workers-native) **and** captures-with-context **and** rethrows:
-// In every catch block
-} catch (error) {
- captureApiException(error, {
- operation: 'featureName.action',
- userId,
- tags: { feature: 'myFeature' },
- extra: { relevantId },
- });
- throw error; // or return an error response
-}
-```
+ ```ts
+ import { record } from '@packrat/api/utils/sentry';
+
+ await record({ operation: 'etl.processLogsBatch', extra: { jobId } }, async () => {
+ await db.insert(logs).values(rows);
+ });
+ ```
+
+3. **Catches that swallow → call `captureApiException`** (object signature). Fail-closed `return false`, best-effort metrics, per-item loops that continue, route catches that return an error response:
+
+ ```ts
+ } catch (error) {
+ captureApiException({ error, operation: 'verifyAdmin', extra: { userId } });
+ return false; // swallowed — nothing to rethrow
+ }
+ ```
-- Use `captureApiException` (not raw `captureException`) — it wraps the call with structured operation context and also logs to console for wrangler dev output.
-- Every route `catch` block and service method that interacts with the DB or an external API must have a `captureApiException` call.
+- Capture is **idempotent + deduped** (a marker is stamped on the error), so `record`/`captureApiException` + the outer boundary (`.onError`, `withSentry`, `instrumentWorkflowWithSentry`) never double-report — enrich-and-rethrow is always safe.
+- Every event in a request shares a **`request_id`** tag (`cf-ray`, set in `.onRequest`), echoed in the `X-Request-Id` response header — pivot on it to tie an `.onError` report to the granular `record`/`captureApiException` events. Sentry's automatic `trace_id` correlates them too.
+- Don't use raw `captureException` — the wrappers add operation context + console logging. Include `httpStatus`/`errorCode` in `extra` for HTTP errors; breadcrumb significant steps with `apiAddBreadcrumb`.
+- **Not** `@elysiajs/opentelemetry`: its Node OTel SDK doesn't run on workerd (BatchSpanProcessor, AsyncHooks). `record` gives the same `record(name, fn)` ergonomics on Sentry's Workers-native tracer.
### API Client (`@packrat/api-client`)
diff --git a/apps/admin/lib/api.ts b/apps/admin/lib/api.ts
index e2d0ff9273..fe267c4bdf 100644
--- a/apps/admin/lib/api.ts
+++ b/apps/admin/lib/api.ts
@@ -1,5 +1,5 @@
import { treaty } from '@elysiajs/eden';
-import type { App } from '@packrat/api';
+import type { App } from '@packrat/api-client';
import { isObject } from '@packrat/guards';
import type {
ActiveUsers,
diff --git a/apps/admin/tsconfig.json b/apps/admin/tsconfig.json
index d5ada533c2..2c9485bba6 100644
--- a/apps/admin/tsconfig.json
+++ b/apps/admin/tsconfig.json
@@ -5,7 +5,6 @@
"@packrat/app": ["../../packages/app/src/index.ts"],
"@packrat/app/*": ["../../packages/app/src/*"],
"admin-app/*": ["./*"],
- "@packrat/api/*": ["../../packages/api/src/*"],
"@packrat/guards": ["../../packages/guards/src"],
"@packrat/guards/*": ["../../packages/guards/src/*"],
"@packrat/web-ui": ["../../packages/web-ui/src"],
diff --git a/apps/expo/package.json b/apps/expo/package.json
index 4f21cfa262..26cfe4f483 100644
--- a/apps/expo/package.json
+++ b/apps/expo/package.json
@@ -54,7 +54,6 @@
"@gorhom/bottom-sheet": "^5.1.2",
"@legendapp/state": "^3.0.0-beta.30",
"@packrat-ai/nativewindui": "2.0.6",
- "@packrat/api": "workspace:*",
"@packrat/api-client": "workspace:*",
"@packrat/config": "workspace:*",
"@packrat/constants": "workspace:*",
diff --git a/apps/expo/tsconfig.json b/apps/expo/tsconfig.json
index 9dc5ceffb1..f0a2f02b03 100644
--- a/apps/expo/tsconfig.json
+++ b/apps/expo/tsconfig.json
@@ -7,8 +7,6 @@
"baseUrl": ".",
"paths": {
"expo-app/*": ["./*"],
- "@packrat/api": ["../../packages/api/src/index.ts"],
- "@packrat/api/*": ["../../packages/api/src/*"],
"@packrat/api-client": ["../../packages/api-client/src/index.ts"],
"@packrat/api-client/*": ["../../packages/api-client/src/*"]
}
diff --git a/apps/expo/vitest.types.config.ts b/apps/expo/vitest.types.config.ts
index 7129ed48f6..30faf776f3 100644
--- a/apps/expo/vitest.types.config.ts
+++ b/apps/expo/vitest.types.config.ts
@@ -5,7 +5,6 @@ export default defineConfig({
resolve: {
alias: {
'expo-app': resolve(__dirname, '.'),
- '@packrat/api': resolve(__dirname, '../../packages/api/src/index.ts'),
'@packrat/api-client': resolve(__dirname, '../../packages/api-client/src/index.ts'),
},
},
diff --git a/apps/guides/lib/enhanceGuideContent.ts b/apps/guides/lib/enhanceGuideContent.ts
index 0e4dbc3876..29aec0ac04 100644
--- a/apps/guides/lib/enhanceGuideContent.ts
+++ b/apps/guides/lib/enhanceGuideContent.ts
@@ -1,6 +1,6 @@
import { openai } from '@ai-sdk/openai';
import { treaty } from '@elysiajs/eden';
-import type { App } from '@packrat/api';
+import type { App } from '@packrat/api-client';
import { guideEnv } from '@packrat/env/next';
import { generateText, tool } from 'ai';
import { z } from 'zod';
diff --git a/apps/guides/package.json b/apps/guides/package.json
index 7838235f2e..0853ca5319 100644
--- a/apps/guides/package.json
+++ b/apps/guides/package.json
@@ -27,7 +27,7 @@
"@ai-sdk/openai": "catalog:",
"@elysiajs/eden": "catalog:",
"@hookform/resolvers": "catalog:",
- "@packrat/api": "workspace:*",
+ "@packrat/api-client": "workspace:*",
"@packrat/env": "workspace:*",
"@packrat/guards": "workspace:*",
"@packrat/schemas": "workspace:*",
diff --git a/apps/landing/__tests__/legal.pages.test.ts b/apps/landing/__tests__/legal.pages.test.ts
new file mode 100644
index 0000000000..6e48439e5c
--- /dev/null
+++ b/apps/landing/__tests__/legal.pages.test.ts
@@ -0,0 +1,123 @@
+/**
+ * Smoke tests for the legal pages (U12 of the MCP connector-store readiness
+ * plan).
+ *
+ * The landing app uses Next.js with `output: 'export'` and a node-environment
+ * vitest setup (see `vitest.config.ts`). React-server-component imports don't
+ * resolve cleanly in that env, so the route-level "GET returns 200 with this
+ * string" test the og-meta suite performs (against the built `out/` HTML)
+ * would be the only true smoke pattern. We don't run a full Next build inside
+ * this suite to keep it fast; instead, the assertions below operate on the
+ * source `.tsx` files for the two legal pages and on the shared
+ * `config/site.ts` block that wires them up.
+ *
+ * What we verify:
+ * - The Terms of Service page source exists, exports the standard metadata
+ * shape, and contains the load-bearing MCP, jurisdiction-TODO, and
+ * hello@packratai.com strings a reviewer will scan for.
+ * - The Privacy Policy page source contains the new MCP / connectors
+ * addendum (heading + key bullet content).
+ * - `siteConfig.footerLinks.legal` exposes BOTH Privacy and Terms, and
+ * `siteConfig.support` advertises the canonical mailto.
+ *
+ * If a route smoke pattern lands later (e.g. happy-dom env + RSC eval, or
+ * a separate `vitest --config out-export.config.ts` workspace), the
+ * file-text assertions can be replaced — the reviewer-facing intent is the
+ * stable contract.
+ */
+import { existsSync, readFileSync } from 'node:fs';
+import { resolve } from 'node:path';
+import { describe, expect, it } from 'vitest';
+import { siteConfig } from '../config/site';
+
+const APP_DIR = resolve(__dirname, '..');
+const TOS_PAGE = resolve(APP_DIR, 'app/terms-of-service/page.tsx');
+const PRIVACY_PAGE = resolve(APP_DIR, 'app/privacy-policy/page.tsx');
+
+describe('Terms of Service page (/terms-of-service)', () => {
+ it('source file exists', () => {
+ expect(existsSync(TOS_PAGE)).toBe(true);
+ });
+
+ const source = existsSync(TOS_PAGE) ? readFileSync(TOS_PAGE, 'utf8') : '';
+
+ it('exports a Next.js metadata block with title/description/robots', () => {
+ expect(source).toContain('export const metadata');
+ expect(source).toContain("title: 'Terms of Service | PackRat'");
+ expect(source).toMatch(/description:\s*'[^']+'/);
+ expect(source).toMatch(/robots:\s*\{[^}]*index:\s*true/);
+ });
+
+ it('renders the "Terms of Service" heading', () => {
+ expect(source).toContain('>Terms of Service<');
+ });
+
+ it('covers MCP connector provisions', () => {
+ // Reviewers grep for "MCP" — this section is the new content this unit
+ // ships and is what Anthropic's policy expects to find.
+ expect(source).toMatch(/MCP/);
+ expect(source).toContain('mcp.packratai.com');
+ expect(source).toMatch(/mcp:admin/);
+ expect(source).toMatch(/OAuth/);
+ });
+
+ it('includes the outdoor-safety disclaimer', () => {
+ expect(source).toMatch(/inherent risks/i);
+ });
+
+ it('surfaces the canonical support contact', () => {
+ expect(source).toContain('hello@packratai.com');
+ });
+
+ it('leaves the operator-jurisdiction TODO marker in place', () => {
+ // U12 deliberately ships with a placeholder jurisdiction (Delaware) and a
+ // TODO so the operator can replace it after legal review. The check
+ // prevents the TODO from being silently lost in a future edit.
+ expect(source).toMatch(/TODO\(operator\): set jurisdiction/);
+ });
+});
+
+describe('Privacy Policy page (/privacy-policy) — MCP addendum', () => {
+ it('source file exists', () => {
+ expect(existsSync(PRIVACY_PAGE)).toBe(true);
+ });
+
+ const source = existsSync(PRIVACY_PAGE) ? readFileSync(PRIVACY_PAGE, 'utf8') : '';
+
+ it('renders the new "MCP Connector & Third-Party Clients" section heading', () => {
+ expect(source).toContain('MCP Connector & Third-Party Clients');
+ });
+
+ it('explains OAuth token storage and rotation', () => {
+ expect(source).toMatch(/refresh token/i);
+ expect(source).toMatch(/Cloudflare KV/);
+ expect(source).toMatch(/60 minutes/);
+ });
+
+ it('clarifies what MCP clients do NOT see', () => {
+ expect(source).toMatch(/never sees your\s+PackRat password|never sees your password/i);
+ expect(source).toMatch(/conversation content/i);
+ });
+
+ it('points users at hello@packratai.com for deletion', () => {
+ expect(source).toContain('hello@packratai.com');
+ });
+});
+
+describe('siteConfig wiring (U12)', () => {
+ it('exposes BOTH Privacy and Terms in the footer legal block', () => {
+ const titles = siteConfig.footerLinks.legal.map((l) => l.title);
+ expect(titles).toContain('Privacy');
+ expect(titles).toContain('Terms');
+
+ const hrefs = siteConfig.footerLinks.legal.map((l) => l.href);
+ expect(hrefs).toContain('/privacy-policy');
+ expect(hrefs).toContain('/terms-of-service');
+ });
+
+ it('exposes the canonical support contact', () => {
+ expect(siteConfig.support).toBeDefined();
+ expect(siteConfig.support.email).toBe('hello@packratai.com');
+ expect(siteConfig.support.mailto).toBe('mailto:hello@packratai.com');
+ });
+});
diff --git a/apps/landing/__tests__/mcp.page.test.ts b/apps/landing/__tests__/mcp.page.test.ts
new file mode 100644
index 0000000000..2a1b1b0d30
--- /dev/null
+++ b/apps/landing/__tests__/mcp.page.test.ts
@@ -0,0 +1,131 @@
+/**
+ * Smoke tests for the MCP public docs page (U13).
+ *
+ * Same vitest-against-source approach as `legal.pages.test.ts`: the landing
+ * app uses Next.js `output: 'export'` and a node-only vitest env, so we
+ * can't import the RSC route directly. Assertions operate on the page
+ * source plus the generated `mcp-catalog.json` to verify reviewer-facing
+ * invariants the connector-store submission will be evaluated against.
+ *
+ * What we verify:
+ * - The page source exists, exports the standard metadata shape with
+ * `robots.index: true` (Anthropic must be able to crawl the docs URL).
+ * - The Quickstart / Scopes / Example prompts / Tool catalog / Resources
+ * / Privacy & security / Reviewer test account sections all render.
+ * - Three example prompts appear (per Software Directory Policy).
+ * - The Claude.ai custom-connector install URL is exactly the production
+ * MCP endpoint string.
+ * - `mcp-catalog.json` is present and non-trivial — the page renders
+ * from it, so a missing or empty JSON would surface as a build-time
+ * RSC error in production.
+ */
+
+import { existsSync, readFileSync } from 'node:fs';
+import { resolve } from 'node:path';
+import { describe, expect, it } from 'vitest';
+
+const APP_DIR = resolve(__dirname, '..');
+const PAGE = resolve(APP_DIR, 'app/mcp/page.tsx');
+const CATALOG = resolve(APP_DIR, 'data/mcp-catalog.json');
+
+describe('MCP public docs page (/mcp)', () => {
+ it('source file exists', () => {
+ expect(existsSync(PAGE)).toBe(true);
+ });
+
+ const source = existsSync(PAGE) ? readFileSync(PAGE, 'utf8') : '';
+
+ it('exports a Next.js metadata block (indexable)', () => {
+ expect(source).toContain('export const metadata');
+ expect(source).toMatch(/title:\s*'PackRat MCP Connector \| PackRat'/);
+ expect(source).toMatch(/robots:\s*\{\s*index:\s*true/);
+ });
+
+ it('renders the hero heading', () => {
+ expect(source).toMatch(/Plan trips, build packs, check weather/);
+ });
+
+ it('exposes the production MCP endpoint URL verbatim', () => {
+ // The submission packet, the public docs page, and the worker's
+ // resourceMetadata MUST all advertise the same URL. A diff here is the
+ // canary on a drift that breaks Anthropic's audience verification.
+ expect(source).toContain('https://mcp.packratai.com/mcp');
+ });
+
+ it('lists the three OAuth scopes', () => {
+ // Sourced from the JSON dump at render time, but the header / table
+ // copy refers to them inline; the smoke test asserts both.
+ for (const scope of ['mcp:read', 'mcp:write', 'mcp:admin']) {
+ expect(source).toContain(scope);
+ }
+ });
+
+ it('uses the Anthropic "custom connector" terminology', () => {
+ expect(source).toMatch(/custom connector/i);
+ });
+
+ it('ships ≥ 3 example prompts (Software Directory Policy)', () => {
+ // Each example prompt is wrapped in a
+ Plan trips, build packs, check weather — from any MCP client.
+
+
+ PackRat runs a Model Context Protocol server at{' '}
+ mcp.packratai.com. Connect Claude or any MCP-capable
+ client, sign in with your PackRat account, and use natural language to manage your gear,
+ plan trips, check conditions, and post to your feed.
+
+ Claude redirects you to PackRat to sign in.{' '}
+
+ You'll briefly see api.packrat.world in your
+ browser address bar
+ {' '}
+ — that's our authorization server, hosted on a separate origin from the MCP
+ endpoint for security (a standard OAuth 2.1 + PKCE split-host pattern). Sign in with
+ your PackRat account, or create one at{' '}
+
+ packratai.com
+
+ .
+
+
+ Approve the requested scopes on the consent screen. Claude requests{' '}
+ mcp:read and{' '}
+ mcp:write by default. You can approve all, deny, or
+ (in a future release) approve a subset. mcp:admin is
+ only granted server-side based on your PackRat user role — non-admins never see it
+ offered.
+
+
+ You're returned to Claude.ai. The connector is now installed and the tool catalog
+ is loaded.
+
+
+
+ Tokens are short-lived (60 minutes) and refresh automatically. Revoke the connection at
+ any time from your PackRat account settings or by emailing{' '}
+
+ hello@packratai.com
+
+ .
+
+
+
+ If your install fails…
+
+
+ The cross-origin install above depends on Claude.ai's OAuth discovery client
+ correctly following the link from the MCP resource server to the authorization
+ server. A handful of failure modes can show up:
+
+
+
+
+ “Could not connect” or a CORS error in the browser console.
+ {' '}
+ The browser blocked Claude's probe of the authorization-server metadata.
+ Verify api.packrat.world is reachable from your network and not
+ filtered by a corporate proxy / VPN.
+
+
+ Sign-in succeeds but you bounce back to Claude with an error.{' '}
+ Some browser extensions strip the Authorization header on
+ cross-origin redirects. Try a fresh browser profile or disable third-party cookie
+ restrictions for claude.ai + api.packrat.world.
+
+
+ The consent screen shows the wrong client name. Claude.ai has
+ been pre-registered with the AS, so “Claude” should appear as the
+ requesting app. If you see unknown or a different name, the install
+ is pointed at the wrong URL — confirm you pasted{' '}
+ https://mcp.packratai.com/mcp exactly.
+
+
+ Tools work for ~60 minutes then stop. Refresh-token rotation
+ failed. Remove the connector in Claude.ai's settings and re-add it; if it
+ recurs, email{' '}
+
+ hello@packratai.com
+ {' '}
+ with the timestamp and we'll check the AS logs.
+
+
+
+ Operators: deeper failure modes (including the reverse-proxy fallback for
+ cross-origin AS issues) are in{' '}
+
+ docs/mcp/runbook.md § Post-refactor dev verification
+
+ .
+
+ PackRat advertises four coarse-grained scopes. Claude.ai requests{' '}
+ mcp:read + mcp:write{' '}
+ by default; mcp:admin is only granted to PackRat admin
+ users and is the gate for destructive admin tooling.
+
+ Three prompts to try after connecting. Each exercises a different tool surface — a
+ read-only query, a multi-tool plan, and a write that triggers an elicitation
+ confirmation.
+
+
+
+
+ Read-only · packs & gear comparison
+
+
+ “What's in my Big 3 right now? Suggest one swap to drop a pound.”
+
+
+ Exercises packrat_list_packs,{' '}
+ packrat_list_pack_items,{' '}
+ packrat_compare_gear_items. Claude reads your current
+ pack, finds the three heaviest items (shelter, sleep, pack), and proposes a single
+ lighter substitute from the gear catalog.
+
+
+
+
+
+ Multi-tool plan · trip + weather + trail status + pack
+
+
+ “Plan a 3-day trip to the Wind River Range next weekend; build the pack, check
+ the weather, and flag any trail closures.”
+
+
+ Exercises packrat_search_trails,{' '}
+ packrat_get_weather,{' '}
+ packrat_list_my_trail_reports,{' '}
+ packrat_create_trip,{' '}
+ packrat_create_pack. Claude composes a trip with the
+ right gear for the forecast and surfaces any user-reported closures along the route.
+
+
+
+
+
+ Write with elicitation · TikTok URL → personal pack template
+
+
+ “Find a TikTok ultralight loadout I saw at <url> and import it as a
+ personal template.”
+
+
+ Exercises packrat_extract_url_content and{' '}
+ packrat_generate_pack_template_from_url (admin-only —
+ for non-admin users, Claude falls back to{' '}
+ packrat_create_pack_template). The tool triggers an
+ MCP elicitation asking you to type{' '}
+ GENERATE before importing — this is the
+ user-confirmation pattern Anthropic's reviewers should see firing on
+ high-blast-radius writes.
+
+ The connector exposes {typedCatalog.totalTools} tools grouped into{' '}
+ {grouped.length} domains: {counts.read} read-only, {counts.write} write, {counts.admin}{' '}
+ admin. Each tool carries explicit MCP annotations (
+ readOnlyHint,{' '}
+ destructiveHint,{' '}
+ idempotentHint,{' '}
+ openWorldHint) so Claude can surface the right
+ confirmation prompts.
+
+
+ Catalog list views and resource lists are capped at 25 items to keep context lean; reach
+ deeper with packrat_search_gear_catalog /{' '}
+ packrat_semantic_gear_search.
+
+
+ Catalog generated {new Date(typedCatalog.generatedAt).toISOString().slice(0, 10)} from
+ the live registration code — see{' '}
+ packages/mcp/scripts/dump-catalog.ts.
+
+ PackRat publishes six MCP resources alongside the tool catalog. Templated resources
+ carry list providers so MCP clients can enumerate the signed-in user's data via{' '}
+ resources/list without guessing IDs.
+
+
+
+ packrat://packs/{packId} — a pack and its items. List provider
+ returns the user's packs.
+
+
+ packrat://trips/{tripId} — a trip's plan, destination, and
+ dates. List provider returns the user's trips.
+
+
+ packrat://catalog/{itemId} — a gear catalog item. List provider
+ returns the first 25 items (use packrat_search_gear_catalog for deeper
+ access).
+
+
+ packrat://catalog/categories — the gear category tree.
+
+
+ packrat://search?q={query} — free-text query against the gear
+ catalog.
+
+
+ packrat://glossary — domain vocabulary (pack/trip/weight/trail/scope
+ terms) as markdown. Reading this once at session start saves Claude tool calls
+ re-learning terminology.
+
+ Tokens. OAuth access tokens are short-lived JWTs (60 minutes) signed
+ by our authorization server on api.packrat.world.
+ Refresh tokens last 30 days and rotate on every use. Token state is held on the
+ authorization-server side; the MCP endpoint itself is stateless and verifies tokens
+ against the AS's public JWKS.
+
+
+ Passwords. Your PackRat password is never visible to the MCP client;
+ sign-in happens entirely on api.packrat.world and
+ only an opaque OAuth code is returned to Claude.
+
+
+ Conversations. We do not log the conversation content you send to MCP
+ clients — only the tool calls those clients make against PackRat.
+
+
+ Audience-bound tokens. Per RFC 8707, every issued access token is
+ bound to https://mcp.packratai.com/mcp so a stolen
+ token can't be replayed against another service.
+
+
+
+ Read the full{' '}
+
+ MCP section of the privacy policy
+
+ , the{' '}
+
+ terms of service
+
+ , or email{' '}
+
+ hello@packratai.com
+ {' '}
+ for support.
+
+ Anthropic reviewers: test-account credentials are provided separately via the submission
+ form. The packet doc (docs/mcp/submission-packet.md in
+ the PackRat repo) lists what's populated in the account: a few packs with realistic
+ items, a sample multi-day trip, and a public feed post. First-run instructions are in
+ the same doc.
+
+ PackRat operates a Model Context Protocol (MCP) connector at{' '}
+ mcp.packratai.com that lets you connect MCP-capable
+ clients (for example, Claude.ai) to your PackRat account. This section explains how we
+ handle data on that surface.
+
+
+
+ OAuth tokens. When you connect an MCP client we store the OAuth
+ refresh token at rest in Cloudflare KV, which encrypts data at rest. Access tokens are
+ short-lived (60 minutes); refresh tokens last 30 days and rotate on use.
+
+
+ What the MCP client sees. Only the data the scopes you approved
+ authorize. mcp:read exposes read-only tools,{' '}
+ mcp:write adds create/update/delete, and{' '}
+ mcp:admin is granted only to PackRat admin users.
+
+
+ What the MCP client does NOT see. The MCP client never sees your
+ PackRat password — sign-in is handled directly by our authentication service. We do
+ not log the conversation content you send to MCP clients; we only see the tool calls
+ those clients make against PackRat.
+
+
+ Retention. OAuth grants are deleted automatically when the refresh
+ token expires, and immediately when you revoke the connection from your PackRat
+ account or by emailing us.
+
+
+ Third-party clients. When you connect a third-party MCP client (e.g.,
+ Claude.ai) to PackRat, that client's own privacy policy governs how it handles the
+ PackRat data it receives. We are not responsible for the data practices of MCP clients
+ we do not operate.
+
+
+ Deletion. To delete your PackRat account, or to revoke just the MCP
+ OAuth grants without deleting your account, use the account-settings flow in the app
+ or contact us at{' '}
+
+ hello@packratai.com
+
+ .
+
+
+
+
User Rights & Choices
Depending on your location, you may have the following rights:
diff --git a/apps/landing/app/terms-of-service/page.tsx b/apps/landing/app/terms-of-service/page.tsx
new file mode 100644
index 0000000000..28c2014b60
--- /dev/null
+++ b/apps/landing/app/terms-of-service/page.tsx
@@ -0,0 +1,232 @@
+/**
+ * Terms of Service — TEMPLATE pending legal review.
+ *
+ * This page is shipped to unblock the Claude Connector Store submission
+ * (Anthropic's Software Directory Policy treats a published ToS + Privacy
+ * Policy as a listing prerequisite). The copy is operator-drafted plain
+ * language, not bar-vetted legalese.
+ *
+ * Operator TODOs before treating this as authoritative:
+ * - Have counsel review every section, especially: limitation of liability,
+ * governing-law selection, MCP-connector provisions, age-of-eligibility,
+ * and the connector-driven-output disclaimer.
+ * - Set the governing jurisdiction in the "Governing law" section below
+ * (currently flagged with a TODO comment).
+ * - Decide whether the 16-and-up eligibility threshold matches your
+ * COPPA / GDPR-K obligations for users in regulated regions.
+ * - Confirm that the MCP-connector subsection accurately matches what the
+ * Worker currently does (scopes, rate limits, revocation path).
+ *
+ * If anything in here drifts from product behavior, fix the copy first,
+ * then re-version + re-publish.
+ */
+
+import Link from 'next/link';
+
+export const metadata = {
+ title: 'Terms of Service | PackRat',
+ description:
+ 'The terms that govern your use of PackRat, including outdoor adventure planning features and MCP connector access.',
+ // TEMPLATE pending legal review (see file header) — keep out of search
+ // indexes until counsel signs off and operator TODOs are resolved.
+ robots: { index: false, follow: false },
+};
+
+export default function TermsOfServicePage() {
+ return (
+
+
+
+
Terms of Service
+
Effective: May 22, 2026
+
+
+
+
Introduction
+
+ These Terms of Service ("Terms") govern your use of PackRat ("we", "us", "our") — the
+ mobile app, web app, public APIs, and the PackRat MCP connector. By creating an account
+ or otherwise using PackRat you agree to these Terms. If you do not agree, do not use the
+ service.
+
+
+
+
+
Eligibility & Accounts
+
+ You must be at least 16 years old to create a PackRat account (older where your local
+ law requires it). You are responsible for the activity that happens under your account,
+ for keeping your sign-in credentials safe, and for the accuracy of the information you
+ provide. If you suspect your account has been compromised, contact us immediately at{' '}
+
+ hello@packratai.com
+
+ .
+
+
+ One account per person. You may not create accounts on behalf of someone else without
+ their explicit permission, or use an account in a way that misrepresents who you are.
+
+
+
+
+
Acceptable Use
+
+ PackRat is built to help you plan and track outdoor trips — packing lists, trail data,
+ weather forecasts, trip notes, and similar planning tools. You may use it for personal,
+ educational, or commercial outdoor-planning purposes. You may not:
+
+
+
Scrape or bulk-download data outside the documented API rate limits.
+
+ Upload illegal content, content you do not have the right to share, or content that
+ targets, harasses, or endangers another person.
+
+
Attempt to access, interfere with, or degrade other users' accounts or data.
+
Probe, scan, or attempt to circumvent any security or authentication mechanism.
+
+ Use PackRat to send unsolicited messages or to operate any kind of automated abuse.
+
+
+
+ We may suspend or revoke access for any account that violates these rules, with or
+ without notice depending on the severity.
+
+
+
+
+
MCP Connector & API Access
+
+ PackRat exposes a Model Context Protocol (MCP) connector at{' '}
+ mcp.packratai.com that lets MCP-capable clients (for
+ example, Claude.ai) read and write your PackRat data on your behalf. The following terms
+ apply specifically to that surface:
+
+
+
+ Connecting an MCP client to PackRat uses OAuth 2.1. The flow requires you to grant one
+ or more scopes — mcp:read,{' '}
+ mcp:write, or{' '}
+ mcp:admin. The client only receives the scopes you
+ approve. The mcp:admin scope is granted only to users
+ with a PackRat admin role.
+
+
+ Tool calls are rate-limited at both the zone and per-user/per-tool level. Sustained
+ abuse — or any pattern that materially degrades the service for other users — may
+ result in tokens being revoked and the client being blocked.
+
+
+ MCP clients are independent software. PackRat is not responsible for the output an MCP
+ client (or its underlying model) produces based on PackRat data, including any
+ suggestions, summaries, or actions the client recommends. Treat MCP-client output as
+ advisory, not authoritative.
+
+
+ You can revoke a connected MCP client at any time from your PackRat account settings,
+ or by contacting{' '}
+
+ hello@packratai.com
+
+ . Revocation invalidates the OAuth refresh token and stops new access tokens from
+ being issued; previously issued access tokens expire on their normal short timer.
+
+
+
+
+
+
Outdoor Safety Disclaimer
+
+ Outdoor adventure planning has inherent risks. PackRat — including trail data, weather
+ forecasts, wildlife notes, route estimates, and any AI- or LLM-generated suggestion — is
+ informational only and is not a substitute for current local conditions, certified
+ guides, official ranger advisories, or your own judgment. You are responsible for the
+ decisions you make about your safety and the safety of anyone with you. Carry
+ appropriate backup navigation, communication, and emergency gear, and check official
+ sources before you go.
+
+
+
+
+
Fees
+
+ PackRat is free to use. There are no subscription fees, in-app purchases, or paid tiers,
+ so there is no refund policy. The service is provided as-is and as-available; we do not
+ commit to a specific uptime, response time, or feature set.
+
+
+
+
+
Termination
+
+ You may stop using PackRat and delete your account at any time. See our{' '}
+
+ Account Deletion page
+ {' '}
+ for the in-app and contact-based deletion paths.
+
+
+ We may suspend or terminate an account if it violates these Terms, if continued service
+ would expose us or other users to risk, or if we are required to by law. Where possible
+ we will give notice and a chance to fix the issue first.
+
+
+
+
+
Limitation of Liability
+
+ To the maximum extent permitted by law, PackRat is provided "as is" without warranty of
+ any kind. We are not liable for indirect, incidental, consequential, special, or
+ punitive damages, or for lost profits, lost data, or business interruption arising from
+ your use of the service. Our total aggregate liability for any claim related to PackRat
+ is capped at the amount you have paid us in the prior twelve months — which, because the
+ service is free, is zero dollars (USD $0).
+
+
+ Some jurisdictions do not allow the exclusion of certain warranties or the limitation of
+ liability for consequential or incidental damages. In those jurisdictions, the above
+ limits apply to the maximum extent permitted by law.
+
+
+
+
+
Governing Law
+ {/* TODO(operator): set jurisdiction — replace this paragraph with the chosen US state's
+ choice-of-law and venue clause once legal review is complete. The placeholder below
+ defaults to the State of Delaware and the federal/state courts located there. */}
+
+ These Terms are governed by the laws of the United States and the State of Delaware,
+ without regard to its conflict-of-laws rules. Any dispute that cannot be resolved
+ informally will be brought exclusively in the state or federal courts located in
+ Delaware, and you and PackRat each consent to that venue.
+
+
+
+
+
Changes to These Terms
+
+ We may update these Terms from time to time. If a change is material, we will notify you
+ by email or with an in-app notice before the change takes effect. Continued use of
+ PackRat after the effective date constitutes acceptance of the updated Terms. The most
+ recent version is always published at{' '}
+
+ packratai.com/terms-of-service
+
+ .
+
+
+
+
+
Contact
+
Questions about these Terms, abuse reports, security issues, or account problems:
+
+ Email:{' '}
+
+ hello@packratai.com
+
+
+
+
+
+ );
+}
diff --git a/apps/landing/config/site.ts b/apps/landing/config/site.ts
index 2d1e7cec5f..3216b8ac2d 100644
--- a/apps/landing/config/site.ts
+++ b/apps/landing/config/site.ts
@@ -352,6 +352,7 @@ export const siteConfig = {
{ title: 'Pricing', href: '/pricing' },
{ title: 'Guides', href: 'https://guides.packratai.com/' },
{ title: 'Integrations', href: '#integrations' },
+ { title: 'MCP Connector', href: '/mcp' },
],
company: [
{ title: 'About', href: '/about' },
@@ -359,7 +360,17 @@ export const siteConfig = {
{ title: 'Careers', href: '/about#careers' },
{ title: 'Contact', href: 'mailto:hello@packratai.com' },
],
- legal: [{ title: 'Privacy', href: '/privacy-policy' }],
+ legal: [
+ { title: 'Privacy', href: '/privacy-policy' },
+ { title: 'Terms', href: '/terms-of-service' },
+ ],
+ },
+
+ // Support contact — surfaced from MCP /health, the login page, and the connector listing.
+ // Email is the canonical channel; we don't run a separate support web page yet.
+ support: {
+ email: 'hello@packratai.com',
+ mailto: 'mailto:hello@packratai.com',
},
// Social links
diff --git a/apps/landing/data/mcp-catalog.json b/apps/landing/data/mcp-catalog.json
new file mode 100644
index 0000000000..cc255a9c56
--- /dev/null
+++ b/apps/landing/data/mcp-catalog.json
@@ -0,0 +1,1385 @@
+{
+ "generatedAt": "2026-05-23T06:02:06.502Z",
+ "totalTools": 103,
+ "counts": {
+ "byClassification": {
+ "read": 43,
+ "write": 30,
+ "admin": 30
+ },
+ "byDomain": {
+ "Packs": 18,
+ "Pack Templates": 11,
+ "Admin & Analytics": 16,
+ "Gear & Catalog": 11,
+ "Trail Conditions": 7,
+ "Trails": 7,
+ "Feed": 9,
+ "Trips": 5,
+ "Database (Admin)": 2,
+ "Knowledge & Search": 2,
+ "Guides": 5,
+ "Account": 3,
+ "Seasons": 1,
+ "Weather": 4,
+ "Wildlife": 1,
+ "Uploads": 1
+ }
+ },
+ "scopes": [
+ {
+ "name": "mcp:read",
+ "description": "Read-only tools: get_*, list_*, search_*, find_*, whoami."
+ },
+ {
+ "name": "mcp:write",
+ "description": "Read plus create/update/delete/submit tools."
+ },
+ {
+ "name": "mcp:admin",
+ "description": "Read + write + admin tools. Only granted to PackRat admin users."
+ }
+ ],
+ "endpoint": "https://mcp.packratai.com/mcp",
+ "tools": [
+ {
+ "name": "packrat_add_pack_item",
+ "title": "Add Pack Item",
+ "description": "Add a gear item to a pack. Provide either a catalog_item_id (from packrat_search_gear_catalog) or specify custom item details. Weight should be in grams.",
+ "domain": "Packs",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_add_pack_template_item",
+ "title": "Add Pack Template Item",
+ "description": "Add an item to a pack template.",
+ "domain": "Pack Templates",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_active_users",
+ "title": "Admin: Active Users",
+ "description": "Daily/weekly/monthly active user counts.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_activity",
+ "title": "Admin: Analytics Activity",
+ "description": "Platform activity metrics over a time period.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_catalog_embeddings",
+ "title": "Admin: Catalog Embedding Stats",
+ "description": "Catalog embedding coverage stats.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_catalog_overview",
+ "title": "Admin: Catalog Overview",
+ "description": "Catalog-wide overview: item count, brands, price ranges, embedding coverage.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_catalog_prices",
+ "title": "Admin: Catalog Prices",
+ "description": "Price distribution across the catalog.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_etl_failure_summary",
+ "title": "Admin: ETL Failure Summary",
+ "description": "Top recent ETL failure patterns. Page size is capped at 50 server-side.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_etl_job_failures",
+ "title": "Admin: ETL Job Failures",
+ "description": "Per-job ETL failure drill-down. Page size is capped at 50 server-side.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_etl_jobs",
+ "title": "Admin: ETL Jobs",
+ "description": "Recent ETL pipeline jobs. Page size is capped at 50 server-side.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_growth",
+ "title": "Admin: Analytics Growth",
+ "description": "Platform user/pack growth metrics.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_pack_breakdown",
+ "title": "Admin: Pack Breakdown",
+ "description": "Distribution of packs by category.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_analytics_top_brands",
+ "title": "Admin: Top Brands",
+ "description": "Top gear brands in the catalog by item count. Page size is capped at 50 server-side.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_delete_catalog_item",
+ "title": "Admin: Delete Catalog Item",
+ "description": "Delete a catalog item as admin. U10: prompts the user to type DELETE before proceeding.",
+ "domain": "Gear & Catalog",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_delete_pack",
+ "title": "Admin: Delete Pack",
+ "description": "Soft-delete a pack as admin (bypasses ownership). U10: prompts the user to type DELETE before proceeding.",
+ "domain": "Packs",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_delete_trail_condition_report",
+ "title": "Admin: Delete Trail Condition Report",
+ "description": "Soft-delete a trail condition report as admin. U10: prompts the user to type DELETE before proceeding.",
+ "domain": "Trail Conditions",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_etl_reset_stuck",
+ "title": "Admin: ETL Reset Stuck Jobs",
+ "description": "Mark stuck-running ETL jobs as failed (admin maintenance).",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_etl_retry_job",
+ "title": "Admin: ETL Retry Job",
+ "description": "Retry a specific failed ETL job.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_get_trail",
+ "title": "Admin: Get Trail",
+ "description": "Get a trail by OSM relation ID (admin).",
+ "domain": "Trails",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_get_trail_geometry",
+ "title": "Admin: Get Trail Geometry",
+ "description": "Get full GeoJSON geometry for a trail (admin).",
+ "domain": "Trails",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_hard_delete_user",
+ "title": "Admin: Hard-Delete User",
+ "description": "GDPR-style hard-delete of a user. Irrevocable. Requires a non-empty `reason` for the audit log. U10: prompts the user to retype the target user_id before proceeding.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_list_catalog",
+ "title": "Admin: List Catalog Items",
+ "description": "Search/list catalog items across the platform. Page size is capped at 50 server-side; walk via the next `offset`.",
+ "domain": "Gear & Catalog",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_list_packs",
+ "title": "Admin: List Packs",
+ "description": "Search/list packs across all users (admin view). Page size is capped at 50 server-side; walk via the next `offset` field.",
+ "domain": "Packs",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_list_trail_condition_reports",
+ "title": "Admin: List Trail Condition Reports",
+ "description": "List trail condition reports across all users (admin). Page size is capped at 50 server-side; walk via the next `offset`.",
+ "domain": "Trail Conditions",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_list_users",
+ "title": "Admin: List Users",
+ "description": "Search/list users (paginated). Use `q` to filter by email or name. Page size is capped at 50 server-side; the API returns a `{ data, total, limit, offset }` envelope which the model can walk via the next `offset`.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_search_trails",
+ "title": "Admin: Search Trails",
+ "description": "Search OSM trails by name/sport (admin view). Page size is capped at 50 server-side; the response carries an `offset` and a `hasMore` flag for continuation.",
+ "domain": "Trails",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_stats",
+ "title": "Admin: Platform Stats",
+ "description": "Get high-level platform stats: user, pack, and catalog counts.",
+ "domain": "Admin & Analytics",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_admin_update_catalog_item",
+ "title": "Admin: Update Catalog Item",
+ "description": "Update a catalog item (name, brand, price, weight, etc.) as admin.",
+ "domain": "Gear & Catalog",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_analyze_pack_gaps",
+ "title": "Analyze Pack Gaps",
+ "description": "Identify missing essential gear categories for a specific trip context. Compares the pack's current categories against recommended essentials and returns what's missing.",
+ "domain": "Packs",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_analyze_pack_image",
+ "title": "Analyze Pack Image",
+ "description": "Submit a gear image (R2 key from packrat_upload_image_url) for item detection. Returns detected items with catalog matches.",
+ "domain": "Gear & Catalog",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_analyze_pack_weight",
+ "title": "Analyze Pack Weight",
+ "description": "Return a detailed weight breakdown for a pack: total / base / worn / consumable grams plus a per-category aggregation sorted heaviest first.",
+ "domain": "Packs",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_compare_gear_items",
+ "title": "Compare Gear Items",
+ "description": "Compare multiple gear items side-by-side on weight, price, and rating. Provide 2–10 catalog item IDs.",
+ "domain": "Gear & Catalog",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_create_app_pack_template",
+ "title": "Create App Pack Template (Admin)",
+ "description": "Create a curated app-level pack template visible to all users. Admin-only — also requires the mcp:admin OAuth scope. For personal templates use packrat_create_pack_template. U10: prompts the admin to type PUBLISH before the template is created (visible to every PackRat user, not easily unpublished).",
+ "domain": "Pack Templates",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_create_catalog_item",
+ "title": "Create Catalog Item",
+ "description": "Submit a new gear item to the catalog. The API will embed and dedupe automatically. Use this for custom items not yet in the catalog.",
+ "domain": "Gear & Catalog",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_create_feed_comment",
+ "title": "Create Feed Comment",
+ "description": "Add a comment to a feed post (or reply to a parent comment).",
+ "domain": "Feed",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_create_feed_post",
+ "title": "Create Feed Post",
+ "description": "Create a feed post with a caption and optional image keys.",
+ "domain": "Feed",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_create_pack",
+ "title": "Create Pack",
+ "description": "Create a new packing list for the user. Returns the newly created pack with its ID.",
+ "domain": "Packs",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_create_pack_template",
+ "title": "Create Pack Template",
+ "description": "Create a personal pack template visible only to you. To create a curated app template, use packrat_create_app_pack_template (admin-only).",
+ "domain": "Pack Templates",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_create_trip",
+ "title": "Create Trip",
+ "description": "Create a new trip plan with destination, dates, and optional link to a pack. Returns the created trip with its ID.",
+ "domain": "Trips",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_delete_feed_comment",
+ "title": "Delete Feed Comment",
+ "description": "Delete one of your own feed comments.",
+ "domain": "Feed",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_delete_feed_post",
+ "title": "Delete Feed Post",
+ "description": "Delete one of your own feed posts.",
+ "domain": "Feed",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_delete_pack",
+ "title": "Delete Pack",
+ "description": "Soft-delete a pack. The pack will no longer appear in listings.",
+ "domain": "Packs",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_delete_pack_template",
+ "title": "Delete Pack Template",
+ "description": "Delete a pack template.",
+ "domain": "Pack Templates",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_delete_pack_template_item",
+ "title": "Delete Pack Template Item",
+ "description": "Delete a pack template item.",
+ "domain": "Pack Templates",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_delete_trail_condition",
+ "title": "Delete Trail Condition Report",
+ "description": "Soft-delete one of your trail condition reports.",
+ "domain": "Trail Conditions",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_delete_trip",
+ "title": "Delete Trip",
+ "description": "Delete a trip. The trip will no longer appear in listings.",
+ "domain": "Trips",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_execute_sql_query",
+ "title": "Execute Read-Only SQL Query",
+ "description": "Execute a read-only SQL SELECT query against the PackRat database for advanced analytics. Only SELECT statements are allowed. Admin-only.",
+ "domain": "Database (Admin)",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_extract_url_content",
+ "title": "Extract URL Content",
+ "description": "Extract the readable article content from any URL using Readability. Useful for ingesting blog posts, trip reports, or gear reviews.",
+ "domain": "Knowledge & Search",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": false,
+ "openWorldHint": true
+ }
+ },
+ {
+ "name": "packrat_generate_pack_template_from_url",
+ "title": "Generate Pack Template From URL (Admin)",
+ "description": "Generate a pack template from a TikTok or YouTube link. Admin-only — the server gates this on `user.role === \"ADMIN\"` on the OAuth-authenticated user, and MCP hides it from non-admin sessions. The `mcp:admin` scope is granted at OAuth callback time when the Better Auth role resolves to ADMIN. U10: prompts the admin to type GENERATE before the LLM call fires (fetched content is processed and a template is created).",
+ "domain": "Pack Templates",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": true
+ }
+ },
+ {
+ "name": "packrat_get_catalog_item",
+ "title": "Get Catalog Item",
+ "description": "Retrieve full details for a specific gear catalog item by ID. Returns specs, dimensions, weight, price, availability, user reviews, Q&A, and product URL.",
+ "domain": "Gear & Catalog",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_database_schema",
+ "title": "Get Database Schema",
+ "description": "Get the PackRat DB schema — table names, columns, types. Admin-only.",
+ "domain": "Database (Admin)",
+ "classification": "admin",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_feed_post",
+ "title": "Get Feed Post",
+ "description": "Get a specific feed post by ID.",
+ "domain": "Feed",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_guide",
+ "title": "Get Guide",
+ "description": "Get a specific guide by ID. Returns MDX/Markdown content.",
+ "domain": "Guides",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_pack",
+ "title": "Get Pack",
+ "description": "Get complete details of a single pack including all items with weights, categories, and computed totals. Use this to analyze pack weight, find gear gaps, or suggest optimizations.",
+ "domain": "Packs",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_pack_item",
+ "title": "Get Pack Item",
+ "description": "Get full details of a single pack item.",
+ "domain": "Packs",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_pack_template",
+ "title": "Get Pack Template",
+ "description": "Get a pack template with its items.",
+ "domain": "Pack Templates",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_pack_weight_history",
+ "title": "Get Pack Weight History",
+ "description": "Get the weight history for all of the user's packs over time.",
+ "domain": "Packs",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_profile",
+ "title": "Get My Profile",
+ "description": "Get the authenticated user's profile (firstName, lastName, email, avatar).",
+ "domain": "Account",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_season_suggestions",
+ "title": "Get Season Suggestions",
+ "description": "Generate season-appropriate pack suggestions for a location + date. Requires at least 20 inventory items on the signed-in user.",
+ "domain": "Seasons",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_trail",
+ "title": "Get Trail",
+ "description": "Get metadata for a specific trail by its OSM relation ID. Returns name, sport, difficulty, distance, and bounding box.",
+ "domain": "Trails",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_trail_conditions",
+ "title": "Get Trail Condition Reports",
+ "description": "Get user-submitted trail condition reports. Filter by trail name to find reports for a specific trail or area.",
+ "domain": "Trail Conditions",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_trail_geometry",
+ "title": "Get Trail Geometry",
+ "description": "Get full GeoJSON geometry for a trail. May be slow for large routes with many segments.",
+ "domain": "Trails",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_trip",
+ "title": "Get Trip",
+ "description": "Get full details for a single trip including location coordinates, dates, notes, and linked pack information.",
+ "domain": "Trips",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_get_weather",
+ "title": "Get Weather Forecast",
+ "description": "Get current weather conditions and multi-day forecast for any location. Returns temperature, precipitation, wind, humidity, and outdoor conditions relevant to trip planning.",
+ "domain": "Weather",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": false,
+ "openWorldHint": true
+ }
+ },
+ {
+ "name": "packrat_get_weather_forecast",
+ "title": "Get Weather Forecast By Location ID",
+ "description": "Fetch a 10-day forecast given a WeatherAPI location ID (returned by packrat_search_weather_location).",
+ "domain": "Weather",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": false,
+ "openWorldHint": true
+ }
+ },
+ {
+ "name": "packrat_identify_wildlife",
+ "title": "Identify Wildlife From Image",
+ "description": "Identify the plant or animal species in an uploaded image (provide the R2 image key from packrat_upload_image_url).",
+ "domain": "Wildlife",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_feed",
+ "title": "List Feed Posts",
+ "description": "List social feed posts (paginated).",
+ "domain": "Feed",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_feed_comments",
+ "title": "List Feed Comments",
+ "description": "List comments on a feed post.",
+ "domain": "Feed",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_gear_categories",
+ "title": "List Gear Categories",
+ "description": "List all available gear categories in the catalog with item counts. Use this to explore what gear types are available before searching.",
+ "domain": "Gear & Catalog",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_guide_categories",
+ "title": "List Guide Categories",
+ "description": "List all guide categories.",
+ "domain": "Guides",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_guides",
+ "title": "List Outdoor Guides",
+ "description": "List PackRat outdoor guides (paginated, filterable by category).",
+ "domain": "Guides",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_my_trail_reports",
+ "title": "List My Trail Reports",
+ "description": "List trail condition reports authored by the signed-in user.",
+ "domain": "Trail Conditions",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_pack_items",
+ "title": "List Pack Items",
+ "description": "List all items in a pack.",
+ "domain": "Packs",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_pack_template_items",
+ "title": "List Pack Template Items",
+ "description": "List items inside a pack template.",
+ "domain": "Pack Templates",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_pack_templates",
+ "title": "List Pack Templates",
+ "description": "List both user-owned and app-curated pack templates.",
+ "domain": "Pack Templates",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_packs",
+ "title": "List My Packs",
+ "description": "List all packs belonging to the authenticated user. Returns pack summaries including name, category, item count, and total weight. Paginated: results are capped at 50 items per call; the response includes a `nextOffset` value (or `null` at the end) to continue iterating.",
+ "domain": "Packs",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_list_trips",
+ "title": "List My Trips",
+ "description": "List all of the user's planned trips. Returns trip summaries including name, destination, dates, and linked pack. Paginated: results are capped at 50 per call; the response includes a `nextOffset` value (or `null` at the end) for continuation.",
+ "domain": "Trips",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_preview_alltrails_url",
+ "title": "Preview AllTrails URL",
+ "description": "Fetch trail metadata (title, description, image) from an AllTrails URL using OpenGraph tags.",
+ "domain": "Trails",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": false,
+ "openWorldHint": true
+ }
+ },
+ {
+ "name": "packrat_record_pack_weight",
+ "title": "Record Pack Weight",
+ "description": "Record a weight measurement for a pack at a specific point in time.",
+ "domain": "Packs",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_remove_pack_item",
+ "title": "Remove Pack Item",
+ "description": "Remove an item from a pack (soft-delete).",
+ "domain": "Packs",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": true,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_search_gear_catalog",
+ "title": "Search Gear Catalog",
+ "description": "Search the PackRat gear catalog of outdoor products with specs, weights, prices, and user reviews. Use this to find specific gear, compare products, or browse categories. Paginated via `page` (1-indexed); page size is capped at 50 server-side.",
+ "domain": "Gear & Catalog",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_search_guides",
+ "title": "Search Outdoor Guides",
+ "description": "Full-text search across PackRat outdoor guides.",
+ "domain": "Guides",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_search_outdoor_guides",
+ "title": "Search Outdoor Knowledge Base",
+ "description": "Search the PackRat outdoor knowledge base using retrieval-augmented search. Contains expert guides on outdoor skills, safety, Leave No Trace principles, gear techniques, navigation, first aid, and outdoor activities. Use this for \"how-to\" questions, technique guidance, or safety information.",
+ "domain": "Guides",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_search_trails",
+ "title": "Search Trails",
+ "description": "Search outdoor trails and routes from OpenStreetMap. Filter by name, sport type, and/or proximity to a location. Returns { trails, hasMore } — paginate via offset.",
+ "domain": "Trails",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_search_weather_by_coordinates",
+ "title": "Search Weather By Coordinates",
+ "description": "Find weather locations near a latitude/longitude pair.",
+ "domain": "Weather",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": true
+ }
+ },
+ {
+ "name": "packrat_search_weather_location",
+ "title": "Search Weather Locations",
+ "description": "Search for weather locations by name. Returns matching locations with IDs.",
+ "domain": "Weather",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": true
+ }
+ },
+ {
+ "name": "packrat_semantic_gear_search",
+ "title": "Semantic Gear Search",
+ "description": "Search the gear catalog using vector/semantic search. Good for natural-language queries like \"warm but lightweight insulation layer for cold shoulder-season camping\" or \"minimalist trail running shoe for rocky terrain\".",
+ "domain": "Gear & Catalog",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_similar_catalog_items",
+ "title": "Find Similar Catalog Items",
+ "description": "Find items similar to a given catalog item by embedding similarity.",
+ "domain": "Gear & Catalog",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_similar_pack_items",
+ "title": "Find Similar Pack Items",
+ "description": "Find catalog gear similar to a specific item in a pack (semantic similarity).",
+ "domain": "Packs",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_submit_trail_condition",
+ "title": "Submit Trail Condition Report",
+ "description": "Submit a trail condition report to help the community. Requires user authentication.",
+ "domain": "Trail Conditions",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_suggest_pack_items",
+ "title": "Suggest Pack Items",
+ "description": "Return catalog item suggestions for a pack based on the items already in it.",
+ "domain": "Packs",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_toggle_feed_comment_like",
+ "title": "Toggle Feed Comment Like",
+ "description": "Like or unlike a feed comment (toggle).",
+ "domain": "Feed",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_toggle_feed_post_like",
+ "title": "Toggle Feed Post Like",
+ "description": "Like or unlike a feed post (toggle).",
+ "domain": "Feed",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_update_pack",
+ "title": "Update Pack",
+ "description": "Update a pack's name, description, category, visibility, or tags.",
+ "domain": "Packs",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_update_pack_item",
+ "title": "Update Pack Item",
+ "description": "Update fields on an existing pack item.",
+ "domain": "Packs",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_update_pack_template",
+ "title": "Update Pack Template",
+ "description": "Update a pack template.",
+ "domain": "Pack Templates",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_update_pack_template_item",
+ "title": "Update Pack Template Item",
+ "description": "Update a pack template item.",
+ "domain": "Pack Templates",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_update_profile",
+ "title": "Update My Profile",
+ "description": "Update the authenticated user's profile fields.",
+ "domain": "Account",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_update_trail_condition",
+ "title": "Update Trail Condition Report",
+ "description": "Update one of your own trail condition reports.",
+ "domain": "Trail Conditions",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_update_trip",
+ "title": "Update Trip",
+ "description": "Update an existing trip's details, dates, location, or linked pack.",
+ "domain": "Trips",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_upload_image_url",
+ "title": "Create Image Upload URL",
+ "description": "Generate a presigned R2 URL the caller can PUT an image to (jpeg/png/webp, ≤10MB). Returns { uploadUrl, key } — use `key` in downstream tools (packrat_analyze_pack_image, packrat_identify_wildlife, etc.).",
+ "domain": "Uploads",
+ "classification": "write",
+ "annotations": {
+ "readOnlyHint": false,
+ "destructiveHint": false,
+ "idempotentHint": false,
+ "openWorldHint": false
+ }
+ },
+ {
+ "name": "packrat_web_search",
+ "title": "Web Search",
+ "description": "Search the public web for current, real-time information. Use this for current trail conditions, recent news, current gear prices and deals, permit availability, or anything requiring up-to-date info not in the PackRat knowledge base.",
+ "domain": "Knowledge & Search",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": false,
+ "openWorldHint": true
+ }
+ },
+ {
+ "name": "packrat_whoami",
+ "title": "Who Am I",
+ "description": "Return the currently authenticated PackRat user profile.",
+ "domain": "Account",
+ "classification": "read",
+ "annotations": {
+ "readOnlyHint": true,
+ "destructiveHint": null,
+ "idempotentHint": true,
+ "openWorldHint": false
+ }
+ }
+ ]
+}
diff --git a/apps/landing/public/favicon.ico b/apps/landing/public/favicon.ico
new file mode 100644
index 0000000000..389995edbe
Binary files /dev/null and b/apps/landing/public/favicon.ico differ
diff --git a/apps/landing/public/mcp-logo-1024.png b/apps/landing/public/mcp-logo-1024.png
new file mode 100644
index 0000000000..d6dd5c24c7
Binary files /dev/null and b/apps/landing/public/mcp-logo-1024.png differ
diff --git a/apps/landing/public/mcp-logo-256.png b/apps/landing/public/mcp-logo-256.png
new file mode 100644
index 0000000000..d45bd2926b
Binary files /dev/null and b/apps/landing/public/mcp-logo-256.png differ
diff --git a/apps/landing/public/mcp-logo-512.png b/apps/landing/public/mcp-logo-512.png
new file mode 100644
index 0000000000..9b5e90b3a8
Binary files /dev/null and b/apps/landing/public/mcp-logo-512.png differ
diff --git a/apps/landing/public/mcp-logo.svg b/apps/landing/public/mcp-logo.svg
new file mode 100644
index 0000000000..0245a629a5
--- /dev/null
+++ b/apps/landing/public/mcp-logo.svg
@@ -0,0 +1,31 @@
+
+
+
diff --git a/biome.json b/biome.json
index 5715215a55..a0e212482f 100644
--- a/biome.json
+++ b/biome.json
@@ -66,6 +66,7 @@
"apps/expo/atoms/atomWith*.ts",
"apps/expo/features/weather/atoms/locationsAtoms.ts",
"apps/expo/lib/api/client.ts",
+ "packages/api/src/app.ts",
"packages/api/src/index.ts",
"packages/api/src/routes/admin/index.ts",
"packages/api/src/services/r2-bucket.ts",
diff --git a/bun.lock b/bun.lock
index 802d9a57bd..1ce83e1ece 100644
--- a/bun.lock
+++ b/bun.lock
@@ -22,7 +22,7 @@
},
"apps/admin": {
"name": "packrat-admin-app",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@elysiajs/eden": "catalog:",
"@packrat/api-client": "workspace:*",
@@ -71,7 +71,7 @@
},
"apps/expo": {
"name": "packrat-expo-app",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@ai-sdk/react": "^3.0.170",
"@better-auth/expo": "^1.6.9",
@@ -80,7 +80,6 @@
"@gorhom/bottom-sheet": "^5.1.2",
"@legendapp/state": "^3.0.0-beta.30",
"@packrat-ai/nativewindui": "2.0.6",
- "@packrat/api": "workspace:*",
"@packrat/api-client": "workspace:*",
"@packrat/config": "workspace:*",
"@packrat/constants": "workspace:*",
@@ -210,12 +209,12 @@
},
"apps/guides": {
"name": "packrat-guides-app",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@ai-sdk/openai": "catalog:",
"@elysiajs/eden": "catalog:",
"@hookform/resolvers": "catalog:",
- "@packrat/api": "workspace:*",
+ "@packrat/api-client": "workspace:*",
"@packrat/env": "workspace:*",
"@packrat/guards": "workspace:*",
"@packrat/schemas": "workspace:*",
@@ -299,7 +298,7 @@
},
"apps/landing": {
"name": "packrat-landing-app",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@emotion/is-prop-valid": "^1.3.1",
"@hookform/resolvers": "catalog:",
@@ -369,7 +368,7 @@
},
"apps/trails": {
"name": "packrat-trails-app",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@packrat/api-client": "workspace:*",
"@packrat/app": "workspace:*",
@@ -442,7 +441,7 @@
},
"packages/analytics": {
"name": "@packrat/analytics",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@duckdb/node-api": "catalog:",
"@packrat/env": "workspace:*",
@@ -459,19 +458,21 @@
},
"packages/api": {
"name": "@packrat/api",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@ai-sdk/google": "^3.0.64",
"@ai-sdk/openai": "catalog:",
"@ai-sdk/perplexity": "^3.0.29",
"@aws-sdk/client-s3": "~3.787.0",
"@aws-sdk/s3-request-presigner": "~3.787.0",
+ "@better-auth/oauth-provider": "1.6.11",
"@cloudflare/containers": "^0.0.30",
"@elysiajs/cors": "catalog:",
"@elysiajs/eden": "catalog:",
"@elysiajs/openapi": "catalog:",
"@mozilla/readability": "^0.6.0",
"@neondatabase/serverless": "catalog:",
+ "@packrat/consent-ui": "workspace:*",
"@packrat/constants": "workspace:*",
"@packrat/db": "workspace:*",
"@packrat/env": "workspace:*",
@@ -492,7 +493,7 @@
"elysia": "catalog:",
"google-auth-library": "catalog:",
"gray-matter": "catalog:",
- "jose": "^5.9.6",
+ "jose": "^6.0.0",
"linkedom": "^0.18.11",
"nodemailer": "^6.10.0",
"pg": "catalog:",
@@ -513,9 +514,9 @@
"@types/ws": "^8.5.14",
"@vitest/coverage-v8": "catalog:",
"better-auth": "catalog:",
- "better-auth-cloudflare": "^0.3.0",
"concurrently": "^8.2.2",
"drizzle-orm": "catalog:",
+ "drizzle-seed": "^0.3.1",
"miniflare": "^4.20260515.0",
"typed-htmx": "^0.3.1",
"vitest": "catalog:",
@@ -524,7 +525,7 @@
},
"packages/api-client": {
"name": "@packrat/api-client",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@elysiajs/eden": "catalog:",
"@packrat/guards": "workspace:*",
@@ -542,7 +543,7 @@
},
"packages/app": {
"name": "@packrat/app",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@packrat/api-client": "workspace:*",
"@packrat/schemas": "workspace:*",
@@ -563,11 +564,11 @@
},
"packages/checks": {
"name": "@packrat/checks",
- "version": "2.0.27",
+ "version": "2.0.28",
},
"packages/cli": {
"name": "@packrat/cli",
- "version": "2.0.27",
+ "version": "2.0.28",
"bin": {
"packrat": "./src/index.ts",
},
@@ -591,21 +592,32 @@
},
"packages/config": {
"name": "@packrat/config",
- "version": "2.0.27",
+ "version": "2.0.28",
+ "dependencies": {
+ "@packrat/guards": "workspace:*",
+ },
+ },
+ "packages/consent-ui": {
+ "name": "@packrat/consent-ui",
+ "version": "2.1.0",
"dependencies": {
+ "@kitajs/html": "^4.2.13",
"@packrat/guards": "workspace:*",
},
+ "devDependencies": {
+ "@kitajs/ts-html-plugin": "^4.1.4",
+ },
},
"packages/constants": {
"name": "@packrat/constants",
- "version": "2.0.27",
+ "version": "2.0.28",
"devDependencies": {
"typescript": "catalog:",
},
},
"packages/db": {
"name": "@packrat/db",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@packrat/constants": "workspace:*",
"drizzle-orm": "catalog:",
@@ -617,14 +629,14 @@
},
"packages/env": {
"name": "@packrat/env",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"zod": "catalog:",
},
},
"packages/guards": {
"name": "@packrat/guards",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"radash": "catalog:",
"ts-extras": "catalog:",
@@ -633,16 +645,18 @@
},
"packages/mcp": {
"name": "@packrat/mcp",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
- "@cloudflare/workers-oauth-provider": "^0.4.0",
- "@modelcontextprotocol/sdk": "^1.11.0",
+ "@modelcontextprotocol/sdk": "^1.29.0",
"@packrat/api-client": "workspace:*",
- "agents": "^0.11.0",
- "magic-regexp": "catalog:",
+ "@packrat/guards": "workspace:*",
+ "@packrat/schemas": "workspace:*",
+ "agents": "^0.13.2",
+ "jose": "^6.0.0",
"zod": "catalog:",
},
"devDependencies": {
+ "@cloudflare/vitest-pool-workers": "0.8.71",
"@cloudflare/workers-types": "catalog:",
"@vitest/coverage-v8": "catalog:",
"partyserver": "^0.4.1",
@@ -653,7 +667,7 @@
},
"packages/osm-db": {
"name": "@packrat/osm-db",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@neondatabase/serverless": "catalog:",
"drizzle-orm": "catalog:",
@@ -667,7 +681,7 @@
},
"packages/osm-import": {
"name": "@packrat/osm-import",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@packrat/env": "workspace:*",
"pg": "catalog:",
@@ -675,7 +689,7 @@
},
"packages/overpass": {
"name": "@packrat/overpass",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@packrat/guards": "workspace:*",
"zod": "catalog:",
@@ -687,7 +701,7 @@
},
"packages/schemas": {
"name": "@packrat/schemas",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@packrat/constants": "workspace:*",
"@packrat/db": "workspace:*",
@@ -700,7 +714,7 @@
},
"packages/types": {
"name": "@packrat/types",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@packrat/constants": "workspace:*",
"@packrat/schemas": "workspace:*",
@@ -711,18 +725,18 @@
},
"packages/typescript-config": {
"name": "@packrat/typescript-config",
- "version": "0.0.0",
+ "version": "2.0.28",
},
"packages/ui": {
"name": "@packrat/ui",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@packrat-ai/nativewindui": "2.0.6",
},
},
"packages/units": {
"name": "@packrat/units",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@packrat/constants": "workspace:*",
"@packrat/guards": "workspace:*",
@@ -734,7 +748,7 @@
},
"packages/web-ui": {
"name": "@packrat/web-ui",
- "version": "2.0.27",
+ "version": "2.0.28",
"dependencies": {
"@packrat/guards": "workspace:*",
"@radix-ui/react-accordion": "catalog:",
@@ -901,40 +915,24 @@
"zod": "^3.24.2",
},
"packages": {
- "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.115", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-xonmGfN9pt54WdKqMzWe68BRYS3rsYvraBzioyA0gfNcecHs8Ir5qk/X8grJSyZ95hghjWiOphrK6bAc11E6SA=="],
+ "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.128", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.28", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-t9Dyqk5thSmIzsNvVTQtZZiO3xqKGkk1hX3+GNpYmro+GuEdW+E6mKFHihb9Y1vCEt3rEyd4pbGUcin4D57FfQ=="],
- "@ai-sdk/google": ["@ai-sdk/google@3.0.75", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-XAm31ftiOrzlb8NjDzT7kw0xw+4lmgFdGFn1QKM73nXFFKyN1kWLESBV75UGNfjXP8X1YJ0YydnMVqO0jaPghw=="],
+ "@ai-sdk/google": ["@ai-sdk/google@3.0.81", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.28" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Xvr/bAdWY/KC63wd593OJwYtRBXFqDpmbQNMPX5HZTTYs6kYFMJ1KQJ/trwUiD/0RxyIsxIjE/b2SfdKEbBnBg=="],
- "@ai-sdk/openai": ["@ai-sdk/openai@3.0.64", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-epO4iS6QwktaY2PF6uBcPnDTJ3BxPOfsGS7/OEtBe3GtNj7C8h8gMDVtIe5K8W16HNDbn0tbR4dcQfpfs+XVFg=="],
+ "@ai-sdk/openai": ["@ai-sdk/openai@3.0.70", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.28" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-0sAaS5IrgHvLF1OUHCB1fV+d4HCvfUvhnf5Hpq2yrzFRPLKdLv6TDohWOt/vmf1A6tXO1DuQKKsSuNqG3Rydgw=="],
- "@ai-sdk/perplexity": ["@ai-sdk/perplexity@3.0.33", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-aNt6pTAzq+akadDXVdg2SjN2dODtaVlkKbw8/35c+sekr+Tx0sJwVqMR1udxrjLzhQvz8qtfsWRuz+hB9pmOnQ=="],
+ "@ai-sdk/perplexity": ["@ai-sdk/perplexity@3.0.34", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.28" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-820xRa/NFzXaRPxAvQgMT0ZIZL9UkktOBrcCxLOXtzFQxURp6vp+8s3tEFjGeISN+deHNpPMmd0EkPdQGpxdDA=="],
"@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="],
- "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
+ "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.28", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-nCtGJY43Kqwoyk0rYLj80a3eyXxcaWwyu+lYZDHgY+U6JbYYyvRdRTSy+XCDIB91rFH0Ul0eMDHmDr+YMYtrSw=="],
- "@ai-sdk/react": ["@ai-sdk/react@3.0.186", "", { "dependencies": { "@ai-sdk/provider-utils": "4.0.27", "ai": "6.0.184", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" } }, "sha512-fy8wuy8pBghYD1ECw/M5vAsGsZp2D3y/oSTp1iOlAnJqRXzvz4rWLBz1n+rjL+aHZNgJK3kR3NHlnifoKYERfA=="],
+ "@ai-sdk/react": ["@ai-sdk/react@3.0.204", "", { "dependencies": { "@ai-sdk/provider-utils": "4.0.28", "ai": "6.0.202", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" } }, "sha512-4I5fq9n/YBCEPfbvYEzc5lFNMxoF2hZRXVrUAsjA6NL7LY8AJo3V3PD2TH9rTKIY08uolnyJSnnQc7YuFXXUIA=="],
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
"@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
- "@appium/base-driver": ["@appium/base-driver@10.5.2", "", { "dependencies": { "@appium/support": "7.2.2", "@appium/types": "1.4.0", "@colors/colors": "1.6.0", "async-lock": "1.4.1", "asyncbox": "6.2.0", "axios": "1.16.0", "bluebird": "3.7.2", "body-parser": "2.2.2", "express": "5.2.1", "fastest-levenshtein": "1.0.16", "http-status-codes": "2.3.0", "lodash": "4.18.1", "lru-cache": "11.3.5", "method-override": "3.0.0", "morgan": "1.10.1", "path-to-regexp": "8.4.2", "serve-favicon": "2.5.1", "type-fest": "5.6.0" }, "optionalDependencies": { "spdy": "4.0.2" } }, "sha512-nTsGHbE9fwi9BxMzD2mBv2EFZgRDAiNqZn6NMLTs1bD/lc3tNflqelq6tEVhrbHwpyWDkaorNACKNz5u/e6BEw=="],
-
- "@appium/base-plugin": ["@appium/base-plugin@3.2.4", "", { "dependencies": { "@appium/base-driver": "10.5.2", "@appium/support": "7.2.2", "@appium/types": "1.4.0" } }, "sha512-0F6O0VCC6qN7NhdnBNvs0aWVqHZo1OBD8Uirn2mKnZGw9ofpiE0bhav0qfKpVPem2sBo30JSQJam4VkzjWhpRg=="],
-
- "@appium/docutils": ["@appium/docutils@2.4.2", "", { "dependencies": { "@appium/support": "7.2.2", "consola": "3.4.2", "diff": "9.0.0", "lilconfig": "3.1.3", "lodash": "4.18.1", "package-directory": "8.2.0", "read-pkg": "10.1.0", "teen_process": "4.1.3", "type-fest": "5.6.0", "yaml": "2.8.4", "yargs": "18.0.0", "yargs-parser": "22.0.0" }, "bin": { "appium-docs": "bin/appium-docs.js" } }, "sha512-NV7rSZohVDFUg8+dkbU6HsGmVv6fOQV2HPmZpQH9vOtY+FdKYkMpc2PtZfC/OOvC5kT/eeXWssE5aPwujjSksg=="],
-
- "@appium/logger": ["@appium/logger@2.0.7", "", { "dependencies": { "console-control-strings": "1.1.0", "lodash": "4.18.1", "lru-cache": "11.3.5", "set-blocking": "2.0.0" } }, "sha512-WqagwYDZlPsSkICrXL9wB1E7qgErnwmYc/Q6NLVAC2ckXkWioh3fZ49AK5zevbJCnnkQbU2y8497Mk4xWDetkg=="],
-
- "@appium/schema": ["@appium/schema@1.1.1", "", { "dependencies": { "json-schema": "0.4.0" } }, "sha512-u2dHLEqnI5oHWYVsKUv3yypeu0a82+6N39awkFz5jKcxVCSbssr+Rvh0/0LOa/gwePGxi1OzjHpZzNXlr7hI7Q=="],
-
- "@appium/support": ["@appium/support@7.2.2", "", { "dependencies": { "@appium/logger": "2.0.7", "@appium/tsconfig": "1.1.2", "@appium/types": "1.4.0", "@colors/colors": "1.6.0", "archiver": "7.0.1", "asyncbox": "6.2.0", "axios": "1.16.0", "base64-stream": "1.0.0", "bluebird": "3.7.2", "bplist-creator": "0.1.1", "bplist-parser": "0.3.2", "form-data": "4.0.5", "get-stream": "9.0.1", "glob": "13.0.5", "jsftp": "2.1.3", "klaw": "4.1.0", "lockfile": "1.0.4", "log-symbols": "7.0.1", "ncp": "2.0.0", "package-directory": "8.2.0", "plist": "4.0.0", "pluralize": "8.0.0", "read-pkg": "10.1.0", "resolve-from": "5.0.0", "sanitize-filename": "1.6.4", "semver": "7.7.4", "shell-quote": "1.8.3", "supports-color": "10.2.2", "teen_process": "4.1.3", "type-fest": "5.6.0", "uuid": "14.0.0", "which": "6.0.1", "yauzl": "3.3.0" }, "optionalDependencies": { "sharp": "0.34.5" } }, "sha512-SfaFg0tAy0cqHQixtyB3BdZSyv287381McIq4/Zd6J070KFGNjXhF2wDGO3f2uN5VaYugwBYz/ZQEgozh6tK8g=="],
-
- "@appium/tsconfig": ["@appium/tsconfig@1.1.2", "", { "dependencies": { "@tsconfig/node20": "20.1.9" } }, "sha512-lHKBm7hXCROc1Ha/cBxS4o3iQkeY96Pz7qM9Uh9vFDkdpTGBk56V1lmc3iGcgBYKBlaRT/LZmTsqClvHoiXhvw=="],
-
- "@appium/types": ["@appium/types@1.4.0", "", { "dependencies": { "@appium/logger": "2.0.7", "@appium/schema": "1.1.1", "@appium/tsconfig": "1.1.2", "type-fest": "5.6.0" } }, "sha512-GeYnDMj1yOIFA8ujOHv0/ZKoZe42F9ldCVSlnEOheYnxqA5ueHGwRI11ifZoIfMBsq7hpU77MAzmu+v9NV1vig=="],
-
"@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="],
"@aws-crypto/crc32c": ["@aws-crypto/crc32c@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag=="],
@@ -1007,7 +1005,7 @@
"@aws-sdk/util-format-url": ["@aws-sdk/util-format-url@3.775.0", "", { "dependencies": { "@aws-sdk/types": "3.775.0", "@smithy/querystring-builder": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Nw4nBeyCbWixoGh8NcVpa/i8McMA6RXJIjQFyloJLaPr7CPquz7ZbSl0MUWMFVwP/VHaJ7B+lNN3Qz1iFCEP/Q=="],
- "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.5", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ=="],
+ "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.7", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-M0D6oIpohdNHjc7udzTHEQyot0+0iuA36jc2I9Hps+f/GtKi2HO/pyijQnCnNcwZqLB5+rtn81z3eZK/GyjAmA=="],
"@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.775.0", "", { "dependencies": { "@aws-sdk/types": "3.775.0", "@smithy/types": "^4.2.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-txw2wkiJmZKVdDbscK7VBK+u+TJnRtlUjRTLei+elZg2ADhpQxfVAQl436FUeIv6AhB/oRHW6/K/EAGXUSWi0A=="],
@@ -1015,57 +1013,59 @@
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.775.0", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-b9NGO6FKJeLGYnV7Z1yvcP1TNU4dkD5jNsLWOF1/sygZoASaQhNOlaiJ/1OH331YQ1R1oWk38nBb0frsYkDsOQ=="],
- "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
+ "@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="],
- "@babel/compat-data": ["@babel/compat-data@7.29.3", "", {}, "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg=="],
+ "@babel/compat-data": ["@babel/compat-data@7.29.7", "", {}, "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg=="],
- "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="],
+ "@babel/core": ["@babel/core@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-module-transforms": "^7.29.7", "@babel/helpers": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA=="],
- "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="],
+ "@babel/generator": ["@babel/generator@7.29.7", "", { "dependencies": { "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ=="],
- "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="],
+ "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" } }, "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw=="],
- "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="],
+ "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.29.7", "", { "dependencies": { "@babel/compat-data": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g=="],
- "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.29.3", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.29.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA=="],
+ "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-member-expression-to-functions": "^7.29.7", "@babel/helper-optimise-call-expression": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/traverse": "^7.29.7", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg=="],
- "@babel/helper-create-regexp-features-plugin": ["@babel/helper-create-regexp-features-plugin@7.28.5", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw=="],
+ "@babel/helper-create-regexp-features-plugin": ["@babel/helper-create-regexp-features-plugin@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg=="],
"@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.8", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "debug": "^4.4.3", "lodash.debounce": "^4.0.8", "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA=="],
- "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
+ "@babel/helper-globals": ["@babel/helper-globals@7.29.7", "", {}, "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA=="],
+
+ "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg=="],
- "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.28.5", "", { "dependencies": { "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5" } }, "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg=="],
+ "@babel/helper-module-imports": ["@babel/helper-module-imports@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g=="],
- "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="],
+ "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg=="],
- "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="],
+ "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" } }, "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong=="],
- "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="],
+ "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="],
- "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="],
+ "@babel/helper-remap-async-to-generator": ["@babel/helper-remap-async-to-generator@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-wrap-function": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og=="],
- "@babel/helper-remap-async-to-generator": ["@babel/helper-remap-async-to-generator@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-wrap-function": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA=="],
+ "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.29.7", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.29.7", "@babel/helper-optimise-call-expression": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ=="],
- "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.28.6", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg=="],
+ "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ=="],
- "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="],
+ "@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="],
- "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
+ "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="],
- "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
+ "@babel/helper-validator-option": ["@babel/helper-validator-option@7.29.7", "", {}, "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw=="],
- "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
+ "@babel/helper-wrap-function": ["@babel/helper-wrap-function@7.29.7", "", { "dependencies": { "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw=="],
- "@babel/helper-wrap-function": ["@babel/helper-wrap-function@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ=="],
+ "@babel/helpers": ["@babel/helpers@7.29.7", "", { "dependencies": { "@babel/template": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg=="],
- "@babel/helpers": ["@babel/helpers@7.29.2", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.29.0" } }, "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw=="],
+ "@babel/highlight": ["@babel/highlight@7.25.9", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw=="],
- "@babel/parser": ["@babel/parser@7.29.3", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA=="],
+ "@babel/parser": ["@babel/parser@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" }, "bin": "./bin/babel-parser.js" }, "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg=="],
- "@babel/plugin-proposal-decorators": ["@babel/plugin-proposal-decorators@7.29.0", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-syntax-decorators": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA=="],
+ "@babel/plugin-proposal-decorators": ["@babel/plugin-proposal-decorators@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-syntax-decorators": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-EtU0Hi3GvrTqD56xKmZvV/uCXK2ZbwVNPNLAquVItcAZpUhkXwWlo3Fmj0c2LxgSf2I8IDULeAepwNP1OefLXg=="],
- "@babel/plugin-proposal-export-default-from": ["@babel/plugin-proposal-export-default-from@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hjlsMBl1aJc5lp8MoCDEZCiYzlgdRAShOjAfRw6X+GlpLpUPU7c3XNLsKFZbQk/1cRzBlJ7CXg3xJAJMrFa1Uw=="],
+ "@babel/plugin-proposal-export-default-from": ["@babel/plugin-proposal-export-default-from@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-p+G5BNXDcy3bOXplhY4HybQ1GxH3i2Tppmdm/3epyRu2VgJJZuUlZ61MqRTg582Q7ZLBdP7fePYvsumSEkMxcQ=="],
"@babel/plugin-syntax-async-generators": ["@babel/plugin-syntax-async-generators@7.8.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw=="],
@@ -1075,21 +1075,21 @@
"@babel/plugin-syntax-class-static-block": ["@babel/plugin-syntax-class-static-block@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw=="],
- "@babel/plugin-syntax-decorators": ["@babel/plugin-syntax-decorators@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA=="],
+ "@babel/plugin-syntax-decorators": ["@babel/plugin-syntax-decorators@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9MTTLbF39X6sqM92JPEsoI7++26hjZvzkxKZy64aMhWLH2mPkJ/Q3AV4QLmls3R14FpSpkOwQQfUh962JGQxxg=="],
"@babel/plugin-syntax-dynamic-import": ["@babel/plugin-syntax-dynamic-import@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ=="],
- "@babel/plugin-syntax-export-default-from": ["@babel/plugin-syntax-export-default-from@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Svlx1fjJFnNz0LZeUaybRukSxZI3KkpApUmIRzEdXC5k8ErTOz0OD0kNrICi5Vc3GlpP5ZCeRyRO+mfWTSz+iQ=="],
+ "@babel/plugin-syntax-export-default-from": ["@babel/plugin-syntax-export-default-from@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-foag0BB37ROhdeIX9O8G0jX7hw0UekJc04cHMrYLOnrErsnBKqJGHJ8eDRpoCFZBvEPPygmmtw4qyU97qa4oOw=="],
- "@babel/plugin-syntax-flow": ["@babel/plugin-syntax-flow@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew=="],
+ "@babel/plugin-syntax-flow": ["@babel/plugin-syntax-flow@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ajMX6QPcyomotqwpzhkYGxcK2i/us0rs1Qo9QvUpa+Fca0FTmqrzKrctoIYLMxcOhGZldGT/BAVkRGTWBiR8gQ=="],
- "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw=="],
+ "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg=="],
"@babel/plugin-syntax-import-meta": ["@babel/plugin-syntax-import-meta@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g=="],
"@babel/plugin-syntax-json-strings": ["@babel/plugin-syntax-json-strings@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA=="],
- "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w=="],
+ "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A=="],
"@babel/plugin-syntax-logical-assignment-operators": ["@babel/plugin-syntax-logical-assignment-operators@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig=="],
@@ -1107,121 +1107,123 @@
"@babel/plugin-syntax-top-level-await": ["@babel/plugin-syntax-top-level-await@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw=="],
- "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A=="],
+ "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA=="],
"@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA=="],
- "@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.29.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1", "@babel/traverse": "^7.29.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w=="],
+ "@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-remap-async-to-generator": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA=="],
- "@babel/plugin-transform-async-to-generator": ["@babel/plugin-transform-async-to-generator@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g=="],
+ "@babel/plugin-transform-async-to-generator": ["@babel/plugin-transform-async-to-generator@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-remap-async-to-generator": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w=="],
- "@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw=="],
+ "@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ=="],
"@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.27.1", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA=="],
- "@babel/plugin-transform-class-static-block": ["@babel/plugin-transform-class-static-block@7.28.6", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ=="],
+ "@babel/plugin-transform-class-static-block": ["@babel/plugin-transform-class-static-block@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A=="],
"@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.28.4", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/traverse": "^7.28.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA=="],
- "@babel/plugin-transform-computed-properties": ["@babel/plugin-transform-computed-properties@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/template": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ=="],
+ "@babel/plugin-transform-computed-properties": ["@babel/plugin-transform-computed-properties@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/template": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA=="],
- "@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw=="],
+ "@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg=="],
- "@babel/plugin-transform-export-namespace-from": ["@babel/plugin-transform-export-namespace-from@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ=="],
+ "@babel/plugin-transform-export-namespace-from": ["@babel/plugin-transform-export-namespace-from@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA=="],
- "@babel/plugin-transform-flow-strip-types": ["@babel/plugin-transform-flow-strip-types@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/plugin-syntax-flow": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg=="],
+ "@babel/plugin-transform-flow-strip-types": ["@babel/plugin-transform-flow-strip-types@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-syntax-flow": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wRHeUjUjCZnMHmiO5bRgjFLcoEh7JyTdByOW11ahhwNa4V0bmeGEaIvt51yq0zQp2yWIpqfxXXPyUP6GFJZHOQ=="],
- "@babel/plugin-transform-for-of": ["@babel/plugin-transform-for-of@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw=="],
+ "@babel/plugin-transform-for-of": ["@babel/plugin-transform-for-of@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ=="],
- "@babel/plugin-transform-function-name": ["@babel/plugin-transform-function-name@7.27.1", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ=="],
+ "@babel/plugin-transform-function-name": ["@babel/plugin-transform-function-name@7.29.7", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg=="],
- "@babel/plugin-transform-literals": ["@babel/plugin-transform-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA=="],
+ "@babel/plugin-transform-literals": ["@babel/plugin-transform-literals@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw=="],
- "@babel/plugin-transform-logical-assignment-operators": ["@babel/plugin-transform-logical-assignment-operators@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A=="],
+ "@babel/plugin-transform-logical-assignment-operators": ["@babel/plugin-transform-logical-assignment-operators@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q=="],
- "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.28.6", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA=="],
+ "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.29.7", "", { "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ=="],
- "@babel/plugin-transform-named-capturing-groups-regex": ["@babel/plugin-transform-named-capturing-groups-regex@7.29.0", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ=="],
+ "@babel/plugin-transform-named-capturing-groups-regex": ["@babel/plugin-transform-named-capturing-groups-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ=="],
"@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA=="],
- "@babel/plugin-transform-numeric-separator": ["@babel/plugin-transform-numeric-separator@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w=="],
+ "@babel/plugin-transform-numeric-separator": ["@babel/plugin-transform-numeric-separator@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw=="],
- "@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.28.6", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-transform-destructuring": "^7.28.5", "@babel/plugin-transform-parameters": "^7.27.7", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA=="],
+ "@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.29.7", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-transform-destructuring": "^7.29.7", "@babel/plugin-transform-parameters": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A=="],
- "@babel/plugin-transform-optional-catch-binding": ["@babel/plugin-transform-optional-catch-binding@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ=="],
+ "@babel/plugin-transform-optional-catch-binding": ["@babel/plugin-transform-optional-catch-binding@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng=="],
"@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg=="],
- "@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.27.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg=="],
+ "@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g=="],
- "@babel/plugin-transform-private-methods": ["@babel/plugin-transform-private-methods@7.28.6", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg=="],
+ "@babel/plugin-transform-private-methods": ["@babel/plugin-transform-private-methods@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug=="],
- "@babel/plugin-transform-private-property-in-object": ["@babel/plugin-transform-private-property-in-object@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA=="],
+ "@babel/plugin-transform-private-property-in-object": ["@babel/plugin-transform-private-property-in-object@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA=="],
- "@babel/plugin-transform-react-display-name": ["@babel/plugin-transform-react-display-name@7.28.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA=="],
+ "@babel/plugin-transform-react-display-name": ["@babel/plugin-transform-react-display-name@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q=="],
- "@babel/plugin-transform-react-jsx": ["@babel/plugin-transform-react-jsx@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-syntax-jsx": "^7.28.6", "@babel/types": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow=="],
+ "@babel/plugin-transform-react-jsx": ["@babel/plugin-transform-react-jsx@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-syntax-jsx": "^7.29.7", "@babel/types": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A=="],
- "@babel/plugin-transform-react-jsx-development": ["@babel/plugin-transform-react-jsx-development@7.27.1", "", { "dependencies": { "@babel/plugin-transform-react-jsx": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q=="],
+ "@babel/plugin-transform-react-jsx-development": ["@babel/plugin-transform-react-jsx-development@7.29.7", "", { "dependencies": { "@babel/plugin-transform-react-jsx": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g=="],
- "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="],
+ "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw=="],
- "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
+ "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q=="],
- "@babel/plugin-transform-react-pure-annotations": ["@babel/plugin-transform-react-pure-annotations@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA=="],
+ "@babel/plugin-transform-react-pure-annotations": ["@babel/plugin-transform-react-pure-annotations@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA=="],
- "@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.29.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog=="],
+ "@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw=="],
- "@babel/plugin-transform-runtime": ["@babel/plugin-transform-runtime@7.29.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "babel-plugin-polyfill-corejs2": "^0.4.14", "babel-plugin-polyfill-corejs3": "^0.13.0", "babel-plugin-polyfill-regenerator": "^0.6.5", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w=="],
+ "@babel/plugin-transform-runtime": ["@babel/plugin-transform-runtime@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "babel-plugin-polyfill-corejs2": "^0.4.14", "babel-plugin-polyfill-corejs3": "^0.13.0", "babel-plugin-polyfill-regenerator": "^0.6.5", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xmAscdE/AsqRW7vutbPNoUmu/nF5SrLKPs7aoJgEjo35lLKA/Bc0i2rMv/hr1+Y0o1bQCiVtith3u2vdgRL39Q=="],
"@babel/plugin-transform-shorthand-properties": ["@babel/plugin-transform-shorthand-properties@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ=="],
- "@babel/plugin-transform-spread": ["@babel/plugin-transform-spread@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA=="],
+ "@babel/plugin-transform-spread": ["@babel/plugin-transform-spread@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ=="],
- "@babel/plugin-transform-sticky-regex": ["@babel/plugin-transform-sticky-regex@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g=="],
+ "@babel/plugin-transform-sticky-regex": ["@babel/plugin-transform-sticky-regex@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA=="],
"@babel/plugin-transform-template-literals": ["@babel/plugin-transform-template-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg=="],
- "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw=="],
+ "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/plugin-syntax-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw=="],
"@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.27.1", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw=="],
- "@babel/preset-react": ["@babel/preset-react@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-transform-react-display-name": "^7.28.0", "@babel/plugin-transform-react-jsx": "^7.27.1", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@babel/plugin-transform-react-pure-annotations": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ=="],
+ "@babel/preset-react": ["@babel/preset-react@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "@babel/plugin-transform-react-display-name": "^7.29.7", "@babel/plugin-transform-react-jsx": "^7.29.7", "@babel/plugin-transform-react-jsx-development": "^7.29.7", "@babel/plugin-transform-react-pure-annotations": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA=="],
"@babel/preset-typescript": ["@babel/preset-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ=="],
- "@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="],
+ "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="],
- "@babel/runtime-corejs3": ["@babel/runtime-corejs3@7.29.2", "", { "dependencies": { "core-js-pure": "^3.48.0" } }, "sha512-Lc94FOD5+0aXhdb0Tdg3RUtqT6yWbI/BbFWvlaSJ3gAb9Ks+99nHRDKADVqC37er4eCB0fHyWT+y+K3QOvJKbw=="],
+ "@babel/runtime-corejs3": ["@babel/runtime-corejs3@7.29.7", "", { "dependencies": { "core-js-pure": "^3.48.0" } }, "sha512-ppj9ouYku+RX0ljtgZd+KMO5mkM2bCqg8H2PYAFWnLsHEIKIdRojqbJ2i3eVHrisuxy7nOFCmngTDdWtUCdXUQ=="],
- "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="],
+ "@babel/template": ["@babel/template@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg=="],
- "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="],
+ "@babel/traverse": ["@babel/traverse@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-globals": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/types": "^7.29.7", "debug": "^4.3.1" } }, "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw=="],
- "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
+ "@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="],
"@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="],
- "@better-auth/core": ["@better-auth/core@1.6.11", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.39.0", "@standard-schema/spec": "^1.1.0", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/utils": "0.4.0", "@better-fetch/fetch": "1.1.21", "@cloudflare/workers-types": ">=4", "@opentelemetry/api": "^1.9.0", "better-call": "1.3.5", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" }, "optionalPeers": ["@cloudflare/workers-types", "@opentelemetry/api"] }, "sha512-LrwidLCV8azdMGjvtwp30nj9tIv1BwI3VhtC0UaGSjQkAVWw4bN42I8qwbxRziPeSQoj+zUVkOpxZzAWBDARtQ=="],
+ "@better-auth/core": ["@better-auth/core@1.6.17", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.39.0", "@standard-schema/spec": "^1.1.0", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/utils": "0.4.1", "@better-fetch/fetch": "1.3.0", "@cloudflare/workers-types": ">=4", "@opentelemetry/api": "^1.9.0", "better-call": "1.3.6", "jose": "^6.1.0", "kysely": "^0.28.5 || ^0.29.0", "nanostores": "^1.0.1" }, "optionalPeers": ["@cloudflare/workers-types", "@opentelemetry/api"] }, "sha512-ithzeL/IKsBEYeCDJs9r1KE2nwYC/6ni8oMA8NCCtP18RoCOiWErFSjrnL+XLaN6zxrB0ko7QxREjyzTNBtusQ=="],
+
+ "@better-auth/drizzle-adapter": ["@better-auth/drizzle-adapter@1.6.17", "", { "peerDependencies": { "@better-auth/core": "^1.6.17", "@better-auth/utils": "0.4.1", "drizzle-orm": "^0.45.2" }, "optionalPeers": ["drizzle-orm"] }, "sha512-Dq52cdZ0vREalUwbP8GXBbpk7XTSw5rZtY8n3nTTwrU09RELsXTi0oYQRW62MFYaUqw0mCHIT4H0emAH/5hy5Q=="],
- "@better-auth/drizzle-adapter": ["@better-auth/drizzle-adapter@1.6.11", "", { "peerDependencies": { "@better-auth/core": "^1.6.11", "@better-auth/utils": "0.4.0", "drizzle-orm": "^0.45.2" }, "optionalPeers": ["drizzle-orm"] }, "sha512-4jpkETIGZOHCf7BK4jnu22fdN6jjomH0/HhEzkaWy3+Eppi5PYlHTF/460jrTmA3Xc+Vqwp9t282ymHiEPypGw=="],
+ "@better-auth/expo": ["@better-auth/expo@1.6.17", "", { "dependencies": { "@better-fetch/fetch": "1.3.0", "better-call": "1.3.6", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "^1.6.17", "better-auth": "^1.6.17", "expo-constants": ">=17.0.0", "expo-linking": ">=7.0.0", "expo-network": ">=8.0.7", "expo-web-browser": ">=14.0.0" }, "optionalPeers": ["expo-constants", "expo-linking", "expo-network", "expo-web-browser"] }, "sha512-+LHlvNi2wBRbarZwor4XbT89NLq60f4lmPqwCey1sjPd58vmUJyugiDROE0WGdt+B0j9MJNqJqDtE3NoNfJ97Q=="],
- "@better-auth/expo": ["@better-auth/expo@1.6.11", "", { "dependencies": { "@better-fetch/fetch": "1.1.21", "better-call": "1.3.5", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "^1.6.11", "better-auth": "^1.6.11", "expo-constants": ">=17.0.0", "expo-linking": ">=7.0.0", "expo-network": ">=8.0.7", "expo-web-browser": ">=14.0.0" }, "optionalPeers": ["expo-constants", "expo-linking", "expo-network", "expo-web-browser"] }, "sha512-ahqtpj5DRF4Tu8+PZuLPkR10Q6b8AntQNsn4LPcOIp6za5IJDAsaD/go1I5qCYIRi+8YKiIXk9vh4qQM54u+hA=="],
+ "@better-auth/kysely-adapter": ["@better-auth/kysely-adapter@1.6.17", "", { "peerDependencies": { "@better-auth/core": "^1.6.17", "@better-auth/utils": "0.4.1", "kysely": "^0.28.17 || ^0.29.0" }, "optionalPeers": ["kysely"] }, "sha512-rhDrpzyGtogEDrJ3Id+nbOUVtT1DxMF9OFl2EwyktUuvTFyCrefClBdvVbmeYZPva9+ERuOsbjma+E9E0SJ0RA=="],
- "@better-auth/kysely-adapter": ["@better-auth/kysely-adapter@1.6.11", "", { "peerDependencies": { "@better-auth/core": "^1.6.11", "@better-auth/utils": "0.4.0", "kysely": "^0.28.17" }, "optionalPeers": ["kysely"] }, "sha512-/g8M9RfIjdcZDnbstSUvQiINkvdNlCeZr248zwqx2/PVksQI1MhQofbzUn3RnQnbPKp0EPwpX/dR3oudRFenUg=="],
+ "@better-auth/memory-adapter": ["@better-auth/memory-adapter@1.6.17", "", { "peerDependencies": { "@better-auth/core": "^1.6.17", "@better-auth/utils": "0.4.1" } }, "sha512-7oU+Gkve7RivIfQkclIet8+qJON6tbbRINihmgGoi67uGPTeEdTy2UixF8R8+lv91gI/Aqea2oNg/MKIalhlIA=="],
- "@better-auth/memory-adapter": ["@better-auth/memory-adapter@1.6.11", "", { "peerDependencies": { "@better-auth/core": "^1.6.11", "@better-auth/utils": "0.4.0" } }, "sha512-hpdfw0BBf8MuzLkIdmbcUZICbY9r/bhLO2RxSnkzT5+/O+0I0u2I8+m0YUP7vNllP/ZCKASHOYgXPLO75Z0f9Q=="],
+ "@better-auth/mongo-adapter": ["@better-auth/mongo-adapter@1.6.17", "", { "peerDependencies": { "@better-auth/core": "^1.6.17", "@better-auth/utils": "0.4.1", "mongodb": "^6.0.0 || ^7.0.0" }, "optionalPeers": ["mongodb"] }, "sha512-nSmolHUVR2/AIKg6WijrSxdF9DCAybbiswulw9ph4FghuCuWl9DDzfTKvG/z+/FpRaYuY+KYFitNbeRiTonn1A=="],
- "@better-auth/mongo-adapter": ["@better-auth/mongo-adapter@1.6.11", "", { "peerDependencies": { "@better-auth/core": "^1.6.11", "@better-auth/utils": "0.4.0", "mongodb": "^6.0.0 || ^7.0.0" }, "optionalPeers": ["mongodb"] }, "sha512-3Tor8rSv8vSEIMEaV2PFpPEuVhqc1gNoZ6eGvoh3LwExXXuj8madew6ob+H1pH7Aphn3Ar5PQ08AguT8TbwFAA=="],
+ "@better-auth/oauth-provider": ["@better-auth/oauth-provider@1.6.11", "", { "dependencies": { "jose": "^6.1.3", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "^1.6.11", "@better-auth/utils": "0.4.0", "@better-fetch/fetch": "1.1.21", "better-auth": "^1.6.11", "better-call": "1.3.5" } }, "sha512-iMywpOEAiAUdtvpaRS8yKye+wO3AieOB3Sfv8czkmPduzFuKBICCWuOEAElQEk5tQz3vzWx64zNlLBkgEAOhuw=="],
- "@better-auth/prisma-adapter": ["@better-auth/prisma-adapter@1.6.11", "", { "peerDependencies": { "@better-auth/core": "^1.6.11", "@better-auth/utils": "0.4.0", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@prisma/client", "prisma"] }, "sha512-Pw+7q7zTp+VSci1V+CYMvuxIbAeVMZLe4lRo46LJoAKMHfjFl5T/ycsyFvWs/DkWC7n9gZZzRDEbHp0I5FiKKw=="],
+ "@better-auth/prisma-adapter": ["@better-auth/prisma-adapter@1.6.17", "", { "peerDependencies": { "@better-auth/core": "^1.6.17", "@better-auth/utils": "0.4.1", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@prisma/client", "prisma"] }, "sha512-DW1eEXw39Hv/z34ctfoR6lB3rZRt/+X/m7j74dYTsSUt7TjaIjfhQkN01mYN7+GeLSqzGxJ132N93L7iGutKuA=="],
- "@better-auth/telemetry": ["@better-auth/telemetry@1.6.11", "", { "peerDependencies": { "@better-auth/core": "^1.6.11", "@better-auth/utils": "0.4.0", "@better-fetch/fetch": "1.1.21" } }, "sha512-hsjDHc8MZbm6/AHeNdtywrWedXevnBjmdvnHTcZub+rTVjOv+Td0roI8USKuC6uUibmrl//2rJfVCsGbopihNA=="],
+ "@better-auth/telemetry": ["@better-auth/telemetry@1.6.17", "", { "peerDependencies": { "@better-auth/core": "^1.6.17", "@better-auth/utils": "0.4.1", "@better-fetch/fetch": "1.3.0" } }, "sha512-ik7gC4UgdR3Jyb0x7yVzLTfc04x5kfjFbSdOraUbhZUXkOF+/7Ee57SuB2QgfffGEr8xhGHp46sqzF9u2D4qoQ=="],
- "@better-auth/utils": ["@better-auth/utils@0.4.0", "", { "dependencies": { "@noble/hashes": "^2.0.1" } }, "sha512-RpMtLUIQAEWMgdPLNVbIF5ON2mm+CH0U3rCdUCU1VyeAUui4m38DyK7/aXMLZov2YDjG684pS1D0MBllrmgjQA=="],
+ "@better-auth/utils": ["@better-auth/utils@0.4.1", "", { "dependencies": { "@noble/hashes": "^2.0.1" } }, "sha512-SZBPRPF3z0nBvE5ygOkxae35wnnXPRShmqFo78S+qslLeFoPu/pMgnXAuNKFMMybac3tiLaVg1e3MQW5MC+1iA=="],
- "@better-fetch/fetch": ["@better-fetch/fetch@1.1.21", "", {}, "sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A=="],
+ "@better-fetch/fetch": ["@better-fetch/fetch@1.3.0", "", {}, "sha512-Lgkl18IrUURFqa1nE38GNDWXf7XGzfxXQDCE/alCQV0yZ98YrPGtlmW61ch1T4YRt3lxrSAGA+Ft73FzuWWb3A=="],
"@biomejs/biome": ["@biomejs/biome@2.4.6", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.6", "@biomejs/cli-darwin-x64": "2.4.6", "@biomejs/cli-linux-arm64": "2.4.6", "@biomejs/cli-linux-arm64-musl": "2.4.6", "@biomejs/cli-linux-x64": "2.4.6", "@biomejs/cli-linux-x64-musl": "2.4.6", "@biomejs/cli-win32-arm64": "2.4.6", "@biomejs/cli-win32-x64": "2.4.6" }, "bin": { "biome": "bin/biome" } }, "sha512-QnHe81PMslpy3mnpL8DnO2M4S4ZnYPkjlGCLWBZT/3R9M6b5daArWMMtEfP52/n174RKnwRIf3oT8+wc9ihSfQ=="],
@@ -1257,27 +1259,23 @@
"@cloudflare/vitest-pool-workers": ["@cloudflare/vitest-pool-workers@0.8.71", "", { "dependencies": { "birpc": "0.2.14", "cjs-module-lexer": "^1.2.3", "devalue": "^5.3.2", "miniflare": "4.20250906.0", "semver": "^7.7.1", "wrangler": "4.35.0", "zod": "^3.22.3" }, "peerDependencies": { "@vitest/runner": "2.0.x - 3.2.x", "@vitest/snapshot": "2.0.x - 3.2.x", "vitest": "2.0.x - 3.2.x" } }, "sha512-keu2HCLQfRNwbmLBCDXJgCFpANTaYnQpE01fBOo4CNwiWHUT7SZGN7w64RKiSWRHyYppStXBuE5Ng7F42+flpg=="],
- "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260515.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-Wtw44el2pNbzixvTkWdfeBDTrQwQbJRz7/JUvPKV27I0pQWXbhNJPpM8cstq/pbrU5AGcA/HjFH6yPMRTIRKig=="],
+ "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260611.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-iJICldmi4sBGgi7IrQles8cStOGXM/Tmv95C4OODVs6VIbMsJPqThUM5h3uYVQNULuJ8I/aVvnJ3Eh/wZCKwuA=="],
- "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260515.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-X8EqkZej6FfmhF9AVAQ3FhyQRr9acS4RcDunMU2YiuxKHF1IU8zzH3vY30/POaG+rUu9vGDp/VgUl49VPenHJQ=="],
+ "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260611.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-yBbVXvbZyltR3I7NJdC4C4ItkItjZSiabcA/3HzEWOUQjLVKFqRh4so6ToHr70VCYh8VGeR8EDZL23igLhXqFQ=="],
- "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260515.1", "", { "os": "linux", "cpu": "x64" }, "sha512-CDC89QxQ7Y7t7RG1Jd9vj/qolE1sQRkI2OSEuV5BMJi0vW/gV4OVG6xjpdK3b1OYnSWDzF7NpvlR5Yg86q7k4g=="],
+ "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260611.1", "", { "os": "linux", "cpu": "x64" }, "sha512-PfNjpxOlaIgZFYuhD7+neEEewCN2Ud993wEEN0fmbtSOax1AK53LGqmXUDvFhnbkHxJLFAxYCSNISW8QbzaAIg=="],
- "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260515.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WxbW/PToYES4fvHXzsr/5qOiETQs/Z9iZ0mjSZAiEwq5cMLZemzGN0COx+uFb9OvQwzh6Pg159qPFnw3+i9FuA=="],
+ "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260611.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-GEp4XbuIKjlF8pakqXcUDJfKiJosD/Q7S83J0d+r+z9XIlYGfF3ntm08e2aiF5TFTwp3fnG4yMoPUAKNhNJpvQ=="],
- "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260515.1", "", { "os": "win32", "cpu": "x64" }, "sha512-WmV/iv+MHjYsvkcMVzpM2B5/mf06UUkdpVhZrtMfV9graWjBGPYFvE/eab8748RPVGKh1Xe1vXofLzDSwc08lA=="],
+ "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260611.1", "", { "os": "win32", "cpu": "x64" }, "sha512-S6JkS0kEbcCKs19RGqEPhjCRbP8GBkQwqYLp2fhBJtD/KTlwqLzOJ9E6PQ7gQKgWHtxy1NBG3oXarlNFRNU/dw=="],
- "@cloudflare/workers-oauth-provider": ["@cloudflare/workers-oauth-provider@0.4.0", "", {}, "sha512-UtbV8hjC2NloB+Ds6J6v/9HiG8rx8MbdeYGCyFwOACT5vANWzDL6SKo3W5UZymsXiameAgC7jAmtUx4cc+Qpaw=="],
-
- "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20260517.1", "", {}, "sha512-OjavgX6VpYoWlKg2xPgLKIhBeiJvNdwFVK8E1P6hF02wh1oEt1sZpTzbp9kdohprqjXo6UVqs7/AuIH0wxIcbw=="],
+ "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20260612.1", "", {}, "sha512-PMQI7XP/wrMhxyjseUHoHj6XFqkHaf4utWQ/hhefVY8oMK2LJ730oeQ7H/nZSVMexZe39DzsdOx7sf1PqMr7+Q=="],
"@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="],
"@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
- "@dabh/diagnostics": ["@dabh/diagnostics@2.0.8", "", { "dependencies": { "@so-ric/colorspace": "^1.1.6", "enabled": "2.0.x", "kuler": "^2.0.0" } }, "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q=="],
-
- "@date-fns/tz": ["@date-fns/tz@1.4.1", "", {}, "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="],
+ "@date-fns/tz": ["@date-fns/tz@1.5.0", "", {}, "sha512-lwYN/vDPeNRULcepoE/LO2Pgx+7/RV+S9ARfbc9lr2DtGkOD7pAiruHvbR1RX3Qyf6ja47EWJDMsNK5vK08DJg=="],
"@dependents/detective-less": ["@dependents/detective-less@5.0.3", "", { "dependencies": { "gonzales-pe": "^4.3.0", "node-source-walk": "^7.0.1" } }, "sha512-v6oD9Ukp+N7V4n6p5I/+mM5fIohSfkrDSGlFm5w/pYmchvbk+sMIHsLxrFJ5Lnujewj1BzWL0K84d88lwZAMQA=="],
@@ -1309,11 +1307,11 @@
"@elysiajs/openapi": ["@elysiajs/openapi@1.4.15", "", { "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-HDtGIrWfFJk6UJS7qbgRmjifbSqnnRGDM3CsU/GVJkxLbEVEkNuQDf+Quh9fGbytSrJ8g4+tX9eVjshYhCH29w=="],
- "@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],
+ "@emnapi/core": ["@emnapi/core@1.11.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q=="],
- "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
+ "@emnapi/runtime": ["@emnapi/runtime@1.11.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg=="],
- "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
+ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="],
"@emotion/is-prop-valid": ["@emotion/is-prop-valid@1.4.0", "", { "dependencies": { "@emotion/memoize": "^0.9.0" } }, "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw=="],
@@ -1383,15 +1381,15 @@
"@eslint/js": ["@eslint/js@8.57.1", "", {}, "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q=="],
- "@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.37", "", {}, "sha512-ll8twI7PcfxmjG2hMDS+QNEZ3qYmMERG0YVSJxgYHPlx3VqSNGCasMDAOgPzCE+RhKAVNqlrgTUcIFc8XrHqZQ=="],
+ "@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.38", "", {}, "sha512-IJkBtN1o8u9BW5fvSii1MyHPQ7Q0HxbWcVBvOrOzgMLpVtZw7R2w94wBTVR7kZwv3w1JNTESMmLA5Sqn1+Z36A=="],
- "@expo/cli": ["@expo/cli@55.0.30", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~55.0.17", "@expo/config-plugins": "~55.0.9", "@expo/devcert": "^1.2.1", "@expo/env": "~2.1.2", "@expo/image-utils": "^0.8.14", "@expo/json-file": "^10.0.14", "@expo/log-box": "55.0.12", "@expo/metro": "~55.1.1", "@expo/metro-config": "~55.0.21", "@expo/osascript": "^2.4.3", "@expo/package-manager": "^1.10.5", "@expo/plist": "^0.5.3", "@expo/prebuild-config": "^55.0.18", "@expo/require-utils": "^55.0.5", "@expo/router-server": "^55.0.16", "@expo/schema-utils": "^55.0.4", "@expo/spawn-async": "^1.7.2", "@expo/ws-tunnel": "^1.0.1", "@expo/xcpretty": "^4.4.0", "@react-native/dev-middleware": "0.83.6", "accepts": "^1.3.8", "arg": "^5.0.2", "better-opn": "~3.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.4", "expo-server": "^55.0.9", "fetch-nodeshim": "^0.4.10", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.1", "multitars": "^1.0.0", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.3", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "source-map-support": "~0.5.21", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "build/bin/cli" } }, "sha512-luWcCgompncWtCi1HqQfY32MVOuD0kUeARpr1Le1LeKVtZykjOwnz7YWXZo5zjISiD7L/gQnBNGVrRjvREsJqg=="],
+ "@expo/cli": ["@expo/cli@55.0.32", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~55.0.17", "@expo/config-plugins": "~55.0.10", "@expo/devcert": "^1.2.1", "@expo/env": "~2.1.2", "@expo/image-utils": "^0.8.14", "@expo/json-file": "^10.0.15", "@expo/log-box": "55.0.12", "@expo/metro": "~55.1.1", "@expo/metro-config": "~55.0.23", "@expo/osascript": "^2.4.4", "@expo/package-manager": "^1.10.5", "@expo/plist": "^0.5.4", "@expo/prebuild-config": "^55.0.18", "@expo/require-utils": "^55.0.5", "@expo/router-server": "^55.0.18", "@expo/schema-utils": "^55.0.4", "@expo/spawn-async": "^1.7.2", "@expo/ws-tunnel": "^1.0.1", "@expo/xcpretty": "^4.4.0", "@react-native/dev-middleware": "0.83.6", "accepts": "^1.3.8", "arg": "^5.0.2", "better-opn": "~3.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.4", "expo-server": "^55.0.11", "fetch-nodeshim": "^0.4.10", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.1", "multitars": "^1.0.0", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.3", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "source-map-support": "~0.5.21", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "build/bin/cli" } }, "sha512-fq+/yUYBVw5ZudT4igNyJ3WaF17R39iS7EZlrkfHkLI7Y1kmUlivabwKviLoAfepJOKjKODKpViti9EPfmG3SQ=="],
"@expo/code-signing-certificates": ["@expo/code-signing-certificates@0.0.6", "", { "dependencies": { "node-forge": "^1.3.3" } }, "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w=="],
"@expo/config": ["@expo/config@55.0.17", "", { "dependencies": { "@expo/config-plugins": "~55.0.9", "@expo/config-types": "^55.0.5", "@expo/json-file": "^10.0.14", "@expo/require-utils": "^55.0.5", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4" } }, "sha512-Y3VaRg7Jllg3MhlUOTQqHm6/dttsqcjYlnS9enhAllZvPUpTHnRA4YPETtUZlxkdMJy6y3UZe986pd/KfJ6OTg=="],
- "@expo/config-plugins": ["@expo/config-plugins@55.0.9", "", { "dependencies": { "@expo/config-types": "^55.0.5", "@expo/json-file": "~10.0.14", "@expo/plist": "^0.5.3", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-jLfpxru8dTo7eU0cqeTWuQav7byyjb37eF/mbXl1/3eTBHBvFU1VGxpeKxanUdTQAAjqzH8KGgWb0fWcce+z1w=="],
+ "@expo/config-plugins": ["@expo/config-plugins@55.0.10", "", { "dependencies": { "@expo/config-types": "^55.0.5", "@expo/json-file": "~10.0.15", "@expo/plist": "^0.5.4", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-1txnRnMLIO5lM/Of/VyvDkCwZap0YFvCyfSTIlUQamhwhx6Rh7r8TXfcIstaDYUQ7X6GTMkNxLXWbcYS6ZAFDw=="],
"@expo/config-types": ["@expo/config-types@55.0.5", "", {}, "sha512-sCmSUZG4mZ/ySXvfyyBdhjivz8Q539X1NondwDdYG7s3SBsk+wsgPJzYsqgAG/P9+l0xWjUD2F+kQ1cAJ6NNLg=="],
@@ -1407,7 +1405,7 @@
"@expo/image-utils": ["@expo/image-utils@0.8.14", "", { "dependencies": { "@expo/require-utils": "^55.0.5", "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "semver": "^7.6.0" } }, "sha512-5Sn+jG4Cw+shC2wDMXoqSAJnvERbiwzHn05FpWtD5IBflfTIs5gUmjzwiGVyjOdlMSQhgRrw/AymPbmO9h9mpQ=="],
- "@expo/json-file": ["@expo/json-file@10.0.14", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "json5": "^2.2.3" } }, "sha512-yWwBFywFv+SxkJp/pIzzA416JVYflNUh7pqQzgaA6nXDqRyK7KfrqVzk8PdUfDnqbBcaZZxpzNssfQZzp5KHrA=="],
+ "@expo/json-file": ["@expo/json-file@10.2.0", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "json5": "^2.2.3" } }, "sha512-S6XzKe3R9GQeHiUPXc3xJjOv2VJhOEwFYf7xdC2z2cUqt3kZJ9mSO877sNQloVdnW/SUCtPY3bexlM7nwq+CAQ=="],
"@expo/local-build-cache-provider": ["@expo/local-build-cache-provider@55.0.13", "", { "dependencies": { "@expo/config": "~55.0.17", "chalk": "^4.1.2" } }, "sha512-Vg5BE10UL+0yg3BVtIeiSoeHU31Qe1m3UxhBPS478ACY1zzKuxZE30x2sym/B2OIWypjmPzXDRt8J9TOGFuFNw=="],
@@ -1415,15 +1413,15 @@
"@expo/metro": ["@expo/metro@55.1.1", "", { "dependencies": { "metro": "0.83.7", "metro-babel-transformer": "0.83.7", "metro-cache": "0.83.7", "metro-cache-key": "0.83.7", "metro-config": "0.83.7", "metro-core": "0.83.7", "metro-file-map": "0.83.7", "metro-minify-terser": "0.83.7", "metro-resolver": "0.83.7", "metro-runtime": "0.83.7", "metro-source-map": "0.83.7", "metro-symbolicate": "0.83.7", "metro-transform-plugins": "0.83.7", "metro-transform-worker": "0.83.7" } }, "sha512-/wfXo5hTuAVpVLG/4hzlmD9NBGJkzkmBEMm/4VICajYRbj7y8OmqqPWbbymzHiBiHB6tI9BnsyXpQM6zVZEECg=="],
- "@expo/metro-config": ["@expo/metro-config@55.0.21", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", "@expo/config": "~55.0.17", "@expo/env": "~2.1.2", "@expo/json-file": "~10.0.14", "@expo/metro": "~55.1.1", "@expo/spawn-async": "^1.7.2", "browserslist": "^4.25.0", "chalk": "^4.1.0", "debug": "^4.3.2", "getenv": "^2.0.0", "glob": "^13.0.0", "hermes-parser": "^0.32.0", "jsc-safe-url": "^0.2.4", "lightningcss": "^1.30.1", "picomatch": "^4.0.3", "postcss": "~8.4.32", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "*" }, "optionalPeers": ["expo"] }, "sha512-pJ8G0uCxqA9KK+XCzXZF7ZI37rduD2l7Cun2e3rVAgB2yeOZagUD+VBvooU9QPiWx9e/7EbimH5/JP81JyhQlg=="],
+ "@expo/metro-config": ["@expo/metro-config@55.0.23", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", "@expo/config": "~55.0.17", "@expo/env": "~2.1.2", "@expo/json-file": "~10.0.15", "@expo/metro": "~55.1.1", "@expo/spawn-async": "^1.7.2", "browserslist": "^4.25.0", "chalk": "^4.1.0", "debug": "^4.3.2", "getenv": "^2.0.0", "glob": "^13.0.0", "hermes-parser": "^0.32.0", "jsc-safe-url": "^0.2.4", "lightningcss": "^1.30.1", "picomatch": "^4.0.3", "postcss": "^8.5.14", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "*" }, "optionalPeers": ["expo"] }, "sha512-Mkw3Ss/1LFlafH3iie3r9E13yKMyJgZqGTEkGviGf6LYp51eY5fR8ATbXrNsH69wVc2z+ty4lT/8lEA18YJv7g=="],
"@expo/metro-runtime": ["@expo/metro-runtime@55.0.11", "", { "dependencies": { "@expo/log-box": "55.0.12", "anser": "^1.4.9", "pretty-format": "^29.7.0", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-dom": "*", "react-native": "*" }, "optionalPeers": ["react-dom"] }, "sha512-4KKi/jGrIEXi2YGu0hYTVr0CEeRJy5SXbCrz9+KDZkuD3ROwKNpM1DBawni5rhPVovFnR323HBck9GaxhnfrRw=="],
- "@expo/osascript": ["@expo/osascript@2.4.3", "", { "dependencies": { "@expo/spawn-async": "^1.7.2" } }, "sha512-wbuj3EebM7W9hN/Wp4xTzKd6rQ2zKJzAxkFxkOOwyysLp0HOAgQ4/5RINyoS241pZUX2rUHq7mAJ7pcCQ8U0Ow=="],
+ "@expo/osascript": ["@expo/osascript@2.6.0", "", { "dependencies": { "@expo/spawn-async": "^1.8.0" } }, "sha512-QvqDBlJXa8CS2vRORJ4wEflY1m0vVI07uSJdIRgBrLxRPBcsrXxrtU7+wXRXMqfq9zLwNP9XbvRsXF2omoDylg=="],
- "@expo/package-manager": ["@expo/package-manager@1.10.5", "", { "dependencies": { "@expo/json-file": "^10.0.14", "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "resolve-workspace-root": "^2.0.0" } }, "sha512-nCP9Mebfl3jvOr0/P6VAuyah6PAtun+aihIL2zAtuE8uSe94JWkVZ7051i0MUVO+y3gFpBqnr8IIH5ch+VJjHA=="],
+ "@expo/package-manager": ["@expo/package-manager@1.12.1", "", { "dependencies": { "@expo/json-file": "^10.2.0", "@expo/spawn-async": "^1.8.0", "chalk": "^4.0.0", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "resolve-workspace-root": "^2.0.0" } }, "sha512-fQLiFAcFRWF53mtuLK32SUJQ1ahhrTcBZPZPedYTiUT5ha5FF+UO6bPtCc0Y/hgj0/m3HCGBAuSHjbg2kI9oPQ=="],
- "@expo/plist": ["@expo/plist@0.5.3", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-jz5oPcPDd3fygwVxwSwmO6wodTwm0Qa14NUyPy0ka7H8sFmCtNZUI2+DzVe/EXjOhq1FbEjrwl89gdlWYOnVjQ=="],
+ "@expo/plist": ["@expo/plist@0.5.4", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-Jqppj0FULNq6Zp5JtQrFICl8TtpMjwwUbxEcEC2T3z7m+TOrTQEHZXz3D3Ay7vhbmvD+VMgfWJ4ARclJXeN8Eg=="],
"@expo/prebuild-config": ["@expo/prebuild-config@55.0.18", "", { "dependencies": { "@expo/config": "~55.0.17", "@expo/config-plugins": "~55.0.9", "@expo/config-types": "^55.0.5", "@expo/image-utils": "^0.8.14", "@expo/json-file": "^10.0.14", "@react-native/normalize-colors": "0.83.6", "debug": "^4.3.1", "resolve-from": "^5.0.0", "semver": "^7.6.0", "xml2js": "0.6.0" }, "peerDependencies": { "expo": "*" } }, "sha512-2oKXyy5pyM87DJqXW5Z+Sakle6rApFFtpPhWOiNsOdoh6rOAD+EqVgyrs2OEEic8CE0tTt27w3SRfSZe/PZrxg=="],
@@ -1431,13 +1429,13 @@
"@expo/require-utils": ["@expo/require-utils@55.0.5", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8" }, "peerDependencies": { "typescript": "^5.0.0 || ^5.0.0-0" }, "optionalPeers": ["typescript"] }, "sha512-U4K/CQ2VpXuwfNGsN+daKmYOt15hCP8v/pXaYH6eut7kdYZo6SfJ1yr67BIcJ+1Gzzs+QzTxswAZChKpXmceyw=="],
- "@expo/router-server": ["@expo/router-server@55.0.16", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@expo/metro-runtime": "^55.0.11", "expo": "*", "expo-constants": "^55.0.16", "expo-font": "^55.0.7", "expo-router": "*", "expo-server": "^55.0.9", "react": "*", "react-dom": "*", "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" }, "optionalPeers": ["@expo/metro-runtime", "expo-router", "react-dom", "react-server-dom-webpack"] }, "sha512-LvAdrm039nQBG+95+ff5Rc4CsBuoc/giDhjQrgxB9lKJqC/ZTq1xbwfEZFNq6yokX6fOCs/vlxdhmSkOjMIrvg=="],
+ "@expo/router-server": ["@expo/router-server@55.0.18", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@expo/metro-runtime": "^55.0.11", "expo": "*", "expo-constants": "^55.0.16", "expo-font": "^55.0.8", "expo-router": "*", "expo-server": "^55.0.11", "react": "*", "react-dom": "*", "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" }, "optionalPeers": ["@expo/metro-runtime", "expo-router", "react-dom", "react-server-dom-webpack"] }, "sha512-W0VsvIiR48OvdlAOUlag4qspGYT/DV4srfYowlbYxwZh5Qw0MjiZAID4Zt7F0qynGZZxx8OZPpFhIX7XsqtRmg=="],
"@expo/schema-utils": ["@expo/schema-utils@55.0.4", "", {}, "sha512-65IdeeE8dAZR3n3J5Eq7LYiQ8BFGeEYCWPBCzycvafL7PkskbCyIclTQarRwf/HXFoRvezKCjaLwy/8v9Prk6g=="],
"@expo/sdk-runtime-versions": ["@expo/sdk-runtime-versions@1.0.0", "", {}, "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ=="],
- "@expo/spawn-async": ["@expo/spawn-async@1.7.2", "", { "dependencies": { "cross-spawn": "^7.0.3" } }, "sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew=="],
+ "@expo/spawn-async": ["@expo/spawn-async@1.8.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-eb9xxd/LbuEGSdua4NumCu/McVB9EM+F/JxB9pWgnERw4HQ9XyTNH1KapG6oqLWR8TuRK2LQfzJlmNi94CVobw=="],
"@expo/sudo-prompt": ["@expo/sudo-prompt@9.3.2", "", {}, "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw=="],
@@ -1475,7 +1473,7 @@
"@hono/node-server": ["@hono/node-server@1.19.14", "", { "peerDependencies": { "hono": "^4" } }, "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw=="],
- "@hookform/resolvers": ["@hookform/resolvers@5.2.2", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.55.0" } }, "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA=="],
+ "@hookform/resolvers": ["@hookform/resolvers@5.4.0", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.55.0" } }, "sha512-EIsqr/t/qbinPIhGjMdtvutIN1Kk4uwbROE9/UQ93CAVGR7GkA7Y92+fX80OzXi/OB67jVFYwKGO1WzkxmkFZw=="],
"@humanwhocodes/config-array": ["@humanwhocodes/config-array@0.13.0", "", { "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" } }, "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw=="],
@@ -1565,6 +1563,10 @@
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
+ "@kitajs/html": ["@kitajs/html@4.2.13", "", { "dependencies": { "csstype": "^3.1.3" } }, "sha512-o+8e61EsoLDPTP7rsPkYolca1YFybHuxU2Lr5fWDZCUkYT/6uBlVkvnZUdCXMQKentJL9dxwpR8/xK2Q+U4LhA=="],
+
+ "@kitajs/ts-html-plugin": ["@kitajs/ts-html-plugin@4.1.4", "", { "dependencies": { "chalk": "^5.6.2", "tslib": "^2.8.1", "yargs": "^18.0.0" }, "peerDependencies": { "@kitajs/html": "^4.2.10", "typescript": "^5.9.3" }, "bin": { "xss-scan": "dist/cli.js", "ts-html-plugin": "dist/cli.js" } }, "sha512-xK5mNrhnIy73kJFKx5yVGChJyWFRGmIaE0sjlVxVYllk5dyaEYVCrIh1N8AfnseEHka8gAqzPGW95HlkhDvnJA=="],
+
"@legendapp/state": ["@legendapp/state@3.0.0-beta.47", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "expo-sqlite": "^15.0.0" }, "optionalPeers": ["expo-sqlite"] }, "sha512-MPgPacXXSoAazAv7ulW/o0ZAtK4YHk3twvXZ241l2HqAHciHozb7tg5SMbEAc2HKUUfC3JBh+9+DXfMsYokLpQ=="],
"@lhci/cli": ["@lhci/cli@0.14.0", "", { "dependencies": { "@lhci/utils": "0.14.0", "chrome-launcher": "^0.13.4", "compression": "^1.7.4", "debug": "^4.3.1", "express": "^4.17.1", "inquirer": "^6.3.1", "isomorphic-fetch": "^3.0.0", "lighthouse": "12.1.0", "lighthouse-logger": "1.2.0", "open": "^7.1.0", "proxy-agent": "^6.4.0", "tmp": "^0.1.0", "uuid": "^8.3.1", "yargs": "^15.4.1", "yargs-parser": "^13.1.2" }, "bin": { "lhci": "./src/cli.js" } }, "sha512-TxOH9pFBnmmN7Jmo2Aimxx5UhE8veqXpHfFJDMWsCVxkwh7mGxcAWchGl84mK139SZbbRmerqZ72c+h2nG9/QQ=="],
@@ -1577,33 +1579,33 @@
"@manypkg/get-packages": ["@manypkg/get-packages@3.1.0", "", { "dependencies": { "@manypkg/find-root": "^3.1.0", "@manypkg/tools": "^2.1.0" } }, "sha512-0TbBVyvPrP7xGYBI/cP8UP+yl/z+HtbTttAD7FMAJgn/kXOTwh5/60TsqP9ZYY710forNfyV0N8P/IE/ujGZJg=="],
- "@manypkg/tools": ["@manypkg/tools@2.1.1", "", { "dependencies": { "jju": "^1.4.0", "js-yaml": "^4.1.0", "tinyglobby": "^0.2.13" } }, "sha512-CEFCOGzhFdx5sIehISBRS9Ev5D1Zp+24YT1uyOkaEcY8uAKeK+kA58NChYfUwXmAFerm3zWZWYhQViUf8XhQcg=="],
+ "@manypkg/tools": ["@manypkg/tools@2.1.2", "", { "dependencies": { "jju": "^1.4.0", "tinyglobby": "^0.2.13", "yaml": "^2.9.0" } }, "sha512-6QEf6yqFbETdwGITKq57aYoPfX/3K8XFNwsAlx0C1M7o8cb79sv1M3w+tWuWvIcSbNqrLF7OD7YpZMVVz335hQ=="],
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="],
"@mozilla/readability": ["@mozilla/readability@0.6.0", "", {}, "sha512-juG5VWh4qAivzTAeMzvY9xs9HY5rAcr2E4I7tiSSCokRFi7XIZCAu92ZkSTsIj1OPceCifL3cpfteP3pDT9/QQ=="],
- "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="],
+ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.5", "", { "dependencies": { "@tybys/wasm-util": "^0.10.2" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q=="],
"@neondatabase/serverless": ["@neondatabase/serverless@1.1.0", "", {}, "sha512-r3ZZhRjEcfEdKIZnoB1RusNgvHuaBRqfCzV4Gi+5A9yUX0S4HTws/ASWqt13wL4y4I+0rqsWGdA2w7EQXHi3+Q=="],
- "@next/env": ["@next/env@15.5.18", "", {}, "sha512-hAV85Ckd9QR6RvH04MEKwsfLTksvFpO47j9xwtoIuvuPnlwecpSi+uZTtm8HirVbtlI2Fnz//xpcSTjFdyJk+g=="],
+ "@next/env": ["@next/env@15.5.19", "", {}, "sha512-sWWluFvcv5v3Fxznmf2ZfjyoVQt/64oCnYqS90inQWGzMPK1VjvekPiz3OPHKmFT30EnHrjlbyaHLt3M0vWabw=="],
- "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.5.18", "", { "os": "darwin", "cpu": "arm64" }, "sha512-w0WvQf1n+txiwns/9pwIQteCJpZTbxzO2SE0FLcwuD4v0WEh1JPOjdyxWL21XwJsdpx8cFRjyzxzCS/siP7HcQ=="],
+ "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.5.19", "", { "os": "darwin", "cpu": "arm64" }, "sha512-jx9wWlTKueHKPvVOndyr7WuaevWCkuYqsQ8gC0TMPKAVWG3MhcdMrjfo9tvIZNXd0QOUYXXvAcZ325y8Uq7uzg=="],
- "@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.5.18", "", { "os": "darwin", "cpu": "x64" }, "sha512-znn71QmDuxm+BOaglihMZfvyySMnNljkVIY5Z2TCssBmm+WqL6c19VhtH5ktFkHa8EZ2bnTUpcNcmNSQsg67og=="],
+ "@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.5.19", "", { "os": "darwin", "cpu": "x64" }, "sha512-291KFcsIQ3OenRdiUDFOR6W3wezzH4auENXm1gbm1Bjd4ANMMRgxPrWTUztQN43BnVoVuMnHCrLeECIMwgFKbA=="],
- "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.5.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-yPPe5MNL+igZUa+OsqQJisqSfh6oarIuA1Q0BDxljGJhRQyZeP+WRHh7rs/jZUGMh5aY0YdIjXZG0VohkKkUdw=="],
+ "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.5.19", "", { "os": "linux", "cpu": "arm64" }, "sha512-WeH+nelQyyMeE2f8FxBRZNrGipya5zHZV2vjzfCOAYyiI6am+NbnWAAldOBFQBB2w0DjJcsvrKqoFT2b7+5YoA=="],
- "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.5.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-glaCczEWIrHsokFZ3pP08U4BpKxwIdnT+txdOM32OBgpL9Yw4aqx8NejmgtZQZOdstQ5f0L3CasIZudzCuD+nw=="],
+ "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.5.19", "", { "os": "linux", "cpu": "arm64" }, "sha512-5xTOE0lDlDCSSfp+BAif7j17VRRCjWp//ZPZy6NI0QpdrhxtQnsZguSx0xAAZ0c9XZLrLLwCe/XVe5YPrRilKw=="],
- "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.5.18", "", { "os": "linux", "cpu": "x64" }, "sha512-oUfg2EgJmU3R0OCOWiokGFUTvZiPfXtriXiuF3YNxRoROCdgvTedHIzYoeKH34gsZxS/V7mHbfq2hpAHwhH1/A=="],
+ "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.5.19", "", { "os": "linux", "cpu": "x64" }, "sha512-LTxRmMgqqMv05Had879W00Fm53quiJd3Zuz8h1JSNJ3nGSlbZ/7Tjs1tKyScgN3Au3t3MyPsjPlq60fMmSHLsg=="],
- "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.5.18", "", { "os": "linux", "cpu": "x64" }, "sha512-JLxSP3KTd9iu/bvUMQxH7RJo9xKSHf55/6RPE4a6FTSZygGn7uvZbCej0AHXydwkggQGSD9UddSjwv6Xz5ESfA=="],
+ "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.5.19", "", { "os": "linux", "cpu": "x64" }, "sha512-eoNQSpA5PQfB9wBO4RA47MTDXWz1fizy9Y3Z6e4DetYIF3dvjuu8sj7aIGn/bFCU6lnFzTK34NtCaffP4NsQ7Q=="],
- "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.5.18", "", { "os": "win32", "cpu": "arm64" }, "sha512-ir1v7enP52K2HNz3tQQvwF+x7VNxBk1ciiZ18WBPvxf4C59IqdfmHPJYK3vH7rSxpuCVw/8C712wTXNAtEp+NA=="],
+ "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.5.19", "", { "os": "win32", "cpu": "arm64" }, "sha512-6UNt2dFuCHOe446sm/Kp69nUe8/wIhnh9bm6Xcqw4qEWCOppLMOvhTBVgvM7invVUNr4SPpP6NOQsACtn2IN9Q=="],
- "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.5.18", "", { "os": "win32", "cpu": "x64" }, "sha512-LIu5me6QTANCd25E7I5uIEfvgQ06RK7tvHAbYo3zCb3VpxQEPvMcSpd87NwUABDT6MbGPdEGR5VRiK4PPTJhQg=="],
+ "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.5.19", "", { "os": "win32", "cpu": "x64" }, "sha512-PhmojAHyqMne56HBLGu9dhDnHPuFmEjrXSQMM/nW0J6j849lk3ESrVtqNJcCk8CKOV7brpTTbaYAjwKPzKM69w=="],
"@noble/ciphers": ["@noble/ciphers@2.2.0", "", {}, "sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA=="],
@@ -1619,7 +1621,7 @@
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.41.1", "", {}, "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA=="],
- "@oxc-project/types": ["@oxc-project/types@0.130.0", "", {}, "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q=="],
+ "@oxc-project/types": ["@oxc-project/types@0.135.0", "", {}, "sha512-wR+xRdFkUBMvcAjBJ2q2kcZM6d+DKu2NgoOyxZgYwZdLhmiv6+rnO8PZ/P68kMiZtIKm+pW7zyEJ4kSOs0vo+Q=="],
"@packrat-ai/nativewindui": ["@packrat-ai/nativewindui@2.0.6", "https://npm.pkg.github.com/download/@packrat-ai/nativewindui/2.0.6/555a865d3d9f1ca8a3ccf1318c26286d7b2f522c", { "peerDependencies": { "@expo/vector-icons": ">=15.0.0", "@gorhom/bottom-sheet": "^5.1.2", "@react-native-community/datetimepicker": "^8.4.0", "@react-native-community/slider": "^5.0.0", "@react-native-picker/picker": "^2.11.0", "@react-native-segmented-control/segmented-control": "^2.5.0", "@react-navigation/drawer": "^7.1.1", "@react-navigation/elements": "^2.3.1", "@react-navigation/native": "^7.0.14", "@rn-primitives/alert-dialog": "^1.1.0", "@rn-primitives/avatar": "^1.0.4", "@rn-primitives/checkbox": "^1.1.0", "@rn-primitives/context-menu": "^1.1.0", "@rn-primitives/dropdown-menu": "^1.1.0", "@rn-primitives/hooks": "^1.1.0", "@rn-primitives/portal": "^1.1.0", "@rn-primitives/slot": "^1.1.0", "@shopify/flash-list": "^2.0.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "expo-blur": "~55.0.0", "expo-device": "~55.0.0", "expo-glass-effect": "~55.0.0", "expo-haptics": "~55.0.0", "expo-image": "~55.0.0", "expo-linear-gradient": "~55.0.0", "expo-navigation-bar": "~55.0.0", "expo-router": "~55.0.0", "expo-symbols": "~55.0.0", "nativewind": "^4.2.3", "react": ">=19.2.0", "react-native": ">=0.83.0", "react-native-keyboard-controller": "^1.21.0", "react-native-reanimated": ">=4.2.0", "react-native-safe-area-context": ">=5.6.0", "react-native-screens": ">=4.23.0", "react-native-uitextview": "^1.1.4", "rn-icon-mapper": "^0.0.1", "tailwind-merge": "^2.2.1" } }, "sha512-AB8MfYtVajR8i1MyQUeeJ7QuoHpkeGPqKjmv4Gu5+FZRDM1LNqtf3YTfuFEEoOx7UJc7/5tEWsDo8hOeOQBzCg=="],
@@ -1637,6 +1639,8 @@
"@packrat/config": ["@packrat/config@workspace:packages/config"],
+ "@packrat/consent-ui": ["@packrat/consent-ui@workspace:packages/consent-ui"],
+
"@packrat/constants": ["@packrat/constants@workspace:packages/constants"],
"@packrat/db": ["@packrat/db@workspace:packages/db"],
@@ -1669,7 +1673,7 @@
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
- "@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="],
+ "@pkgr/core": ["@pkgr/core@0.3.6", "", {}, "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA=="],
"@playwright/test": ["@playwright/test@1.60.0", "", { "dependencies": { "playwright": "1.60.0" }, "bin": { "playwright": "cli.js" } }, "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag=="],
@@ -1677,7 +1681,7 @@
"@pnpm/network.ca-file": ["@pnpm/network.ca-file@1.0.2", "", { "dependencies": { "graceful-fs": "4.2.10" } }, "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA=="],
- "@pnpm/npm-conf": ["@pnpm/npm-conf@3.0.2", "", { "dependencies": { "@pnpm/config.env-replace": "^1.1.0", "@pnpm/network.ca-file": "^1.0.1", "config-chain": "^1.1.11" } }, "sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA=="],
+ "@pnpm/npm-conf": ["@pnpm/npm-conf@3.0.3", "", { "dependencies": { "@pnpm/config.env-replace": "^1.1.0", "@pnpm/network.ca-file": "^1.0.1", "config-chain": "^1.1.11" } }, "sha512-//0sR/cow/s4ICQaYoAobOl4aU8cjU6x/V24V7XkKotb9+O+3zySIYp146vpaobYHnxa4pZX8NkV54Z5AwbDKA=="],
"@poppinss/colors": ["@poppinss/colors@4.1.6", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg=="],
@@ -1687,115 +1691,115 @@
"@puppeteer/browsers": ["@puppeteer/browsers@2.3.0", "", { "dependencies": { "debug": "^4.3.5", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.4.0", "semver": "^7.6.3", "tar-fs": "^3.0.6", "unbzip2-stream": "^1.4.3", "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" } }, "sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA=="],
- "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
+ "@radix-ui/number": ["@radix-ui/number@1.1.2", "", {}, "sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig=="],
- "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
+ "@radix-ui/primitive": ["@radix-ui/primitive@1.1.4", "", {}, "sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ=="],
- "@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA=="],
+ "@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collapsible": "1.1.13", "@radix-ui/react-collection": "1.1.9", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-xITxBB2p5m5tAe7M0F95kb4uAh7jSIKGlExMEm93HlW+XxZHV2eXFbPWLktd4JhRiwcnXNbO7iekcrbZy6ZCvA=="],
- "@radix-ui/react-alert-dialog": ["@radix-ui/react-alert-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dialog": "1.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw=="],
+ "@radix-ui/react-alert-dialog": ["@radix-ui/react-alert-dialog@1.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-dialog": "1.1.16", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-slot": "1.2.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vPaIgo0mxYlvcFaM9jB2Uot9TjGXMuAPEvrc6BOLeV+I5U8s1dkIoouYaa6lmSfc5SPMo5x5djOTOTvaigdGMQ=="],
- "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
+ "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-yqHW5WQ/cTpU/un7dqqIKNy2iRU8BC0JB78PEzTfCCYvZu1U6W9KwObAniMk9nhSfyotKPQTYaUD/HB0f5muig=="],
- "@radix-ui/react-aspect-ratio": ["@radix-ui/react-aspect-ratio@1.1.8", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5nZrJTF7gH+e0nZS7/QxFz6tJV4VimhQb1avEgtsJxvvIp5JilL+c58HICsKzPxghdwaDt48hEfPM1au4zGy+w=="],
+ "@radix-ui/react-aspect-ratio": ["@radix-ui/react-aspect-ratio@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Xy+Dpxt/5n9rVTdPrNFmf8GwG1NlT1pzCF/z1MgOGZMLZWdWl+km+ZRWGQAPEhbkzSwYEsfYmTca8NhUtVxqnw=="],
- "@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.1.11", "", { "dependencies": { "@radix-ui/react-context": "1.1.3", "@radix-ui/react-primitive": "2.1.4", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q=="],
+ "@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.1.12", "", { "dependencies": { "@radix-ui/react-context": "1.1.4", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-is-hydrated": "0.1.1", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-NQCQyWC7QrDPhjMn8hUqFeU0lUrprIgm1AyMgLbzuQJibNnatdc3SSMo3/UGFu/eUkJUU1cEcKCnyhXTQzq6tA=="],
- "@radix-ui/react-checkbox": ["@radix-ui/react-checkbox@1.3.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw=="],
+ "@radix-ui/react-checkbox": ["@radix-ui/react-checkbox@1.3.4", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-previous": "1.1.2", "@radix-ui/react-use-size": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m3JmIOAX5ZzZ6VPjxEU2dbTOhoHi0nT5riwcDwe8idocsWf4a5DXJLDtZ6LfJwMBx7W+A2b7kp2TgPEKtaiF6A=="],
- "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA=="],
+ "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F0s8+p2XNpfc3k02zBfB0jPWbkHVG162+p7BdUMyJ2308QMqZ+oaclX+FAzKFovgL5OqRU+Rvy6f/vbdlJVaqA=="],
- "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
+ "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.9", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-slot": "1.2.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zuSVi7ziP7uQRqc+yGxsKJfNkdyHv3ZKDaHe0gzg4dRgws96TPKWIiz84tVHP4GEcEl8bC0mdt17NkcxaJHmaQ=="],
- "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
+ "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA=="],
- "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
+ "@radix-ui/react-context": ["@radix-ui/react-context@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg=="],
- "@radix-ui/react-context-menu": ["@radix-ui/react-context-menu@2.2.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww=="],
+ "@radix-ui/react-context-menu": ["@radix-ui/react-context-menu@2.3.0", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-menu": "2.1.17", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-d7CouXhAW+CGmFOqmB+IEvd3E9GcaqfgvfjCc3hfulp2pkaUCEVEGa0SN5nNWYA+IvQ6g1Pt+S5dpNn1AoY9hg=="],
- "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="],
+ "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.12", "@radix-ui/react-focus-guards": "1.1.4", "@radix-ui/react-focus-scope": "1.1.9", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-portal": "1.1.11", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-slot": "1.2.5", "@radix-ui/react-use-controllable-state": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-l9ok83YBclEZhbjgzt76Hw733e6cvRKPNgO6GJ/IETlufXG9p+fRu2wlvpImQvR6xdJ8h7J8J2DBvsPEiEsKMw=="],
- "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
+ "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA=="],
- "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
+ "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-escape-keydown": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-MhoruH6xEzsbvOmo4TNgMfmtvRGyDZw4MDSdf4ybMHfezjqwzv6hyd4lsMzBp8K9Sn6sGzCF62x1I7BYUECXOg=="],
- "@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw=="],
+ "@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.17", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-menu": "2.1.17", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-S6b3Jm57sY5EdDyOMLkacbB0qMnKhy1RCKZCt795ZkmtUOAvojYIZ5p7dXHIh5Cyr3jCLLI5/g64V3FKLudZmw=="],
- "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="],
+ "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q=="],
- "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="],
+ "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.9", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-callback-ref": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9Se8t+Zry+1rEOL7Y6l/4ANYU/TOtAtf8O2fKdwLltcaMcm6kOqYGbzO4tMFQ0bvzO920pRAoHpFZ4W85S3keQ=="],
- "@radix-ui/react-hover-card": ["@radix-ui/react-hover-card@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg=="],
+ "@radix-ui/react-hover-card": ["@radix-ui/react-hover-card@1.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.12", "@radix-ui/react-popper": "1.3.0", "@radix-ui/react-portal": "1.1.11", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-hAileDBtd6CX7nlZOarOnISQ6PP4q0e16BX51ulzdZ+7IzjL0sDTVpFdmSYrIjw6zVNsfQBao5gG6AWr3qwfvA=="],
- "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
+ "@radix-ui/react-id": ["@radix-ui/react-id@1.1.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA=="],
- "@radix-ui/react-label": ["@radix-ui/react-label@2.1.8", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A=="],
+ "@radix-ui/react-label": ["@radix-ui/react-label@2.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-rDoTeMbCwRVcnmo7NGT9IlPo1yXmEI+xc1URP3oeewwZEV4mdTp1dYUhYbQdo4D1q2SjKVvv4N1gNY77QAQtjA=="],
- "@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg=="],
+ "@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.17", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collection": "1.1.9", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.12", "@radix-ui/react-focus-guards": "1.1.4", "@radix-ui/react-focus-scope": "1.1.9", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-popper": "1.3.0", "@radix-ui/react-portal": "1.1.11", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-roving-focus": "1.1.12", "@radix-ui/react-slot": "1.2.5", "@radix-ui/react-use-callback-ref": "1.1.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-fmbNnFyf+JYCN0DhhWnEdUTDnZD1mXaPQWivdsPIb8oOSbARfD3LIQJbLCG8a8QLCwoMxiJ7GVPIFcC8Dw8v2Q=="],
- "@radix-ui/react-menubar": ["@radix-ui/react-menubar@1.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA=="],
+ "@radix-ui/react-menubar": ["@radix-ui/react-menubar@1.1.17", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collection": "1.1.9", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-menu": "2.1.17", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-roving-focus": "1.1.12", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-AKtZ4O782yO7qwIyq73WpulYt1IHhQ0htDb6wNcxzxnSDCcSWMVBiU9ycpcA90XzQO4IVIxIErtak6Kg/Vt0rQ=="],
- "@radix-ui/react-navigation-menu": ["@radix-ui/react-navigation-menu@1.2.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w=="],
+ "@radix-ui/react-navigation-menu": ["@radix-ui/react-navigation-menu@1.2.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collection": "1.1.9", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.12", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-layout-effect": "1.1.2", "@radix-ui/react-use-previous": "1.1.2", "@radix-ui/react-visually-hidden": "1.2.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/fS8hKCcRt4DwCGa5QIB3juRXmfYSOk4a2AEe/BDIyy7Hm+eje2Y13oUx5zejl+wFt1owrM7E8NWlbaEl5EGpg=="],
- "@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA=="],
+ "@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.12", "@radix-ui/react-focus-guards": "1.1.4", "@radix-ui/react-focus-scope": "1.1.9", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-popper": "1.3.0", "@radix-ui/react-portal": "1.1.11", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-slot": "1.2.5", "@radix-ui/react-use-controllable-state": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-8brVpAU5Uq7Bh0c8EFc4ZTf2JJTYn0o+1L+CUJB3UYIOkTjKGMgoHvduylrahdmNlr3DfH0rFq2DrbNZXgaspw=="],
- "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.8", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw=="],
+ "@radix-ui/react-popper": ["@radix-ui/react-popper@1.3.0", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.9", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.2", "@radix-ui/react-use-rect": "1.1.2", "@radix-ui/react-use-size": "1.1.2", "@radix-ui/rect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9PB589e1aWZbrlFUHdz6WiPCL+xLZHQFX7oibqG/6Q0SwOkxDyQX9W/cyPa+sAPPKuC8cpLCpRczE5a/1DiwVQ=="],
- "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],
+ "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.11", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UEytdjgEh2tJGgD/gZK4FUx6t1rNIlM3U0DENhSrG7I75FGm1DnaDuVUWF1pWAWUwGmn1sCJ1VGHn8LhN1aTOw=="],
- "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
+ "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.6", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ=="],
- "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
+ "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.5", "", { "dependencies": { "@radix-ui/react-slot": "1.2.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zifXeB8Y88qCYx8PLZ5oQb32KwZub+s925mMoZsBBq9KUQqWKkREubTfs6ASjRPPBe7Jt9O8OHH89+95VG+grA=="],
- "@radix-ui/react-progress": ["@radix-ui/react-progress@1.1.8", "", { "dependencies": { "@radix-ui/react-context": "1.1.3", "@radix-ui/react-primitive": "2.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA=="],
+ "@radix-ui/react-progress": ["@radix-ui/react-progress@1.1.9", "", { "dependencies": { "@radix-ui/react-context": "1.1.4", "@radix-ui/react-primitive": "2.1.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-+EOkvg1Zn1vI1+fRDfRSAiJ7BWfcDAo5ASMmbqrcLZ4s4USk2FGkoHgeb2X+CkUgo2zJMiyObwf1k44CrRWsyw=="],
- "@radix-ui/react-radio-group": ["@radix-ui/react-radio-group@1.3.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ=="],
+ "@radix-ui/react-radio-group": ["@radix-ui/react-radio-group@1.4.0", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-roving-focus": "1.1.12", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-previous": "1.1.2", "@radix-ui/react-use-size": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-eHdV5bLx9sH+tBnbDjkIBdvQEH/c6MEtQYhTbxkaDK9qsIFFLtmJYEQFVdwhnruWotLfQmIuWEL/J+L3utE8rQ=="],
- "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="],
+ "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collection": "1.1.9", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-FvgPt1bRmg8Xt2QpF7NUZW3dE0ZQHGm41dAdgT2J2GJPoIXz+9Em3NobAxf4fupcxhgHu03E5CRiU2MWvObXyg=="],
- "@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.10", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A=="],
+ "@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.11", "", { "dependencies": { "@radix-ui/number": "1.1.2", "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-DS39ziOgea75U/TrXKU2/oKp0be2jrDHnzFLvahg/0iNAT1Zq16e4Uw0WXwyXvsK+mG3BRyMb7A3NRZMDuEXtQ=="],
- "@radix-ui/react-select": ["@radix-ui/react-select@2.2.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ=="],
+ "@radix-ui/react-select": ["@radix-ui/react-select@2.3.0", "", { "dependencies": { "@radix-ui/number": "1.1.2", "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collection": "1.1.9", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.12", "@radix-ui/react-focus-guards": "1.1.4", "@radix-ui/react-focus-scope": "1.1.9", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-popper": "1.3.0", "@radix-ui/react-portal": "1.1.11", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-slot": "1.2.5", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-layout-effect": "1.1.2", "@radix-ui/react-use-previous": "1.1.2", "@radix-ui/react-visually-hidden": "1.2.5", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mENc7WpJvJcW8hlMpzfFcHcEhTvYS5JMBmi9HVC1Q00uhBwML086MHYUV8QQdQv6lcu0Wg8dzd1RB8AFADcG/g=="],
- "@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.8", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g=="],
+ "@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-gvgW+JV/Mbjj6darztTetnmElpQEzZrXpJvfj+dOxNAxiyHEAyUvEjjl4zxblvmjmKmi3jfPoy7ZdxzCuUBJSA=="],
- "@radix-ui/react-slider": ["@radix-ui/react-slider@1.3.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw=="],
+ "@radix-ui/react-slider": ["@radix-ui/react-slider@1.4.0", "", { "dependencies": { "@radix-ui/number": "1.1.2", "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collection": "1.1.9", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-layout-effect": "1.1.2", "@radix-ui/react-use-previous": "1.1.2", "@radix-ui/react-use-size": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-RHcPlLOThRJM51DSIC33ZnpDEBYhyEFroVWkd2P54PGGjkmAt14RboYUU9E1MFst666zFHM0tGtWvMjSOtU1pw=="],
- "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
+ "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-rCMO3QsIVKv5JTY5CVbo2MvO77SpEqqYc8AvRE7OWqRDOIqAKjsp+DrmnY9uc8NPdxB5E2z47HTYGeE2+NTptg=="],
- "@radix-ui/react-switch": ["@radix-ui/react-switch@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ=="],
+ "@radix-ui/react-switch": ["@radix-ui/react-switch@1.3.0", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-previous": "1.1.2", "@radix-ui/react-use-size": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-GP1EZwhoZO/GGnhM1P5/2Vpm8iN8EnngyU0oezn2l78kN8tj25pyrvjIaT7azBhK615KSt+P2w39y57YV5jVkA=="],
- "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="],
+ "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-roving-focus": "1.1.12", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-D5jwp9JNuwDeCw3CYD2Fz+sSHo0droQjC8u75dJHe4aWr5q6yBiXZU+hurXnKudRgEpUkD5TsI6bjHPo5ThUxA=="],
- "@radix-ui/react-toast": ["@radix-ui/react-toast@1.2.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g=="],
+ "@radix-ui/react-toast": ["@radix-ui/react-toast@1.2.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collection": "1.1.9", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.12", "@radix-ui/react-portal": "1.1.11", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-layout-effect": "1.1.2", "@radix-ui/react-visually-hidden": "1.2.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-WUymDDiN2DpoGudRN1aW4wF5O3BNQjZZO/5nngPoNiEVqjyOzirvZZNO0R6dC1ifucSINVaSv8JX1aq47VGgiA=="],
- "@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ=="],
+ "@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-FikrKJemoBGZQ6uRID0HJqSPBP6D7OppdD2OhLl0ZYLlAyPXI7MezoYGmumwNkrAoRm35xXkb4C8JPfJZZzcaw=="],
- "@radix-ui/react-toggle-group": ["@radix-ui/react-toggle-group@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-toggle": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q=="],
+ "@radix-ui/react-toggle-group": ["@radix-ui/react-toggle-group@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-roving-focus": "1.1.12", "@radix-ui/react-toggle": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TEgECgJaWGAHJJZGzNNEYTNBdIXqX7LchANycpyP7DkfjmuiSN7ISt1k/ZRGVJgVJonsgP4vwaiKMn5utrcwWQ=="],
- "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="],
+ "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.9", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.12", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-popper": "1.3.0", "@radix-ui/react-portal": "1.1.11", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.5", "@radix-ui/react-slot": "1.2.5", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-visually-hidden": "1.2.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-u6F9MmTtBSLkiXNVDrtB/yPCZarM9smNswC24YYLV/M+bth6J3Gs3vlJezEoFwKZvPvxhCpUYdUnOsNG/0XOlA=="],
- "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
+ "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw=="],
- "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
+ "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.3", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.3", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA=="],
- "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
+ "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.3", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA=="],
- "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
+ "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.2", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-2uVLvLjgO7NZCWw01/FdqRwmA42J0BcjPMUCA+koFEOAb+zjqIP7SiFz/7zWPrKnVmSqr76Omq2ALyCuX4dhLw=="],
- "@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.0", "", { "dependencies": { "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA=="],
+ "@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-qwOiz4Tjo8CNnrOLAYUMXeZwDzXgXpvK4TKQPmWLECM9XoWvA6+0Z2/7Ag3A4ivjS4ovbLJPbskkxioFyBhr8A=="],
- "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
+ "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA=="],
- "@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ=="],
+ "@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-IGBQPtRFdhN6MQ8dbegVmBq1LVZluya3F1jWY+puIcQC3MHctRwTDSBWCkL/3ZcnMJLTMJ++Z+ktmvg0F89iCw=="],
- "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="],
+ "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.2", "", { "dependencies": { "@radix-ui/rect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-d8a+bBY/FxikNPlgJJoaBHZX+zKVbWHYJGTLnLvveQgFSTntkGdEKv3JDtHrMS0DNYpllz2nRsTLGLKYttbpmw=="],
- "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="],
+ "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-giWQp+4mxjBPt4KZ0MmyuykFNWfbDxKt4x+fPkRYmgRFJSbCZFzUglvMb/Kjn38tm10YP4ufiQZDx3zna4LU6w=="],
- "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.3", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug=="],
+ "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.5", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tPcHNI3FajdDBFpl/Ez1m2WL0ufJqBKyHxMDBvKitopamK36WwBGOMicuMEZKkM5Wce41QxUyv6BsiqfrWBiGg=="],
- "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
+ "@radix-ui/rect": ["@radix-ui/rect@1.1.2", "", {}, "sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA=="],
"@react-leaflet/core": ["@react-leaflet/core@3.0.0", "", { "peerDependencies": { "leaflet": "^1.9.0", "react": "^19.0.0", "react-dom": "^19.0.0" } }, "sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ=="],
@@ -1839,19 +1843,19 @@
"@react-native/virtualized-lists": ["@react-native/virtualized-lists@0.83.6", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^19.2.0", "react": "*", "react-native": "*" }, "optionalPeers": ["@types/react"] }, "sha512-gNSFXeb4P7qHtauLvl+zESroULIyX6Ltpvau3dhwy/QmfanBv0KUcrIU/7aVXxtWcXgp+54oWJyu2LIrsZ9+LQ=="],
- "@react-navigation/bottom-tabs": ["@react-navigation/bottom-tabs@7.16.1", "", { "dependencies": { "@react-navigation/elements": "^2.9.18", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0" }, "peerDependencies": { "@react-navigation/native": "^7.2.4", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-wjFATJmbq0K8B96Ax0JcK2+Eu7syfYvQ5qUd/tgcv8JuCYLwKKqojJMAl31qdjpKqFG09pQ6TSdEDHOek60CAA=="],
+ "@react-navigation/bottom-tabs": ["@react-navigation/bottom-tabs@7.18.0", "", { "dependencies": { "@react-navigation/elements": "^2.9.23", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0" }, "peerDependencies": { "@react-navigation/native": "^7.3.1", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-jH5T+1T9wfz8NGpHiuALs+fQAnZzVDG8tRssbckMlvkao0lYm+usBomrn8KJo2m8TaBWn133UPEEBNFk9uG+MA=="],
- "@react-navigation/core": ["@react-navigation/core@7.17.4", "", { "dependencies": { "@react-navigation/routers": "^7.5.5", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "query-string": "^7.1.3", "react-is": "^19.1.0", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": ">= 18.2.0" } }, "sha512-Rv9E2oNNQEkPGpmu9q+vJwGJRSQR6LBg5L+Yo1QHjtwGbHUbjkIKOdYymDZoZYgNzX2OD4rAIlfuzbDKa3cCeA=="],
+ "@react-navigation/core": ["@react-navigation/core@7.20.0", "", { "dependencies": { "@react-navigation/routers": "^7.6.0", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "query-string": "^7.1.3", "react-is": "^19.1.0", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": ">= 18.2.0" } }, "sha512-Lqw5cDQWWxiQnaWv6RhQV95Wr4fh+38/IFVNn1grssyLWV+wXGJjlucXOoU7EVh9jdtcLT8pGyzvsyrvSDywWA=="],
- "@react-navigation/drawer": ["@react-navigation/drawer@7.10.2", "", { "dependencies": { "@react-navigation/elements": "^2.9.18", "color": "^4.2.3", "react-native-drawer-layout": "^4.2.4", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "@react-navigation/native": "^7.2.4", "react": ">= 18.2.0", "react-native": "*", "react-native-gesture-handler": ">= 2.0.0", "react-native-reanimated": ">= 2.0.0", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-/ccYFvBPJNzOYioiMQsqjAR4dcQ+7+yjzcuMDTKgsMahLD7Jn7FdOFNtGwMaIQWhfK8KFVMH2KOXAlH/uAGZXw=="],
+ "@react-navigation/drawer": ["@react-navigation/drawer@7.12.0", "", { "dependencies": { "@react-navigation/elements": "^2.9.23", "color": "^4.2.3", "react-native-drawer-layout": "^4.2.5", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "@react-navigation/native": "^7.3.1", "react": ">= 18.2.0", "react-native": "*", "react-native-gesture-handler": ">= 2.0.0", "react-native-reanimated": ">= 2.0.0", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-OP8ti/ESCPng79/UzafQxYYP/EVHmgSCnNL91RGnT3ghsIpjr8xut5Ax+5N5+vwfEWBbHaxPCeuVHwukcmdtQw=="],
- "@react-navigation/elements": ["@react-navigation/elements@2.9.18", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@react-native-masked-view/masked-view": ">= 0.2.0", "@react-navigation/native": "^7.2.4", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0" }, "optionalPeers": ["@react-native-masked-view/masked-view"] }, "sha512-mKEvDr6CkCVYZSb8W9WubNseihL+1c8M7ktZJCTCbMk8rQgdQfkdRNwpSUQKspdGpUHCb9cyzvaiuzl1NtjVgw=="],
+ "@react-navigation/elements": ["@react-navigation/elements@2.9.23", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@react-native-masked-view/masked-view": ">= 0.2.0", "@react-navigation/native": "^7.3.1", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0" }, "optionalPeers": ["@react-native-masked-view/masked-view"] }, "sha512-sp+FgihDyMBoEXoCUsUCT/iibN/sg6LYGq/rciy6NjT8bnfv4Cu3el8SAaJ0bfRG3tdchHy6gweKmcaJs/BAYQ=="],
- "@react-navigation/native": ["@react-navigation/native@7.2.4", "", { "dependencies": { "@react-navigation/core": "^7.17.4", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*" } }, "sha512-eWC2D3JjhYLId2fVTZhhCiUpWIaPhO9XyEb7Wq8ElmOHyIODlbOzgZ0rKia02OIsDKr9BzZl2sK1dL70yMxDaw=="],
+ "@react-navigation/native": ["@react-navigation/native@7.3.1", "", { "dependencies": { "@react-navigation/core": "^7.20.0", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "standard-navigation": "^0.0.7", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*" } }, "sha512-g1o8jBm87WviR0Eq0wT0M43TSi+uBTz4x8YfHh4XRQ+FHqhNr+uGbuxtGu72QhHtOz0LWnb8UWyvd+M6xWkWHQ=="],
- "@react-navigation/native-stack": ["@react-navigation/native-stack@7.15.1", "", { "dependencies": { "@react-navigation/elements": "^2.9.18", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0", "warn-once": "^0.1.1" }, "peerDependencies": { "@react-navigation/native": "^7.2.4", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-kNrJggwoB/onC0MpZIuZ6qaqeAziFchz+W9txBzhd6qbWmB1OkPVUnu6fWgc6BQc7MeMf59djVmqgX+6kJU1Ug=="],
+ "@react-navigation/native-stack": ["@react-navigation/native-stack@7.17.3", "", { "dependencies": { "@react-navigation/elements": "^2.9.23", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0", "warn-once": "^0.1.1" }, "peerDependencies": { "@react-navigation/native": "^7.3.1", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-8X9AxW0BACB62eCL+DAL+Nf5lFAxXi3w1qaj2D/i0axYjxUZbI5AwrfuHjRo0B231K5WWa6HKyscF07IDHcKHg=="],
- "@react-navigation/routers": ["@react-navigation/routers@7.5.5", "", { "dependencies": { "nanoid": "^3.3.11" } }, "sha512-9/hhMte12Kgu+pMnLfA4EWJ0OQmIEAMVMX06FPH2yGkEQSQ3JhhCN/GkcRikzQhtEi97VYYQA15umptBUShcOQ=="],
+ "@react-navigation/routers": ["@react-navigation/routers@7.6.0", "", { "dependencies": { "nanoid": "^3.3.11" } }, "sha512-lblhDXfS75jLc7G2K7BZGM+7cjqQXk13X/MA4fq/12r62zM+fBhhreLzYflSitrDDXFRJpSvJXy0ziiGU04Xow=="],
"@reduxjs/toolkit": ["@reduxjs/toolkit@2.12.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", "immer": "^11.0.0", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, "optionalPeers": ["react", "react-redux"] }, "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw=="],
@@ -1875,96 +1879,94 @@
"@rn-primitives/utils": ["@rn-primitives/utils@1.4.0", "", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native", "react-native-web"] }, "sha512-nMFZ99AGKakMRDAlfbsYUfqwKO0LItWtp58YTwxmNuGVhXG43/zIfyWWaB3FJeOL+hhcpUn0YR7C1Vsrg0FgvQ=="],
- "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.1", "", { "os": "android", "cpu": "arm64" }, "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg=="],
+ "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.1.1", "", { "os": "android", "cpu": "arm64" }, "sha512-BLf9Wak/gfwVb7NQTQW4wBgL3oAfPy7ArEkhwV543OVw/uY6B47z5xYsqPSZ9PDOorvURPinws6ThaFuNgGLgA=="],
- "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg=="],
+ "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.1.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rRZRPy/Ynb+Mxu0O6tfPldHeDgAn0sRij+IOUy6sFdUlv3hArGW/DloE3GfAxtqpOJuRNgF74Nr5gM4xBeU2jQ=="],
- "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg=="],
+ "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.1.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/MtefPxhKPyWWFM8L45OWiEqRf+eSU2Qv9ZAyTaoZOoGcoPKxbbhjTJO2/U2IThv0uDZ4NWHc3/oTsR6IEOtww=="],
- "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw=="],
+ "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.1.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-202K+cpIi1kx/Zn7AtxBi4LTXSY67Aszb2K9rNsuW7FeBeh0nqoNmYLOSZidV0p88VPBzMmTZcHAdPNo3kRYzQ=="],
- "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.1", "", { "os": "linux", "cpu": "arm" }, "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ=="],
+ "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.1.1", "", { "os": "linux", "cpu": "arm" }, "sha512-wl9NfeXNUwrXtUc063tddmZFUI6qiNs1CNOwni0OL4vC7MqVSYugra3ZgtDmtVy8e0DluJTENmzIv2BwqLzT4Q=="],
- "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A=="],
+ "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-at2EO4o7D/PJLC4Xik16bU4CcjQE2tSv1LfqMA0TRYQYQihRm3gZeDB8xaX28A9SFedibcAk5DeMCKt4REKG0A=="],
- "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg=="],
+ "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-5PUjZx366h9tkJTPJF5eibxOlK3sGoeRiBJLLjjEB5/kLDuhr6qB3LkhqLz1smXNgsX+pBhnbcJBrPE30HznAA=="],
- "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg=="],
+ "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.1.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1WK84XPeio3tjP1sM/TMXiC0G1i1iq1qGZ71KfNQjEFLU1kwD+Cv5T8nGySg/JUFwLbaScu6ve9DmeXlmqpkFA=="],
- "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ=="],
+ "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.1.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-1nS1X5z1uMJ369RU25hTpKCFvUwXZp12dIzlzk4S+UxCTcSVGsAE6tzkOSufv/7jnmAtK0ZlrsJxh2fGmsnVSw=="],
- "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.1", "", { "os": "linux", "cpu": "x64" }, "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw=="],
+ "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-NwX/wspnq4vYyMFsqbYvzums3ki/Tk8FZbMzMAovPDp3OfLeYKby/D+9osokadXuYEV3OvpeHlwnr/bG8QMixA=="],
- "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.1", "", { "os": "linux", "cpu": "x64" }, "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ=="],
+ "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-+n46LhDrJFQM+229y4oXtVpj1G50U/+XuHMlpnisFTEXhrg9f/YIjp/HymX+PVJjBEr7XHRs3CFLelV464pqwA=="],
- "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.1", "", { "os": "none", "cpu": "arm64" }, "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ=="],
+ "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.1.1", "", { "os": "none", "cpu": "arm64" }, "sha512-qGwEu47zOWYo7LdRHhCWTNhzwGtxXpdY6CERs8QEOqC0PXGGics/e3vHnyEUKt8xK6YkbZXFUCeklrpB6js8ag=="],
- "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.1", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ=="],
+ "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.1.1", "", { "dependencies": { "@emnapi/core": "1.11.0", "@emnapi/runtime": "1.11.0", "@napi-rs/wasm-runtime": "^1.1.5" }, "cpu": "none" }, "sha512-qczfgEH8u0wHGGOXtA7UMAybNKuQjjEXairyQaw4WzjiMztfbgatG1h4OKays/smhtwbWltpKCRGtVhU6h40Sg=="],
- "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw=="],
+ "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.1.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-4psXSh63mSbwJF+mB8/9yfUUEzBiHYcUjxa32EO9ZwKy0Ypwjcg4F10D8SvVXgd+isy2UUUjF9HJJnDu1T/4Gg=="],
- "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.1", "", { "os": "win32", "cpu": "x64" }, "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ=="],
+ "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.1.1", "", { "os": "win32", "cpu": "x64" }, "sha512-MUvC/HLXVjzkQkWiExdVTEEWf0py+GfWm8WKSZsekG3ih6a21iy0BHPF07X3JIf3ifoklZXTIaHTLPBgH1C3dw=="],
"@rolldown/plugin-babel": ["@rolldown/plugin-babel@0.2.3", "", { "dependencies": { "picomatch": "^4.0.4" }, "peerDependencies": { "@babel/core": "^7.29.0 || ^8.0.0-rc.1", "@babel/plugin-transform-runtime": "^7.29.0 || ^8.0.0-rc.1", "@babel/runtime": "^7.27.0 || ^8.0.0-rc.1", "rolldown": "^1.0.0-rc.5", "vite": "^8.0.0" }, "optionalPeers": ["@babel/plugin-transform-runtime", "@babel/runtime", "vite"] }, "sha512-+zEk16yGlz1F9STiRr6uG9hmIXb6nprjLczV/htGptYuLoCuxb+itZ03RKCEeOhBpDDd1NU7qF6x1VLMUp62bw=="],
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="],
- "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.4", "", { "os": "android", "cpu": "arm" }, "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ=="],
+ "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.61.1", "", { "os": "android", "cpu": "arm" }, "sha512-JnBB8MdXj45cajvTuO5FmPlvFVJRQgvrz1uSEl3NwqFnReAPGwb8EanbGi4z2nRaqLzjJSv5/JmycoTKlRZxHA=="],
- "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.4", "", { "os": "android", "cpu": "arm64" }, "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw=="],
+ "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.61.1", "", { "os": "android", "cpu": "arm64" }, "sha512-Jx2g7iSjw4AOT0HDPHM9RV3GNjRXwybWtSFZiZAYUTjUwjVrYIwq3kBf+LnhqJlzXFAqTAh2F7IGI+O568exPw=="],
- "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.60.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA=="],
+ "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.61.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0F1L/Z3Eqv8mT2n3dCpeO8GcTvHvVqkP5/t6DMsn0KzhYVcg+s7Ncl5DS8qjKYEeio6Az0Gt6nyBORay5qIlCA=="],
- "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.60.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg=="],
+ "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.61.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-qLttcH871ujY4YcVfUSShhOw+CsoTatYz8gRbHO7Bb92QH059/P0y5do1KMs41fY0BpD2x4AJH/gID0zFiqVKQ=="],
- "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.60.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g=="],
+ "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.61.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-fUI4RapGE0Oh3mb8mgfvC1O2nU1RpDZUKnDQm3xB1Ipg7C2wTs5Kstz7G2uWK99a8S2yTMq8/P4uycwNa0nJyw=="],
- "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.60.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw=="],
+ "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.61.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-H5YrdvJaDtI/U9/emrD4b++xkvp3y/JvOe4rizHbxvkyMfRS/CiRYdji+Pl8D0brEaNFWUh1drQxgAGIl6Xudw=="],
- "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.60.4", "", { "os": "linux", "cpu": "arm" }, "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA=="],
+ "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.61.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Q8CBCCQtDFrYtXoeUXSrnFXKOnyUhx6bz+SkL6A0E7V8kAiCJ5pamq1WtbfpVGhR5TSpXY6ak3avmDc5fHTyJA=="],
- "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.60.4", "", { "os": "linux", "cpu": "arm" }, "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w=="],
+ "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.61.1", "", { "os": "linux", "cpu": "arm" }, "sha512-nwnhk1581l0FBVellGcVCAT0Oi06onEA3WB53sf01VO3I0UPBkMH9sXONYME2K0ovXcNayJfNtHfm6mpJElatQ=="],
- "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.60.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg=="],
+ "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.61.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-x5Xr49hwt3hdW75UOZm3395YwwzPyauktslv29KpWL/T+vVAzoT3azLcTWv0eMciBNrx+DYjH4paehHoLpPvpg=="],
- "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.60.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A=="],
+ "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.61.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-unMS3H73DpaoPyyEVPjGKleM/s0mkmsauTENpw4INQY8y4+IuLNjkueQ5QCtC0D3N38Y38yhAU8OoZ20S2Tm6w=="],
- "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ=="],
+ "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.61.1", "", { "os": "linux", "cpu": "none" }, "sha512-zNZzGRnAhwjFEYmvphJRV5XaQGjs62cCmeYYHUT//NbvEnHauw+I85nGG+SiVg5ld4GX8D1IbKIX+ozITQnhMQ=="],
- "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw=="],
+ "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.61.1", "", { "os": "linux", "cpu": "none" }, "sha512-LdpWGL8X209B2SIvWjqlc8VZgM6PKfontSerGepuldQmHYrAOtnMCXeJkxXGbC+PPZVOuu5czJo7fNV6aeW8rQ=="],
- "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.60.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg=="],
+ "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.61.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-EC5kTtNaNGOmbMGqar8dvJy6y/hg99GAwjfBz++pxZhQATXGcRjd6c5en5wcbru0vkRmiMGsQKdMJOOf6sza4g=="],
- "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.60.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A=="],
+ "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.61.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-8hiwp6D4acEcNK78I4rP0/XtS1sknWIAMJBPdR4l6zUtyTm5KiTDr5bXmWt4foY7nAN7AThDHgkLIEZOWKbzWw=="],
- "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA=="],
+ "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.61.1", "", { "os": "linux", "cpu": "none" }, "sha512-10dh/h/BqA7DuMPWSxkR8uks18FRwnwOEqr5zOTEl+NOwP/OMzKX8OFR/Of9xxDA7D5qef1Nzar5WDD2kCCr1g=="],
- "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw=="],
+ "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.61.1", "", { "os": "linux", "cpu": "none" }, "sha512-YKJ5lg35DP17gcAOggnihe+APw9HLyj1Xn7gsmGumBJAUDa6NGXNixJzmkWLhcK9TOuuyQjdamzvJefkO7qHZQ=="],
- "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.60.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ=="],
+ "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.61.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-Mlil5G2Jj6a7B3LWGctg+XPL9vdXYuzCtNXfxOQ0nPjc2m6ueUktocPGH9bnAM0bNRKb/bAWTujUU7IJQdQA+g=="],
- "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.60.4", "", { "os": "linux", "cpu": "x64" }, "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ=="],
+ "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.61.1", "", { "os": "linux", "cpu": "x64" }, "sha512-bVWIOIk6pV01p4CdUbPP7CJ/434z+OooYjDuFcR+44N35YvKUC66G8MGnvcWx5mWKW3g61J+t74l3Kj15Kwn2Q=="],
- "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.60.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg=="],
+ "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.61.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qy5pBvZbqNFheBz61R1rzsezjm0J7O2oNGoWtGoY89SZYLUfxAJTBAqDChqAIdB4rCiIbi9nF7yZ83GnNiLwSw=="],
- "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.60.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA=="],
+ "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.61.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-E83TXjI4zm0+5f2qO+UOudaCYIhYwpJ5jq6YCZNIZ+6CbfhKrkAGezeiASBL9ElxAxFsRS9ZhESv8mfnj6TKeg=="],
- "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.60.4", "", { "os": "none", "cpu": "arm64" }, "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg=="],
+ "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.61.1", "", { "os": "none", "cpu": "arm64" }, "sha512-fbWnKqVkjrJN38vNe3ahkbk6iejS/3b0Nt7EEtPpE6RBacZcGXNKbzfHN3GUUlXOPghUg0j6XUGrtjX9z1sIvA=="],
- "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.60.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw=="],
+ "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.61.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-ArMl38iVAbk0New1ogihQNY6iphLi4ZaRsa037gUzv5yeKPY8TD3Dmy4x2RNC1VztU/uqm+G+/RwFrSka3Oy2g=="],
- "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.60.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA=="],
+ "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.61.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-0mYtjHS9ucAbcATycCNK9IGBk/cCe/ma7EmSLGZdsxnOA8cjRIyU04wDpVAD9NiOfLUR9KTxdiO53uOkherqjQ=="],
- "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.60.4", "", { "os": "win32", "cpu": "x64" }, "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw=="],
+ "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.61.1", "", { "os": "win32", "cpu": "x64" }, "sha512-gK1iCEPfpoSG9wfBihXxvBMi8ZfcWffYkEsC/Eih+iFENTaewvNcrEQ69lIOWYO5pePHKLHHO7nq5AILGO/HQQ=="],
- "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.60.4", "", { "os": "win32", "cpu": "x64" }, "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw=="],
+ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.61.1", "", { "os": "win32", "cpu": "x64" }, "sha512-X+zaP2x+j4RXGfbp/seSoRHWnPxzApilDszisZxbYH5C/jTxFhCtDNdPGZb9lJyYPs24wGxruPF7Y+sIXt9Gzw=="],
"@ronradtke/react-native-markdown-display": ["@ronradtke/react-native-markdown-display@8.1.0", "", { "dependencies": { "css-to-react-native": "^3.2.0", "markdown-it": "^13.0.1", "prop-types": "^15.7.2", "react-native-fit-image": "^1.5.5" }, "peerDependencies": { "react": ">=16.2.0", "react-native": ">=0.50.4" } }, "sha512-pAtefWI76vpkxsEgIFivyq1q6ej8rDyR7oVM/cWAxUydyBej9LOvULjLAeFuFLbYAelHTNoYXmGxQOlFLBa0+w=="],
"@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="],
- "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="],
-
"@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.37.0", "", { "dependencies": { "@sentry/core": "10.37.0" } }, "sha512-rqdESYaVio9Ktz55lhUhtBsBUCF3wvvJuWia5YqoHDd+egyIfwWxITTAa0TSEyZl7283A4WNHNl0hyeEMblmfA=="],
"@sentry-internal/feedback": ["@sentry-internal/feedback@10.37.0", "", { "dependencies": { "@sentry/core": "10.37.0" } }, "sha512-P0PVlfrDvfvCYg2KPIS7YUG/4i6ZPf8z1MicXx09C9Cz9W9UhSBh/nii13eBdDtLav2BFMKhvaFMcghXHX03Hw=="],
@@ -1995,9 +1997,9 @@
"@sentry/cli-win32-x64": ["@sentry/cli-win32-x64@2.58.4", "", { "os": "win32", "cpu": "x64" }, "sha512-cSzN4PjM1RsCZ4pxMjI0VI7yNCkxiJ5jmWncyiwHXGiXrV1eXYdQ3n1LhUYLZ91CafyprR0OhDcE+RVZ26Qb5w=="],
- "@sentry/cloudflare": ["@sentry/cloudflare@10.53.1", "", { "dependencies": { "@opentelemetry/api": "^1.9.1", "@sentry/core": "10.53.1" }, "peerDependencies": { "@cloudflare/workers-types": "^4.x" }, "optionalPeers": ["@cloudflare/workers-types"] }, "sha512-iSohVibGRAKg7zLUflfA2ePG69Uw6bqm6iCQLM18hoG2gT4DGigaKcjJmZLTfAtW1DInMCb0DYc/mltCznxMrQ=="],
+ "@sentry/cloudflare": ["@sentry/cloudflare@10.57.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.1", "@sentry/core": "10.57.0" }, "peerDependencies": { "@cloudflare/workers-types": "^4.x" }, "optionalPeers": ["@cloudflare/workers-types"] }, "sha512-LDKk177la/uG92ILNozcwQR7+4/pizPu01Y7M7l9J7o1uwAi9WjElafh/HU2Jqw+vST1BKknw/tQB1pnsnkDlA=="],
- "@sentry/core": ["@sentry/core@10.53.1", "", {}, "sha512-XG4ezlkyuAPjBC5+9kXC94rXXuqYTw9NRhfaDHssbTFaGnqBR8vQX2UUgZfY7ucbeelRDGfBu1sywoU+mB04uA=="],
+ "@sentry/core": ["@sentry/core@10.57.0", "", {}, "sha512-kntItTA2kiT0YpL7encXaF6mkdZMB+y48lwj8w1wkfBpfJAC7sifdgrzLQZqmsqVNE3crg9VfufaAGA+78uFMg=="],
"@sentry/hub": ["@sentry/hub@6.19.7", "", { "dependencies": { "@sentry/types": "6.19.7", "@sentry/utils": "6.19.7", "tslib": "^1.9.3" } }, "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA=="],
@@ -2015,8 +2017,6 @@
"@shopify/flash-list": ["@shopify/flash-list@2.0.2", "", { "dependencies": { "tslib": "2.8.1" }, "peerDependencies": { "@babel/runtime": "*", "react": "*", "react-native": "*" } }, "sha512-zhlrhA9eiuEzja4wxVvotgXHtqd3qsYbXkQ3rsBfOgbFA9BVeErpDE/yEwtlIviRGEqpuFj/oU5owD6ByaNX+w=="],
- "@sidvind/better-ajv-errors": ["@sidvind/better-ajv-errors@5.0.0", "", { "dependencies": { "kleur": "^4.1.0" }, "peerDependencies": { "ajv": "^7.0.0 || ^8.0.0" } }, "sha512-FeI/V2KGtOaDX+r0akidCGYy79lVR4YnAqk1GFgZFuHADErCAEmtZL4+IdCAcDXHqfZsII3fs9DrfC1pIR+19w=="],
-
"@sinclair/typebox": ["@sinclair/typebox@0.34.49", "", {}, "sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A=="],
"@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="],
@@ -2027,91 +2027,89 @@
"@sinonjs/fake-timers": ["@sinonjs/fake-timers@10.3.0", "", { "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA=="],
- "@smithy/config-resolver": ["@smithy/config-resolver@4.5.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-TpS6Am5zSEtx3ow7VynThEL7UwRM06zZZcmFaP6Ij9hqKPfsFhTYCLcgU7gjFjw9QAI2kzwXrfS7InH8BivJTA=="],
+ "@smithy/config-resolver": ["@smithy/config-resolver@4.5.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-AXbvUX9aNY2qCLOMCikpl1Df5w2CNFEqbEb6XafG81FJbAbB8avIT7BOx1KDqiO86J/38qKQ3YuakfAfY3iBkQ=="],
- "@smithy/core": ["@smithy/core@3.24.3", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-Ep/7tPamGY8mgESE3LyLKtxJyy6U52WWAqr/3wial47Sj4u3PiIF73AOGI27UyLy9duTkhZbgzodOfLV4TduZg=="],
+ "@smithy/core": ["@smithy/core@3.24.6", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-wBXDRup6UU97VKyaiRo8AssnfStPtG0oAAfpq/bC0a1YYau8pM86YB4kM6ccoVi1mS8l/UHbn9oDM+7uozr/ug=="],
- "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-I2Bti0DKFo2IJyN28ijCsx51BAumEYR4/1yZ1FXyBygy9MqbnMqCev4JPth/MbpRfBSRAX35hITSnAdJRo1u5w=="],
+ "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.3.8", "", { "dependencies": { "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-5cAM+KZC02sTqDt6NaLXyu50M/GNMd1eTzDVR8Lb0BBsVtu7RWHo47VPPEEv1vt3Yub6uzr+M5FHC+GtoT0USg=="],
- "@smithy/eventstream-serde-browser": ["@smithy/eventstream-serde-browser@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-LXg5yYJPYnVSrpa6LOZ+/wqpI2OlIccy7j5F16EFNYDbXWmnhry/PFRRPyM30H+hJeqfVgckFuvNGnAGCt56cA=="],
+ "@smithy/eventstream-serde-browser": ["@smithy/eventstream-serde-browser@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-BQao/dBhLCJqo953N1hadkcF3M/9G+i6qIgnMupfdpBQomwyhfV7Xfc5jjpCkm8HxfzaWAGrM/2nNnzronFqVQ=="],
- "@smithy/eventstream-serde-config-resolver": ["@smithy/eventstream-serde-config-resolver@4.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-MdQxEX5SFNc3QmpiLXtcZXsWk4imCfGVN7Ikz9I/XvavypvHT4mqxwo5JHdr/LBKCfAv89+8193ZWlUwDp8YXQ=="],
+ "@smithy/eventstream-serde-config-resolver": ["@smithy/eventstream-serde-config-resolver@4.4.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-OUoNRXJGZMM4ivoU7QIzOvCLbavD1YnadNEairrtYhTi+gmGhyn3c2wToL9CxEs4Cw2Ab/KeQM39T1K+/e9YdQ=="],
- "@smithy/eventstream-serde-node": ["@smithy/eventstream-serde-node@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-54RbRsw9eVaVnqYUXi3F6nMAPgUyKsBvAKBY2lf+81mIgM7N+yS9V5LYk7yUGbrM789b2e1qBuyDSjX1/Axxcw=="],
+ "@smithy/eventstream-serde-node": ["@smithy/eventstream-serde-node@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-M6FeKRMi3oecpTy4EL5n1hLPWydw+xInFYQIzjbGYGBnFtW7IlJjnXrKr/Ev1GpMtmw44QCmrl8+ACEFPmRsIg=="],
- "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-F+DRf8IJazRJgYog2A/yJK7eYVc0rqTlRzO+5ZxjJd4WkZoKz0IJRncf7G6t1pdVT3kryJcwuTFhN1c5m6N47A=="],
+ "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.4.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-FEwEYJ1jlBKdhe9TPzfghEi1bP55ZeEImlDkEa62bBBYzUcnB6RUCyuiS2mqKt6ZVjUbBgcNhzfIctH+Hevx9g=="],
- "@smithy/hash-blob-browser": ["@smithy/hash-blob-browser@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-TkGfDlYeWOGwYvAunHHHmKgvFtD7DFAl6gWxATI4pv4B6w0Wnx6RK5zCMoXTTqMVd+zPcWm7w8RPTgHytoCDJA=="],
+ "@smithy/hash-blob-browser": ["@smithy/hash-blob-browser@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-/8D8rOFs2VEwvHwsx68sb6nE7XfVr2wbJTbC1YuKBHPhHeMnOt7IHxr7CoT5wBWujdV4fjVoLPn1BXXP4Ijlow=="],
- "@smithy/hash-node": ["@smithy/hash-node@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-tSUA38sM7kzMoLhqQ2aCGTwLXovjurz3jjG+a0sxqD4qT/4FhQr/wxMdhCumT70giM+axC1pPjimAHLlEQCfzw=="],
+ "@smithy/hash-node": ["@smithy/hash-node@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-lIZyQ7gDxURrnfkjalM0lKmDnfZYuPzNBYlkza3czPTQNVYsg4e0o90Zx/RpxhamKKOGsQGCsopp0ULsJqltNQ=="],
- "@smithy/hash-stream-node": ["@smithy/hash-stream-node@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-ZyDAlpKKc7BKHUp+kDBiTwNhiHrOf3syQdvQadvnwWs0QJhYMHMg6QSarlhpzN6qr+KBFM/oF/xP/bvzR6KI9w=="],
+ "@smithy/hash-stream-node": ["@smithy/hash-stream-node@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-Ziap41FoxpKqmlO9IE68NeFwPKhUJD4PVNcCQ2tl6IUCPSj0KykIuAPnJNWIQbWXvApwCauhRNlAFdt9KRvDpw=="],
- "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-wUWowbCm7DGczl6bfLI6wGGtoxwN5Pon8DhF0Q8AA4NvgLwYfLo3h2DWI7sHr33lLcEsyTLQKeUeTHydqSfQ5Q=="],
+ "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-jUH1Eth7Sgn4KPBX5OKYDRpNjzul7AzsIhxKXT1rHXPTSfY00/7Kb9RtNil5SDAlPPsxaUiesR/rql2wjackmw=="],
- "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-RRxYqjUa/n8dRVkbhyuiRarppLzt4H/AtMUEFmiHlDy8o4wrgqAdzxsk9naemzu6iX67ZV375fNmX7Q8dynGKw=="],
+ "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-/cSYHP8jPffkhBClQzH9fAJujIh8dwMwg2swrVF4stXQsUWO5Oi2bwyaMUcBPIyulUI5IxaJFxd9C8UQX+YZsQ=="],
- "@smithy/md5-js": ["@smithy/md5-js@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-pFw8gEMrHw9BbRwNm//UU4WgnVO7+dhfFRaSAkFPfwslWU2LXt0mM+oap3iFwGbdD8kuAWIeOAxqSiamOcM3Dw=="],
+ "@smithy/md5-js": ["@smithy/md5-js@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-LYcuBrO9oiajdRFHyFx3FJAWNKrP89s0grI6mcfpwTAeX2ZJ/9Xyi7Imghh9LT6CIcAy6/k6/MpoUiPNjXr1/w=="],
- "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-Up1XAYnj6oxFBypWpkhNpgX+yReQxkKAV/iLaeP0KVLb2oTkmA9X+UJuGBVvEA9uZIN06y0irDi7sBMuTZMVJg=="],
+ "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-nfpYCrzSFAgfIXmIHFTjOGNeTV3DVF5E5rfi3ZuNfsOjKSpePBOJF3rjyXlWYND0anvxVoqioIwClWCNdKt4Og=="],
- "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.5.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-p60HGFflWsJC6V9GAYeFgbfORn+9ILx8FqgMa/8PzA0rhIUxF57EKoOR4Irs6oe1oy8RLzhjhcGS8CBtPv/t+Q=="],
+ "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.5.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-zdG5bJZOiM2PRgL2lwcgui6uwZ+s5y6Qsk/rk05Q69sZJT6oi1x+v8Kn++V/q9VY94EgOtEe5kivpu+eGau0wQ=="],
- "@smithy/middleware-retry": ["@smithy/middleware-retry@4.6.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-MnfYnJs3cBXK3ZBqbPzXRPHIp+QtgpkX5NogcUOWHPU5GbgTAQSIfPLi91lTcEbkFDcH2YbgjLPQjWeyQ689rA=="],
+ "@smithy/middleware-retry": ["@smithy/middleware-retry@4.6.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-MWppaYUlc+W4cU2JZnYuMFeOxCWbKO4A57BWti6aCb7hRBK3+CL6llADGpX084hjImsqr3EvCGewArOj7G81eA=="],
- "@smithy/middleware-serde": ["@smithy/middleware-serde@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-RUVCZgn92izDAARs5OJSM2+KWSfTRvQWwN9t0MmiybT3pquRgDx9vD9t/YZjd/5lwcFbsNuPojJSddYQEZGeWw=="],
+ "@smithy/middleware-serde": ["@smithy/middleware-serde@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-I3fPVYKKEog3a3qdqt1nttP1NBuQOAlNoQxEp6j5pMogSx0HHfid63difhcDgslV6p1XsTXG6D6ieTe13ycJtQ=="],
- "@smithy/middleware-stack": ["@smithy/middleware-stack@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-+BPabWluqxo3EfMMvOgnAmPtWnCSzj+gf5mJ27wTZUbvS0hpdUIU1g80R01bEGKZx4JCi8P58jAXD9FUGMjhwA=="],
+ "@smithy/middleware-stack": ["@smithy/middleware-stack@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-QhNiWfg47Kl4SJHmuQvnlzCtlD1eX1J7d/vuuttIE17Ra2YUKp9Srv5lCwa3OvoYaSNWMKYn0PjGIsfCLMJsEA=="],
- "@smithy/node-config-provider": ["@smithy/node-config-provider@4.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-vDtz5OuytrjP4o9GtAOz1JloN003p94utJIQeO0WAjorhpafFFjpbDOrP6btPoCN3UxaU/U84OIEt5dM7ZRRLA=="],
+ "@smithy/node-config-provider": ["@smithy/node-config-provider@4.4.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-M+gG6eQ0y073mSmNB+erRXJvwpsqsN72ol2w6vcd8FEKeG7pqYK0JvzfVqONkPj2ElBB2pg+cU13I850b//Wag=="],
- "@smithy/node-http-handler": ["@smithy/node-http-handler@4.7.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA=="],
+ "@smithy/node-http-handler": ["@smithy/node-http-handler@4.7.7", "", { "dependencies": { "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-ZAFvHXrEk6K180EVhmZVg8GU5pUH5BSFqRs27JW3j1qEFx9YyYwWFx17x/MHcjALYimGAji7qEOlF1++be+G5A=="],
- "@smithy/property-provider": ["@smithy/property-provider@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-nmeVi9Ww/RMyttqj1Dh0PA+iVieKm4dxDlnT6tNP118O/5U/Qqb9b3DV5A3RX+slR/m4/MABSZ2zNfSkpVV8dw=="],
+ "@smithy/property-provider": ["@smithy/property-provider@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-0rhHv1Ww27kajF6qewme2aRtJmKFtSwE6EZ2dj5KxdX/R3ANsUugqTnH0tvpZwGiQ3MOMhetuCGFAeKVv3/Onw=="],
- "@smithy/protocol-http": ["@smithy/protocol-http@5.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-P16TBD/d8ZcD9MHQ0ubQ9BbOYSd5HZKbHOLsyFWxKk2oBEoghbRFPfGOoqToZX1yrfLITXRylL16EyPP4IzLPg=="],
+ "@smithy/protocol-http": ["@smithy/protocol-http@5.4.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-H6S7NyaaL+7qO8kIL7VQ7KyrGnKXdllGzJqvtp3hvDen25UOydKV51qGDVK0UciW125jV3CoLJQy/ihc0OEC6A=="],
- "@smithy/querystring-builder": ["@smithy/querystring-builder@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-2+/Nwh4OPVBW9snd6dYqgnSwy84kQOI8fnKv2kC6sW5BEv/qZMBRdZjMShwhtjUHHlnL+SZbYolFeDWTEVbHlA=="],
+ "@smithy/querystring-builder": ["@smithy/querystring-builder@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-BicTiH0vBGknILtW9mIO+fdO1UY5khbqOMehbGDv6iecYruVSRuEyOazsThj9OSQHw0LfDGQaxj6s6rwWhvggw=="],
- "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.5.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-9fgVSJBB1k79oZkT5eLHaPx289LZg8wDi2xNEDKlD2Wy2GpPQfvUhnzJCXEWQxIJ5hhj+peI/todWUFBXhi86w=="],
+ "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.5.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-In8gYD2R66EKlGAq9QrNKVrMOGaGBD7LUNp2kUjeQ4V9zNktFIXBPmrCySr4YYo+jVeVL6CnWj26sOamcF0qIg=="],
- "@smithy/signature-v4": ["@smithy/signature-v4@5.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-53+75QuPl6DL+ct6vVEB51FDO5oulXr20TPV46VvJZg76lIlXNWfxi8j+G2V/t0I2qxCBOa3vX/8bmjrpFVo9g=="],
+ "@smithy/signature-v4": ["@smithy/signature-v4@5.4.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-Ojg4B6oIDlIr1R86xCDJt1zJWnYa0VINmqdjfe9qxWjdRivHalZ3iSlQgVqYbW0MdpFOC5XfHEWsnbmdnpIILQ=="],
- "@smithy/smithy-client": ["@smithy/smithy-client@4.13.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-Z8mQ+YryjP5krDadV6unnp5035L4S1brafXpTiRmjPweKSaQ6X9CYDYWvmEggXjDIa1oufX/2a/bdwu8EIz/lw=="],
+ "@smithy/smithy-client": ["@smithy/smithy-client@4.13.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-tAf35/JW/DvMlACcazcoIOKOV0JBqyOvxjPTEME9W+m9wLcE0G1rwADc7Ntu38rY5C9OH8jZjpo4tbtjmIjEBQ=="],
- "@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="],
+ "@smithy/types": ["@smithy/types@4.14.3", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YupL0ZWmFtJexUN2cHzkvvF/b9pKrtAIfT1o7/oY/Ppu8IYeZ+lDPM5vZdQJaSeA132dJCqojjGC9NhXeF71VQ=="],
- "@smithy/url-parser": ["@smithy/url-parser@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-TsMTAOnjuMOv1zJBw8cfYGWhopyc3og8tZX/KuyCPjg7V3ji3f4YjFOVu843UjBmrfS/+X6kwFv5ZKg7sSm1bQ=="],
+ "@smithy/url-parser": ["@smithy/url-parser@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-9MRJzwUrlswwHogOR7raDcykuzojZn74qGdQdbEQLVaixlvJuMiIT0g/CejKcmAIgrUVs8brBrnGtmYmBc0iuA=="],
- "@smithy/util-base64": ["@smithy/util-base64@4.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-91lxjhFpAktA9yPBxniqVR/NSH9zyjMjLmoa+jbQHQFR9WiJA+n61T7HBrfh5APdEoAledJwGq8l4cS+ZJFUnQ=="],
+ "@smithy/util-base64": ["@smithy/util-base64@4.4.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-V6ApAGvCQnb7Wy1Sy60AQc+7UOEaNQxvAXBLdMi5Zzm66cmX0srvfAxDmg7BGuJ+9H9ez0PPWS/AeFgWxwGavA=="],
- "@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-/M6Ya1Fjq8hg3rYjiwwqTen6s1bAa3U3g/2eicBaBQfaoa4ymLUke/x4T8mwb9dSq/L8TQ4YgndS0MaB9ShgmA=="],
+ "@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-+3vGcNHuvzuFLVWL9/wJgucOuQWufhuGhb3oxVDj9SWFGtwkOmtC2nFUwVC2IJoPe45uhs6TAb8bgE4IXDSPzA=="],
- "@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-M+zdSrevWj0grtZx2RBULPUyjTq1aB+n+13Hrm9owiGpow6DqY/WqiSj6sHVQy/rKp0j7NzV3TNf2LrwDel8JQ=="],
+ "@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-T15zTQJ/xKYdS0/3CFckhz1QBbhxmhk/xjL6FKvHKgkJPN4E985If2FI9CcV2kh2v0sfiWMfXVEOKFbqgw4m4w=="],
"@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
- "@smithy/util-config-provider": ["@smithy/util-config-provider@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-F91as00Ae3SP2xQkB0g4WsHFLvPOkZ3o3bQMmM9x4GQssvHR4Ii3S2Ksbg3dsQpAjdPcc3YRiiqzej3gG4waWw=="],
+ "@smithy/util-config-provider": ["@smithy/util-config-provider@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-cRLfIk8UK8iu9OsaI2dlHrE0oSuyGfNVxAy9sk81wMZTf7A2leM2fn8G2oOMisuUriRuLLNcNoJjmofaf0IvUA=="],
- "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-Q60hxKkMEkmBsOEzxlMWEymBWov0dtWGgoJhOUs6mE8k2FDPjK8NlsRdMkmO80n2pwzreHtrYcX5jiRP7ZkP3w=="],
+ "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.4.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-dRCZKu05AL7KQWrVuRJPotfjCRnvGkCjV56XNP067CRfyTtvgi/Ygu44qrBKb814Hsa52bWwDJ+Vt3pd04BjPA=="],
- "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-RYj+8gr95WiiBqvVghoRvL12NS9ryvLyufp7FOs7EzKwGX0W5gOVlXdCrFkJScSf8gxdjQMRyIZ3Y82/MvXQ3Q=="],
+ "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-tTR8tayMoa0WeRhtMH7j3WpHUtggBXjh7rBdf7j6POYI69R85gpWBW6B32kaJRnlQU8+0gOGAzJj50S7SU1Egw=="],
- "@smithy/util-endpoints": ["@smithy/util-endpoints@3.5.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-2JqSmzQtKDKqBckLl/9NXTL1fY+zQBU5fNGMpud7AT65vql0tVFhb2UEZNZmLSHayLeD+X/Qzn84oXw5KS+KSQ=="],
+ "@smithy/util-endpoints": ["@smithy/util-endpoints@3.5.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-kaB41eVUYC7ajVWUsZRqagxwRaa3VupjQ/Z2Z2v/Vffh/gJ/fFOS25s6mTyR2Lw1FrnBbRWo1iShR9BhekpPeQ=="],
- "@smithy/util-middleware": ["@smithy/util-middleware@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-8NZwlQ+nyAIWn9YZxH14FC8ca0i6ZGW1aJyPjD+zMZz3k9jOhXXKhdCSRvjmcSYLW42uhbrxavXqMkrTKHyY3A=="],
+ "@smithy/util-middleware": ["@smithy/util-middleware@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-TrAgOcL63TRi7G92arTzq0n+VDrmZifwP1I1T9y2xU3lJpybsHdm33S2d3xaFfG0c8zJNIF9yYRqLSe6rbhH/A=="],
- "@smithy/util-retry": ["@smithy/util-retry@4.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-8RJXeU5lEhdNfXm4XAuHlf6VtNzd279Z2FJZSR7VaELYCR46ffgjJBSjc+3UAy7V1YqBOLV0G9gWhLB/nA44nA=="],
+ "@smithy/util-retry": ["@smithy/util-retry@4.4.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-E/kFnvWQL6rIPr0Ucjk8oDgJSkKx2bv0nJkJ/cB3ywys7xCqeL1AXP9liHjgYONdQ+MKw/xT06IQK3vgbtu2Ww=="],
- "@smithy/util-stream": ["@smithy/util-stream@4.6.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-DSpJpPg0rQwjZk9/CSlOTplD6xSUu+bz8eDJQkq/Fmy9JlSD4ZGhXG/qFl0aRHmouDbBF75tnZ00lPxiL/sgRQ=="],
+ "@smithy/util-stream": ["@smithy/util-stream@4.6.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-g+hQ45sPnaIDU4CnaG8EufmeWwziQlcpIvPG6hVY7v65RcUgasM63J/WNfSsXEcZ1zFu9rS/r/qqfDxkIrQtDw=="],
- "@smithy/util-utf8": ["@smithy/util-utf8@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-c1QpRBn3aMsoqE64dd4Imgjy8Pynfw+eR7GkjElquxUFSnezwYVaOFm8JcYa+Bo/5ssbEyPKcT3+4bmrWYh6eQ=="],
+ "@smithy/util-utf8": ["@smithy/util-utf8@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-tAa4sePYB7mlJzdYbdBqdv37KwFKWixmM/r3ihcI0HFOVjf+a5oGvtcLXcGm4S1bY4DFsLAIOHgjubtp+oRufw=="],
- "@smithy/util-waiter": ["@smithy/util-waiter@4.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "tslib": "^2.6.2" } }, "sha512-WSHSF865zDGFGtJdMmYPI2Blq/MbUrn5CB4bLDg4ARbQ9z7oA87ZZ/FSiwNZbQrU/EiVyl9lpINswALgI4lZXA=="],
+ "@smithy/util-waiter": ["@smithy/util-waiter@4.4.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-oTt3OP9NcJkrySCSCCdSbP6XLSMNgOmt/ulaiYtb0Ng6tfEWtXQ1mwfyqmLd+GapmDUjbU2mgkf7QIq9H4ij/g=="],
- "@so-ric/colorspace": ["@so-ric/colorspace@1.1.6", "", { "dependencies": { "color": "^5.0.2", "text-hex": "1.0.x" } }, "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw=="],
-
- "@speed-highlight/core": ["@speed-highlight/core@1.2.15", "", {}, "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw=="],
+ "@speed-highlight/core": ["@speed-highlight/core@1.2.16", "", {}, "sha512-yNm/fYEcnpRjYduLMaddTK9XKYil6xB88+qFg79ZdZhHu1PadfoQmFW7pVTx7FZqMBNcUuThiAhxhENgtAO2/w=="],
"@stablelib/base64": ["@stablelib/base64@1.0.1", "", {}, "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ=="],
@@ -2125,27 +2123,27 @@
"@tabby_ai/hijri-converter": ["@tabby_ai/hijri-converter@1.0.5", "", {}, "sha512-r5bClKrcIusDoo049dSL8CawnHR6mRdDwhlQuIgZRNty68q0x8k3Lf1BtPAMxRf/GgnHBnIO4ujd3+GQdLWzxQ=="],
- "@tailwindcss/typography": ["@tailwindcss/typography@0.5.19", "", { "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg=="],
+ "@tailwindcss/typography": ["@tailwindcss/typography@0.5.20", "", { "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || >=4.0.0 || insiders" } }, "sha512-hwbzQuNUfcPvbegQFatVPl/MY/tcM9KLl963hQ5laJKPh81TEZ1+dNG9PirGvcaDBkp+BCshExAyKVPW91dozw=="],
"@tanstack/devtools-event-client": ["@tanstack/devtools-event-client@0.4.3", "", { "bin": { "intent": "bin/intent.js" } }, "sha512-OZI6QyULw0FI0wjgmeYzCIfbgPsOEzwJtCpa69XrfLMtNXLGnz3d/dIabk7frg0TmHo+Ah49w5I4KC7Tufwsvw=="],
- "@tanstack/form-core": ["@tanstack/form-core@1.32.0", "", { "dependencies": { "@tanstack/devtools-event-client": "^0.4.1", "@tanstack/pacer-lite": "^0.1.1", "@tanstack/store": "^0.9.1" } }, "sha512-Tn5VRDSjyqjmaet2tJMuEWDRFyrCaon03vxXPlSSaiSs6C/N7lCIwGCXJbZXEUq1kTj8jYN9qyXHbsz4LQHcow=="],
+ "@tanstack/form-core": ["@tanstack/form-core@1.33.0", "", { "dependencies": { "@tanstack/devtools-event-client": "^0.4.1", "@tanstack/pacer-lite": "^0.1.1", "@tanstack/store": "^0.11.0" } }, "sha512-AV4Pw9Dk4orFsuPBcDssfWMJFs+yMYBae7zZ4oTqrCf4ftNGQKxvrQRZeqKHG6A4TkiLeSvf2kzIjcVkrW7E6w=="],
"@tanstack/pacer-lite": ["@tanstack/pacer-lite@0.1.1", "", {}, "sha512-y/xtNPNt/YeyoVxE/JCx+T7yjEzpezmbb+toK8DDD1P4m7Kzs5YR956+7OKexG3f8aXgC3rLZl7b1V+yNUSy5w=="],
- "@tanstack/query-core": ["@tanstack/query-core@5.100.10", "", {}, "sha512-8UR0yJR+GiQ40m3lPhUr0xbfAupe6GSQiksSBSa9SM2NjezFyxXCIA69/lz8cSoNKZLrw1/PktIyQBJcVeMi3w=="],
+ "@tanstack/query-core": ["@tanstack/query-core@5.101.0", "", {}, "sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow=="],
- "@tanstack/query-devtools": ["@tanstack/query-devtools@5.100.10", "", {}, "sha512-3DmJf25hDPus5IpVvp6ujXv6bKV2zPzI9vpbAmpJigsL/H6DPvPjmf7/Q9yVKEke//8fgeQ45abjgnLuyYxAiw=="],
+ "@tanstack/query-devtools": ["@tanstack/query-devtools@5.101.0", "", {}, "sha512-MVqw17k08RQtGGLEL654+dX/btbX9p/8WjkznO//zusLTMaObxi3Q+MoFwGVkC9K3tqjn8qrrNhJevXx4fJTeQ=="],
- "@tanstack/react-form": ["@tanstack/react-form@1.32.0", "", { "dependencies": { "@tanstack/form-core": "1.32.0", "@tanstack/react-store": "^0.9.1" }, "peerDependencies": { "@tanstack/react-start": "*", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@tanstack/react-start"] }, "sha512-6WP5SQTA6/H9crCpvpq3ZppYWqtrdE5NjOy6ebABi6uAQPqhfTzrdjS9t40mCZCFtGI5585OhJV6zBP/KN2zcw=="],
+ "@tanstack/react-form": ["@tanstack/react-form@1.33.0", "", { "dependencies": { "@tanstack/form-core": "1.33.0", "@tanstack/react-store": "^0.11.0" }, "peerDependencies": { "@tanstack/react-start": "*", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@tanstack/react-start"] }, "sha512-unaee+VS4MvKo+s1dmgGUXI4902VeAhuaUbKsQbhFe3MceOpB3JpAUGCDpyzjQPXVFkFY0COKfLrUNX2XZYW4g=="],
- "@tanstack/react-query": ["@tanstack/react-query@5.100.10", "", { "dependencies": { "@tanstack/query-core": "5.100.10" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-FLaZf2RCrA/Zgp4aiu5tG3TyasTRO7aZ99skxQpr3Hg/zXOhu6yq5FZCYQ/tRaJtM9ylnoK8tFK7PolXQadv6Q=="],
+ "@tanstack/react-query": ["@tanstack/react-query@5.101.0", "", { "dependencies": { "@tanstack/query-core": "5.101.0" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg=="],
- "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.100.10", "", { "dependencies": { "@tanstack/query-devtools": "5.100.10" }, "peerDependencies": { "@tanstack/react-query": "^5.100.10", "react": "^18 || ^19" } }, "sha512-zes0+o9ef5rAZXJ9f/SeaLs2nufJaeVkZkl/Or9NGrWVF41kL9Od9ED9nCwtQlgiF2VGtrzhEw5AU/igAO+aAg=="],
+ "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.101.0", "", { "dependencies": { "@tanstack/query-devtools": "5.101.0" }, "peerDependencies": { "@tanstack/react-query": "^5.101.0", "react": "^18 || ^19" } }, "sha512-cpZA0+WqKXwrwMfiWZEGGF6QrIWVQFbhBtxqDF5sQsAfrFf47HIE6fiPbQU3wyAUEN2+7UNqLCQe7oG6m3f93w=="],
- "@tanstack/react-store": ["@tanstack/react-store@0.9.3", "", { "dependencies": { "@tanstack/store": "0.9.3", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg=="],
+ "@tanstack/react-store": ["@tanstack/react-store@0.11.0", "", { "dependencies": { "@tanstack/store": "0.11.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-tX4YXh3PDkmpvGQWkWqKpzs/MSqbtuwY9dWdWhtV9Q50PmO+jOkUKIWIX4G85dwt7lxdHLXsiaEKPdKmC8F41w=="],
- "@tanstack/store": ["@tanstack/store@0.9.3", "", {}, "sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw=="],
+ "@tanstack/store": ["@tanstack/store@0.11.0", "", {}, "sha512-WlzzCt3xi0G6pCAJu1U+2jiECwabETDpQDi3hfkFZvJii9AuZqEKbOiVarX1/bWhTNjU486yQtJCCasi/0q+Cw=="],
"@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="],
@@ -2153,19 +2151,17 @@
"@tootallnate/quickjs-emscripten": ["@tootallnate/quickjs-emscripten@0.23.0", "", {}, "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="],
- "@tsconfig/node20": ["@tsconfig/node20@20.1.9", "", {}, "sha512-IjlTv1RsvnPtUcjTqtVsZExKVq+KQx4g5pCP5tI7rAs6Xesl2qFwSz/tPDBC4JajkL/MlezBu3gPUwqRHl+RIg=="],
-
- "@turbo/darwin-64": ["@turbo/darwin-64@2.9.16", "", { "os": "darwin", "cpu": "x64" }, "sha512-jLjApWTSNd7JZ5JaLYfelW1ytnGQOvB7ivl+2RD1xQvJTbi8I9gBjzcga7tDZVPyaxpl10YTfJt3BrYXR18KDw=="],
+ "@turbo/darwin-64": ["@turbo/darwin-64@2.9.18", "", { "os": "darwin", "cpu": "x64" }, "sha512-9f27peFu16ur8c0v9nUFUEyBnbKuuFsUTjHFWfmwGfzySBXbHwzU44QhZon6Mznz0cHsIr3984NQj/bVrnGSRw=="],
- "@turbo/darwin-arm64": ["@turbo/darwin-arm64@2.9.16", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YPgrn+5HIGzrx0O2a631SV4MBQUe4W/DafMFUuBVgaU32PW9/OTT0ehviF0QSxTXuRJlHvW2eUTemddF5/spmw=="],
+ "@turbo/darwin-arm64": ["@turbo/darwin-arm64@2.9.18", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9A6TMRq/Ib+QnbhLlgkhOm+624wO4pzSQ/yQviQfWHOlFvaYxdnIAYmu2H6TS6y7kSVL0DvzNe04NbESTOzFVQ=="],
- "@turbo/linux-64": ["@turbo/linux-64@2.9.16", "", { "os": "linux", "cpu": "x64" }, "sha512-vAEf1H6l26lTpl9FJ/peQo1NUB8RC0sbEJJz5mPcUhHA2bPDup2x3CZPgo/bH8S4cUcBLm4FN3UHd5iUO2RAew=="],
+ "@turbo/linux-64": ["@turbo/linux-64@2.9.18", "", { "os": "linux", "cpu": "x64" }, "sha512-zCdIDtz69AnbYh913elJRRoF3QY5aa2HNnf+4rAkc7bQ+tWujiDkCNV7stazOUPggaDvhKIf2Z87qHftTeXSkw=="],
- "@turbo/linux-arm64": ["@turbo/linux-arm64@2.9.16", "", { "os": "linux", "cpu": "arm64" }, "sha512-xDBLR2PZg4BrQOchfG6svgpv5FCNJ2TOtT2psLdEJcdKo1BH+pnPs9Xj6pvUjgfkHbuvBOfeE4R6tvxMoQKDHQ=="],
+ "@turbo/linux-arm64": ["@turbo/linux-arm64@2.9.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-Va1kXI04naMgYwqv/5Dfa36dTDx8015U7oaQAjrXa45ua9OoFjSV4OmvkML4EmXvUclQHCiBRbY8bvd0jV7eAg=="],
- "@turbo/windows-64": ["@turbo/windows-64@2.9.16", "", { "os": "win32", "cpu": "x64" }, "sha512-NBAJnaUiGdgkSzQwUIdOvkCkcpTSu58G/sBGa0mvBtzfvFOOgrQwepKOOQ8cp6sWM6OcKDNFj2p1dsZA1OWjPg=="],
+ "@turbo/windows-64": ["@turbo/windows-64@2.9.18", "", { "os": "win32", "cpu": "x64" }, "sha512-m0kDhZANxSNz9ck1ybogFscHabriAsp4eDFNrN/1H5WrgTF7b3VlcPZnhuO3v2+E2KnCbeAc+UUT10BZZHdDKw=="],
- "@turbo/windows-arm64": ["@turbo/windows-arm64@2.9.16", "", { "os": "win32", "cpu": "arm64" }, "sha512-Y7SJppD0Z8wjO3Ec0ZGd9KQ4Yv0BMnA8CIowj5Vp+OEVsosXDG2weK6/t1RRLfJmc2Ozrnd6y4DOgQys+mn3WQ=="],
+ "@turbo/windows-arm64": ["@turbo/windows-arm64@2.9.18", "", { "os": "win32", "cpu": "arm64" }, "sha512-nUdR8WqoomUys9iIQmG45TMiizJ+5BV8egSeLLZba/AWblyp3fVBcIH1kSE58OtK4g2YzbMJEth6Ttv9w5rqMA=="],
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="],
@@ -2233,26 +2229,22 @@
"@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
- "@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="],
+ "@types/mdx": ["@types/mdx@2.0.14", "", {}, "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg=="],
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
- "@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="],
-
- "@types/nodemailer": ["@types/nodemailer@6.4.23", "", { "dependencies": { "@types/node": "*" } }, "sha512-aFV3/NsYFLSx9mbb5gtirBSXJnAlrusoKNuPbxsASWc7vrKLmIrTQRpdcxNcSFL3VW2A2XpeLEavwb2qMi6nlQ=="],
+ "@types/node": ["@types/node@25.9.3", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg=="],
- "@types/normalize-package-data": ["@types/normalize-package-data@2.4.4", "", {}, "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA=="],
+ "@types/nodemailer": ["@types/nodemailer@6.4.24", "", { "dependencies": { "@types/node": "*" } }, "sha512-Ww4u0rT9wQNXh4JiQaIwx3QWdcOFXzOjQA2zc+jtFYNmQiT4mIUqcDin51bDFdkzKubFnQCZNK7FIHlPKQ/q9w=="],
"@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="],
- "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
+ "@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="],
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
"@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="],
- "@types/triple-beam": ["@types/triple-beam@1.3.5", "", {}, "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="],
-
"@types/ungap__structured-clone": ["@types/ungap__structured-clone@1.2.0", "", {}, "sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA=="],
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
@@ -2273,11 +2265,11 @@
"@typescript-eslint/parser": ["@typescript-eslint/parser@7.18.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", "@typescript-eslint/typescript-estree": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.56.0", "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg=="],
- "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.59.3", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.59.3", "@typescript-eslint/types": "^8.59.3", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-ECiUWa/KYRGDFUqTNehaRgzDshnJfkTABJxVemHk4ko22gcr0ukloKjWvyQ64g8YCV/UI47kN1dbmjf/GaQYng=="],
+ "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.61.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.61.0", "@typescript-eslint/types": "^8.61.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA=="],
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0" } }, "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA=="],
- "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.59.3", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-PcIJHjmaREXLgIAIzLnSY9VucEzz8FKXsRgFa1DmdGCK/5tJpW03TKJF01Q6VZd1lLdz2sIKPWaDUZN9dp//dw=="],
+ "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.61.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ=="],
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@7.18.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "7.18.0", "@typescript-eslint/utils": "7.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "eslint": "^8.56.0", "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA=="],
@@ -2315,7 +2307,7 @@
"@vitest/mocker": ["@vitest/mocker@3.1.4", "", { "dependencies": { "@vitest/spy": "3.1.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-8IJ3CvwtSw/EFXqWFL8aCMu+YyYXG2WUSrQbViOZkWTKTVicVwZ/YiEZDSqD00kX+v/+W+OnxhNWoeVKorHygA=="],
- "@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="],
+ "@vitest/pretty-format": ["@vitest/pretty-format@3.2.6", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA=="],
"@vitest/runner": ["@vitest/runner@3.1.4", "", { "dependencies": { "@vitest/utils": "3.1.4", "pathe": "^2.0.3" } }, "sha512-djTeF1/vt985I/wpKVFBMWUlk/I7mb5hmD5oP8K9ACRmVXgKTae3TUOtXAEBfslNKPzUQvnKhNd34nnRSYgLNQ=="],
@@ -2325,15 +2317,15 @@
"@vitest/utils": ["@vitest/utils@3.1.4", "", { "dependencies": { "@vitest/pretty-format": "3.1.4", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" } }, "sha512-yriMuO1cfFhmiGc8ataN51+9ooHRuURdfAZfwFd3usWynjzpLslZdYnRegTv32qdgtJTsj15FoeZe2g15fY1gg=="],
- "@vue/compiler-core": ["@vue/compiler-core@3.5.34", "", { "dependencies": { "@babel/parser": "^7.29.3", "@vue/shared": "3.5.34", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw=="],
+ "@vue/compiler-core": ["@vue/compiler-core@3.5.38", "", { "dependencies": { "@babel/parser": "^7.29.7", "@vue/shared": "3.5.38", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-s99aGxWYig9ErHbct27KXEGhrBYlRI6c4MwAgXErOAbX9xiW37/uMa+XUDO69zLz83dng8UUZ70CTOJrLrYrEQ=="],
- "@vue/compiler-dom": ["@vue/compiler-dom@3.5.34", "", { "dependencies": { "@vue/compiler-core": "3.5.34", "@vue/shared": "3.5.34" } }, "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw=="],
+ "@vue/compiler-dom": ["@vue/compiler-dom@3.5.38", "", { "dependencies": { "@vue/compiler-core": "3.5.38", "@vue/shared": "3.5.38" } }, "sha512-JTqp25l8aFfJYF7/KmsXZjAxJz7T+SjmTJLoXVjHtc2BrSgSiW2n9Aem/cWq1OPe68A8JL06B3eVdhlP0H4TVw=="],
- "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.34", "", { "dependencies": { "@babel/parser": "^7.29.3", "@vue/compiler-core": "3.5.34", "@vue/compiler-dom": "3.5.34", "@vue/compiler-ssr": "3.5.34", "@vue/shared": "3.5.34", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.14", "source-map-js": "^1.2.1" } }, "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg=="],
+ "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.38", "", { "dependencies": { "@babel/parser": "^7.29.7", "@vue/compiler-core": "3.5.38", "@vue/compiler-dom": "3.5.38", "@vue/compiler-ssr": "3.5.38", "@vue/shared": "3.5.38", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.15", "source-map-js": "^1.2.1" } }, "sha512-DuA2GiZawSEW442iw/9+Fkol8hTgb4Ke5KkhmSry65QA7YuyMbIdy8p0XZRMvNwJdgRz307W8g1CSzdvS4nuNg=="],
- "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.34", "", { "dependencies": { "@vue/compiler-dom": "3.5.34", "@vue/shared": "3.5.34" } }, "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ=="],
+ "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.38", "", { "dependencies": { "@vue/compiler-dom": "3.5.38", "@vue/shared": "3.5.38" } }, "sha512-7s+W5Gc42FGxZMcuwl8H5B29T8BJPMdBT7KHFE+BbAuZ/iTEdTtv7z2XiMjiaUUw4w3ZcCEdHs36RuYJ2VA7bA=="],
- "@vue/shared": ["@vue/shared@3.5.34", "", {}, "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA=="],
+ "@vue/shared": ["@vue/shared@3.5.38", "", {}, "sha512-FTW0AFZNaK5/mOqvGBwVfUlNLU38TiQn4+DQgIFUnrBBJQ1crMJ82yeGQLV5jyKFsO8yRukpbuP7x+nRbH6aug=="],
"@xmldom/xmldom": ["@xmldom/xmldom@0.8.13", "", {}, "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw=="],
@@ -2349,9 +2341,9 @@
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
- "agents": ["agents@0.11.9", "", { "dependencies": { "@babel/plugin-proposal-decorators": "^7.29.0", "@cfworker/json-schema": "^4.1.1", "@modelcontextprotocol/sdk": "1.29.0", "@rolldown/plugin-babel": "^0.2.3", "cron-schedule": "^6.0.0", "mimetext": "^3.0.28", "nanoid": "^5.1.9", "partyserver": "^0.5.5", "partysocket": "1.1.18", "yargs": "^18.0.0" }, "peerDependencies": { "@cloudflare/ai-chat": ">=0.5.2 <1.0.0", "@cloudflare/codemode": ">=0.3.4 <1.0.0", "@tanstack/ai": ">=0.10.2 <1.0.0", "@x402/core": "^2.0.0", "@x402/evm": "^2.0.0", "ai": "^6.0.0", "react": "^19.0.0", "vite": ">=6.0.0 <9.0.0", "zod": "^4.0.0" }, "optionalPeers": ["@cloudflare/ai-chat", "@cloudflare/codemode", "@tanstack/ai", "@x402/core", "@x402/evm", "vite"], "bin": { "agents": "dist/cli/index.js" } }, "sha512-La8kXl/zEr9tu17Xc5BXb5Xz5yfrH+Oh98nnWtj1OxteO1AB0i2R26w77pXCT0ffViLaE3RtgN2dOq8QGDTwsA=="],
+ "agents": ["agents@0.13.3", "", { "dependencies": { "@babel/plugin-proposal-decorators": "^7.29.0", "@cfworker/json-schema": "^4.1.1", "@modelcontextprotocol/sdk": "1.29.0", "@rolldown/plugin-babel": "^0.2.3", "cron-schedule": "^6.0.0", "mimetext": "^3.0.28", "nanoid": "^5.1.11", "partyserver": "^0.5.6", "partysocket": "1.1.19", "yargs": "^18.0.0" }, "peerDependencies": { "@cloudflare/ai-chat": ">=0.6.1 <1.0.0", "@cloudflare/codemode": ">=0.3.4 <1.0.0", "@tanstack/ai": ">=0.10.2 <1.0.0", "@x402/core": "^2.0.0", "@x402/evm": "^2.0.0", "ai": "^6.0.0", "chat": "^4.29.0", "react": "^19.0.0", "vite": ">=6.0.0 <9.0.0", "zod": "^4.0.0" }, "optionalPeers": ["@cloudflare/ai-chat", "@cloudflare/codemode", "@tanstack/ai", "@x402/core", "@x402/evm", "chat", "vite"], "bin": { "agents": "dist/cli/index.js" } }, "sha512-sanbvHT9rdMuxq9rsBukqqVr88W7s0t6WXFuRdA0uxqikTMCb7Oki9aGWcgjoUN0qvaV/qlJ9RLTQAVSw/eLNg=="],
- "ai": ["ai@6.0.184", "", { "dependencies": { "@ai-sdk/gateway": "3.0.115", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@opentelemetry/api": "^1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-j//zHkKvj5ra27l8izHco8cj1g1Pr7vx1ZK+hrzrkHvndgIRmdfZKOb6+RAPpvbk42qGIsuYvlYbGlVAu3erNQ=="],
+ "ai": ["ai@6.0.202", "", { "dependencies": { "@ai-sdk/gateway": "3.0.128", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.28", "@opentelemetry/api": "^1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-14O7uyHVa5lXyt1RzduRqM1zwOnLBN+EaE+btWiP2R7GLHd5oh+Z9uaebR785V/Y2hXlxvuQGsw2Gj6iHpkxsg=="],
"ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="],
@@ -2371,22 +2363,6 @@
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
- "appium": ["appium@3.4.2", "", { "dependencies": { "@appium/base-driver": "10.5.2", "@appium/base-plugin": "3.2.4", "@appium/docutils": "2.4.2", "@appium/logger": "2.0.7", "@appium/schema": "1.1.1", "@appium/support": "7.2.2", "@appium/types": "1.4.0", "@sidvind/better-ajv-errors": "5.0.0", "ajv": "8.20.0", "ajv-formats": "3.0.1", "argparse": "2.0.1", "axios": "1.16.0", "bluebird": "3.7.2", "lilconfig": "3.1.3", "lodash": "4.18.1", "lru-cache": "11.3.5", "ora": "5.4.1", "package-changed": "3.0.0", "resolve-from": "5.0.0", "semver": "7.7.4", "teen_process": "4.1.3", "type-fest": "5.6.0", "winston": "3.19.0", "ws": "8.20.0", "yaml": "2.8.4" }, "bin": { "appium": "index.js" } }, "sha512-c3v2klHLuKBKFgvcKiZ88gGDNJQmSFhEbutjKSWrXuMlfl2rV3TPuYvQPb4TNfXTm1B96Uw130ND1RRpmBLgfw=="],
-
- "appium-adb": ["appium-adb@14.5.0", "", { "dependencies": { "@appium/support": "^7.2.2", "async-lock": "^1.0.0", "asyncbox": "^6.0.1", "ini": "^6.0.0", "lru-cache": "^11.1.0", "semver": "^7.0.0", "teen_process": "^4.0.4" } }, "sha512-7o+zmfSqODMH98YrCd1ryaJGv5KTr7mmLLalPp8DJzbtuncuuTrFI5R+WfSWs10WEWxxsT3Kqfv7s8f/OmB8sQ=="],
-
- "appium-android-driver": ["appium-android-driver@13.2.2", "", { "dependencies": { "@appium/support": "^7.2.2", "@colors/colors": "^1.6.0", "appium-adb": "^14.3.0", "appium-chromedriver": "^8.2.25", "asyncbox": "^6.1.0", "axios": "^1.16.0", "io.appium.settings": "^7.0.4", "lodash": "^4.17.4", "lru-cache": "^11.1.0", "moment": "^2.24.0", "moment-timezone": "^0.x", "portscanner": "^2.2.0", "semver": "^7.0.0", "teen_process": "^4.0.7", "ws": "^8.0.0" }, "peerDependencies": { "appium": "^3.0.0-rc.2" } }, "sha512-Mblt0QrV7HVrj++WWwArJXvI+jGQ+Fj4jLd+6p3a2rjwVvyTuygm1tr/8C8UBQQoqoBm4WViYDHBFmScTCaDfw=="],
-
- "appium-chromedriver": ["appium-chromedriver@8.4.1", "", { "dependencies": { "@appium/base-driver": "^10.0.0-rc.2", "@appium/support": "^7.2.2", "@xmldom/xmldom": "^0.x", "appium-adb": "^14.0.0", "asyncbox": "^6.0.1", "axios": "^1.16.0", "compare-versions": "^6.0.0", "semver": "^7.0.0", "teen_process": "^4.0.4", "xpath": "^0.x" } }, "sha512-GGftJvpu2L6wJFNZ/WbRDhRZhP5AUchYoQnokDL0gLQVwsAcil/6AMPI1YUv+AJzjEnCtBSlGyTgSo+AuoeQ2A=="],
-
- "appium-uiautomator2-driver": ["appium-uiautomator2-driver@7.4.0", "", { "dependencies": { "appium-adb": "^14.0.0", "appium-android-driver": "^13.1.1", "appium-uiautomator2-server": "^10.1.0", "asyncbox": "^6.0.1", "axios": "^1.16.0", "css-selector-parser": "^3.0.0", "io.appium.settings": "^7.0.1", "portscanner": "^2.2.0", "teen_process": "^4.0.4" }, "peerDependencies": { "appium": "^3.0.0-rc.2" } }, "sha512-4T+ItO/ZeRJqhOcHuCARXSXKuJXjhLNPdf/uaA4njx+AzYHEE2kDvN3taplKf6SCjTVdfssqMJCFuLOqnunqTw=="],
-
- "appium-uiautomator2-server": ["appium-uiautomator2-server@10.1.0", "", {}, "sha512-4YvWcyTTn1UtWvB3giNtGCo0yaji2c+7mcDwsOyk6dMoQ1JO0noxJ3rqpqTD7Kq14cXGcuR2OXwaVz5RGruXFg=="],
-
- "archiver": ["archiver@7.0.1", "", { "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", "buffer-crc32": "^1.0.0", "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", "zip-stream": "^6.0.1" } }, "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ=="],
-
- "archiver-utils": ["archiver-utils@5.0.2", "", { "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA=="],
-
"arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="],
"argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
@@ -2425,25 +2401,15 @@
"ast-types": ["ast-types@0.13.4", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w=="],
- "async": ["async@2.6.4", "", { "dependencies": { "lodash": "^4.17.14" } }, "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA=="],
-
"async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
- "async-lock": ["async-lock@1.4.1", "", {}, "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ=="],
-
- "asyncbox": ["asyncbox@6.3.0", "", { "dependencies": { "p-limit": "^7.2.0" } }, "sha512-7IFpnQDltd5rYQjhIJIpyismJtdWmw/pOABZKJfv2WVo0a6iYh2ZzUuCJJclae5mBtK0H/EychxXg91GB7rGdQ=="],
-
- "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
-
"autoprefixer": ["autoprefixer@10.5.0", "", { "dependencies": { "browserslist": "^4.28.2", "caniuse-lite": "^1.0.30001787", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong=="],
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
"await-lock": ["await-lock@2.2.2", "", {}, "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw=="],
- "axe-core": ["axe-core@4.11.4", "", {}, "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA=="],
-
- "axios": ["axios@1.16.1", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A=="],
+ "axe-core": ["axe-core@4.12.1", "", {}, "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA=="],
"b4a": ["b4a@1.8.1", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw=="],
@@ -2469,7 +2435,7 @@
"babel-preset-current-node-syntax": ["babel-preset-current-node-syntax@1.2.0", "", { "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0 || ^8.0.0-0" } }, "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg=="],
- "babel-preset-expo": ["babel-preset-expo@55.0.21", "", { "dependencies": { "@babel/generator": "^7.20.5", "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.83.6", "babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.32.0", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "resolve-from": "^5.0.0" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "*", "expo-widgets": "^55.0.17", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["@babel/runtime", "expo", "expo-widgets"] }, "sha512-anXoUZBcxydLdVs2L+r3bWKGUvZv2FtgOl8xRJ12i/YfKICBpwTGZWSTiEYTqBByZ6GkA3mE9+3TW97X2ocFTQ=="],
+ "babel-preset-expo": ["babel-preset-expo@55.0.22", "", { "dependencies": { "@babel/generator": "^7.20.5", "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.83.6", "babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.32.0", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "resolve-from": "^5.0.0" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "*", "expo-widgets": "^55.0.19", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["@babel/runtime", "expo", "expo-widgets"] }, "sha512-Se6kPnvCNN13jJVIa6JJvlmImVoVRzu9stagAbivCPcfrq2VNrsEiYpJZ1+H32kXinKW/y797/wctGuxPy0APw=="],
"babel-preset-jest": ["babel-preset-jest@29.6.3", "", { "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA=="],
@@ -2477,37 +2443,31 @@
"balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
- "bare-events": ["bare-events@2.8.3", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-HdUm8EMQBLaJvGUdidNNbqpA1kYkwNcb+MYxkxCLAPJGQzlv9J0C24h8V65Z4c5GLd/JEALDvpFCQgpLJqc0zw=="],
+ "bare-events": ["bare-events@2.9.1", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg=="],
- "bare-fs": ["bare-fs@4.7.1", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-WDRsyVN52eAx/lBamKD6uyw8H4228h/x0sGGGegOamM2cd7Pag88GfMQalobXI+HaEUxpCkbKQUDOQqt9wawRw=="],
+ "bare-fs": ["bare-fs@4.7.2", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-aTvMFUWkBmjzKtEQMDGGDNF8bkfpD5N1b/FCwt7A3wrU4t1o/e/85Wzkluh6JlODCjqVESYCkQCdTXqZ9G7VFg=="],
"bare-os": ["bare-os@3.9.1", "", {}, "sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ=="],
- "bare-path": ["bare-path@3.0.0", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw=="],
+ "bare-path": ["bare-path@3.0.1", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ=="],
- "bare-stream": ["bare-stream@2.13.1", "", { "dependencies": { "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { "bare-abort-controller": "*", "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-abort-controller", "bare-buffer", "bare-events"] }, "sha512-Vp0cnjYyrEC4whYTymQ+YZi6pBpfiICZO3cfRG8sy67ZNWe951urv1x4eW1BKNngw3U+3fPYb5JQvHbCtxH7Ow=="],
+ "bare-stream": ["bare-stream@2.13.2", "", { "dependencies": { "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { "bare-abort-controller": "*", "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-abort-controller", "bare-buffer", "bare-events"] }, "sha512-2V5j0dOfxv3iIngIWMnW1O6UPXpeoU70HJzUJGVth/+RURhDyq7SEWTD70Y2SkUB0MQonYYWpIX3f85P/I22+Q=="],
- "bare-url": ["bare-url@2.4.3", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-Kccpc7ACfXaxfeInfqKcZtW4pT5YBn1mesc4sCsun6sRwtbJ4h+sNOaksUpYEJUKfN65YWC6Bw2OJEFiKxq8nQ=="],
+ "bare-url": ["bare-url@2.4.5", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ=="],
"base-64": ["base-64@0.1.0", "", {}, "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="],
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
- "base64-stream": ["base64-stream@1.0.0", "", {}, "sha512-BQQZftaO48FcE1Kof9CmXMFaAdqkcNorgc8CxesZv9nMbbTF1EFyQe89UOuh//QMmdtfUDXyO8rgUalemL5ODA=="],
-
- "baseline-browser-mapping": ["baseline-browser-mapping@2.10.30", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-xjOFN16Ha1+Rz4nFYKqHU/LSB+gx/Vi3yQLX7r7sAW+Wa+8hhF2h4pvqTrTMc8+WcDBEunnUurr46Jvv0jk3Vg=="],
-
- "basic-auth": ["basic-auth@2.0.1", "", { "dependencies": { "safe-buffer": "5.1.2" } }, "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg=="],
+ "baseline-browser-mapping": ["baseline-browser-mapping@2.10.36", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-lVq/Df7LXlO79MVaaUHztSwWiG9oXoWHlgvNS51v8Dpd4+G4/VIy6qYePTw31nAVls33nUtnfezYeLkYAak9dg=="],
"basic-ftp": ["basic-ftp@5.3.1", "", {}, "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw=="],
"bcryptjs": ["bcryptjs@3.0.3", "", { "bin": { "bcrypt": "bin/bcrypt" } }, "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g=="],
- "better-auth": ["better-auth@1.6.11", "", { "dependencies": { "@better-auth/core": "1.6.11", "@better-auth/drizzle-adapter": "1.6.11", "@better-auth/kysely-adapter": "1.6.11", "@better-auth/memory-adapter": "1.6.11", "@better-auth/mongo-adapter": "1.6.11", "@better-auth/prisma-adapter": "1.6.11", "@better-auth/telemetry": "1.6.11", "@better-auth/utils": "0.4.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.1.1", "@noble/hashes": "^2.0.1", "better-call": "1.3.5", "defu": "^6.1.4", "jose": "^6.1.3", "kysely": "^0.28.17", "nanostores": "^1.1.1", "zod": "^4.3.6" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": "^0.45.2", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "@tanstack/solid-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-Wwt6+q07dwIhsp6XiM7L1qSXVUWBEtNl+eZvwM778CguFqDZFBN9Pt6LtFaHl55t8Z+Zc//5kxcbgDY8/79vFQ=="],
-
- "better-auth-cloudflare": ["better-auth-cloudflare@0.3.0", "", { "dependencies": { "drizzle-orm": "^0.45.0", "mime": "^4.1.0", "zod": "^4.3.0" }, "peerDependencies": { "@better-auth/drizzle-adapter": "^1.5.0", "@cloudflare/workers-types": "^4.0.0", "better-auth": "^1.5.0" } }, "sha512-u0TrMbFhHNL2IFzkCbCQYyA/beeBSivdL+vfrNywYnsVrQO1qT5CC/yKhnRdrkwXLeNi9tCeoSwWoygTMSl0Yg=="],
+ "better-auth": ["better-auth@1.6.17", "", { "dependencies": { "@better-auth/core": "1.6.17", "@better-auth/drizzle-adapter": "1.6.17", "@better-auth/kysely-adapter": "1.6.17", "@better-auth/memory-adapter": "1.6.17", "@better-auth/mongo-adapter": "1.6.17", "@better-auth/prisma-adapter": "1.6.17", "@better-auth/telemetry": "1.6.17", "@better-auth/utils": "0.4.1", "@better-fetch/fetch": "1.3.0", "@noble/ciphers": "^2.1.1", "@noble/hashes": "^2.0.1", "better-call": "1.3.6", "defu": "^6.1.4", "jose": "^6.1.3", "kysely": "^0.28.17 || ^0.29.0", "nanostores": "^1.1.1", "zod": "^4.3.6" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": "^0.45.2", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "@tanstack/solid-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-M0XMJ9/KE9hlmuN2Zha1VayShZW5CQifAMPaoz41gtao2la6YpT5KrnL5MAeIAM/3d4DkdYA2BVMY1Gt4iEzHw=="],
- "better-call": ["better-call@1.3.5", "", { "dependencies": { "@better-auth/utils": "^0.4.0", "@better-fetch/fetch": "^1.1.21", "rou3": "^0.7.12", "set-cookie-parser": "^3.0.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-kOFJkBP7utAQLEYrobZm3vkTH8mXq5GNgvjc5/XEST1ilVHaxXUXfeDeFlqoETMtyqS4+3/h4ONX2i++ebZrvA=="],
+ "better-call": ["better-call@1.3.6", "", { "dependencies": { "@better-auth/utils": "^0.4.0", "@better-fetch/fetch": "^1.1.21", "rou3": "^0.7.12", "set-cookie-parser": "^3.0.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-no1jI+h6Bkxs1NVBo4rONbVIzsPjZ8IUu7IHaJBiFwVX1XEQGN8KpHots5fSWmXe9nNyLuLIcgx6WEUcE6EDaA=="],
"better-opn": ["better-opn@3.0.2", "", { "dependencies": { "open": "^8.0.4" } }, "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ=="],
@@ -2519,12 +2479,8 @@
"birpc": ["birpc@0.2.14", "", {}, "sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA=="],
- "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
-
"blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="],
- "bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="],
-
"body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
@@ -2545,7 +2501,7 @@
"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
- "buffer-crc32": ["buffer-crc32@1.0.0", "", {}, "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w=="],
+ "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
"buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
@@ -2575,7 +2531,7 @@
"camelize": ["camelize@1.0.1", "", {}, "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ=="],
- "caniuse-lite": ["caniuse-lite@1.0.30001793", "", {}, "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA=="],
+ "caniuse-lite": ["caniuse-lite@1.0.30001799", "", {}, "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw=="],
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
@@ -2639,18 +2595,12 @@
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
- "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
-
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
"commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
"comment-json": ["comment-json@4.6.2", "", { "dependencies": { "array-timsort": "^1.0.3", "esprima": "^4.0.1" } }, "sha512-R2rze/hDX30uul4NZoIZ76ImSJLFxn/1/ZxtKC1L77y2X1k+yYu1joKbAtMA2Fg3hZrTOiw0I5mwVMo0cf250w=="],
- "compare-versions": ["compare-versions@6.1.1", "", {}, "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg=="],
-
- "compress-commons": ["compress-commons@6.0.2", "", { "dependencies": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", "is-stream": "^2.0.1", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg=="],
-
"compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="],
"compression": ["compression@1.8.1", "", { "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" } }, "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w=="],
@@ -2667,8 +2617,6 @@
"consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="],
- "console-control-strings": ["console-control-strings@1.1.0", "", {}, "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="],
-
"content-disposition": ["content-disposition@1.1.0", "", {}, "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g=="],
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
@@ -2685,15 +2633,9 @@
"core-js-pure": ["core-js-pure@3.49.0", "", {}, "sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw=="],
- "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
-
"cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="],
- "cosmiconfig": ["cosmiconfig@9.0.1", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ=="],
-
- "crc-32": ["crc-32@1.2.2", "", { "bin": { "crc32": "bin/crc32.njs" } }, "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="],
-
- "crc32-stream": ["crc32-stream@6.0.0", "", { "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" } }, "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g=="],
+ "cosmiconfig": ["cosmiconfig@9.0.2", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg=="],
"cron-schedule": ["cron-schedule@6.0.0", "", {}, "sha512-BoZaseYGXOo5j5HUwTaegIog3JJbuH4BbrY9A1ArLjXpy+RWb3mV28F/9Gv1dDA7E2L8kngWva4NWisnLTyfgQ=="],
@@ -2711,8 +2653,6 @@
"css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="],
- "css-selector-parser": ["css-selector-parser@3.3.0", "", {}, "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g=="],
-
"css-to-react-native": ["css-to-react-native@3.2.0", "", { "dependencies": { "camelize": "^1.0.0", "css-color-keywords": "^1.0.0", "postcss-value-parser": "^4.0.2" } }, "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ=="],
"css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="],
@@ -2757,7 +2697,7 @@
"data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
- "date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="],
+ "date-fns": ["date-fns@4.4.0", "", {}, "sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w=="],
"date-fns-jalali": ["date-fns-jalali@4.1.0-0", "", {}, "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg=="],
@@ -2793,8 +2733,6 @@
"degenerator": ["degenerator@5.0.1", "", { "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", "esprima": "^4.0.1" } }, "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ=="],
- "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
-
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
@@ -2807,8 +2745,6 @@
"detect-newline": ["detect-newline@4.0.1", "", {}, "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog=="],
- "detect-node": ["detect-node@2.1.0", "", {}, "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="],
-
"detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="],
"detective-amd": ["detective-amd@6.1.0", "", { "dependencies": { "ast-module-types": "^6.0.1", "escodegen": "^2.1.0", "get-amd-module-type": "^6.0.2", "node-source-walk": "^7.0.1" }, "bin": { "detective-amd": "bin/cli.js" } }, "sha512-fmI6LGMvotqd49QaA3ZYw+q0aGp2yXmMjzIuY6fH9j9YFIXY/73yDhMwhX9cPbhWd+AH06NH1Di/LKOuCH0Ubg=="],
@@ -2817,7 +2753,7 @@
"detective-es6": ["detective-es6@5.0.2", "", { "dependencies": { "node-source-walk": "^7.0.1" } }, "sha512-+qHHGYhjupiVs4rnIpI9nZ5B130A4AmE35ZX1w33hb46vcZ7T3jfDbvmPw0FhWtMHn5BS5HHu7ZtnZ53bMcXZA=="],
- "detective-postcss": ["detective-postcss@8.0.3", "", { "dependencies": { "is-url-superb": "^4.0.0", "postcss-values-parser": "^6.0.2" }, "peerDependencies": { "postcss": "^8.4.47" } }, "sha512-0AQjxn13b14tLmeXQq0QAFXSP6vBZhWFfmEazyFQ+JVlVwfrYlKF6dGy4R06hqAiSZ9cRvFx0FW4uvVnx0WXiw=="],
+ "detective-postcss": ["detective-postcss@8.0.4", "", { "dependencies": { "is-url-superb": "^4.0.0", "postcss-values-parser": "^6.0.2" }, "peerDependencies": { "postcss": "^8.4.47" } }, "sha512-DZ7M/hWPZyr17ZUdoQ+TVXaPj70mYr4XXrAE+GeJbca44haCvZgb191L/jLJmFYewhxRJuBd4lUtNSu986TXag=="],
"detective-sass": ["detective-sass@6.0.2", "", { "dependencies": { "gonzales-pe": "^4.3.0", "node-source-walk": "^7.0.1" } }, "sha512-i3xpXHDKS0qI2aFW4asQ7fqlPK00ndOVZELvQapFJCaF0VxYmsNWtd0AmvXbTLMk7bfO5VdIeorhY9KfmHVoVA=="],
@@ -2837,13 +2773,11 @@
"didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="],
- "diff": ["diff@9.0.0", "", {}, "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw=="],
-
"dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="],
"dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="],
- "dnssd-advertise": ["dnssd-advertise@1.1.4", "", {}, "sha512-AmGyK9WpNf06WeP5TjHZq/wNzP76OuEeaiTlKr9E/EEelYLczywUKoqRz+DPRq/ErssjT4lU+/W7wzJW+7K/ZA=="],
+ "dnssd-advertise": ["dnssd-advertise@1.1.6", "", {}, "sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg=="],
"doctrine": ["doctrine@3.0.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="],
@@ -2861,12 +2795,12 @@
"drizzle-orm": ["drizzle-orm@0.45.2", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "prisma": "*", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "prisma", "sql.js", "sqlite3"] }, "sha512-kY0BSaTNYWnoDMVoyY8uxmyHjpJW1geOmBMdSSicKo9CIIWkSxMIj2rkeSR51b8KAPB7m+qysjuHme5nKP+E5Q=="],
+ "drizzle-seed": ["drizzle-seed@0.3.1", "", { "dependencies": { "pure-rand": "^6.1.0" }, "peerDependencies": { "drizzle-orm": ">=0.36.4" }, "optionalPeers": ["drizzle-orm"] }, "sha512-F/0lgvfOAsqlYoHM/QAGut4xXIOXoE5VoAdv2FIl7DpGYVXlAzKuJO+IphkKUFK3Dz+rFlOsQLnMNrvoQ0cx7g=="],
+
"drizzle-zod": ["drizzle-zod@0.8.3", "", { "peerDependencies": { "drizzle-orm": ">=0.36.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-66yVOuvGhKJnTdiqj1/Xaaz9/qzOdRJADpDa68enqS6g3t0kpNkwNYjUuaeXgZfO/UWuIM9HIhSlJ6C5ZraMww=="],
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
- "duplexer": ["duplexer@0.1.2", "", {}, "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="],
-
"eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
"ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
@@ -2875,7 +2809,7 @@
"effector": ["effector@23.4.4", "", {}, "sha512-QkZboRN28K/iwxigDhlJcI3ux3aNbt8kYGGH/GkqWG0OlGeyuBhb7PdM89Iu+ogV8Lmz16xIlwnXR2UNWI6psg=="],
- "electron-to-chromium": ["electron-to-chromium@1.5.357", "", {}, "sha512-NHlTIQDK8fmVwHwuIzmXYEJ1Ewq3D9wDNc0cWXxDGysP6Pb21giwGNkxiTifyKy/4SoPuN5l6GLP1W9Sv7zB2g=="],
+ "electron-to-chromium": ["electron-to-chromium@1.5.372", "", {}, "sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA=="],
"elysia": ["elysia@1.4.28", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-Vrx8sBnvq8squS/3yNBzR1jBXI+SgmnmvwawPjNuEHndUe5l1jV2Gp6JJ4ulDkEB8On6bWmmuyPpA+bq4t+WYg=="],
@@ -2889,15 +2823,13 @@
"empathic": ["empathic@1.1.0", "", {}, "sha512-rsPft6CK3eHtrlp9Y5ALBb+hfK+DWnA4WFebbazxjWyx8vSm3rZeoM3z9irsjcqO3PYRzlfv27XIB4tz2DV7RA=="],
- "enabled": ["enabled@2.0.0", "", {}, "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="],
-
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
"encoding-sniffer": ["encoding-sniffer@0.2.1", "", { "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" } }, "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw=="],
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
- "enhanced-resolve": ["enhanced-resolve@5.21.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q=="],
+ "enhanced-resolve": ["enhanced-resolve@5.24.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-SkE2t82KlkkxQRVMVLAGKxLfORGQfrkx5dkj+vlgXRVNEdPc4eZcR+J/Fvj8C+yKSFH5L0q3NFlyufOVQnCcYQ=="],
"enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="],
@@ -2917,11 +2849,11 @@
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
- "es-iterator-helpers": ["es-iterator-helpers@1.3.2", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "math-intrinsics": "^1.1.0" } }, "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw=="],
+ "es-iterator-helpers": ["es-iterator-helpers@1.3.3", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "math-intrinsics": "^1.1.0" } }, "sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g=="],
"es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="],
- "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
+ "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="],
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
@@ -2929,7 +2861,7 @@
"es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
- "es-toolkit": ["es-toolkit@1.46.1", "", {}, "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ=="],
+ "es-toolkit": ["es-toolkit@1.47.0", "", {}, "sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw=="],
"esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="],
@@ -2947,11 +2879,11 @@
"eslint-config-prettier": ["eslint-config-prettier@9.1.2", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ=="],
- "eslint-config-universe": ["eslint-config-universe@15.0.4", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "^8.29.1", "@typescript-eslint/parser": "^8.29.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.31.0", "eslint-plugin-n": "^17.17.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^5.2.6", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "globals": "^16.0.0" }, "peerDependencies": { "eslint": ">=8.10", "prettier": ">=3" }, "optionalPeers": ["prettier"] }, "sha512-7XTb/JTLzntJTUHXnR7ADl78kzRpQLm75NOjx1kYFnEMArJk69mDJ96WREzttro4/TOlQ9paGL+WFsRXk1vLkw=="],
+ "eslint-config-universe": ["eslint-config-universe@15.2.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "^8.59.0", "@typescript-eslint/parser": "^8.59.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.31.0", "eslint-plugin-n": "^17.17.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^5.2.6", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^7.0.0", "globals": "^16.0.0" }, "peerDependencies": { "eslint": ">=8.10", "prettier": ">=3" }, "optionalPeers": ["prettier"] }, "sha512-n2662q/mM+2pTFVz7ELosqhN+/nbR75Ut/4vLme40kKSHHe0oPbPMxgPqyYrASlANuSDP4aAJ71rRviDMCZTxg=="],
"eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.10", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.16.1", "resolve": "^2.0.0-next.6" } }, "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ=="],
- "eslint-module-utils": ["eslint-module-utils@2.12.1", "", { "dependencies": { "debug": "^3.2.7" }, "peerDependencies": { "eslint": "*" }, "optionalPeers": ["eslint"] }, "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw=="],
+ "eslint-module-utils": ["eslint-module-utils@2.13.0", "", { "dependencies": { "debug": "^3.2.7" }, "peerDependencies": { "eslint": "*" }, "optionalPeers": ["eslint"] }, "sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ=="],
"eslint-plugin-es": ["eslint-plugin-es@3.0.1", "", { "dependencies": { "eslint-utils": "^2.0.0", "regexpp": "^3.0.0" }, "peerDependencies": { "eslint": ">=4.19.1" } }, "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ=="],
@@ -2963,11 +2895,11 @@
"eslint-plugin-node": ["eslint-plugin-node@11.1.0", "", { "dependencies": { "eslint-plugin-es": "^3.0.0", "eslint-utils": "^2.0.0", "ignore": "^5.1.1", "minimatch": "^3.0.4", "resolve": "^1.10.1", "semver": "^6.1.0" }, "peerDependencies": { "eslint": ">=5.16.0" } }, "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g=="],
- "eslint-plugin-prettier": ["eslint-plugin-prettier@5.5.5", "", { "dependencies": { "prettier-linter-helpers": "^1.0.1", "synckit": "^0.11.12" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw=="],
+ "eslint-plugin-prettier": ["eslint-plugin-prettier@5.5.6", "", { "dependencies": { "prettier-linter-helpers": "^1.0.1", "synckit": "^0.11.13" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ=="],
"eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="],
- "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
+ "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.1.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g=="],
"eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="],
@@ -2997,13 +2929,11 @@
"eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="],
- "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
-
"events-universal": ["events-universal@1.0.1", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="],
"eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
- "eventsource-parser": ["eventsource-parser@3.0.8", "", {}, "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ=="],
+ "eventsource-parser": ["eventsource-parser@3.1.0", "", {}, "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg=="],
"exact-mirror": ["exact-mirror@0.2.7", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-+MeEmDcLA4o/vjK2zujgk+1VTxPR4hdp23qLqkWfStbECtAq9gmsvQa3LW6z/0GXZyHJobrCnmy1cdeE7BjsYg=="],
@@ -3011,7 +2941,7 @@
"expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
- "expo": ["expo@55.0.24", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "55.0.30", "@expo/config": "~55.0.17", "@expo/config-plugins": "~55.0.9", "@expo/devtools": "55.0.3", "@expo/fingerprint": "0.16.7", "@expo/local-build-cache-provider": "55.0.13", "@expo/log-box": "55.0.12", "@expo/metro": "~55.1.1", "@expo/metro-config": "55.0.21", "@expo/vector-icons": "^15.0.2", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~55.0.21", "expo-asset": "~55.0.17", "expo-constants": "~55.0.16", "expo-file-system": "~55.0.20", "expo-font": "~55.0.7", "expo-keep-awake": "~55.0.8", "expo-modules-autolinking": "55.0.22", "expo-modules-core": "55.0.25", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-minimum": "^0.1.2" }, "peerDependencies": { "@expo/dom-webview": "*", "@expo/metro-runtime": "*", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/dom-webview", "@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-nU95y+GIfD1dm9CSjsitDdltSU83dDqemxD1UUBxJPH8zKf7B5AdGVNyE6/jLWyCM/p/EmHfCeiqdrWCy9ljZA=="],
+ "expo": ["expo@55.0.26", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "55.0.32", "@expo/config": "~55.0.17", "@expo/config-plugins": "~55.0.10", "@expo/devtools": "55.0.3", "@expo/fingerprint": "0.16.7", "@expo/local-build-cache-provider": "55.0.13", "@expo/log-box": "55.0.12", "@expo/metro": "~55.1.1", "@expo/metro-config": "55.0.23", "@expo/vector-icons": "^15.0.2", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~55.0.22", "expo-asset": "~55.0.17", "expo-constants": "~55.0.16", "expo-file-system": "~55.0.22", "expo-font": "~55.0.8", "expo-keep-awake": "~55.0.8", "expo-modules-autolinking": "55.0.24", "expo-modules-core": "55.0.25", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-minimum": "^0.1.2" }, "peerDependencies": { "@expo/dom-webview": "*", "@expo/metro-runtime": "*", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/dom-webview", "@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-MuVW6Uzd/Jh6E37ICOYAiTOm9nflNMUNzf6wH5ld/IXFyuF2Lo86a8fCSMgHcvTGsSjRsJ5Uxhf+WHZcvGPfrg=="],
"expo-apple-authentication": ["expo-apple-authentication@55.0.13", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-Qvh3DmhXqhtWOe7BC9e7UVApR3XS1qE7+68tVLqb3KI/sET7QV9KT5JgOJogWmmCJVxA/kaot0M136yvW1pdWA=="],
@@ -3023,11 +2953,11 @@
"expo-constants": ["expo-constants@55.0.16", "", { "dependencies": { "@expo/env": "~2.1.2" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-Z15/No94UHoogD+pulxjudGAeOHTEIWZgb/vnX48Wx5D+apWTeCbnKxQZZtGQlosvduYL5kaic2/W8U+NHfBQQ=="],
- "expo-dev-client": ["expo-dev-client@55.0.34", "", { "dependencies": { "expo-dev-launcher": "55.0.35", "expo-dev-menu": "55.0.29", "expo-dev-menu-interface": "55.0.2", "expo-manifests": "~55.0.17", "expo-updates-interface": "~55.1.6" }, "peerDependencies": { "expo": "*" } }, "sha512-IiQcIyzE/ixWtOa73XGf/7bsIN4DRnMvrmheCvCkqFIUv/mi+RLQt9D+xRRVbIwfnmjgDCjGxOLJVzFEcUbcIg=="],
+ "expo-dev-client": ["expo-dev-client@55.0.35", "", { "dependencies": { "expo-dev-launcher": "55.0.36", "expo-dev-menu": "55.0.30", "expo-dev-menu-interface": "55.0.2", "expo-manifests": "~55.0.17", "expo-updates-interface": "~55.1.6" }, "peerDependencies": { "expo": "*" } }, "sha512-DN50x9gqWYAfnJpxgiJm3zK2bFvDhxJ5JjFq0wFot7o4knZ7H3BVwiL6zZMHG29g6gfxdgpzGG69WPiSR/Ipgg=="],
- "expo-dev-launcher": ["expo-dev-launcher@55.0.35", "", { "dependencies": { "@expo/schema-utils": "^55.0.4", "expo-dev-menu": "55.0.29", "expo-manifests": "~55.0.17" }, "peerDependencies": { "expo": "*" } }, "sha512-Cfdx4exreS9J7zLe9iE+ARItpse1ixjdXn+5W0ZdqCYdSrN+AabKtHmevXOYImBn+R1aXdA8UGkJ/W6OoCXjNQ=="],
+ "expo-dev-launcher": ["expo-dev-launcher@55.0.36", "", { "dependencies": { "@expo/schema-utils": "^55.0.4", "expo-dev-menu": "55.0.30", "expo-manifests": "~55.0.17" }, "peerDependencies": { "expo": "*" } }, "sha512-Dn2om4J71aavWqi1jLzK3QlGZjDiFv7nIBZkQyzy2zW62IOD9kLwOOvHHj07Ra/6n9cqFEpNYzwpPkR7KHuYZA=="],
- "expo-dev-menu": ["expo-dev-menu@55.0.29", "", { "dependencies": { "expo-dev-menu-interface": "55.0.2" }, "peerDependencies": { "expo": "*" } }, "sha512-dzKE+2Ag8nHhTgSetjDVR+u4UvgaCfRdQrl6tJyFbeYHJ2CZVxhRsMfH4ULQxF5ry/bJeSxZ9dbQWizGnXP9mg=="],
+ "expo-dev-menu": ["expo-dev-menu@55.0.30", "", { "dependencies": { "expo-dev-menu-interface": "55.0.2" }, "peerDependencies": { "expo": "*" } }, "sha512-uwDI4cEPzpRemf06Ts5O41azJcz8BBcE6QOkNaTX8JlzdJ05eq9jWxmbA1WhoSoE5C+NFo8njHSvmHqUqTpOng=="],
"expo-dev-menu-interface": ["expo-dev-menu-interface@55.0.2", "", { "peerDependencies": { "expo": "*" } }, "sha512-DomUNvGzY/xliwnMdbAYY780sCv19N7zIbifc0ClcoCzJZpNSCkvJ2qGIFRPyM/7DmqmlHGCKi8di7kYYLKNEg=="],
@@ -3035,17 +2965,17 @@
"expo-eas-client": ["expo-eas-client@55.0.5", "", {}, "sha512-wRagCeSbSnSGVXgP7V+qiGfXzZ9hTVKWvKIOP7lwrX3MIEenNmNlO4D3RVC3aNU2GhmO3ZCZIIEre80KZoUUHA=="],
- "expo-file-system": ["expo-file-system@55.0.20", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-sBCHhNlCT3EiqCcE6xSbyvOLUAlKx7+p0qjo+c+UPyC/gMrXUdva99g25uptM+fEMwy2co25MUQQ0U0guQLOQA=="],
+ "expo-file-system": ["expo-file-system@55.0.22", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-T5Rfv3vqcFyhVrl/tEEeglc/J8LJbcZQgC3TMT5jxzIgUgWmIgJEgncGYqB/YNXFgUTL2LiuCvqrU51Dzp83NQ=="],
- "expo-font": ["expo-font@55.0.7", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-oH39Xb+3i6Y69b7YRP+P+5WLx7621t+ep/RAgLwJJYpTjs7CnSohUG+873rEtqsTAuQGi63ms7x9ZeHj1E9LYw=="],
+ "expo-font": ["expo-font@55.0.8", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-WyP75pnKqhLNktYwDn3xKAUNt5rLihRDv8XWGhhz6VEhVqypixpT86NA3uGtiDTlM3gGjhrYCY7o7ypXgCUOZg=="],
"expo-glass-effect": ["expo-glass-effect@55.0.11", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-wqq7GUOqSkfoFJzreZvBG0jzjsq5c582m3glhWSjcmIuByxXXWp6j6GY6hyFuYKzpOXhbuvusVxGCQi0yWnp3g=="],
"expo-haptics": ["expo-haptics@55.0.14", "", { "peerDependencies": { "expo": "*" } }, "sha512-KjDItBsA9mi1f5nRwf8g1wOdfEcLHwvEdt5Jl1sMCDETR/homcGOl+F3QIiPOl/PRlbGVieQsjTtF4DGtHOj6g=="],
- "expo-image": ["expo-image@55.0.10", "", { "dependencies": { "sf-symbols-typescript": "^2.2.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-We+vq/Z8jy8zmGxcOP8vrhiWkkwyXFdSks8cSlPi0bpu6D0Ei6l9Nj2xHWCD+yoENh92aCEe1+QRujAwXbogGA=="],
+ "expo-image": ["expo-image@55.0.11", "", { "dependencies": { "sf-symbols-typescript": "^2.2.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-PVIBYQJW/h1f6Zb9xnoWlgfqyOPVm2yb6eo6ZogaKbvMrhb/Q/fiERbagi4oqmR6IPljWPEpkXXQyFBUh7TjpQ=="],
- "expo-image-loader": ["expo-image-loader@55.0.0", "", { "peerDependencies": { "expo": "*" } }, "sha512-NOjp56wDrfuA5aiNAybBIjqIn1IxKeGJ8CECWZncQ/GzjZfyTYAHTCyeApYkdKkMBLHINzI4BbTGSlbCa0fXXQ=="],
+ "expo-image-loader": ["expo-image-loader@55.0.1", "", { "peerDependencies": { "expo": "*" } }, "sha512-o8gCo1j59XpXDh0/llgNYPcnfecYQhafQAO0yw5pb+kukPizvNoEqea8tFQIIQmNYqxd6Ljgs7lLXed0gXpOdQ=="],
"expo-image-picker": ["expo-image-picker@55.0.20", "", { "dependencies": { "expo-image-loader": "~55.0.0" }, "peerDependencies": { "expo": "*" } }, "sha512-lfWt/0rPWdKz8AdDEGmGHZIJSNlVc720Dlx5bfou10FU16ZV5wAbTU63nm2jkXd8hbXke4a/2Ha1dzxCVA+LQQ=="],
@@ -3057,13 +2987,13 @@
"expo-linking": ["expo-linking@55.0.15", "", { "dependencies": { "expo-constants": "~55.0.16", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-/RQh2vkNqV8Bim9Owm/evVqn2fqTvCDYHkpYPoSKbLAdydSGdHC2xZNw7Odl4wu1i1/3L4Xz//LKd3NsPWYWBQ=="],
- "expo-localization": ["expo-localization@55.0.14", "", { "dependencies": { "rtl-detect": "^1.0.2" }, "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-Q7VeW5gs0qMunYxIDB8+SpY/4T/h3CUE2kl6r6jnbYc6MPpmrK9bx/D9MeCfh0LmXW8oefy3MJYZQdPciEXU7Q=="],
+ "expo-localization": ["expo-localization@55.0.15", "", { "dependencies": { "rtl-detect": "^1.0.2" }, "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-+HD55LeeIWyVRLvpQ909Am89XS16dUBkbB4/ruCJXS9oWv1K8W+FoXuOPTpmdvwHfC9cxt0loiwPWUiw2fdgbg=="],
"expo-location": ["expo-location@55.1.10", "", { "dependencies": { "@expo/image-utils": "^0.8.14" }, "peerDependencies": { "expo": "*" } }, "sha512-MkcFucsZ567Bn8ChElVTYVbOs2QXn27IKaBrVKogw7ZcbooImdj3L/UR6E7s3LkgF33YubKynAp9Opvixdwl7g=="],
"expo-manifests": ["expo-manifests@55.0.17", "", { "dependencies": { "expo-json-utils": "~55.0.2" }, "peerDependencies": { "expo": "*" } }, "sha512-vKZvFivX3usVJKfBODKQcFHso0g38zlGbRGqGAppz+il0zKvG6umpJ47OZbzLod7iJpjd+ZDD2AGuOxacixonA=="],
- "expo-modules-autolinking": ["expo-modules-autolinking@55.0.22", "", { "dependencies": { "@expo/require-utils": "^55.0.5", "@expo/spawn-async": "^1.7.2", "chalk": "^4.1.0", "commander": "^7.2.0" }, "bin": { "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, "sha512-13x32V0HMHJDjND4K/gU2lQIZNxYn5S5rFzujqHmnXvOO6WGrVVELpk/0p5FmBfeuQ7GGFsATbhazQk+FeukUw=="],
+ "expo-modules-autolinking": ["expo-modules-autolinking@55.0.24", "", { "dependencies": { "@expo/require-utils": "^55.0.5", "@expo/spawn-async": "^1.7.2", "chalk": "^4.1.0", "commander": "^7.2.0" }, "bin": { "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, "sha512-A0OyMbTPZqibYrwqj98HFYTNSvl4NSS4Zt+R5A8qiAx3nM0mc81e6Iqw7Wl4J8M/t36lJ+cT3WuVTz5Oszj6Hw=="],
"expo-modules-core": ["expo-modules-core@55.0.25", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-worklets": "^0.7.4 || ^0.8.0" }, "optionalPeers": ["react-native-worklets"] }, "sha512-yXpfg7aHLbuqoXocK34Vua6Aey5SCyqLygAsXAMbul9P8vfBjLpaOPiTJ5cLVF7Drfq8ownqVJO6qpGEtZ6GOw=="],
@@ -3071,11 +3001,11 @@
"expo-network": ["expo-network@55.0.14", "", { "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-Sy544zTPjVh+tbOLUOU8fBX87oRSrNQqUZY6TLO0w0WF/QTNb7yxlwRh6v6wfKKRg9xpZypTIIEtdG/s6q8ZQA=="],
- "expo-router": ["expo-router@55.0.14", "", { "dependencies": { "@expo/metro-runtime": "^55.0.11", "@expo/schema-utils": "^55.0.4", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-navigation/bottom-tabs": "^7.15.5", "@react-navigation/native": "^7.1.33", "@react-navigation/native-stack": "^7.14.5", "client-only": "^0.0.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "expo-glass-effect": "^55.0.11", "expo-image": "^55.0.10", "expo-server": "^55.0.9", "expo-symbols": "^55.0.8", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-native-is-edge-to-edge": "^1.2.1", "semver": "~7.6.3", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "use-latest-callback": "^0.2.1", "vaul": "^1.1.2" }, "peerDependencies": { "@expo/log-box": "55.0.12", "@react-navigation/drawer": "^7.9.4", "@testing-library/react-native": ">= 13.2.0", "expo": "*", "expo-constants": "^55.0.16", "expo-linking": "^55.0.15", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-screens": "*", "react-native-web": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@react-navigation/drawer", "@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-rOn/wosp2hAPM+O2o41hnarbP5Zqv9UkHWa31KoSoiOme1tpmZd2yc93XtRAtzP0P5E5xzqq7a2rbEAarpP5XA=="],
+ "expo-router": ["expo-router@55.0.16", "", { "dependencies": { "@expo/metro-runtime": "^55.0.11", "@expo/schema-utils": "^55.0.4", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-navigation/bottom-tabs": "^7.15.5", "@react-navigation/native": "^7.1.33", "@react-navigation/native-stack": "^7.14.5", "client-only": "^0.0.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "expo-glass-effect": "^55.0.11", "expo-image": "^55.0.11", "expo-server": "^55.0.11", "expo-symbols": "^55.0.9", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-native-is-edge-to-edge": "^1.2.1", "semver": "~7.6.3", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "use-latest-callback": "^0.2.1", "vaul": "^1.1.2" }, "peerDependencies": { "@expo/log-box": "55.0.12", "@react-navigation/drawer": "^7.9.4", "@testing-library/react-native": ">= 13.2.0", "expo": "*", "expo-constants": "^55.0.16", "expo-linking": "^55.0.15", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-screens": "*", "react-native-web": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@react-navigation/drawer", "@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-xVwWsDz3Ar2+3hRpMMrZMYFzkJak322vCA5/XCP7WOL0hEXnWhgQGhv5IEYZyz/TXZbl2IYD6/1MnH9mBhjwKQ=="],
"expo-secure-store": ["expo-secure-store@55.0.14", "", { "peerDependencies": { "expo": "*" } }, "sha512-OKp9pDiTa4kgChop8+pTRJGBPhkJUcAxP5c6JbivNr4bmx3I+gKmAj1ov4KOXkY95TpWdHO+GQ4+0BgSY2P3JQ=="],
- "expo-server": ["expo-server@55.0.9", "", {}, "sha512-N5Ipn1NwqaJzEm+G97o0Jbe4g/th3R/16N1DabnYryXKCiZwDkK13/w3VfGkQN9LOOaBP+JIRxGf4M8lQKPzyA=="],
+ "expo-server": ["expo-server@55.0.11", "", {}, "sha512-AxRdHqcv0H1g4s923vu+5n1Nrhne23bjXbP+Vl7+Lwfpe7MG9PuU1IS95IJK6a+7BVV1mRN6QlZvs8Yv7EEXNQ=="],
"expo-sqlite": ["expo-sqlite@55.0.16", "", { "dependencies": { "await-lock": "^2.2.2" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-v6EIL4ygqWt/+ZfI76jIIv+IIaU8PnWPNjkmIN95vEQgh0FrWqzwssqe5ffQmm79kIfqIPTtAgTdl8MuZv88gg=="],
@@ -3085,11 +3015,11 @@
"expo-structured-headers": ["expo-structured-headers@55.0.2", "", {}, "sha512-KITovrWigTOtsII5hRQ9/3ydaNcxCux5g6O+eTPLyjnye9dpkDKl5GmCLVPVKIL/d7253OtbGtWMD4m0gha5pw=="],
- "expo-symbols": ["expo-symbols@55.0.8", "", { "dependencies": { "@expo-google-fonts/material-symbols": "^0.4.1", "sf-symbols-typescript": "^2.0.0" }, "peerDependencies": { "expo": "*", "expo-font": "*", "react": "*", "react-native": "*" } }, "sha512-Dg6BTu+fCWukdlh+3XYIr6NbqJWmK4aAQ6i6BInKnWU0ALuzVUJcMDq8Lk9bHok2hOh3OhzJqlCqEoBXPInIVQ=="],
+ "expo-symbols": ["expo-symbols@55.0.9", "", { "dependencies": { "@expo-google-fonts/material-symbols": "^0.4.1", "sf-symbols-typescript": "^2.0.0" }, "peerDependencies": { "expo": "*", "expo-font": "*", "react": "*", "react-native": "*" } }, "sha512-F85C/8ExQjd2gYjasLVKMT8wPj+1+19TVTqg4jAeVjVZklqiQtLO72io9Ji1xAjYNgmDeUI0diVHlFMMTC4Ekg=="],
"expo-system-ui": ["expo-system-ui@55.0.18", "", { "dependencies": { "@react-native/normalize-colors": "0.83.6", "debug": "^4.3.2" }, "peerDependencies": { "expo": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-Fbc0HJgqMpABeA/gI7NJFnSXwUeLrEMjjXq8Nl+4gTXyacIK2iOOrzCkvq41rKBBde0CR6kVnB1DXj0j9ZYnjg=="],
- "expo-updates": ["expo-updates@55.0.22", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/plist": "^0.5.3", "@expo/spawn-async": "^1.7.2", "arg": "^4.1.0", "chalk": "^4.1.2", "debug": "^4.3.4", "expo-eas-client": "~55.0.5", "expo-manifests": "~55.0.17", "expo-structured-headers": "~55.0.2", "expo-updates-interface": "~55.1.6", "getenv": "^2.0.0", "glob": "^13.0.0", "ignore": "^5.3.1", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" }, "bin": { "expo-updates": "bin/cli.js" } }, "sha512-xLprYCwHYLrH+rtI5yMHWWScv6vMRRRpc+JHGjkLTeaFKHt1Lo1Kk7RUSOgSd61uiWX3yvI9mLRypdJbRvD5Mw=="],
+ "expo-updates": ["expo-updates@55.0.24", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/plist": "^0.5.4", "@expo/spawn-async": "^1.7.2", "arg": "^4.1.0", "chalk": "^4.1.2", "debug": "^4.3.4", "expo-eas-client": "~55.0.5", "expo-manifests": "~55.0.17", "expo-structured-headers": "~55.0.2", "expo-updates-interface": "~55.1.6", "getenv": "^2.0.0", "glob": "^13.0.0", "ignore": "^5.3.1", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" }, "bin": { "expo-updates": "bin/cli.js" } }, "sha512-aqbsRT5GyKG8++RndIb4+jFUknsPgqWImzYUG20PiPjwPlQ25MSfz5+r1IAI8YfvGuLRIIRt8yDQ2Ob+RV+fyg=="],
"expo-updates-interface": ["expo-updates-interface@55.1.6", "", { "peerDependencies": { "expo": "*" } }, "sha512-evxNpagCkjT3lE6bGV570TFzRtKuIuLY8I37RYHoriXCJ+ZKCN1hbmklK29uAixya+BxGpeTI2K4FqYeJLvfrw=="],
@@ -3149,8 +3079,6 @@
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
- "fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="],
-
"fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
"fetch-nodeshim": ["fetch-nodeshim@0.4.10", "", {}, "sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w=="],
@@ -3169,33 +3097,25 @@
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
- "find-up-simple": ["find-up-simple@1.0.1", "", {}, "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ=="],
-
"flat-cache": ["flat-cache@3.2.0", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw=="],
"flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
"flow-enums-runtime": ["flow-enums-runtime@0.0.6", "", {}, "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw=="],
- "fn.name": ["fn.name@1.1.0", "", {}, "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="],
-
- "follow-redirects": ["follow-redirects@1.16.0", "", { "peerDependencies": { "debug": "*" }, "optionalPeers": ["debug"] }, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="],
-
"fontfaceobserver": ["fontfaceobserver@2.3.0", "", {}, "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg=="],
"for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
- "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
-
"formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
"fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="],
- "framer-motion": ["framer-motion@12.38.0", "", { "dependencies": { "motion-dom": "^12.38.0", "motion-utils": "^12.36.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g=="],
+ "framer-motion": ["framer-motion@12.40.0", "", { "dependencies": { "motion-dom": "^12.40.0", "motion-utils": "^12.39.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-uaBd3qC1v3KQqBEjwTUd183K6PbS+j0yR9w9VmEOLWA/tnUcSn8Xa3uck7t4dgpDoUss8xQTcj8W2L07lrnLFg=="],
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
@@ -3207,15 +3127,13 @@
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
- "ftp-response-parser": ["ftp-response-parser@1.0.1", "", { "dependencies": { "readable-stream": "^1.0.31" } }, "sha512-++Ahlo2hs/IC7UVQzjcSAfeUpCwTTzs4uvG5XfGnsinIFkWUYF4xWwPd5qZuK8MJrmUIxFMuHcfqaosCDjvIWw=="],
-
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
- "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="],
+ "function.prototype.name": ["function.prototype.name@1.2.0", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2", "hasown": "^2.0.4", "is-callable": "^1.2.7", "is-document.all": "^1.0.0" } }, "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew=="],
"functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
- "gaxios": ["gaxios@7.1.4", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA=="],
+ "gaxios": ["gaxios@7.1.5", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg=="],
"gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="],
@@ -3239,7 +3157,7 @@
"get-stdin": ["get-stdin@4.0.1", "", {}, "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw=="],
- "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
+ "get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
"get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
@@ -3267,7 +3185,7 @@
"gonzales-pe": ["gonzales-pe@4.3.0", "", { "dependencies": { "minimist": "^1.2.5" }, "bin": { "gonzales": "bin/gonzales.js" } }, "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ=="],
- "google-auth-library": ["google-auth-library@10.6.2", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw=="],
+ "google-auth-library": ["google-auth-library@10.7.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-QpTAbNJ36TliZLx3TTtahR8HG0hN9RllL1e3FymOvQSIKK8JmgV58H924ub2wa2DsS3ANjjP1Aw1N+Ramc8hqQ=="],
"google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="],
@@ -3279,8 +3197,6 @@
"gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="],
- "handle-thing": ["handle-thing@2.0.1", "", {}, "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg=="],
-
"has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
@@ -3293,7 +3209,7 @@
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
- "hasown": ["hasown@2.0.3", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg=="],
+ "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="],
"hast-util-sanitize": ["hast-util-sanitize@5.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "unist-util-position": "^5.0.0" } }, "sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg=="],
@@ -3305,18 +3221,16 @@
"hermes-compiler": ["hermes-compiler@0.14.1", "", {}, "sha512-+RPPQlayoZ9n6/KXKt5SFILWXCGJ/LV5d24L5smXrvTDrPS4L6dSctPczXauuvzFP3QEJbD1YO7Z3Ra4a+4IhA=="],
- "hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
+ "hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
- "hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="],
+ "hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
"hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
- "hono": ["hono@4.12.19", "", {}, "sha512-xa3eYXYXx68XTT4hZ7dRzsXBhaq85ToSrlUJNoR0gwz/1Ap/CNwX47wfvV7pc/xWhjKVVkLT7zBJy8chhNguqQ=="],
+ "hono": ["hono@4.12.25", "", {}, "sha512-2NFaIyNVgJmBs/ecmtGzlmluTFs5cHEWGTdu0t1HBwYzoGXOL5nUQBRMXsXWla5i4KkG//QMzVP88m1+I3fdAQ=="],
"hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="],
- "hpack.js": ["hpack.js@2.1.6", "", { "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", "readable-stream": "^2.0.1", "wbuf": "^1.1.0" } }, "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ=="],
-
"html-escaper": ["html-escaper@3.0.3", "", {}, "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="],
"html-parse-stringify": ["html-parse-stringify@3.0.1", "", { "dependencies": { "void-elements": "3.1.0" } }, "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg=="],
@@ -3325,16 +3239,12 @@
"htmlparser2": ["htmlparser2@10.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "entities": "^7.0.1" } }, "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ=="],
- "http-deceiver": ["http-deceiver@1.2.7", "", {}, "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw=="],
-
"http-errors": ["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" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
"http-link-header": ["http-link-header@1.1.3", "", {}, "sha512-3cZ0SRL8fb9MUlU3mKM61FcQvPfXx2dBrZW3Vbg5CXa8jFlK8OaEpePenLe1oEXQduhz8b0QjsqfS59QP4AJDQ=="],
"http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
- "http-status-codes": ["http-status-codes@2.3.0", "", {}, "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA=="],
-
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
"hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="],
@@ -3361,13 +3271,11 @@
"indent-string": ["indent-string@2.1.0", "", { "dependencies": { "repeating": "^2.0.0" } }, "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg=="],
- "index-to-position": ["index-to-position@1.2.0", "", {}, "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw=="],
-
"inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="],
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
- "ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="],
+ "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
"inline-style-prefixer": ["inline-style-prefixer@7.0.1", "", { "dependencies": { "css-in-js-utils": "^3.1.0" } }, "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw=="],
@@ -3383,8 +3291,6 @@
"invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="],
- "io.appium.settings": ["io.appium.settings@7.1.2", "", { "dependencies": { "@appium/logger": "^2.0.0-rc.1", "asyncbox": "^6.0.1", "semver": "^7.5.4", "teen_process": "^4.0.4" } }, "sha512-WdvMHAO3aH6cfzg0bcTxowH/QvqBydkFfnacpoNt/+nZeLCp+TcUSci+v8EZWG+GcEzQ9wK6w0ycU8S1mmqEEg=="],
-
"ip-address": ["ip-address@10.2.0", "", {}, "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA=="],
"ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
@@ -3411,6 +3317,8 @@
"is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
+ "is-document.all": ["is-document.all@1.0.0", "", { "dependencies": { "call-bound": "^1.0.4" } }, "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g=="],
+
"is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="],
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
@@ -3425,16 +3333,12 @@
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
- "is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="],
-
"is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
"is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
- "is-number-like": ["is-number-like@1.0.8", "", { "dependencies": { "lodash.isfinite": "^3.3.2" } }, "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA=="],
-
"is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="],
"is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="],
@@ -3451,8 +3355,6 @@
"is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="],
- "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
-
"is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="],
"is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="],
@@ -3461,8 +3363,6 @@
"is-typedarray": ["is-typedarray@1.0.0", "", {}, "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="],
- "is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="],
-
"is-url-superb": ["is-url-superb@4.0.0", "", {}, "sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA=="],
"is-utf8": ["is-utf8@0.2.1", "", {}, "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q=="],
@@ -3519,15 +3419,15 @@
"jju": ["jju@1.4.0", "", {}, "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA=="],
- "jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="],
+ "jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="],
- "jotai": ["jotai@2.20.0", "", { "peerDependencies": { "@babel/core": ">=7.0.0", "@babel/template": ">=7.0.0", "@types/react": ">=17.0.0", "react": ">=17.0.0" }, "optionalPeers": ["@babel/core", "@babel/template", "@types/react", "react"] }, "sha512-b5GAqgmXmXzB4WPaTH26ppk9Sl7AA9WSQX7yfdM+gJ1rFROiWcVbi97gFuN/yVCojOcbcvop2sfLL+fjxW0JVg=="],
+ "jotai": ["jotai@2.20.1", "", { "peerDependencies": { "@babel/core": ">=7.0.0", "@babel/template": ">=7.0.0", "@types/react": ">=17.0.0", "react": ">=17.0.0" }, "optionalPeers": ["@babel/core", "@babel/template", "@types/react", "react"] }, "sha512-dnuKfU/GLi8B28RRMjQ3AfoN7kfzP8o41+AX2FmITZqEMY8PHnjABq+VkEooomLwYaGjda+pgy0yFSjaHX/ZPg=="],
"jpeg-js": ["jpeg-js@0.4.4", "", {}, "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="],
"js-base64": ["js-base64@3.7.8", "", {}, "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow=="],
- "js-cookie": ["js-cookie@3.0.7", "", {}, "sha512-z/wZZgDrkNV1eA0ULjM/F9/50Ya8fbzgKneSpoPsXSGd0KnpdtHfOZWK+GcwLk+EZbS4F9RBhU+K2RgzuDaItw=="],
+ "js-cookie": ["js-cookie@3.0.8", "", {}, "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw=="],
"js-library-detector": ["js-library-detector@6.7.0", "", {}, "sha512-c80Qupofp43y4cJ7+8TTDN/AsDwLi5oOm/plBrWI+iQt485vKXCco+yVmOwEgdo9VOdsYTuV0UlTeetVPTriXA=="],
@@ -3539,8 +3439,6 @@
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
- "jsftp": ["jsftp@2.1.3", "", { "dependencies": { "debug": "^3.1.0", "ftp-response-parser": "^1.0.1", "once": "^1.4.0", "parse-listing": "^1.1.3", "stream-combiner": "^0.2.2", "unorm": "^1.4.1" } }, "sha512-r79EVB8jaNAZbq8hvanL8e8JGu2ZNr2bXdHC4ZdQhRImpSPpnWwm5DYVzQ5QxJmtGtKhNNuvqGgbNaFl604fEQ=="],
-
"json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
@@ -3569,20 +3467,14 @@
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
- "klaw": ["klaw@4.1.0", "", {}, "sha512-1zGZ9MF9H22UnkpVeuaGKOjfA2t6WrfdrJmGjy16ykcjnKQDmHVX+KI477rpbGevz/5FD4MC3xf1oxylBgcaQw=="],
-
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
- "kuler": ["kuler@2.0.0", "", {}, "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="],
-
"ky": ["ky@1.14.3", "", {}, "sha512-9zy9lkjac+TR1c2tG+mkNSVlyOpInnWdSMiue4F+kq8TwJSgv6o8jhLRg8Ho6SnZ9wOYUq/yozts9qQCfk7bIw=="],
- "kysely": ["kysely@0.28.17", "", {}, "sha512-nbD8lB9EB3wNdMhOCdx5Li8DxnLbvKByylRLcJ1h+4SkrowVeECAyZlyiKMThF7xFdRz0jSQ2MoJr+wXux2y0Q=="],
+ "kysely": ["kysely@0.29.2", "", {}, "sha512-s6WVJyEZrbm6jhBpiKHsGHyePMrVQKJ85wZCFCr9W4QHv6WTjWIrdvTmO9hDEA3bNK0xkrE2DqrHsXMLWuZpQg=="],
"lan-network": ["lan-network@0.2.1", "", { "bin": { "lan-network": "dist/lan-network-cli.js" } }, "sha512-ONPnazC96VKDntab9j9JKwIWhZ4ZUceB4A9Epu4Ssg0hYFmtHZSeQ+n15nIwTFmcBUKtExOer8WTJ4GF9MO64A=="],
- "lazystream": ["lazystream@1.0.1", "", { "dependencies": { "readable-stream": "^2.0.5" } }, "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw=="],
-
"leaflet": ["leaflet@1.9.4", "", {}, "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="],
"lefthook": ["lefthook@1.13.6", "", { "optionalDependencies": { "lefthook-darwin-arm64": "1.13.6", "lefthook-darwin-x64": "1.13.6", "lefthook-freebsd-arm64": "1.13.6", "lefthook-freebsd-x64": "1.13.6", "lefthook-linux-arm64": "1.13.6", "lefthook-linux-x64": "1.13.6", "lefthook-openbsd-arm64": "1.13.6", "lefthook-openbsd-x64": "1.13.6", "lefthook-windows-arm64": "1.13.6", "lefthook-windows-x64": "1.13.6" }, "bin": { "lefthook": "bin/index.js" } }, "sha512-ojj4/4IJ29Xn4drd5emqVgilegAPN3Kf0FQM2p/9+lwSTpU+SZ1v4Ig++NF+9MOa99UKY8bElmVrLhnUUNFh5g=="],
@@ -3655,24 +3547,18 @@
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
- "lockfile": ["lockfile@1.0.4", "", { "dependencies": { "signal-exit": "^3.0.2" } }, "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA=="],
-
"lodash": ["lodash@4.18.1", "", {}, "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="],
"lodash-es": ["lodash-es@4.18.1", "", {}, "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="],
"lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
- "lodash.isfinite": ["lodash.isfinite@3.3.2", "", {}, "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA=="],
-
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
"lodash.throttle": ["lodash.throttle@4.1.1", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="],
"log-symbols": ["log-symbols@2.2.0", "", { "dependencies": { "chalk": "^2.0.1" } }, "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg=="],
- "logform": ["logform@2.7.0", "", { "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="],
-
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
"lookup-closest-locale": ["lookup-closest-locale@6.2.0", "", {}, "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ=="],
@@ -3683,11 +3569,11 @@
"loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
- "lru-cache": ["lru-cache@11.3.6", "", {}, "sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A=="],
+ "lru-cache": ["lru-cache@11.5.1", "", {}, "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A=="],
"lru_map": ["lru_map@0.3.3", "", {}, "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ=="],
- "lucide-react": ["lucide-react@1.16.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-dYwyPzb4MEKpGUmNYk3WKWPnMrHs3FKM+q94kAnJrcDIqqn1hq2xY8scaS2ovsOCM5D51ey2gaRG3PBb1vgoYQ=="],
+ "lucide-react": ["lucide-react@1.17.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-9FA9evdox/JQL5PT57fdA1x/yg8T7knJ98+zjTL3UfKza6pflQUUh3XtaQIHKvnsJw1lmsEyHVlt5jchYxOQ5w=="],
"magic-regexp": ["magic-regexp@0.11.0", "", { "dependencies": { "magic-string": "^0.30.21", "regexp-tree": "^0.1.27", "type-level-regexp": "~0.1.17", "unplugin": "^3.0.0" } }, "sha512-LG77Z/gVnwz7oaDpD4heX6ryl+lcr4l1B2gnP4MMvt2pGhGC1Dfj7dl1pXpP4ih+VQFLuAadeKVa+lARAzfW+Q=="],
@@ -3755,8 +3641,6 @@
"metaviewport-parser": ["metaviewport-parser@0.3.0", "", {}, "sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ=="],
- "method-override": ["method-override@3.0.0", "", { "dependencies": { "debug": "3.1.0", "methods": "~1.1.2", "parseurl": "~1.3.2", "vary": "~1.1.2" } }, "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA=="],
-
"methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="],
"metro": ["metro@0.83.7", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "accepts": "^2.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.35.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.7", "metro-cache": "0.83.7", "metro-cache-key": "0.83.7", "metro-config": "0.83.7", "metro-core": "0.83.7", "metro-file-map": "0.83.7", "metro-resolver": "0.83.7", "metro-runtime": "0.83.7", "metro-source-map": "0.83.7", "metro-symbolicate": "0.83.7", "metro-transform-plugins": "0.83.7", "metro-transform-worker": "0.83.7", "mime-types": "^3.0.1", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-SPaPEyvTsTmd0LpT7RaZciQyDw2i/JB7+iY9L5VfBo72+psescFxBqpI1TL9dnL+pmnfkU+l/J1mEEGLeF65EQ=="],
@@ -3845,7 +3729,7 @@
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
- "mime": ["mime@4.1.0", "", { "bin": { "mime": "bin/cli.js" } }, "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw=="],
+ "mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
@@ -3855,9 +3739,7 @@
"mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="],
- "miniflare": ["miniflare@4.20260515.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "^0.34.5", "undici": "7.24.8", "workerd": "1.20260515.1", "ws": "8.18.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-2j0oQWizk1Eu4Cm8tDX7Z+Nsjd0nebIj1TQcQ+Oy1QKeo0Ay9+bdn8wfLAtOj9znDCybDCUlnS1+nYvKXEdfNg=="],
-
- "minimalistic-assert": ["minimalistic-assert@1.0.1", "", {}, "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="],
+ "miniflare": ["miniflare@4.20260611.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.34.5", "undici": "7.24.8", "workerd": "1.20260611.1", "ws": "8.20.1", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-i+JwEo8vN96naz1WL3ntFgFyRluBDYL408zwhHKvR2jefJ464KsZ/gCmJAQ5k+oaWeb5Ug+s7yne5AyiAEswjg=="],
"minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
@@ -3871,15 +3753,9 @@
"module-definition": ["module-definition@6.0.2", "", { "dependencies": { "ast-module-types": "^6.0.1", "node-source-walk": "^7.0.1" }, "bin": { "module-definition": "bin/cli.js" } }, "sha512-SvAU3lB0+Yjbq55yHY3wkRZBOh+fhU1SnIF3IFbTewv6mtAh7yUT8ACHAJ2mGIJ7tCes2QuCL/cl6m0JSZ/ArA=="],
- "moment": ["moment@2.30.1", "", {}, "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="],
-
- "moment-timezone": ["moment-timezone@0.6.2", "", { "dependencies": { "moment": "^2.29.4" } }, "sha512-lDsQv8FoGdBUdf0+TjGsq2orxKuXdwFlQ6Zw6TX3xIcTwTfEpCLyKqvEauvCHJ8iu3KBV8+uPhlv70YsNGdUBQ=="],
+ "motion-dom": ["motion-dom@12.40.0", "", { "dependencies": { "motion-utils": "^12.39.0" } }, "sha512-HxU3ZaBwNPVQUBQf1xxgq+7JrPNZvjLVxgbpEZL7RrWJnsxOf0/OM+yrHG9ogLQ31Do/r57Oz2gQWPK+6q62mg=="],
- "morgan": ["morgan@1.10.1", "", { "dependencies": { "basic-auth": "~2.0.1", "debug": "2.6.9", "depd": "~2.0.0", "on-finished": "~2.3.0", "on-headers": "~1.1.0" } }, "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A=="],
-
- "motion-dom": ["motion-dom@12.38.0", "", { "dependencies": { "motion-utils": "^12.36.0" } }, "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA=="],
-
- "motion-utils": ["motion-utils@12.36.0", "", {}, "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg=="],
+ "motion-utils": ["motion-utils@12.39.0", "", {}, "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
@@ -3895,17 +3771,15 @@
"nanostores": ["nanostores@1.3.0", "", {}, "sha512-XPUa/jz+P1oJvN9VBxw4L9MtdFfaH3DAryqPssqhb2kXjmb9npz0dly6rCsgFWOPr4Yg9mTfM3MDZgZZ+7A3lA=="],
- "nativewind": ["nativewind@4.2.4", "", { "dependencies": { "comment-json": "^4.2.5", "debug": "^4.3.7", "react-native-css-interop": "0.2.4" }, "peerDependencies": { "tailwindcss": ">3.3.0" } }, "sha512-PRO7X5a5cnmJD5ryijqeDJhmtabfbbZiPLk3ItTtL7trDzH3uWOv7kPJIqm6L0QFH98m2ynZ55DRPe3AETEOAQ=="],
+ "nativewind": ["nativewind@4.2.5", "", { "dependencies": { "comment-json": "^4.2.5", "debug": "^4.3.7", "react-native-css-interop": "0.2.5" }, "peerDependencies": { "tailwindcss": ">3.3.0" } }, "sha512-kKy2BG2xCca7tn3GZ65+sQ2aZH5T2hJ/sN/vlA1WSDu2YPn1rkdjsBOHy2TMv0I/au/HAuvgKIbX+LsSXvcf1Q=="],
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
- "ncp": ["ncp@2.0.0", "", { "bin": { "ncp": "./bin/ncp" } }, "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA=="],
-
"negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="],
"netmask": ["netmask@2.1.1", "", {}, "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA=="],
- "next": ["next@15.5.18", "", { "dependencies": { "@next/env": "15.5.18", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.5.18", "@next/swc-darwin-x64": "15.5.18", "@next/swc-linux-arm64-gnu": "15.5.18", "@next/swc-linux-arm64-musl": "15.5.18", "@next/swc-linux-x64-gnu": "15.5.18", "@next/swc-linux-x64-musl": "15.5.18", "@next/swc-win32-arm64-msvc": "15.5.18", "@next/swc-win32-x64-msvc": "15.5.18", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-eKL8zUJkX9Y5lE+RX/2YJoItVdGlIscyVyboeD9wSpp0PaGqjoA4tTpT2qPqz9ax+5IzGESyLSeZ/RCwbSZ2uQ=="],
+ "next": ["next@15.5.19", "", { "dependencies": { "@next/env": "15.5.19", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.5.19", "@next/swc-darwin-x64": "15.5.19", "@next/swc-linux-arm64-gnu": "15.5.19", "@next/swc-linux-arm64-musl": "15.5.19", "@next/swc-linux-x64-gnu": "15.5.19", "@next/swc-linux-x64-musl": "15.5.19", "@next/swc-win32-arm64-msvc": "15.5.19", "@next/swc-win32-x64-msvc": "15.5.19", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-xNOW6tYshGX1/Oi3F8uuk4gpDeWsSUE/1Z0G5uUMekIxaQ0xc03UXd9II0VQHYMWviMeA0OHpJFAKsHf8bTYVg=="],
"next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
@@ -3919,7 +3793,7 @@
"node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
- "node-releases": ["node-releases@2.0.44", "", {}, "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ=="],
+ "node-releases": ["node-releases@2.0.47", "", {}, "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og=="],
"node-source-walk": ["node-source-walk@7.0.2", "", { "dependencies": { "@babel/parser": "^7.29.0" } }, "sha512-71kFFjYaSshDTA8/a2HiTYPLdASWjLJxUyJxGE+ffxU+KhxSBtM9kiLUX+R2yooFdSFKMFpi4n3PFtDy6qXv8A=="],
@@ -3957,8 +3831,6 @@
"object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="],
- "obuf": ["obuf@1.1.2", "", {}, "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="],
-
"ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="],
"on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
@@ -3967,8 +3839,6 @@
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
- "one-time": ["one-time@1.0.0", "", { "dependencies": { "fn.name": "1.x.x" } }, "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g=="],
-
"onetime": ["onetime@2.0.1", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ=="],
"open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
@@ -3995,10 +3865,6 @@
"pac-resolver": ["pac-resolver@7.0.1", "", { "dependencies": { "degenerator": "^5.0.0", "netmask": "^2.0.2" } }, "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg=="],
- "package-changed": ["package-changed@3.0.0", "", { "dependencies": { "commander": "^6.2.0" }, "bin": { "package-changed": "bin/package-changed.js" } }, "sha512-HSRbrO+Ab5AuqqYGSevtKJ1Yt96jW1VKV7wrp8K4SKj5tyDp/7D96uPCQyCPiNtWTEH/7nA3hZ4z2slbc9yFxg=="],
-
- "package-directory": ["package-directory@8.2.0", "", { "dependencies": { "find-up-simple": "^1.0.0" } }, "sha512-qJSu5Mo6tHmRxCy2KCYYKYgcfBdUpy9dwReaZD/xwf608AUk/MoRtIOWzgDtUeGeC7n/55yC3MI1Q+MbSoektw=="],
-
"package-json": ["package-json@10.0.1", "", { "dependencies": { "ky": "^1.2.0", "registry-auth-token": "^5.0.2", "registry-url": "^6.0.1", "semver": "^7.6.0" } }, "sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg=="],
"package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
@@ -4023,8 +3889,6 @@
"parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
- "parse-listing": ["parse-listing@1.1.3", "", {}, "sha512-a1p1i+9Qyc8pJNwdrSvW1g5TPxRH0sywVi6OzVvYHRo6xwF9bDWBxtH0KkxeOOvhUE8vAMtiSfsYQFOuK901eA=="],
-
"parse-png": ["parse-png@2.1.0", "", { "dependencies": { "pngjs": "^3.3.0" } }, "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ=="],
"parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
@@ -4037,7 +3901,7 @@
"partyserver": ["partyserver@0.4.1", "", { "dependencies": { "nanoid": "^5.1.6" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20240729.0" } }, "sha512-StSs0oY8RmTxjGNil7VbCG4gnTN+4rYX20fiUIItAxTPpr/5rPDZT6PIvMROkk9M1Gn7GzE1wuQXwhxceaGhXA=="],
- "partysocket": ["partysocket@1.1.18", "", { "dependencies": { "event-target-polyfill": "^0.0.4" }, "peerDependencies": { "react": ">=17" }, "optionalPeers": ["react"] }, "sha512-SyuvH9VavWOSa14v6dYdp3yfSUDII4BQB1+TkGOFBkjfZKjnDBiba4fhdhwBlqGBkqw4ea3gTA1DYhSffX24Wg=="],
+ "partysocket": ["partysocket@1.1.19", "", { "dependencies": { "event-target-polyfill": "^0.0.4" }, "peerDependencies": { "react": ">=17" }, "optionalPeers": ["react"] }, "sha512-hPwsXSdUc8PKNCinET6TD3JQOxzQ2JaP0bUZQXBVl6UM8UuLn1odgf1LcJXHy4UHSQwWL/RU3AnyhEsGM+W+sg=="],
"path": ["path@0.12.7", "", { "dependencies": { "process": "^0.11.1", "util": "^0.10.3" } }, "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q=="],
@@ -4063,17 +3927,17 @@
"pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="],
- "pg": ["pg@8.20.0", "", { "dependencies": { "pg-connection-string": "^2.12.0", "pg-pool": "^3.13.0", "pg-protocol": "^1.13.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA=="],
+ "pg": ["pg@8.21.0", "", { "dependencies": { "pg-connection-string": "^2.13.0", "pg-pool": "^3.14.0", "pg-protocol": "^1.14.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.4.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-AUP1EYJuHraQGsVoCQVIcM7TEJVGtDzxWtGFZd8rds9d+CCXlU5Js1rYgfLNvxy9iJrpHjGrRjoi/3BT9fRyiA=="],
- "pg-cloudflare": ["pg-cloudflare@1.3.0", "", {}, "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ=="],
+ "pg-cloudflare": ["pg-cloudflare@1.4.0", "", {}, "sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A=="],
- "pg-connection-string": ["pg-connection-string@2.12.0", "", {}, "sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ=="],
+ "pg-connection-string": ["pg-connection-string@2.13.0", "", {}, "sha512-EMnU9E2fSULdsbErBbMaXJvFeD9B4+nPcM3f+4lsiCR0BHLPrLVjv3DbyM2hgQQviKJaTWIRRTjKjWlHg3p2ig=="],
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
- "pg-pool": ["pg-pool@3.13.0", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA=="],
+ "pg-pool": ["pg-pool@3.14.0", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw=="],
- "pg-protocol": ["pg-protocol@1.13.0", "", {}, "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w=="],
+ "pg-protocol": ["pg-protocol@1.14.0", "", {}, "sha512-n5taZ1kO3s9ngDTVxsEznOqCyToTgz0FLuPq0B33COy5pPpuWJpY3/2oRBVETuOgzdqRXfWpM9HIhp2LBBT1BA=="],
"pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
@@ -4103,13 +3967,11 @@
"pngjs": ["pngjs@3.4.0", "", {}, "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="],
- "portscanner": ["portscanner@2.2.0", "", { "dependencies": { "async": "^2.6.0", "is-number-like": "^1.0.3" } }, "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw=="],
-
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
"postal-mime": ["postal-mime@2.7.4", "", {}, "sha512-0WdnFQYUrPGGTFu1uOqD2s7omwua8xaeYGdO6rb88oD5yJ/4pPHDA4sdWqfD8wQVfCny563n/HQS7zTFft+f/g=="],
- "postcss": ["postcss@8.5.14", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg=="],
+ "postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="],
"postcss-import": ["postcss-import@16.1.1", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ=="],
@@ -4119,7 +3981,7 @@
"postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="],
- "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="],
+ "postcss-selector-parser": ["postcss-selector-parser@6.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ=="],
"postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
@@ -4137,7 +3999,7 @@
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
- "prettier": ["prettier@3.8.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw=="],
+ "prettier": ["prettier@3.8.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q=="],
"prettier-linter-helpers": ["prettier-linter-helpers@1.0.1", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg=="],
@@ -4151,8 +4013,6 @@
"process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="],
- "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
-
"progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],
"promise": ["promise@8.3.0", "", { "dependencies": { "asap": "~2.0.6" } }, "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg=="],
@@ -4161,7 +4021,7 @@
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
- "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
+ "property-information": ["property-information@7.2.0", "", {}, "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg=="],
"proto-list": ["proto-list@1.2.4", "", {}, "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="],
@@ -4177,6 +4037,8 @@
"puppeteer-core": ["puppeteer-core@22.15.0", "", { "dependencies": { "@puppeteer/browsers": "2.3.0", "chromium-bidi": "0.6.3", "debug": "^4.3.6", "devtools-protocol": "0.0.1312386", "ws": "^8.18.0" } }, "sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA=="],
+ "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
+
"qs": ["qs@6.15.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw=="],
"query-string": ["query-string@7.1.3", "", { "dependencies": { "decode-uri-component": "^0.2.2", "filter-obj": "^1.1.0", "split-on-first": "^1.0.0", "strict-uri-encode": "^2.0.0" } }, "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg=="],
@@ -4203,27 +4065,27 @@
"react-dom": ["react-dom@19.2.6", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.6" } }, "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g=="],
- "react-error-boundary": ["react-error-boundary@6.1.1", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-BrYwPOdXi5mqkk5lw+Uvt0ThHx32rCt3BkukS4X23A2AIWDPSGX6iaWTc0y9TU/mHDA/6qOSGel+B2ERkOvD1w=="],
+ "react-error-boundary": ["react-error-boundary@6.1.2", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-3DpCr5HVdZ0caUjYE/kIHBEJN0mNP3ZCgf16c48uJ5TbWjorKVp+YG8W3XqlJ7vJAVNw6wNIImyPXmFydwmyng=="],
"react-fast-compare": ["react-fast-compare@3.2.2", "", {}, "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="],
"react-freeze": ["react-freeze@1.0.4", "", { "peerDependencies": { "react": ">=17.0.0" } }, "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA=="],
- "react-hook-form": ["react-hook-form@7.76.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-eKtLGgFeSgkHqQD8J59AMZ9a4uD1D83iSIzt4YlTGD7liDen5rrjcUO1rVIGd9yC1gofryjtHbv+4ny4hkLWlw=="],
+ "react-hook-form": ["react-hook-form@7.78.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-EEZqc+N23moyzTlz61Pj+JvcXo76ICkpfOZo8JZw+sM4+wLQGh6nI2Ms+PdMOYNluFu0ghlM7B8mCzhRYtJCnA=="],
"react-i18next": ["react-i18next@17.0.8", "", { "dependencies": { "@babel/runtime": "^7.29.2", "html-parse-stringify": "^3.0.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "i18next": ">= 26.2.0", "react": ">= 16.8.0", "react-dom": "*", "react-native": "*", "typescript": "^5 || ^6" }, "optionalPeers": ["react-dom", "react-native", "typescript"] }, "sha512-0ooKbGLU8JXhe1zwpQUWIeXSgLPOfwJmgheWRIUpcoA0CpyabpGhayjdG+/eA5esC1AQ8h2jWpXjJfzQzeDOCw=="],
- "react-is": ["react-is@19.2.6", "", {}, "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw=="],
+ "react-is": ["react-is@19.2.7", "", {}, "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A=="],
"react-leaflet": ["react-leaflet@5.0.0", "", { "dependencies": { "@react-leaflet/core": "^3.0.0" }, "peerDependencies": { "leaflet": "^1.9.0", "react": "^19.0.0", "react-dom": "^19.0.0" } }, "sha512-CWbTpr5vcHw5bt9i4zSlPEVQdTVcML390TjeDG0cK59z1ylexpqC6M1PJFjV8jD7CF+ACBFsLIDs6DRMoLEofw=="],
"react-native": ["react-native@0.83.6", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.83.6", "@react-native/codegen": "0.83.6", "@react-native/community-cli-plugin": "0.83.6", "@react-native/gradle-plugin": "0.83.6", "@react-native/js-polyfills": "0.83.6", "@react-native/normalize-colors": "0.83.6", "@react-native/virtualized-lists": "0.83.6", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "hermes-compiler": "0.14.1", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.6", "metro-source-map": "^0.83.6", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.0" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-H513+8VzviNFXOdPnStRzX9S3/jiJGg++QZ1zd+ROyAvBEKqFqKUPHH0d82y3QyRPct5qKjdOa7J6vNehCvXYA=="],
- "react-native-blob-util": ["react-native-blob-util@0.24.8", "", { "dependencies": { "appium-uiautomator2-driver": "^7.0.0", "base-64": "0.1.0", "glob": "13.0.1", "uuid": "^13.0.0" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-uYux4Teh6JOrqlRXtdhfj0fHt8i0bBWsERR9h7P4Wj4Paa//MeigDHSo805X77WjHXdL0dpv6Nh5B+rMcZCRhg=="],
+ "react-native-blob-util": ["react-native-blob-util@0.24.9", "", { "dependencies": { "base-64": "0.1.0", "glob": "13.0.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-tG3+m0WhVdBGifvxSFxZDVqtr85D0fGBJU6E4UxmK3tU+RabJZTumXEn8k7jn5/NFe8OhQhPjtBEZ11ZJ6L7Vw=="],
- "react-native-css-interop": ["react-native-css-interop@0.2.4", "", { "dependencies": { "@babel/helper-module-imports": "^7.22.15", "@babel/traverse": "^7.23.0", "@babel/types": "^7.23.0", "debug": "^4.3.7", "lightningcss": "~1.27.0", "semver": "^7.6.3" }, "peerDependencies": { "react": ">=18", "react-native": "*", "react-native-reanimated": ">=3.6.2", "react-native-safe-area-context": "*", "react-native-svg": "*", "tailwindcss": "~3" }, "optionalPeers": ["react-native-safe-area-context", "react-native-svg"] }, "sha512-ATP3BACxGM4h/l8cisFauGMGxnXpu8Bcp4Bc3O7iNZpq7j0VJjc1RRRBUSBY4C4WuI7VA/xvp3puijVS9d95rg=="],
+ "react-native-css-interop": ["react-native-css-interop@0.2.5", "", { "dependencies": { "@babel/helper-module-imports": "^7.22.15", "@babel/traverse": "^7.23.0", "@babel/types": "^7.23.0", "debug": "^4.3.7", "lightningcss": "~1.27.0", "semver": "^7.6.3" }, "peerDependencies": { "react": ">=18", "react-native": "*", "react-native-reanimated": ">=3.6.2", "react-native-safe-area-context": "*", "react-native-svg": "*", "tailwindcss": "~3" }, "optionalPeers": ["react-native-safe-area-context", "react-native-svg"] }, "sha512-V8/d9lBqn4w8m4d7dmwQPOFJB49bqga/9dmamfRHSGTQjGzrY/jAvDFOzSe+Ew2XuGz1ShVBD2cFIClFYasGyw=="],
- "react-native-drawer-layout": ["react-native-drawer-layout@4.2.4", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*", "react-native-gesture-handler": ">= 2.0.0", "react-native-reanimated": ">= 2.0.0" } }, "sha512-l1Le5HcVidobnJm8xqFZo46Rs8FDHdxbTZhkjxpNSRgU+QMoQXilOfzTHAeNjEGiKVGgIs9cW3ctXeHqgp5jJg=="],
+ "react-native-drawer-layout": ["react-native-drawer-layout@4.2.5", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*", "react-native-gesture-handler": ">= 2.0.0", "react-native-reanimated": ">= 2.0.0" } }, "sha512-Yl82uLkXjXuq7222hWGIDsq5A6R/bsCeCEgdIxQUxAEHf00oRdDnRByLx3Fsij3qwtmYNPGrHV1NH8G8hbCbLQ=="],
"react-native-fit-image": ["react-native-fit-image@1.5.5", "", { "dependencies": { "prop-types": "^15.5.10" } }, "sha512-Wl3Vq2DQzxgsWKuW4USfck9zS7YzhvLNPpkwUUCF90bL32e1a0zOVQ3WsJILJOwzmPdHfzZmWasiiAUNBkhNkg=="],
@@ -4263,7 +4125,7 @@
"react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
- "react-resizable-panels": ["react-resizable-panels@4.11.1", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-kA4w58V6wYdRLm2rg9pzroZwGlqBLul1FjMP0J8kqTo3zSHtjeH+LXmZaldCo6+HWqs1e5hOcPoajKXdOze37Q=="],
+ "react-resizable-panels": ["react-resizable-panels@4.11.2", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-+kfFbDZ8mygc7g0vxOcDzCVGuwiIUOnILqPoUHo6/uP+Mmyx6HzZU+kj1aOPDlktXuobYbr6BtQekvJwHRX4Eg=="],
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
@@ -4275,10 +4137,6 @@
"read-pkg-up": ["read-pkg-up@1.0.1", "", { "dependencies": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" } }, "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A=="],
- "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
-
- "readdir-glob": ["readdir-glob@1.1.3", "", { "dependencies": { "minimatch": "^5.1.0" } }, "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA=="],
-
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
"recharts": ["recharts@3.8.1", "", { "dependencies": { "@reduxjs/toolkit": "^1.9.0 || 2.x.x", "clsx": "^2.1.1", "decimal.js-light": "^2.5.1", "es-toolkit": "^1.39.3", "eventemitter3": "^5.0.1", "immer": "^10.1.1", "react-redux": "8.x.x || 9.x.x", "reselect": "5.1.1", "tiny-invariant": "^1.3.3", "use-sync-external-store": "^1.2.2", "victory-vendor": "^37.0.2" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-mwzmO1s9sFL0TduUpwndxCUNoXsBw3u3E/0+A+cLcrSfQitSG62L32N69GhqUrrT5qKcAE3pCGVINC6pqkBBQg=="],
@@ -4333,7 +4191,7 @@
"reselect": ["reselect@5.1.1", "", {}, "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="],
- "resend": ["resend@6.12.3", "", { "dependencies": { "postal-mime": "2.7.4", "svix": "1.92.2" }, "peerDependencies": { "@react-email/render": "*" }, "optionalPeers": ["@react-email/render"] }, "sha512-FkEi6YPnVL96/LvH8+QP7NaeaBy5brYXwlRqUCqZZeNL0/iyKij18IPmyPXYauT/2ODn1JG04qKz+qlJfzqzTw=="],
+ "resend": ["resend@6.12.4", "", { "dependencies": { "postal-mime": "2.7.4", "standardwebhooks": "1.0.0" }, "peerDependencies": { "@react-email/render": "*" }, "optionalPeers": ["@react-email/render"] }, "sha512-lRpJ2Hxd+ht+JPDm97juRcUp9HOMuZyxaRFRFmc9Tx8iNWiei94Dx9v6SWufgKk2667C/uCeKKspMotOHSpCSg=="],
"resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="],
@@ -4353,9 +4211,9 @@
"robots-parser": ["robots-parser@3.0.1", "", {}, "sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ=="],
- "rolldown": ["rolldown@1.0.1", "", { "dependencies": { "@oxc-project/types": "=0.130.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.1", "@rolldown/binding-darwin-arm64": "1.0.1", "@rolldown/binding-darwin-x64": "1.0.1", "@rolldown/binding-freebsd-x64": "1.0.1", "@rolldown/binding-linux-arm-gnueabihf": "1.0.1", "@rolldown/binding-linux-arm64-gnu": "1.0.1", "@rolldown/binding-linux-arm64-musl": "1.0.1", "@rolldown/binding-linux-ppc64-gnu": "1.0.1", "@rolldown/binding-linux-s390x-gnu": "1.0.1", "@rolldown/binding-linux-x64-gnu": "1.0.1", "@rolldown/binding-linux-x64-musl": "1.0.1", "@rolldown/binding-openharmony-arm64": "1.0.1", "@rolldown/binding-wasm32-wasi": "1.0.1", "@rolldown/binding-win32-arm64-msvc": "1.0.1", "@rolldown/binding-win32-x64-msvc": "1.0.1" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ=="],
+ "rolldown": ["rolldown@1.1.1", "", { "dependencies": { "@oxc-project/types": "=0.135.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.1.1", "@rolldown/binding-darwin-arm64": "1.1.1", "@rolldown/binding-darwin-x64": "1.1.1", "@rolldown/binding-freebsd-x64": "1.1.1", "@rolldown/binding-linux-arm-gnueabihf": "1.1.1", "@rolldown/binding-linux-arm64-gnu": "1.1.1", "@rolldown/binding-linux-arm64-musl": "1.1.1", "@rolldown/binding-linux-ppc64-gnu": "1.1.1", "@rolldown/binding-linux-s390x-gnu": "1.1.1", "@rolldown/binding-linux-x64-gnu": "1.1.1", "@rolldown/binding-linux-x64-musl": "1.1.1", "@rolldown/binding-openharmony-arm64": "1.1.1", "@rolldown/binding-wasm32-wasi": "1.1.1", "@rolldown/binding-win32-arm64-msvc": "1.1.1", "@rolldown/binding-win32-x64-msvc": "1.1.1" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-IN750c0p+s3jqJIsFLRZrQazmbAB1kkQDTtQjSt/gbS2ywLhlv4R5Shazer0FZKmuo/BsO3/w2UoYnUjuOZqHg=="],
- "rollup": ["rollup@4.60.4", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.4", "@rollup/rollup-android-arm64": "4.60.4", "@rollup/rollup-darwin-arm64": "4.60.4", "@rollup/rollup-darwin-x64": "4.60.4", "@rollup/rollup-freebsd-arm64": "4.60.4", "@rollup/rollup-freebsd-x64": "4.60.4", "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", "@rollup/rollup-linux-arm-musleabihf": "4.60.4", "@rollup/rollup-linux-arm64-gnu": "4.60.4", "@rollup/rollup-linux-arm64-musl": "4.60.4", "@rollup/rollup-linux-loong64-gnu": "4.60.4", "@rollup/rollup-linux-loong64-musl": "4.60.4", "@rollup/rollup-linux-ppc64-gnu": "4.60.4", "@rollup/rollup-linux-ppc64-musl": "4.60.4", "@rollup/rollup-linux-riscv64-gnu": "4.60.4", "@rollup/rollup-linux-riscv64-musl": "4.60.4", "@rollup/rollup-linux-s390x-gnu": "4.60.4", "@rollup/rollup-linux-x64-gnu": "4.60.4", "@rollup/rollup-linux-x64-musl": "4.60.4", "@rollup/rollup-openbsd-x64": "4.60.4", "@rollup/rollup-openharmony-arm64": "4.60.4", "@rollup/rollup-win32-arm64-msvc": "4.60.4", "@rollup/rollup-win32-ia32-msvc": "4.60.4", "@rollup/rollup-win32-x64-gnu": "4.60.4", "@rollup/rollup-win32-x64-msvc": "4.60.4", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g=="],
+ "rollup": ["rollup@4.61.1", "", { "dependencies": { "@types/estree": "1.0.9" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.61.1", "@rollup/rollup-android-arm64": "4.61.1", "@rollup/rollup-darwin-arm64": "4.61.1", "@rollup/rollup-darwin-x64": "4.61.1", "@rollup/rollup-freebsd-arm64": "4.61.1", "@rollup/rollup-freebsd-x64": "4.61.1", "@rollup/rollup-linux-arm-gnueabihf": "4.61.1", "@rollup/rollup-linux-arm-musleabihf": "4.61.1", "@rollup/rollup-linux-arm64-gnu": "4.61.1", "@rollup/rollup-linux-arm64-musl": "4.61.1", "@rollup/rollup-linux-loong64-gnu": "4.61.1", "@rollup/rollup-linux-loong64-musl": "4.61.1", "@rollup/rollup-linux-ppc64-gnu": "4.61.1", "@rollup/rollup-linux-ppc64-musl": "4.61.1", "@rollup/rollup-linux-riscv64-gnu": "4.61.1", "@rollup/rollup-linux-riscv64-musl": "4.61.1", "@rollup/rollup-linux-s390x-gnu": "4.61.1", "@rollup/rollup-linux-x64-gnu": "4.61.1", "@rollup/rollup-linux-x64-musl": "4.61.1", "@rollup/rollup-openbsd-x64": "4.61.1", "@rollup/rollup-openharmony-arm64": "4.61.1", "@rollup/rollup-win32-arm64-msvc": "4.61.1", "@rollup/rollup-win32-ia32-msvc": "4.61.1", "@rollup/rollup-win32-x64-gnu": "4.61.1", "@rollup/rollup-win32-x64-msvc": "4.61.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-I4KW6iuRpuu2uHBLraZ1wNZe0DP7lnRha+VJ9tNaYVaVgKhW0aI3h4RYnoRPeql0flHm/Co55b7snEDcOfOJrA=="],
"rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="],
@@ -4377,12 +4235,8 @@
"safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
- "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="],
-
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
- "sanitize-filename": ["sanitize-filename@1.6.4", "", { "dependencies": { "truncate-utf8-bytes": "^1.0.0" } }, "sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg=="],
-
"sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="],
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
@@ -4391,18 +4245,14 @@
"secure-json-parse": ["secure-json-parse@2.7.0", "", {}, "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="],
- "select-hose": ["select-hose@2.0.0", "", {}, "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg=="],
-
"sembear": ["sembear@0.7.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-XyLTEich2D02FODCkfdto3mB9DetWPLuTzr4tvoofe9SvyM27h4nQSbV3+iVcYQz94AFyKtqBv5pcZbj3k2hdA=="],
- "semver": ["semver@7.8.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="],
+ "semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="],
"send": ["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.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
"serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="],
- "serve-favicon": ["serve-favicon@2.5.1", "", { "dependencies": { "etag": "~1.8.1", "fresh": "~0.5.2", "ms": "~2.1.3", "parseurl": "~1.3.2", "safe-buffer": "~5.2.1" } }, "sha512-JndLBslCLA/ebr7rS3d+/EKkzTsTi1jI2T9l+vHfAaGJ7A7NhtDpSZ0lx81HCNWnnE0yHncG+SSnVf9IMxOwXQ=="],
-
"serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="],
"server-only": ["server-only@0.0.1", "", {}, "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="],
@@ -4431,9 +4281,9 @@
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
- "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="],
+ "shell-quote": ["shell-quote@1.8.4", "", {}, "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ=="],
- "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
+ "side-channel": ["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" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="],
"side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="],
@@ -4465,7 +4315,7 @@
"sort-object-keys": ["sort-object-keys@2.1.0", "", {}, "sha512-SOiEnthkJKPv2L6ec6HMwhUcN0/lppkeYuN1x63PbyPRrgSPIuBJCiYxYyvWRTtjMlOi14vQUCGUJqS6PLVm8g=="],
- "sort-package-json": ["sort-package-json@3.6.1", "", { "dependencies": { "detect-indent": "^7.0.2", "detect-newline": "^4.0.1", "git-hooks-list": "^4.1.1", "is-plain-obj": "^4.1.0", "semver": "^7.7.3", "sort-object-keys": "^2.0.1", "tinyglobby": "^0.2.15" }, "bin": { "sort-package-json": "cli.js" } }, "sha512-Chgejw1+10p2D0U2tB7au1lHtz6TkFnxmvZktyBCRyV0GgmF6nl1IxXxAsPtJVsUyg/fo+BfCMAVVFUVRkAHrQ=="],
+ "sort-package-json": ["sort-package-json@3.7.1", "", { "dependencies": { "detect-indent": "^7.0.2", "detect-newline": "^4.0.1", "git-hooks-list": "^4.1.1", "is-plain-obj": "^4.1.0", "semver": "^7.7.3", "sort-object-keys": "^2.0.1", "tinyglobby": "^0.2.15" }, "bin": { "sort-package-json": "cli.js" } }, "sha512-ssk1HG7whF8N/T1IsNAQrtHG5Cbdi0rAgRJZXYBr9hF5xaHnBNzUx/W6LcthEW7FhOwvZssbESZuO+GxssqAyA=="],
"source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
@@ -4485,10 +4335,6 @@
"spdx-license-ids": ["spdx-license-ids@3.0.23", "", {}, "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw=="],
- "spdy": ["spdy@4.0.2", "", { "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", "http-deceiver": "^1.2.7", "select-hose": "^2.0.0", "spdy-transport": "^3.0.0" } }, "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA=="],
-
- "spdy-transport": ["spdy-transport@3.0.0", "", { "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", "hpack.js": "^2.1.6", "obuf": "^1.1.2", "readable-stream": "^3.0.6", "wbuf": "^1.7.3" } }, "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw=="],
-
"speedline-core": ["speedline-core@1.4.3", "", { "dependencies": { "@types/node": "*", "image-ssim": "^0.2.0", "jpeg-js": "^0.4.1" } }, "sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog=="],
"split-on-first": ["split-on-first@1.1.0", "", {}, "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="],
@@ -4497,8 +4343,6 @@
"sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
- "stack-trace": ["stack-trace@0.0.10", "", {}, "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="],
-
"stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "^2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="],
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
@@ -4507,13 +4351,15 @@
"stacktrace-parser": ["stacktrace-parser@0.1.11", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg=="],
+ "standard-navigation": ["standard-navigation@0.0.7", "", {}, "sha512-NCGLCNyuXrFOkGHxdNZFnpsehGtiq1oXbPhKl7ZuxFO5J//H2evqqOchmD4YwEUJnkjO4kH9Xp4hQX6hdAYCKQ=="],
+
"standardwebhooks": ["standardwebhooks@1.0.0", "", { "dependencies": { "@stablelib/base64": "^1.0.0", "fast-sha256": "^1.3.0" } }, "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg=="],
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
"std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
- "steiger": ["steiger@0.5.12", "", { "dependencies": { "@clack/prompts": "^0.9.1", "@feature-sliced/steiger-plugin": "0.5.8", "chokidar": "^4.0.3", "cosmiconfig": "^9.0.0", "effector": "^23.4.2", "empathic": "^1.1.0", "fastest-levenshtein": "^1.0.16", "globby": "^14.1.0", "immer": "^10.1.1", "lodash-es": "^4.17.21", "micromatch": "^4.0.8", "patronum": "^2.3.0", "picocolors": "^1.1.1", "prexit": "^2.3.0", "yargs": "^17.7.2", "zod": "^3.25.76", "zod-validation-error": "^3.5.3" }, "bin": { "steiger": "dist/cli.mjs" } }, "sha512-ZIqsRMRVG0Yr3Y+TQ3kfH+3FXQKRAza/sC77UuCzaXOBRD7NnuXVzWqB/SklBAZC8GMO10neo2V3M53ZnpSJrA=="],
+ "steiger": ["steiger@0.5.13", "", { "dependencies": { "@clack/prompts": "^0.9.1", "@feature-sliced/steiger-plugin": "0.6.0", "chokidar": "^4.0.3", "cosmiconfig": "^9.0.0", "effector": "^23.4.2", "empathic": "^1.1.0", "fastest-levenshtein": "^1.0.16", "globby": "^14.1.0", "immer": "^10.1.1", "lodash-es": "^4.17.21", "micromatch": "^4.0.8", "patronum": "^2.3.0", "picocolors": "^1.1.1", "prexit": "^2.3.0", "yargs": "^17.7.2", "zod": "^3.25.76", "zod-validation-error": "^3.5.3" }, "bin": { "steiger": "dist/cli.mjs" } }, "sha512-Vbgb9tMmxo3wf1jXvn+px3hDEOELdYJdWji6DT++zFcWwVHgjY22DjxYbCjq+dtEE6BWYSyv6OhwbPZPy8ovQQ=="],
"stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="],
@@ -4521,9 +4367,7 @@
"stream-buffers": ["stream-buffers@2.2.0", "", {}, "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg=="],
- "stream-combiner": ["stream-combiner@0.2.2", "", { "dependencies": { "duplexer": "~0.1.1", "through": "~2.3.4" } }, "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ=="],
-
- "streamx": ["streamx@2.25.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg=="],
+ "streamx": ["streamx@2.27.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-WZ189TKnHoAokYHvwzaAQMpd55cgUmFIcJFzBSgGcb886jau5DL+XdDhTWV4ps3FLvk+OORp0dLRTPsLZ21CSA=="],
"strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="],
@@ -4535,14 +4379,12 @@
"string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="],
- "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="],
+ "string.prototype.trim": ["string.prototype.trim@1.2.11", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-object-atoms": "^1.1.2", "has-property-descriptors": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w=="],
- "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="],
+ "string.prototype.trimend": ["string.prototype.trimend@1.0.10", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.2" } }, "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw=="],
"string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="],
- "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
-
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
@@ -4575,11 +4417,9 @@
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
- "svix": ["svix@1.92.2", "", { "dependencies": { "standardwebhooks": "1.0.0" } }, "sha512-ZmuA3UVvlnF9EgxlzmPtF7CKjQb64Z6OFlyfdDfU0sdcC7dJa+3aOYX5B9mA+RS6ch1AxBa4UP/l6KmqfGtWBQ=="],
-
"swr": ["swr@2.4.1", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-2CC6CiKQtEwaEeNiqWTAw9PGykW8SR5zZX8MZk6TeAvEAnVS7Visz8WzphqgtQ8v2xz/4Q5K+j+SeMaKXeeQIA=="],
- "synckit": ["synckit@0.11.12", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ=="],
+ "synckit": ["synckit@0.11.13", "", { "dependencies": { "@pkgr/core": "^0.3.6" } }, "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg=="],
"tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
@@ -4595,20 +4435,16 @@
"tar-stream": ["tar-stream@3.2.0", "", { "dependencies": { "b4a": "^1.6.4", "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg=="],
- "teen_process": ["teen_process@4.1.3", "", { "dependencies": { "shell-quote": "^1.8.1" } }, "sha512-8W7Xp7WtJ5ZXjv0iHMsCgPPKzUt6ACfG/rDWX0tMIlMJaYcTYsPw3ZQQ9+hG7YsY+gm+DUATiyah3AraJ9JYpg=="],
-
"teex": ["teex@1.0.1", "", { "dependencies": { "streamx": "^2.12.5" } }, "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg=="],
"terminal-link": ["terminal-link@2.1.1", "", { "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" } }, "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ=="],
- "terser": ["terser@5.47.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw=="],
+ "terser": ["terser@5.48.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q=="],
"test-exclude": ["test-exclude@7.0.2", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^10.4.1", "minimatch": "^10.2.2" } }, "sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw=="],
"text-decoder": ["text-decoder@1.2.7", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ=="],
- "text-hex": ["text-hex@1.0.0", "", {}, "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="],
-
"text-table": ["text-table@0.2.0", "", {}, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="],
"thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="],
@@ -4627,9 +4463,9 @@
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
- "tinyexec": ["tinyexec@1.1.2", "", {}, "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA=="],
+ "tinyexec": ["tinyexec@1.2.4", "", {}, "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg=="],
- "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="],
+ "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="],
"tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="],
@@ -4661,12 +4497,8 @@
"trim-newlines": ["trim-newlines@1.0.0", "", {}, "sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw=="],
- "triple-beam": ["triple-beam@1.4.1", "", {}, "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg=="],
-
"trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
- "truncate-utf8-bytes": ["truncate-utf8-bytes@1.0.2", "", { "dependencies": { "utf8-byte-length": "^1.0.1" } }, "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ=="],
-
"ts-api-utils": ["ts-api-utils@1.4.3", "", { "peerDependencies": { "typescript": ">=4.2.0" } }, "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw=="],
"ts-declaration-location": ["ts-declaration-location@1.0.7", "", { "dependencies": { "picomatch": "^4.0.2" }, "peerDependencies": { "typescript": ">=4.0.0" } }, "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA=="],
@@ -4681,15 +4513,15 @@
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
- "tsx": ["tsx@4.22.1", "", { "dependencies": { "esbuild": "~0.28.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-TvncJykhxAzFCk0VQZKBTClall4Pm7qXDSodb6uxi8QFa8X8mT6ABjxxsQ2opDRYxG7AzcRWXaFtruz5HJKuWg=="],
+ "tsx": ["tsx@4.22.4", "", { "dependencies": { "esbuild": "~0.28.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg=="],
- "turbo": ["turbo@2.9.16", "", { "optionalDependencies": { "@turbo/darwin-64": "2.9.16", "@turbo/darwin-arm64": "2.9.16", "@turbo/linux-64": "2.9.16", "@turbo/linux-arm64": "2.9.16", "@turbo/windows-64": "2.9.16", "@turbo/windows-arm64": "2.9.16" }, "bin": { "turbo": "bin/turbo" } }, "sha512-NqgRQy6j6dPYcdSdv0q1g9QsZg7SWg87RERM8otw/1AtKU2yTFVClOM7cbwKzOonZr/Ek1blTBucw64L9H0Bwg=="],
+ "turbo": ["turbo@2.9.18", "", { "optionalDependencies": { "@turbo/darwin-64": "2.9.18", "@turbo/darwin-arm64": "2.9.18", "@turbo/linux-64": "2.9.18", "@turbo/linux-arm64": "2.9.18", "@turbo/windows-64": "2.9.18", "@turbo/windows-arm64": "2.9.18" }, "bin": { "turbo": "bin/turbo" } }, "sha512-bwabv6PupzeavybzEoArBAkwq5fnzwf8OFnRtpHwnviFWuwJPFxtyH+aVp36TmIqK3aYYgtTJ3J0m2ysxxSzQg=="],
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
"type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="],
- "type-fest": ["type-fest@5.6.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA=="],
+ "type-fest": ["type-fest@5.7.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg=="],
"type-is": ["type-is@2.1.0", "", { "dependencies": { "content-type": "^2.0.0", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA=="],
@@ -4701,7 +4533,7 @@
"typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="],
- "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
+ "typed-array-length": ["typed-array-length@1.0.8", "", { "dependencies": { "call-bind": "^1.0.9", "for-each": "^0.3.5", "gopd": "^1.2.0", "is-typed-array": "^1.1.15", "possible-typed-array-names": "^1.1.0", "reflect.getprototypeof": "^1.0.10" } }, "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g=="],
"typed-html": ["typed-html@3.0.1", "", {}, "sha512-JKCM9zTfPDuPqQqdGZBWSEiItShliKkBFg5c6yOR8zth43v763XkAzTWaOlVqc0Y6p9ee8AaAbipGfUnCsYZUA=="],
@@ -4757,8 +4589,6 @@
"universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
- "unorm": ["unorm@1.6.0", "", {}, "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA=="],
-
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
"unplugin": ["unplugin@3.0.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg=="],
@@ -4779,8 +4609,6 @@
"use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
- "utf8-byte-length": ["utf8-byte-length@1.0.5", "", {}, "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA=="],
-
"util": ["util@0.10.4", "", { "dependencies": { "inherits": "2.0.3" } }, "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A=="],
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
@@ -4803,7 +4631,7 @@
"victory-vendor": ["victory-vendor@37.3.6", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ=="],
- "vite": ["vite@6.4.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ=="],
+ "vite": ["vite@6.4.3", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A=="],
"vite-node": ["vite-node@3.1.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA=="],
@@ -4817,12 +4645,12 @@
"warn-once": ["warn-once@0.1.1", "", {}, "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q=="],
- "wbuf": ["wbuf@1.7.3", "", { "dependencies": { "minimalistic-assert": "^1.0.0" } }, "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA=="],
-
"wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="],
"web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
+ "web-tree-sitter": ["web-tree-sitter@0.26.9", "", {}, "sha512-YJwSHANl6XFgeEjB8nitgj0qZYt5gkIesJ4w2srS2wcLB4GUa4xcOkM0YaMsU6WNR53YVIkDSY7Ej4pf3IXtCA=="],
+
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
"webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="],
@@ -4847,21 +4675,17 @@
"which-module": ["which-module@2.0.1", "", {}, "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="],
- "which-typed-array": ["which-typed-array@1.1.20", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg=="],
+ "which-typed-array": ["which-typed-array@1.1.22", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw=="],
"why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
- "winston": ["winston@3.19.0", "", { "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.7.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.9.0" } }, "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA=="],
-
- "winston-transport": ["winston-transport@4.9.0", "", { "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A=="],
-
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
- "workerd": ["workerd@1.20260515.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260515.1", "@cloudflare/workerd-darwin-arm64": "1.20260515.1", "@cloudflare/workerd-linux-64": "1.20260515.1", "@cloudflare/workerd-linux-arm64": "1.20260515.1", "@cloudflare/workerd-windows-64": "1.20260515.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-MjKOJLcvU45xXedQowvuiHtJTxu4WTHYQeIlF7YmjuqhiI6dImTFxWCEoRQHiskztxuVSNEmdO7/0UfDu6OMnQ=="],
+ "workerd": ["workerd@1.20260611.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260611.1", "@cloudflare/workerd-darwin-arm64": "1.20260611.1", "@cloudflare/workerd-linux-64": "1.20260611.1", "@cloudflare/workerd-linux-arm64": "1.20260611.1", "@cloudflare/workerd-windows-64": "1.20260611.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-CS/640T7pIJ2HYX6x2DwKFGbcSckAWN3tgcdq+ptB6SaqjWUhlzIgA/YhPuwIU+/NnMnGpqOFX/hC18Oyge63w=="],
"workers-ai-provider": ["workers-ai-provider@0.7.5", "", { "dependencies": { "@ai-sdk/provider": "^1.1.3", "@ai-sdk/provider-utils": "^2.2.8" } }, "sha512-dhCwgc3D65oDDTpH3k8Gf0Ek7KItzvaQidn2N5L5cqLo3WG8GM/4+Nr4rU56o8O3oZRsloB1gUCHYaRv2j7Y0A=="],
- "wrangler": ["wrangler@4.92.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.27.3", "miniflare": "4.20260515.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260515.1" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20260515.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-/DKpQHPxkuZbQsO9dFW2700VTD/4DSZMHjy92fO/frNoDRi/zQsFCAd2ONCV6TGqcUoXcP3D8Bo2gj/L4M0qQQ=="],
+ "wrangler": ["wrangler@4.100.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.27.3", "miniflare": "4.20260611.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260611.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20260611.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "cf-wrangler": "bin/cf-wrangler.js", "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-dSQO7DO+mD6XDzkVWIWBoGLO3yw+lacWSc/KhFvd7pgfpth+kX98qb5SGRHZN8ACCDhhfwzDLXwB6qHsIHhfBg=="],
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
@@ -4871,7 +4695,7 @@
"write-file-atomic": ["write-file-atomic@4.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" } }, "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg=="],
- "ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="],
+ "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="],
"xcode": ["xcode@3.0.1", "", { "dependencies": { "simple-plist": "^1.1.0", "uuid": "^7.0.3" } }, "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA=="],
@@ -4881,8 +4705,6 @@
"xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
- "xpath": ["xpath@0.0.34", "", {}, "sha512-FxF6+rkr1rNSQrhUNYrAFJpRXNzlDoMxeXN5qI84939ylEv3qqPFKa85Oxr6tDaJKqwW6KKyo2v26TSv3k6LeA=="],
-
"xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
@@ -4895,20 +4717,16 @@
"yargs-parser": ["yargs-parser@13.1.2", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg=="],
- "yauzl": ["yauzl@3.3.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "pend": "~1.2.0" } }, "sha512-PtGEvEP30p7sbIBJKUBjUnqgTVOyMURc4dLo9iNyAJnNIEz9pm88cCXF21w94Kg3k6RXkeZh5DHOGS0qEONvNQ=="],
+ "yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="],
"yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="],
- "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="],
-
"youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="],
"youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="],
"youtube-transcript": ["youtube-transcript@1.3.1", "", {}, "sha512-NDCjwad113TGybbYF51y9Z4tcwzBHUZWQdF9veULNca18L+FdDbHHtTHIr69WVa3bB90l67S8kN0HtL2JO9fhg=="],
- "zip-stream": ["zip-stream@6.0.1", "", { "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" } }, "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA=="],
-
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
"zod-openapi": ["zod-openapi@5.4.6", "", { "peerDependencies": { "zod": "^3.25.74 || ^4.0.0" } }, "sha512-P2jsOOBAq/6hCwUsMCjUATZ8szkMsV5VAwZENfyxp2Hc/XPJQpVwAgevWZc65xZauCwWB9LAn7zYeiCJFAEL+A=="],
@@ -4917,56 +4735,12 @@
"zod-validation-error": ["zod-validation-error@3.5.4", "", { "peerDependencies": { "zod": "^3.24.4" } }, "sha512-+hEiRIiPobgyuFlEojnqjJnhFvg4r/i3cqgcm67eehZf/WBaK3g6cD02YU9mtdVxZjv8CzCA9n/Rhrs3yAAvAw=="],
- "zustand": ["zustand@5.0.13", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-efI2tVaVQPqtOh114loML/Z80Y4NP3yc+Ff0fYiZJPauNeWZeIp/bRFD7I9bfmCOYBh/PHxlglQ9+wvlwnPikQ=="],
+ "zustand": ["zustand@5.0.14", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g=="],
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
"@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
- "@appium/base-driver/@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="],
-
- "@appium/base-driver/asyncbox": ["asyncbox@6.2.0", "", { "dependencies": { "p-limit": "^7.2.0" } }, "sha512-z1XpHkoT3y+1aXfazEY5d7HN2eOi50fLq7ZTxG0H4WegLxrtEAI5Vsc6OR9dOwoC3SJQLXyV0ZVnPEh6GIgMKQ=="],
-
- "@appium/base-driver/axios": ["axios@1.16.0", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } }, "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w=="],
-
- "@appium/base-driver/lru-cache": ["lru-cache@11.3.5", "", {}, "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw=="],
-
- "@appium/base-driver/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
-
- "@appium/docutils/read-pkg": ["read-pkg@10.1.0", "", { "dependencies": { "@types/normalize-package-data": "^2.4.4", "normalize-package-data": "^8.0.0", "parse-json": "^8.3.0", "type-fest": "^5.4.4", "unicorn-magic": "^0.4.0" } }, "sha512-I8g2lArQiP78ll51UeMZojewtYgIRCKCWqZEgOO8c/uefTI+XDXvCSXu3+YNUaTNvZzobrL5+SqHjBrByRRTdg=="],
-
- "@appium/docutils/yaml": ["yaml@2.8.4", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog=="],
-
- "@appium/docutils/yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="],
-
- "@appium/docutils/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
-
- "@appium/logger/lru-cache": ["lru-cache@11.3.5", "", {}, "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw=="],
-
- "@appium/support/@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="],
-
- "@appium/support/asyncbox": ["asyncbox@6.2.0", "", { "dependencies": { "p-limit": "^7.2.0" } }, "sha512-z1XpHkoT3y+1aXfazEY5d7HN2eOi50fLq7ZTxG0H4WegLxrtEAI5Vsc6OR9dOwoC3SJQLXyV0ZVnPEh6GIgMKQ=="],
-
- "@appium/support/axios": ["axios@1.16.0", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } }, "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w=="],
-
- "@appium/support/bplist-creator": ["bplist-creator@0.1.1", "", { "dependencies": { "stream-buffers": "2.2.x" } }, "sha512-Ese7052fdWrxp/vqSJkydgx/1MdBnNOCV2XVfbmdGWD2H6EYza+Q4pyYSuVSnCUD22hfI/BFI4jHaC3NLXLlJQ=="],
-
- "@appium/support/glob": ["glob@13.0.5", "", { "dependencies": { "minimatch": "^10.2.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw=="],
-
- "@appium/support/log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="],
-
- "@appium/support/plist": ["plist@4.0.0", "", { "dependencies": { "@xmldom/xmldom": "^0.9.10", "xmlbuilder": "^15.1.1" } }, "sha512-4dOqNo0Y2NpfSf9q4+zr4bh7pzNWeckIam34Z0KYJhg8qtNNfh59VbD+Yna5SjwcxawVvLKx5w5FtuCijpEF4Q=="],
-
- "@appium/support/read-pkg": ["read-pkg@10.1.0", "", { "dependencies": { "@types/normalize-package-data": "^2.4.4", "normalize-package-data": "^8.0.0", "parse-json": "^8.3.0", "type-fest": "^5.4.4", "unicorn-magic": "^0.4.0" } }, "sha512-I8g2lArQiP78ll51UeMZojewtYgIRCKCWqZEgOO8c/uefTI+XDXvCSXu3+YNUaTNvZzobrL5+SqHjBrByRRTdg=="],
-
- "@appium/support/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
-
- "@appium/support/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
-
- "@appium/support/uuid": ["uuid@14.0.0", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg=="],
-
- "@appium/support/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
-
"@aws-crypto/sha1-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
"@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
@@ -4983,16 +4757,18 @@
"@babel/helper-create-regexp-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+ "@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
+
"@babel/plugin-transform-runtime/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@better-auth/core/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
- "@better-auth/core/jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="],
-
"@better-auth/core/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
"@better-auth/expo/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
+ "@better-auth/oauth-provider/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
+
"@cloudflare/vitest-pool-workers/miniflare": ["miniflare@4.20250906.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "^7.10.0", "workerd": "1.20250906.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-T/RWn1sa0ien80s6NjU+Un/tj12gR6wqScZoiLeMJDD4/fK0UXfnbWXJDubnUED8Xjm7RPQ5ESYdE+mhPmMtuQ=="],
"@cloudflare/vitest-pool-workers/wrangler": ["wrangler@4.35.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.7.3", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20250906.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.21", "workerd": "1.20250906.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250906.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-HbyXtbrh4Fi3mU8ussY85tVdQ74qpVS1vctUgaPc+bPrXBTqfDLkZ6VRtHAVF/eBhz4SFmhJtCQpN1caY2Ak8A=="],
@@ -5003,7 +4779,7 @@
"@eslint/eslintrc/ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="],
- "@eslint/eslintrc/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
+ "@eslint/eslintrc/js-yaml": ["js-yaml@4.2.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw=="],
"@eslint/eslintrc/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
@@ -5017,6 +4793,8 @@
"@expo/config/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
+ "@expo/config-plugins/@expo/json-file": ["@expo/json-file@10.0.16", "", { "dependencies": { "@babel/code-frame": "~7.10.4", "json5": "^2.2.3" } }, "sha512-fcVkWEj+hLuP2yt5W0aw6LmDRqSPWDLUSxOMcmFeV+algmIF59sQVKCwB9btjQLd4V6x9N0pISkQEkBubUHrCw=="],
+
"@expo/config-plugins/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"@expo/config-plugins/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
@@ -5035,19 +4813,21 @@
"@expo/local-build-cache-provider/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
+ "@expo/metro-config/@expo/json-file": ["@expo/json-file@10.0.16", "", { "dependencies": { "@babel/code-frame": "~7.10.4", "json5": "^2.2.3" } }, "sha512-fcVkWEj+hLuP2yt5W0aw6LmDRqSPWDLUSxOMcmFeV+algmIF59sQVKCwB9btjQLd4V6x9N0pISkQEkBubUHrCw=="],
+
"@expo/metro-config/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"@expo/metro-config/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
- "@expo/metro-config/lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
+ "@expo/metro-config/hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="],
- "@expo/metro-config/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="],
+ "@expo/metro-config/lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
"@expo/package-manager/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"@expo/xcpretty/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
- "@expo/xcpretty/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
+ "@expo/xcpretty/js-yaml": ["js-yaml@4.2.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw=="],
"@gorhom/portal/nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
@@ -5061,52 +4841,20 @@
"@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
+ "@kitajs/ts-html-plugin/yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="],
+
"@lhci/cli/express": ["express@4.22.2", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "~1.20.5", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.3.1", "fresh": "~0.5.2", "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", "qs": "~6.15.1", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", "serve-static": "~1.16.2", "setprototypeof": "1.2.0", "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q=="],
"@lhci/cli/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
"@lhci/cli/yargs": ["yargs@15.4.1", "", { "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" } }, "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A=="],
- "@manypkg/tools/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
-
- "@modelcontextprotocol/sdk/jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="],
-
"@modelcontextprotocol/sdk/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
"@pnpm/network.ca-file/graceful-fs": ["graceful-fs@4.2.10", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="],
"@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
- "@radix-ui/react-alert-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
- "@radix-ui/react-aspect-ratio/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
-
- "@radix-ui/react-avatar/@radix-ui/react-context": ["@radix-ui/react-context@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw=="],
-
- "@radix-ui/react-avatar/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
-
- "@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
- "@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
- "@radix-ui/react-label/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
-
- "@radix-ui/react-menu/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
- "@radix-ui/react-popover/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
- "@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
- "@radix-ui/react-progress/@radix-ui/react-context": ["@radix-ui/react-context@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw=="],
-
- "@radix-ui/react-progress/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
-
- "@radix-ui/react-select/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
- "@radix-ui/react-separator/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
-
- "@radix-ui/react-tooltip/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
"@react-native-ai/apple/@ai-sdk/provider": ["@ai-sdk/provider@2.0.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-h88OPkavHTiN9tMn2l5awAznGB0lXzjcLhgR1/rvjB2zlLprsNxbM2tt6OJsHUxduLC3klq0/eqaSf6fX5XVww=="],
"@react-native-ai/apple/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.25", "", { "dependencies": { "@ai-sdk/provider": "2.0.3", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-CvsRu+32Y8a167s+lrIBtsybvgTHp8j9y+6BeTvLeoW3Q+okw/b4CnNUFOLIXsRaKHQKAH+IHNJPYWywfpw0LA=="],
@@ -5121,11 +4869,13 @@
"@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
+ "@react-native/codegen/hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="],
+
"@react-native/dev-middleware/chrome-launcher": ["chrome-launcher@0.15.2", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0" }, "bin": { "print-chrome-path": "bin/print-chrome-path.js" } }, "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ=="],
"@react-native/dev-middleware/serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="],
- "@react-native/dev-middleware/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
+ "@react-native/dev-middleware/ws": ["ws@7.5.11", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA=="],
"@react-navigation/core/nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
@@ -5133,8 +4883,6 @@
"@react-navigation/routers/nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
- "@reduxjs/toolkit/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
-
"@reduxjs/toolkit/immer": ["immer@11.1.8", "", {}, "sha512-/tbkHMW7y10Lx6i1crLjD4/OhNkRG+Fo7byZHtah0547nIeXYcpIXaUh0IAQY6gO5459qpGGYapcEOHtFXkIuA=="],
"@sentry-internal/browser-utils/@sentry/core": ["@sentry/core@10.37.0", "", {}, "sha512-hkRz7S4gkKLgPf+p3XgVjVm7tAfvcEPZxeACCC6jmoeKhGkzN44nXwLiqqshJ25RMcSrhfFvJa/FlBg6zupz7g=="],
@@ -5181,13 +4929,9 @@
"@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
- "@so-ric/colorspace/color": ["color@5.0.3", "", { "dependencies": { "color-convert": "^3.1.3", "color-string": "^2.1.3" } }, "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA=="],
-
"@tailwindcss/typography/postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="],
- "@types/glob/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
-
- "@typescript-eslint/project-service/@typescript-eslint/types": ["@typescript-eslint/types@8.59.3", "", {}, "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg=="],
+ "@typescript-eslint/project-service/@typescript-eslint/types": ["@typescript-eslint/types@8.61.0", "", {}, "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg=="],
"@typescript-eslint/typescript-estree/globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="],
@@ -5211,36 +4955,6 @@
"anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
- "appium/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
-
- "appium/axios": ["axios@1.16.0", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } }, "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w=="],
-
- "appium/lru-cache": ["lru-cache@11.3.5", "", {}, "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw=="],
-
- "appium/ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="],
-
- "appium/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
-
- "appium/ws": ["ws@8.20.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA=="],
-
- "appium/yaml": ["yaml@2.8.4", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog=="],
-
- "appium-android-driver/@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="],
-
- "archiver/async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="],
-
- "archiver/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
-
- "archiver-utils/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
-
- "archiver-utils/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
-
- "asyncbox/p-limit": ["p-limit@7.3.0", "", { "dependencies": { "yocto-queue": "^1.2.1" } }, "sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw=="],
-
- "axios/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
-
- "axios/proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="],
-
"babel-jest/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"babel-jest/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
@@ -5249,22 +4963,16 @@
"babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
- "basic-auth/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
-
- "better-auth/jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="],
+ "babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="],
"better-auth/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
- "better-auth-cloudflare/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
-
"better-opn/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
"burnt/sf-symbols-typescript": ["sf-symbols-typescript@1.0.0", "", {}, "sha512-DkS7q3nN68dEMb4E18HFPDAvyrjDZK9YAQQF2QxeFu9gp2xRDXFMF8qLJ1EmQ/qeEGQmop4lmMM1WtYJTIcCMw=="],
"camelcase-keys/camelcase": ["camelcase@2.1.1", "", {}, "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw=="],
- "cheerio/undici": ["undici@7.25.0", "", {}, "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ=="],
-
"chrome-launcher/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
"chrome-launcher/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
@@ -5275,18 +4983,12 @@
"chromium-edge-launcher/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
- "cmdk/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
-
- "compress-commons/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
-
"compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
"concurrently/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"concurrently/date-fns": ["date-fns@2.30.0", "", { "dependencies": { "@babel/runtime": "^7.21.0" } }, "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw=="],
- "config-chain/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
-
"configstore/make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="],
"configstore/write-file-atomic": ["write-file-atomic@3.0.3", "", { "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", "signal-exit": "^3.0.2", "typedarray-to-buffer": "^3.1.5" } }, "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q=="],
@@ -5295,13 +4997,11 @@
"connect/finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="],
- "cosmiconfig/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
-
- "crc32-stream/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
+ "cosmiconfig/js-yaml": ["js-yaml@4.2.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw=="],
"cross-fetch/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
- "detective-typescript/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.59.3", "", { "dependencies": { "@typescript-eslint/project-service": "8.59.3", "@typescript-eslint/tsconfig-utils": "8.59.3", "@typescript-eslint/types": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg=="],
+ "detective-typescript/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.61.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.61.0", "@typescript-eslint/tsconfig-utils": "8.61.0", "@typescript-eslint/types": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA=="],
"dir-glob/path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
@@ -5317,13 +5017,13 @@
"eslint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
- "eslint/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
+ "eslint/js-yaml": ["js-yaml@4.2.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw=="],
"eslint/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.59.3", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.59.3", "@typescript-eslint/type-utils": "8.59.3", "@typescript-eslint/utils": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.59.3", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-PwFvSKsXGShKGW6n5bZOhGHEcCZXM8HofLK9fNsEwZXzFRjoY+XT1Vsf1zgyXdwTr0ZYz1/2tkZ0DBTT9jZjhw=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.61.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.61.0", "@typescript-eslint/type-utils": "8.61.0", "@typescript-eslint/utils": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.61.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw=="],
- "eslint-config-universe/@typescript-eslint/parser": ["@typescript-eslint/parser@8.59.3", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.59.3", "@typescript-eslint/types": "8.59.3", "@typescript-eslint/typescript-estree": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-HPwA+hVkfcriajbNvTmZv4VRauibay+cWArYUYq7u7W7PmGShMxbPxLvrwDme55a6d5alG3nrYfhyJ/G28XlLg=="],
+ "eslint-config-universe/@typescript-eslint/parser": ["@typescript-eslint/parser@8.61.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.61.0", "@typescript-eslint/types": "8.61.0", "@typescript-eslint/typescript-estree": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w=="],
"eslint-config-universe/globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="],
@@ -5355,6 +5055,8 @@
"eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+ "eslint-plugin-react-hooks/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
+
"eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@1.3.0", "", {}, "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ=="],
"expo-modules-autolinking/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
@@ -5379,10 +5081,6 @@
"external-editor/tmp": ["tmp@0.0.33", "", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="],
- "extract-zip/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
-
- "extract-zip/yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="],
-
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"fbjs/object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
@@ -5395,12 +5093,6 @@
"flat-cache/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
- "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
-
- "ftp-response-parser/readable-stream": ["readable-stream@1.1.14", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ=="],
-
- "get-stream/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
-
"get-uri/data-uri-to-buffer": ["data-uri-to-buffer@6.0.2", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="],
"globals/type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="],
@@ -5411,8 +5103,6 @@
"hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
- "hpack.js/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
-
"import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
"inquirer/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
@@ -5443,10 +5133,6 @@
"jest-validate/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
- "jsftp/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
-
- "lazystream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
-
"lighthouse/chrome-launcher": ["chrome-launcher@1.2.1", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^2.0.1" }, "bin": { "print-chrome-path": "bin/print-chrome-path.cjs" } }, "sha512-qmFR5PLMzHyuNJHwOloHPAHhbaNglkfeV/xDtt5b7xiFFyU1I+AZZX0PYseMuhenJSSirgxELYIbswcoc+5H4A=="],
"lighthouse/lighthouse-logger": ["lighthouse-logger@2.0.2", "", { "dependencies": { "debug": "^4.4.1", "marky": "^1.2.2" } }, "sha512-vWl2+u5jgOQuZR55Z1WM0XDdrJT6mzMP8zHUct7xTlWhuQs+eV0g+QL0RQdFjT54zVmbhLCP8vIVpy1wGn/gCg=="],
@@ -5455,7 +5141,7 @@
"lighthouse/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
- "lighthouse/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
+ "lighthouse/ws": ["ws@7.5.11", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA=="],
"lighthouse/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
@@ -5467,12 +5153,8 @@
"load-json-file/strip-bom": ["strip-bom@2.0.0", "", { "dependencies": { "is-utf8": "^0.2.0" } }, "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g=="],
- "lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
-
"log-symbols/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
- "logform/@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="],
-
"loud-rejection/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
"markdown-it/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
@@ -5483,13 +5165,11 @@
"merge-options/is-plain-obj": ["is-plain-obj@2.1.0", "", {}, "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="],
- "method-override/debug": ["debug@3.1.0", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g=="],
-
"metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
"metro/hermes-parser": ["hermes-parser@0.35.0", "", { "dependencies": { "hermes-estree": "0.35.0" } }, "sha512-9JLjeHxBx8T4CAsydZR49PNZUaix+WpQJwu9p2010lu+7Kwl6D/7wYFFJxoz+aXkaaClp9Zfg6W6/zVlSJORaA=="],
- "metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
+ "metro/ws": ["ws@7.5.11", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA=="],
"metro-babel-transformer/hermes-parser": ["hermes-parser@0.35.0", "", { "dependencies": { "hermes-estree": "0.35.0" } }, "sha512-9JLjeHxBx8T4CAsydZR49PNZUaix+WpQJwu9p2010lu+7Kwl6D/7wYFFJxoz+aXkaaClp9Zfg6W6/zVlSJORaA=="],
@@ -5497,11 +5177,7 @@
"mimetext/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
- "miniflare/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
-
- "morgan/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
-
- "morgan/on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="],
+ "miniflare/ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="],
"mz/object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
@@ -5515,16 +5191,12 @@
"npm-package-arg/validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="],
- "open-graph-scraper/undici": ["undici@7.25.0", "", {}, "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ=="],
-
"ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
"ora/strip-ansi": ["strip-ansi@5.2.0", "", { "dependencies": { "ansi-regex": "^4.1.0" } }, "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA=="],
"p-locate/p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
- "package-changed/commander": ["commander@6.2.1", "", {}, "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="],
-
"parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
"playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
@@ -5545,20 +5217,16 @@
"proxy-agent/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
- "rc/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
-
"rc/strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
- "react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
+ "react-devtools-core/ws": ["ws@7.5.11", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA=="],
"react-native/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
- "react-native/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
+ "react-native/ws": ["ws@7.5.11", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA=="],
"react-native-blob-util/glob": ["glob@13.0.1", "", { "dependencies": { "minimatch": "^10.1.2", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-B7U/vJpE3DkJ5WXTgTpTRN63uV42DseiXXKMwG14LQBXmsdeIoHAPbU/MEo6II0k5ED74uc2ZGTC6MwHFQhF6w=="],
- "react-native-blob-util/uuid": ["uuid@13.0.2", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw=="],
-
"react-native-reanimated/react-native-is-edge-to-edge": ["react-native-is-edge-to-edge@1.2.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q=="],
"react-native-reanimated/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
@@ -5573,18 +5241,12 @@
"read-pkg-up/find-up": ["find-up@1.1.2", "", { "dependencies": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" } }, "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA=="],
- "readdir-glob/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="],
-
"restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
"rimraf/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
- "rollup/@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
-
"router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
- "serve-favicon/fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="],
-
"simple-plist/bplist-parser": ["bplist-parser@0.3.1", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA=="],
"simple-swizzle/is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
@@ -5595,6 +5257,8 @@
"stacktrace-parser/type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="],
+ "steiger/@feature-sliced/steiger-plugin": ["@feature-sliced/steiger-plugin@0.6.0", "", { "dependencies": { "@feature-sliced/filesystem": "^3.1.0", "fastest-levenshtein": "^1.0.16", "lodash-es": "^4.17.21", "pluralize": "^8.0.0", "tsconfck": "^3.1.6", "web-tree-sitter": "^0.26.8" } }, "sha512-TO7DbHYcldgyasVK5iwoou+J0rJonDgH18B+IBQqXedeB2/MURpkbUw9PFPV84pysG5C3uvIDhk+lLMW2MgQ4Q=="],
+
"sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
"supports-hyperlinks/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
@@ -5605,7 +5269,7 @@
"terminal-link/ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
- "terser/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
+ "terser/acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="],
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
@@ -5615,7 +5279,7 @@
"tsconfig-paths/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
- "tsx/esbuild": ["esbuild@0.28.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.0", "@esbuild/android-arm": "0.28.0", "@esbuild/android-arm64": "0.28.0", "@esbuild/android-x64": "0.28.0", "@esbuild/darwin-arm64": "0.28.0", "@esbuild/darwin-x64": "0.28.0", "@esbuild/freebsd-arm64": "0.28.0", "@esbuild/freebsd-x64": "0.28.0", "@esbuild/linux-arm": "0.28.0", "@esbuild/linux-arm64": "0.28.0", "@esbuild/linux-ia32": "0.28.0", "@esbuild/linux-loong64": "0.28.0", "@esbuild/linux-mips64el": "0.28.0", "@esbuild/linux-ppc64": "0.28.0", "@esbuild/linux-riscv64": "0.28.0", "@esbuild/linux-s390x": "0.28.0", "@esbuild/linux-x64": "0.28.0", "@esbuild/netbsd-arm64": "0.28.0", "@esbuild/netbsd-x64": "0.28.0", "@esbuild/openbsd-arm64": "0.28.0", "@esbuild/openbsd-x64": "0.28.0", "@esbuild/openharmony-arm64": "0.28.0", "@esbuild/sunos-x64": "0.28.0", "@esbuild/win32-arm64": "0.28.0", "@esbuild/win32-ia32": "0.28.0", "@esbuild/win32-x64": "0.28.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw=="],
+ "tsx/esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="],
"type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
@@ -5627,10 +5291,6 @@
"whatwg-encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
- "winston/@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="],
-
- "winston/async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="],
-
"workers-ai-provider/@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="],
"workers-ai-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="],
@@ -5643,44 +5303,14 @@
"yargs/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
- "yauzl/buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
-
- "zip-stream/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
-
- "@appium/base-driver/asyncbox/p-limit": ["p-limit@7.3.0", "", { "dependencies": { "yocto-queue": "^1.2.1" } }, "sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw=="],
-
- "@appium/base-driver/axios/proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="],
-
- "@appium/docutils/read-pkg/normalize-package-data": ["normalize-package-data@8.0.0", "", { "dependencies": { "hosted-git-info": "^9.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" } }, "sha512-RWk+PI433eESQ7ounYxIp67CYuVsS1uYSonX3kA6ps/3LWfjVQa/ptEg6Y3T6uAMq1mWpX9PQ+qx+QaHpsc7gQ=="],
-
- "@appium/docutils/read-pkg/parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="],
-
- "@appium/docutils/read-pkg/unicorn-magic": ["unicorn-magic@0.4.0", "", {}, "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw=="],
-
- "@appium/docutils/yargs/cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="],
-
- "@appium/docutils/yargs/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+ "@babel/highlight/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
- "@appium/support/asyncbox/p-limit": ["p-limit@7.3.0", "", { "dependencies": { "yocto-queue": "^1.2.1" } }, "sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw=="],
+ "@babel/highlight/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
- "@appium/support/axios/proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="],
-
- "@appium/support/log-symbols/is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
-
- "@appium/support/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.9.10", "", {}, "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw=="],
-
- "@appium/support/read-pkg/normalize-package-data": ["normalize-package-data@8.0.0", "", { "dependencies": { "hosted-git-info": "^9.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" } }, "sha512-RWk+PI433eESQ7ounYxIp67CYuVsS1uYSonX3kA6ps/3LWfjVQa/ptEg6Y3T6uAMq1mWpX9PQ+qx+QaHpsc7gQ=="],
-
- "@appium/support/read-pkg/parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="],
-
- "@appium/support/read-pkg/unicorn-magic": ["unicorn-magic@0.4.0", "", {}, "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw=="],
-
- "@appium/support/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
+ "@babel/highlight/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
"@cloudflare/vitest-pool-workers/miniflare/sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
- "@cloudflare/vitest-pool-workers/miniflare/undici": ["undici@7.25.0", "", {}, "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ=="],
-
"@cloudflare/vitest-pool-workers/miniflare/workerd": ["workerd@1.20250906.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250906.0", "@cloudflare/workerd-darwin-arm64": "1.20250906.0", "@cloudflare/workerd-linux-64": "1.20250906.0", "@cloudflare/workerd-linux-arm64": "1.20250906.0", "@cloudflare/workerd-windows-64": "1.20250906.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-ryVyEaqXPPsr/AxccRmYZZmDAkfQVjhfRqrNTlEeN8aftBk6Ca1u7/VqmfOayjCXrA+O547TauebU+J3IpvFXw=="],
"@cloudflare/vitest-pool-workers/miniflare/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
@@ -5745,7 +5375,7 @@
"@eslint/eslintrc/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
- "@eslint/eslintrc/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "@eslint/eslintrc/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
"@expo/cli/accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
@@ -5759,6 +5389,8 @@
"@expo/cli/send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="],
+ "@expo/config-plugins/@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
+
"@expo/config-plugins/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"@expo/devtools/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
@@ -5771,8 +5403,12 @@
"@expo/local-build-cache-provider/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+ "@expo/metro-config/@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
+
"@expo/metro-config/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+ "@expo/metro-config/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
+
"@expo/metro-config/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
"@expo/metro-config/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
@@ -5793,15 +5429,13 @@
"@expo/metro-config/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
- "@expo/metro-config/postcss/nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
-
"@expo/package-manager/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"@expo/xcpretty/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"@expo/xcpretty/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
- "@humanwhocodes/config-array/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "@humanwhocodes/config-array/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
"@istanbuljs/load-nyc-config/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
@@ -5809,6 +5443,12 @@
"@jest/types/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+ "@kitajs/ts-html-plugin/yargs/cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="],
+
+ "@kitajs/ts-html-plugin/yargs/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+
+ "@kitajs/ts-html-plugin/yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
+
"@lhci/cli/express/accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="],
"@lhci/cli/express/body-parser": ["body-parser@1.20.5", "", { "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "~1.2.0", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" } }, "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA=="],
@@ -5843,27 +5483,23 @@
"@lhci/cli/yargs/yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="],
- "@manypkg/tools/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
-
"@react-native-ai/apple/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@react-native-ai/llama/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@react-native/codegen/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
+ "@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
+
"@react-native/dev-middleware/serve-static/send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="],
"@sentry/cli/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
"@sentry/node/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
- "@so-ric/colorspace/color/color-convert": ["color-convert@3.1.3", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg=="],
-
- "@so-ric/colorspace/color/color-string": ["color-string@2.1.4", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg=="],
-
"@typescript-eslint/typescript-estree/globby/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
- "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="],
+ "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.1.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA=="],
"agents/yargs/cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="],
@@ -5871,38 +5507,18 @@
"agents/yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
- "appium/axios/proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="],
-
- "appium/ora/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
-
- "appium/ora/cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
-
- "appium/ora/log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],
-
- "archiver-utils/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
-
- "archiver-utils/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
-
- "archiver-utils/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
-
- "archiver-utils/readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
-
- "archiver/readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
-
- "axios/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
-
"babel-jest/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"babel-plugin-istanbul/test-exclude/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
"babel-plugin-istanbul/test-exclude/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
+ "babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
+
"chrome-launcher/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
"chromium-edge-launcher/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
- "compress-commons/readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
-
"compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
"concurrently/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
@@ -5921,11 +5537,9 @@
"cosmiconfig/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
- "crc32-stream/readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
+ "detective-typescript/@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.61.0", "", {}, "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg=="],
- "detective-typescript/@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.59.3", "", {}, "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg=="],
-
- "detective-typescript/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.59.3", "", { "dependencies": { "@typescript-eslint/types": "8.59.3", "eslint-visitor-keys": "^5.0.0" } }, "sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg=="],
+ "detective-typescript/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.61.0", "", { "dependencies": { "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ=="],
"detective-typescript/@typescript-eslint/typescript-estree/ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
@@ -5981,31 +5595,31 @@
"drizzle-kit/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.59.3", "", { "dependencies": { "@typescript-eslint/types": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3" } }, "sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.61.0", "", { "dependencies": { "@typescript-eslint/types": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0" } }, "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.59.3", "", { "dependencies": { "@typescript-eslint/types": "8.59.3", "@typescript-eslint/typescript-estree": "8.59.3", "@typescript-eslint/utils": "8.59.3", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-g71d8QD8UaiHGvrJwyIS1hCX5r63w6Jll+4VEYhEAHXTDIqX1JgxhTAbEHtKntL9kuc4jRo7/GWw5xfCepSccQ=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.61.0", "", { "dependencies": { "@typescript-eslint/types": "8.61.0", "@typescript-eslint/typescript-estree": "8.61.0", "@typescript-eslint/utils": "8.61.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/utils": ["@typescript-eslint/utils@8.59.3", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.59.3", "@typescript-eslint/types": "8.59.3", "@typescript-eslint/typescript-estree": "8.59.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-JAvT14goBzRzzzZyqq3P9BLArIxTtQURUtFgQ/V7FO+eU+Gg6ES+5ymOPP1wRxXcxAYeivCk4uS3jCKWI1K8Zg=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/utils": ["@typescript-eslint/utils@8.61.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.61.0", "@typescript-eslint/types": "8.61.0", "@typescript-eslint/typescript-estree": "8.61.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.59.3", "", { "dependencies": { "@typescript-eslint/types": "8.59.3", "eslint-visitor-keys": "^5.0.0" } }, "sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.61.0", "", { "dependencies": { "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ=="],
"eslint-config-universe/@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
"eslint-config-universe/@typescript-eslint/eslint-plugin/ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
- "eslint-config-universe/@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.59.3", "", { "dependencies": { "@typescript-eslint/types": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3" } }, "sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA=="],
+ "eslint-config-universe/@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.61.0", "", { "dependencies": { "@typescript-eslint/types": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0" } }, "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA=="],
- "eslint-config-universe/@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.59.3", "", {}, "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg=="],
+ "eslint-config-universe/@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.61.0", "", {}, "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg=="],
- "eslint-config-universe/@typescript-eslint/parser/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.59.3", "", { "dependencies": { "@typescript-eslint/project-service": "8.59.3", "@typescript-eslint/tsconfig-utils": "8.59.3", "@typescript-eslint/types": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg=="],
+ "eslint-config-universe/@typescript-eslint/parser/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.61.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.61.0", "@typescript-eslint/tsconfig-utils": "8.61.0", "@typescript-eslint/types": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA=="],
- "eslint-config-universe/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.59.3", "", { "dependencies": { "@typescript-eslint/types": "8.59.3", "eslint-visitor-keys": "^5.0.0" } }, "sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg=="],
+ "eslint-config-universe/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.61.0", "", { "dependencies": { "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ=="],
- "eslint-plugin-import/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "eslint-plugin-import/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
- "eslint-plugin-node/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "eslint-plugin-node/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
- "eslint-plugin-react/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "eslint-plugin-react/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
"eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
@@ -6013,28 +5627,14 @@
"eslint/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
- "eslint/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "eslint/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
"expo-modules-autolinking/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"expo-updates/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
- "extract-zip/yauzl/buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
-
"flat-cache/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
- "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
-
- "ftp-response-parser/readable-stream/isarray": ["isarray@0.0.1", "", {}, "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="],
-
- "ftp-response-parser/readable-stream/string_decoder": ["string_decoder@0.10.31", "", {}, "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="],
-
- "hpack.js/readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
-
- "hpack.js/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
-
- "hpack.js/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
-
"inquirer/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
"inquirer/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
@@ -6055,12 +5655,6 @@
"jest-validate/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
- "lazystream/readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
-
- "lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
-
- "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
-
"lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
"log-symbols/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
@@ -6069,16 +5663,12 @@
"log-symbols/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
- "method-override/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
-
"metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.35.0", "", {}, "sha512-xVx5Opwy8Oo1I5yGpVRhCvWL/iV3M+ylksSKVNlxxD90cpDpR/AR1jLYqK8HWihm065a6UI3HeyAmYzwS8NOOg=="],
"metro/hermes-parser/hermes-estree": ["hermes-estree@0.35.0", "", {}, "sha512-xVx5Opwy8Oo1I5yGpVRhCvWL/iV3M+ylksSKVNlxxD90cpDpR/AR1jLYqK8HWihm065a6UI3HeyAmYzwS8NOOg=="],
"mimetext/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
- "morgan/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
-
"next/postcss/nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
"ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
@@ -6095,8 +5685,6 @@
"read-pkg-up/find-up/path-exists": ["path-exists@2.1.0", "", { "dependencies": { "pinkie-promise": "^2.0.0" } }, "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ=="],
- "readdir-glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="],
-
"tailwindcss/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
@@ -6111,57 +5699,57 @@
"tmp/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
- "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA=="],
+ "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="],
- "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.28.0", "", { "os": "android", "cpu": "arm" }, "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ=="],
+ "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="],
- "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.0", "", { "os": "android", "cpu": "arm64" }, "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw=="],
+ "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="],
- "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.28.0", "", { "os": "android", "cpu": "x64" }, "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA=="],
+ "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="],
- "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q=="],
+ "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="],
- "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ=="],
+ "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="],
- "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q=="],
+ "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="],
- "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw=="],
+ "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="],
- "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw=="],
+ "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="],
- "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A=="],
+ "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="],
- "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ=="],
+ "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="],
- "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg=="],
+ "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="],
- "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w=="],
+ "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="],
- "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg=="],
+ "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="],
- "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ=="],
+ "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="],
- "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q=="],
+ "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="],
- "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.0", "", { "os": "linux", "cpu": "x64" }, "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ=="],
+ "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="],
- "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.0", "", { "os": "none", "cpu": "arm64" }, "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw=="],
+ "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="],
- "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.0", "", { "os": "none", "cpu": "x64" }, "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw=="],
+ "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="],
- "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.0", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g=="],
+ "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="],
- "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA=="],
+ "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="],
- "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.0", "", { "os": "none", "cpu": "arm64" }, "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w=="],
+ "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="],
- "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.0", "", { "os": "sunos", "cpu": "x64" }, "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw=="],
+ "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="],
- "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA=="],
+ "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="],
- "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA=="],
+ "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="],
- "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.0", "", { "os": "win32", "cpu": "x64" }, "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw=="],
+ "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="],
"vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
@@ -6217,25 +5805,9 @@
"workers-ai-provider/@ai-sdk/provider-utils/nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
- "zip-stream/readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
-
- "@appium/docutils/read-pkg/normalize-package-data/hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="],
-
- "@appium/docutils/read-pkg/parse-json/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
-
- "@appium/docutils/yargs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
-
- "@appium/docutils/yargs/cliui/wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
-
- "@appium/docutils/yargs/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+ "@babel/highlight/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
- "@appium/docutils/yargs/string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
-
- "@appium/support/read-pkg/normalize-package-data/hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="],
-
- "@appium/support/read-pkg/normalize-package-data/semver": ["semver@7.8.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="],
-
- "@appium/support/read-pkg/parse-json/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
+ "@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
@@ -6285,8 +5857,6 @@
"@cloudflare/vitest-pool-workers/miniflare/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250906.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Q8Qjfs8jGVILnZL6vUpQ90q/8MTCYaGR3d1LGxZMBqte8Vr7xF3KFHPEy7tFs0j0mMjnqCYzlofmPNY+9ZaDRg=="],
- "@cloudflare/vitest-pool-workers/wrangler/@cloudflare/kv-asset-handler/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
-
"@cloudflare/vitest-pool-workers/wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="],
"@cloudflare/vitest-pool-workers/wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="],
@@ -6357,6 +5927,14 @@
"@istanbuljs/load-nyc-config/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
+ "@kitajs/ts-html-plugin/yargs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
+
+ "@kitajs/ts-html-plugin/yargs/cliui/wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
+
+ "@kitajs/ts-html-plugin/yargs/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+
+ "@kitajs/ts-html-plugin/yargs/string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
+
"@lhci/cli/express/accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
"@lhci/cli/express/accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
@@ -6377,7 +5955,7 @@
"@lhci/cli/yargs/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
- "@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
"@react-native/dev-middleware/serve-static/send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
@@ -6385,10 +5963,6 @@
"@react-native/dev-middleware/serve-static/send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="],
- "@so-ric/colorspace/color/color-convert/color-name": ["color-name@2.1.0", "", {}, "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg=="],
-
- "@so-ric/colorspace/color/color-string/color-name": ["color-name@2.1.0", "", {}, "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg=="],
-
"@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"agents/yargs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
@@ -6399,17 +5973,7 @@
"agents/yargs/string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
- "appium/ora/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
-
- "appium/ora/cli-cursor/restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
-
- "archiver-utils/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
-
- "archiver-utils/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="],
-
- "archiver-utils/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
-
- "babel-plugin-istanbul/test-exclude/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "babel-plugin-istanbul/test-exclude/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
"chrome-launcher/rimraf/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
@@ -6417,17 +5981,17 @@
"detective-typescript/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.59.3", "", {}, "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.61.0", "", {}, "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.59.3", "", {}, "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.61.0", "", {}, "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.59.3", "", { "dependencies": { "@typescript-eslint/project-service": "8.59.3", "@typescript-eslint/tsconfig-utils": "8.59.3", "@typescript-eslint/types": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.61.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.61.0", "@typescript-eslint/tsconfig-utils": "8.61.0", "@typescript-eslint/types": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.59.3", "", {}, "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.61.0", "", {}, "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.59.3", "", { "dependencies": { "@typescript-eslint/project-service": "8.59.3", "@typescript-eslint/tsconfig-utils": "8.59.3", "@typescript-eslint/types": "8.59.3", "@typescript-eslint/visitor-keys": "8.59.3", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.61.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.61.0", "@typescript-eslint/tsconfig-utils": "8.61.0", "@typescript-eslint/types": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA=="],
- "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.59.3", "", {}, "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg=="],
+ "eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.61.0", "", {}, "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg=="],
"eslint-config-universe/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
@@ -6459,27 +6023,27 @@
"ora/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
- "react-native/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
-
- "readdir-glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
+ "react-native/glob/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
"tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
"test-exclude/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
- "test-exclude/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="],
+ "test-exclude/glob/minimatch/brace-expansion": ["brace-expansion@2.1.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA=="],
"test-exclude/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
"tmp/rimraf/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
- "@appium/docutils/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
+ "@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
- "@appium/docutils/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
+ "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
- "@appium/docutils/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
+ "@kitajs/ts-html-plugin/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
- "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
+ "@kitajs/ts-html-plugin/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
+
+ "@kitajs/ts-html-plugin/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
"@lhci/cli/express/accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
@@ -6497,25 +6061,13 @@
"agents/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
- "appium/ora/cli-cursor/restore-cursor/onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
-
- "appium/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
-
- "archiver-utils/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
-
- "archiver-utils/glob/jackspeak/@isaacs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
-
- "archiver-utils/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
-
- "archiver-utils/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
-
"babel-plugin-istanbul/test-exclude/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
- "chrome-launcher/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "chrome-launcher/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
- "chromium-edge-launcher/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "chromium-edge-launcher/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
- "flat-cache/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "flat-cache/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
"inquirer/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
@@ -6533,18 +6085,10 @@
"test-exclude/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
- "tmp/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
+ "tmp/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
"@lhci/cli/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
- "appium/ora/cli-cursor/restore-cursor/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
-
- "archiver-utils/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
-
- "archiver-utils/glob/jackspeak/@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
-
- "archiver-utils/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
-
"chrome-launcher/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"chromium-edge-launcher/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
diff --git a/docs/mcp/README.md b/docs/mcp/README.md
new file mode 100644
index 0000000000..b79f84bbb5
--- /dev/null
+++ b/docs/mcp/README.md
@@ -0,0 +1,41 @@
+# PackRat MCP — operator docs
+
+Internal-facing docs for the PackRat MCP Worker (`packages/mcp`). User-facing
+docs live at [packratai.com/mcp](https://packratai.com/mcp) and inside
+`packages/mcp/README.md`.
+
+- [runbook.md](./runbook.md) — deploy, secret rotation, DNS setup, JWKS
+ rotation, R11 dev verification, common operations
+- [submission-packet.md](./submission-packet.md) — the artifacts assembled for
+ Anthropic's Claude Connector Store submission form (added in U18)
+- [better-auth-oauth-provider-spike-2026-05-25.md](./better-auth-oauth-provider-spike-2026-05-25.md) — empirical verification that backed the consolidation refactor
+- [adr-0001-oauth-provider-vs-mcp-plugin.md](./adr-0001-oauth-provider-vs-mcp-plugin.md) — why we chose `@better-auth/oauth-provider` over the bundled `mcp()` plugin
+
+## Architecture at a glance
+
+Post-refactor (2026-05-25), the MCP worker is a **pure protected resource**.
+The OAuth authorization server lives on `api.packrat.world` via
+`@better-auth/oauth-provider`; the MCP worker validates JWT access tokens
+locally against the AS's JWKS.
+
+- **Worker name (prod):** `packrat-mcp` → `mcp.packratai.com`
+- **Worker name (dev):** `packrat-mcp-dev` → `*.workers.dev`
+- **Transport:** Streamable HTTP at `/mcp`
+- **Auth posture:** Pure protected resource. OAuth 2.1 + PKCE S256 + RFC 8707
+ audience binding are enforced by the AS on `api.packrat.world`; the MCP
+ worker only validates JWTs.
+- **Authorization server:** `api.packrat.world`, hosted by
+ `@better-auth/oauth-provider` (inside `packages/api`). The AS owns all
+ client / grant / token state in the API's Postgres + `AUTH_KV`.
+- **JWT validation:** `packages/mcp/src/token-verify.ts` —
+ `verifyMcpToken` fetches and caches the JWKS from
+ `${PACKRAT_API_URL}/api/auth/jwks` (60s SWR cache, single-retry on
+ stale `kid`).
+- **Discovery chain:** PRM on the MCP (`/.well-known/oauth-protected-resource`)
+ → `authorization_servers: [https://api.packrat.world]` → AS metadata on
+ the API (`/.well-known/oauth-authorization-server`) → OAuth flow on the
+ API origin.
+- **State:** Durable Object (`PackRatMCP`, sqlite-backed) per MCP session.
+ No KV on the MCP worker — `OAUTH_KV` is gone.
+- **Refactor plan:** [docs/plans/2026-05-25-001-refactor-mcp-auth-onto-better-auth-plan.md](../plans/2026-05-25-001-refactor-mcp-auth-onto-better-auth-plan.md)
+- **Connector-store readiness plan (the tool/resource surface):** [docs/plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md](../plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md)
diff --git a/docs/mcp/adr-0001-oauth-provider-vs-mcp-plugin.md b/docs/mcp/adr-0001-oauth-provider-vs-mcp-plugin.md
new file mode 100644
index 0000000000..ce6fe82afb
--- /dev/null
+++ b/docs/mcp/adr-0001-oauth-provider-vs-mcp-plugin.md
@@ -0,0 +1,230 @@
+---
+title: "ADR-0001: Better Auth `@better-auth/oauth-provider` over the bundled `mcp()` plugin"
+type: adr
+status: accepted
+date: 2026-05-31
+supersedes: none
+related:
+ - docs/plans/2026-05-25-001-refactor-mcp-auth-onto-better-auth-plan.md
+ - docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md
+ - docs/plans/2026-04-30-feat-better-auth-migration-plan.md
+---
+
+# ADR-0001: `@better-auth/oauth-provider` over the bundled `mcp()` plugin
+
+## Status
+
+Accepted — 2026-05-31. Documents a decision already implemented by the
+`plan/mcp-connector-store-readiness` branch (PR #2497); written retroactively
+so the "why not the `mcp()` plugin" reasoning lives in the repo rather than only
+in review threads.
+
+## Risk status (read this before trusting green CI)
+
+This ADR records **two** things at **different** confidence levels. Don't let a
+green pipeline collapse them:
+
+- **The plugin decision (this ADR's subject) — verified at the unit level.**
+ `withMcpAuth`'s in-process requirement is a fact of the installed type
+ signature; the capability gaps are spike-verified against the package source
+ (2026-05-25); and `oauth-provider.test.ts` asserts issuer-match, PKCE S256, and
+ JWT-only-when-`resource`-is-present. Choosing `@better-auth/oauth-provider` +
+ a standalone RS verifier over `mcp()` is settled.
+
+- **The cross-origin assumption it sits on — NOT yet verified; gated on R11.**
+ The whole local-JWKS design depends on Claude.ai sending the `resource`
+ parameter. If it doesn't, `@better-auth/oauth-provider` issues an **opaque**
+ token (`isJwtAccessToken = audience && !disableJwtPlugin`, spike Q4), the RS
+ can't verify it without introspection, and the architecture breaks. The unit
+ tests prove the AS behaves correctly *given* `resource`; they do **not** prove
+ Claude sends it. That proof is the **R11 / U9 dev-verification gate** — a
+ manual operator install in a real Claude.ai account against the dev deploy —
+ and **as of this ADR it has not been run.** Code-complete + green CI is *not*
+ the finish line; R11 is.
+
+ Related unknown: the closed-as-not-planned Claude cross-origin AS bugs
+ (`claude-ai-mcp` #82, #248, #291, #11814) are "real but unconfirmed-current,"
+ caught only by R11.
+
+ **If R11 fails:** do not pivot off Better Auth or the worker split. The
+ documented fallback is to **reverse-proxy the AS endpoints onto
+ `mcp.packratai.com`** so Claude sees a single origin — a degradation path that
+ preserves this decision, not a rewrite.
+
+## Context
+
+Better Auth (v1.6.x, installed via `catalog:`) ships **three** overlapping ways
+to stand up OAuth for an MCP server. During the May 2026 consolidation research
+(see the refactor plan's Problem Frame) all three were on the table:
+
+1. **`mcp()` plugin** (`better-auth/plugins/mcp`) — the purpose-built, batteries-
+ included MCP helper. Exports `mcp`, `withMcpAuth`, `getMcpSession`,
+ `oAuthDiscoveryMetadata`, `oAuthProtectedResourceMetadata`,
+ `getMCPProtectedResourceMetadata`, `getMCPProviderMetadata`.
+2. **`oidcProvider()` plugin** (`better-auth/plugins/oidc-provider`) — the
+ general OIDC AS that `mcp()` is built on. (`mcp/index.d.mts` imports
+ `OIDCMetadata`, `OIDCOptions` from `../oidc-provider/types` — i.e. `mcp()` is
+ a thin MCP-flavoured wrapper over `oidcProvider()`.)
+3. **`@better-auth/oauth-provider`** — a **separate, newer package** (not part of
+ core `better-auth`) that is the actively-maintained OAuth 2.1 AS. This is what
+ we chose.
+
+The decisive architectural constraint is that PackRat runs **two workers**:
+
+- **AS** — `api.packrat.world` (the `packages/api` Elysia worker). Owns user
+ identity, Postgres, `AUTH_KV`, and now all OAuth client/grant/token state.
+- **RS** — `mcp.packratai.com` (the `packages/mcp` worker). A separate Cloudflare
+ Worker with its own Durable Object (`PackRatMCP`, sqlite-backed) per MCP
+ session, Streamable-HTTP transport, custom domain, deploy pipeline, and
+ runbook. It holds **no** signing keys, **no** DB connection, and **no** Better
+ Auth instance.
+
+Claude.ai discovers and authenticates across the origin boundary via the RFC
+9728 → RFC 8414 chain: PRM on the RS → `authorization_servers: [api...]` → AS
+metadata on the API origin → OAuth flow on the API origin → JWT bound to
+`aud = https://mcp.packratai.com/mcp`, which the RS verifies locally against the
+AS's JWKS.
+
+## Decision
+
+Host the OAuth 2.1 Authorization Server in the API worker using
+**`@better-auth/oauth-provider`**, and keep the MCP worker a **stateless
+protected resource** that validates JWTs locally with a hand-written
+`verifyMcpToken` (`packages/mcp/src/token-verify.ts`) and serves its own RFC 9728
+metadata (`packages/mcp/src/metadata.ts`).
+
+**Do not** adopt the `mcp()` plugin (nor the bundled `oidcProvider()` it wraps).
+
+## Why not the `mcp()` plugin
+
+The `mcp()` plugin is the right tool for the **single-app** shape: one Better
+Auth instance that both *is* the AS and *hosts* the `/mcp` transport, validating
+each request in-process with `withMcpAuth`. PackRat is deliberately not that
+shape. Concretely:
+
+### 1. `withMcpAuth` requires the auth instance in-process — the RS doesn't have one
+
+The plugin's validation helper is typed as:
+
+```ts
+declare const withMcpAuth: Promise }
+}>(auth: Auth, handler: ...) => ...
+```
+
+`withMcpAuth(auth, handler)` validates a request by calling **back into the auth
+instance's** `/mcp/get-session` endpoint — a session/DB-backed lookup that
+returns an `OAuthAccessToken`. That only works where the Better Auth instance,
+its Postgres connection, and its KV live in the **same** worker as the MCP
+transport. Our RS worker has none of those by design. To use `withMcpAuth` on
+`mcp.packratai.com` we would have to ship the entire Better Auth instance + DB
+binding to the RS — collapsing the two-worker separation the architecture exists
+to maintain.
+
+### 2. We need stateless JWKS verification with a bespoke failure contract
+
+`withMcpAuth`'s `getMcpSession` path is a stateful callback (session/introspection
+lookup). We need the opposite: a zero-round-trip, JWKS-only verification at the
+edge with three properties the plugin does not expose:
+
+- **Never throws** → maps to `401` (not `500`). Claude's discovery-retry loop
+ only re-fetches `/.well-known/oauth-protected-resource` on a `401`; a bubbled
+ `jose` error surfacing as `500` breaks the connector handshake
+ (better-auth#9654).
+- **Stale-while-revalidate JWKS** — 60s cache TTL, plus a single force-reload-
+ and-retry on an unknown `kid` (the post-rotation case), then `null`.
+- **No HTTP introspection** on the hot path — every `/mcp` call verifies the
+ token signature locally and returns.
+
+These live in `verifyMcpToken` precisely because they are RS-policy decisions we
+want to own, not behaviours we want delegated to an upstream plugin's session
+endpoint.
+
+### 3. `mcp()` wraps the *deprecated* bundled OIDC provider; the features we needed are in the new package
+
+`mcp()` is a wrapper over the bundled `oidcProvider()`. The consolidation plan
+treats the bundled `mcp`/`oidcProvider` plugins as the now-deprecated path and
+`@better-auth/oauth-provider` as the actively-maintained replacement. The
+pre-flight spike (2026-05-25) verified, against the installed source, that the
+**new** package provides the load-bearing capabilities for our listing:
+
+| Capability we required | `@better-auth/oauth-provider` (chosen) | Notes |
+| --- | --- | --- |
+| RFC 8707 audience binding | `validAudiences` — `checkResource` rejects unknown `resource` with `400 invalid_request` | Spike Q6 |
+| Consent-time **scope reduction** (strip `mcp:admin` from non-admins) | custom `consentPage` POSTs a filtered `scope` to `/oauth2/consent`; the granted record + JWT carry only the reduced set | Spike Q1–Q2; this is *the* admin-gating mechanism |
+| Dynamic Client Registration | `auth.api.createOAuthClient(...)` + seed script | Spike Q7 |
+| Refresh-token rotation | dedicated `oauthRefreshToken` table | Spike Q3 |
+| JWT-vs-opaque token control | JWT issued only when `resource` is sent and `disableJwtPlugin` is unset | Spike Q4 |
+
+Building on `mcp()` would have meant building on the deprecated OIDC base and
+re-deriving these guarantees through a wrapper not designed to expose them.
+
+### 4. RFC 9728 metadata belongs on the RS origin
+
+The `mcp()` plugin can emit protected-resource metadata
+(`getMCPProtectedResourceMetadata` / `oAuthProtectedResourceMetadata`) — but it
+emits it from **inside the AS app**, where the discovery helpers and the
+`withMcpAuth` validator are co-located. Claude fetches PRM from the **resource
+origin** (`mcp.packratai.com`), not the AS origin. With separate workers, PRM
+must be served by the RS worker regardless of what the AS plugin can generate, so
+we keep `buildResourceMetadata` in `packages/mcp/src/metadata.ts` — the
+architecturally correct RFC 9728 location, and one the spike (Q5) flagged as
+not even shipping from the AS-side package.
+
+## Options considered
+
+**A. `mcp()` plugin, co-locate the `/mcp` transport in the API worker.**
+The plugin's happy path. Rejected: it forces the MCP transport, its Durable
+Object, and its scaling/deploy story into the API worker. That is a large blast
+radius for the connector work, abandons the independent `packrat-mcp` deploy +
+custom domain + runbook, and still leaves us fighting the deprecated OIDC base
+for scope reduction and audience binding. The two-worker split predates this
+decision and constrains it.
+
+**B. `oidcProvider()` directly.** Same deprecated base as (A) without even the
+MCP convenience helpers. No reason to prefer it over the maintained package.
+
+**C. Keep `@cloudflare/workers-oauth-provider` on the MCP worker** (the April
+2026 plan's approach). Rejected by the May refactor: it means two parallel OAuth
+systems (every feature considered twice) plus glue code — the `/callback` role
+bridge, `trustedOrigins` repair — papering over the split. Consolidating onto
+Better Auth removes the duplication.
+
+**D. `@better-auth/oauth-provider` (AS) + standalone `verifyMcpToken` (RS).**
+Chosen. Single source of identity truth in the API worker; the RS stays a thin,
+stateless, independently-deployable JWT verifier; OAuth 2.1 / PKCE / RFC 8707 /
+DCR / refresh rotation / scope reduction all come from one maintained package.
+
+## Consequences
+
+**Positive**
+- One identity system. Passkeys, MFA, social providers, and scope/rate-limit
+ policy are configured once, in the API worker.
+- The RS is stateless and cheap to reason about: JWKS in, allow/deny out, no DB.
+- Token-verification failure semantics (never-throw, stale-`kid` retry) are
+ owned by us where the Claude discovery loop needs them.
+- The two workers deploy, scale, and roll back independently.
+
+**Negative / costs**
+- We hand-maintain `verifyMcpToken` and `buildResourceMetadata` instead of
+ inheriting them from a plugin — covered by unit tests in
+ `packages/mcp/src/__tests__`.
+- Cross-origin discovery (RFC 9728 → RFC 8414) is inherently more moving parts
+ than single-origin; the `issuer`/`aud` values must stay pinned and aligned.
+ Mitigated by the canonical-URL pinning in `metadata.ts` and the R-series dev
+ verification in the runbook.
+- We carry a hard dependency on Claude sending the `resource` parameter (else it
+ receives an opaque token the RS can't verify). Guarded by a regression test
+ and called out in the runbook.
+
+## When we would revisit
+
+- If the MCP transport were ever folded into the API worker (single-origin),
+ `mcp()` + `withMcpAuth` would become the natural fit and this ADR should be
+ re-litigated.
+- If `@better-auth/oauth-provider` were deprecated in favour of a unified core
+ plugin that supports `validAudiences`, consent-time scope reduction, and a
+ stateless RS verification helper.
+- If JWKS-rotation latency became an operational problem, the per-isolate SWR
+ cache decision (deferred cross-isolate caching, spike SEC-005) would be the
+ thing to change — independent of the plugin choice here.
diff --git a/docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md b/docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md
new file mode 100644
index 0000000000..ad1fdc1cd2
--- /dev/null
+++ b/docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md
@@ -0,0 +1,95 @@
+# Pre-flight spike: `@better-auth/oauth-provider@1.6.11` empirical findings
+
+Date: 2026-05-25
+Spike location: `/tmp/bao-spike` (throwaway, not committed)
+Purpose: verify the six API-contract claims + the load-bearing scope-reduction question before committing to the 9-unit consolidation plan (`docs/plans/2026-05-25-001-refactor-mcp-auth-onto-better-auth-plan.md`).
+
+## Result: plan is implementable; D1 has a clean native answer
+
+Every empirical question resolved positively except `customAccessTokenClaims` for scope reduction (already known broken; native alternative confirmed).
+
+---
+
+## Findings by question
+
+### Q1. Can `customAccessTokenClaims` reduce granted scopes?
+**No.** Confirmed via source inspection of `node_modules/@better-auth/oauth-provider/dist/index.mjs`:
+```js
+async function createJwtAccessToken(ctx, opts, ..., scopes, ...) {
+ const customClaims = opts.customAccessTokenClaims ? await opts.customAccessTokenClaims({user, scopes, ...}) : {};
+ return signJWT(ctx, { payload: { ...customClaims, sub: user?.id, /* scope set elsewhere */ } });
+}
+```
+The hook spreads into the payload but `scopes` is set from the granted-scope list determined upstream during consent. Returning a different `scope` key gets ignored at the token-write layer. The plugin documentation makes this explicit: *"Unlike `customAccessTokenClaims` (which adds claims inside the JWT payload), this adds fields to the JSON response envelope alongside `access_token`..."* — adds, not replaces.
+
+### Q2. What's the actual scope-reduction mechanism?
+**The `consentPage` + `/oauth2/consent` POST.** This is the clean native answer the original plan missed. From the endpoint's Zod schema:
+```js
+oauth2Consent: createAuthEndpoint("/oauth2/consent", {
+ method: "POST",
+ body: z.object({
+ accept: z.boolean(),
+ scope: z.string().optional().meta({ description: "List of accepted space-separated scopes. If none is provided, then all originally requested scopes are accepted." }),
+ oauth_query: z.string().optional()
+ }),
+ ...
+});
+```
+A custom `consentPage` can pre-filter scopes server-side (read `user.role` → strip `mcp:admin` for non-admins) and POST the reduced subset. The granted scope record + the issued JWT will only carry what's POSTed. First-class scope-reduction via UI gating.
+
+### Q3. Schema tables required
+**Four**, not three. Confirmed in `oauth-BqWgUea8.d.mts`:
+- `oauthClient` (line 8) — NOT `oauthApplication` (that's the bundled OIDC plugin's name)
+- `oauthRefreshToken` (line 141) — **was missing from the plan**; required for refresh-token rotation
+- `oauthAccessToken` (line 212)
+- `oauthConsent` (line 272)
+
+### Q4. JWT signing default
+**Default-on; opt-out via `disableJwtPlugin: true`.** No `useJWTPlugin` option exists. Critical additional finding: JWT tokens are ONLY issued when an `audience` was determined from the request's `resource` parameter AND `disableJwtPlugin !== true`:
+```js
+const audience = await checkResource(ctx, opts, scopes);
+const isJwtAccessToken = audience && !opts.disableJwtPlugin;
+```
+If a client doesn't send `resource=...` in the auth request, it gets an opaque token, not a JWT. Claude.ai MUST send `resource` per the MCP 2025-11-25 spec (RFC 8707) — verify Claude does this empirically during R11 dev verification. If it doesn't, the cross-worker JWT validation architecture breaks down (MCP would receive opaque tokens it can't verify without HTTP introspection).
+
+### Q5. Discovery metadata helpers
+**`oauthProviderAuthServerMetadata` + `oauthProviderOpenIdConfigMetadata`** — confirmed in `dist/index.d.mts`. No `oAuthDiscoveryMetadata` export exists. The PRM helper does NOT ship from this AS-side package; it lives under `@better-auth/oauth-provider/resource-client` for RS-side use, OR keep PackRat's existing `buildResourceMetadata` in `packages/mcp/src/metadata.ts` (architecturally correct location per RFC 9728).
+
+### Q6. RFC 8707 audience binding
+**Enforced via `validAudiences` option.** `checkResource` rejects with 400 `invalid_request` if the requested resource isn't in the `validAudiences` set. The plan's `validAudiences: ['https://mcp.packratai.com/mcp']` will block any token mint for a different audience.
+
+### Q7. `trustedClients` option
+**Does NOT exist.** Only `cachedTrustedClients?: Set` (a cache marker, not a registration mechanism). Pre-registration happens via `auth.api.createOAuthClient(...)` → DB write to `oauthClient` table. Plan needs a seed script (analog to the deleted `register-claude-clients.ts`), NOT a config array.
+
+### Q8. `clientPrivileges` hook
+**Unrelated to scope grants.** Despite the suggestive name, the action enum is `"create" | "read" | "update" | "delete" | "list" | "rotate"` — CRUD operations on OAuth client records, not scope authorization. Don't confuse with a scope-policy hook.
+
+### Q9. Schema field names
+**`redirectUris` in the schema, `redirect_uris` on the wire.** Both correct depending on layer (TypeScript camelCase vs RFC 7591 snake_case). Plan used `redirectUrls` (with L) — wrong everywhere.
+
+---
+
+## Implications for the plan
+
+| Decision | Spike resolution |
+| --- | --- |
+| **D1** (admin gating) | Build custom `consentPage` that POSTs filtered `scope` to `/oauth2/consent` for non-admin users. Resource-server re-check on `mcp:admin` calls stays as defense-in-depth. **This collapses D1 + D4** — the consentPage is both branded AND scope-filtering in one. |
+| **D2** (pre-flight spike) | Done. Every empirical question resolved. |
+| **D3** (parallel mounting) | Clean cutover is fine. Spike de-risked the load-bearing unknowns. |
+| **D4** (branded consent) | Folds into D1. The consentPage we write for scope-filtering is the branded surface. |
+| **D5** (audience mismatch) | Defer to U2 with three concrete options. Spike confirmed `validAudiences` is strictly enforced — so option (a) "loosen API audience" requires explicit `validAudiences` extension to include `api.packrat.world`. |
+
+## Plan amendments needed
+
+1. R5 + Key Technical Decisions: replace "RS re-check primary" with "custom `consentPage` is primary mechanism; RS re-check is defense-in-depth backstop"
+2. U1: add `consentPage: '/oauth/consent'` to plugin config; add a new file `packages/api/src/auth/consent-page.ts` (or wherever the route lives) that renders the branded consent UI with server-side scope filtering
+3. Lift "branded consent UI" from Future Considerations to in-scope (it's now an explicit U1 deliverable that solves D1)
+4. R2 + U1: document that Claude.ai MUST send `resource` parameter for JWT tokens to be issued (MCP spec requires this anyway); add R11 verification step to confirm
+5. U1 scope-rejection test: assert that a request without `resource` parameter receives opaque token, not JWT (regression guard)
+
+## What still needs runtime testing
+
+Not blocking-blocking, but should land in U1's test scenarios:
+- Verify that after a `consentPage` POST with `scope: 'mcp:read mcp:write'` (no `mcp:admin`), the issued JWT's `scope` claim is exactly `'mcp:read mcp:write'`
+- Verify that Better Auth's `/oauth2/consent` requires authenticated session (CSRF via session cookie binding)
+- Verify default consent screen behavior when no `consentPage` is configured (fallback / what does Anthropic see?)
diff --git a/docs/mcp/runbook.md b/docs/mcp/runbook.md
new file mode 100644
index 0000000000..c5ad80a575
--- /dev/null
+++ b/docs/mcp/runbook.md
@@ -0,0 +1,1767 @@
+# PackRat MCP — operator runbook
+
+Operational reference for deploying and maintaining `packages/mcp` (the
+PackRat MCP Worker). User-facing docs are at
+[packratai.com/mcp](https://packratai.com/mcp); this doc is for whoever
+operates the Worker.
+
+> **Status: in progress.** Sections are filled in as their corresponding
+> implementation units land. Anything marked `TODO (operator)` is an action
+> a human with Cloudflare access has to perform — not something the code can
+> automate.
+
+## Domains & environments
+
+| Env | Worker name | URL | Branch trigger |
+| ---- | ------------------ | ------------------------------------ | -------------- |
+| prod | `packrat-mcp` | `https://mcp.packratai.com` | tag push (U17) |
+| dev | `packrat-mcp-dev` | `https://packrat-mcp-dev..workers.dev` | manual (`bun run deploy:dev`) |
+
+## Post-refactor: AS lives on api.packrat.world
+
+As of the 2026-05-25 OAuth consolidation refactor, the MCP worker is a
+**pure protected resource**. It no longer runs its own authorization
+server, no longer issues tokens, no longer brokers DCR or login. All of
+that lives on `api.packrat.world` via the `@better-auth/oauth-provider`
+plugin (U1 of the refactor plan).
+
+### Architecture overview
+
+| Component | Lives on | Owned by |
+| ------------------------------- | -------------------- | ---------------------------------------------- |
+| Authorization server (AS) | `api.packrat.world` | `@better-auth/oauth-provider` plugin |
+| Consent / login UI | `api.packrat.world` | `consent-page.ts` (U1 of the refactor) |
+| OAuth clients / grants / tokens | `api.packrat.world` | Better Auth tables in Postgres + `AUTH_KV` |
+| JWKS | `api.packrat.world` | Better Auth (`/api/auth/jwks`) |
+| Protected resource (MCP) | `mcp.packratai.com` | This worker — validates JWTs only |
+| MCP tool / resource surface | `mcp.packratai.com` | This worker — unchanged from U7–U16 |
+
+The MCP worker validates incoming JWTs via `verifyMcpToken`
+(`packages/mcp/src/token-verify.ts`), which fetches and caches the
+JWKS from `${PACKRAT_API_URL}/api/auth/jwks`.
+
+### Discovery chain
+
+When Claude.ai connects to the MCP for the first time:
+
+1. Claude POSTs to `https://mcp.packratai.com/mcp` with no Authorization.
+2. MCP returns 401 with
+ `WWW-Authenticate: Bearer resource_metadata="https://mcp.packratai.com/.well-known/oauth-protected-resource"`.
+3. Claude fetches the PRM document, which advertises
+ `authorization_servers: ["https://api.packrat.world"]`.
+4. Claude fetches
+ `https://api.packrat.world/.well-known/oauth-authorization-server`
+ to discover the AS endpoints (Better Auth's plugin serves this).
+5. Claude runs the OAuth flow entirely against `api.packrat.world`:
+ `/api/auth/oauth/authorize` → consent page → `/api/auth/oauth/token`.
+6. Claude receives the issued bearer (a JWT signed by Better Auth) and
+ redirects back to `https://claude.ai/api/mcp/auth_callback`.
+7. Claude retries the MCP request with `Authorization: Bearer `;
+ the MCP worker validates the JWT locally (JWKS cache hit after the
+ first request per isolate) and dispatches the tool call.
+
+References:
+
+- [Refactor plan](../plans/2026-05-25-001-refactor-mcp-auth-onto-better-auth-plan.md)
+ for the architectural decision, requirements, rollout strategy, and
+ alternatives considered.
+- [Spike doc](./better-auth-oauth-provider-spike-2026-05-25.md) for the
+ empirical verification that `@better-auth/oauth-provider` carries
+ the MCP integration end-to-end.
+
+### Operator note: force isolate rotation after the deploy
+
+Better Auth is memoized in a per-isolate singleton on the API side
+(`authCache` in `packages/api/src/auth/index.ts`). The MCP worker has
+its own per-isolate JWKS cache. After the refactor deploy, existing
+isolates on both workers will keep their old config until they rotate.
+Force a rotation by bumping a benign env var on each worker so the new
+plugin config / JWKS endpoint is picked up immediately rather than
+waiting on natural isolate churn. See § "Forcing isolate rotation
+after a deploy" further down for the pattern.
+
+## One-time operator setup
+
+These steps are required before `wrangler deploy --env prod` can succeed.
+They live outside the codebase because they touch Cloudflare account state.
+
+### 1. ~~Remove leftover `OAUTH_KV` namespaces + DCR secret~~ — nothing to do (verified)
+
+**Verified 2026-05-31 against the `packratai.com` Cloudflare account — there is
+nothing to clean up.** The MCP connector has never been deployed to any
+environment:
+
+- KV namespaces `0ac2e23b…` (prod) / `be554ba7…` (dev) **do not exist** — they
+ were never created (the `development` `wrangler.jsonc` still carries
+ `__TODO_OAUTH_KV_*_ID__` placeholders). The only KV in the account is
+ `AUTH_KV` / `AUTH_KV_preview` — the **current** Better Auth namespaces used by
+ the API worker. **Do not delete those.**
+- Workers `packrat-mcp` / `packrat-mcp-dev` **do not exist** (`wrangler` →
+ "Worker not found"), so no `MCP_INITIAL_ACCESS_TOKEN` secret exists either.
+
+The IDs that appear elsewhere in the plan/runbook are notional — recorded in the
+plan, never provisioned. The first MCP deploy will be a **net-new first deploy**
+(the U17 workflow creates the workers on first tag), not a migration off
+anything. No pre-deploy cleanup step is required.
+
+No equivalent provisioning step exists anymore: Better Auth's OAuth
+provider on `api.packrat.world` owns all client / grant / token state in
+the API's Postgres + `AUTH_KV`. Pre-registered Claude clients are seeded
+once via `cd packages/api && bun run db:seed:oauth-clients` (script:
+`packages/api/src/db/seed-claude-oauth-client.ts`) — see § "Post-refactor:
+AS lives on api.packrat.world" below for the architecture overview.
+
+### 2. Provision the `mcp.packratai.com` custom domain
+
+In the Cloudflare dashboard, on the `packratai.com` zone:
+
+1. Workers & Pages → `packrat-mcp` → Settings → Domains & Routes → Add → Custom Domain
+2. Enter `mcp.packratai.com`
+3. Cloudflare will provision the certificate automatically; allow up to 15 minutes
+4. The `routes` block in `packages/mcp/wrangler.jsonc` references this
+ already, but the domain has to exist on the zone before
+ `wrangler deploy --env prod` will succeed against it
+
+### 3. Set secrets per environment
+
+```bash
+# Required for both prod and dev
+wrangler secret put PACKRAT_API_URL --env prod
+# value: https://api.packrat.world (the AS host — used by token-verify.ts
+# to fetch JWKS at ${PACKRAT_API_URL}/api/auth/jwks)
+
+# Optional (used by U15)
+wrangler secret put SENTRY_DSN --env prod
+```
+
+Repeat for `--env dev` with dev values.
+
+Pre-registration of Claude as an OAuth client now happens on the API side
+once via `cd packages/api && bun run db:seed:oauth-clients` (script:
+`packages/api/src/db/seed-claude-oauth-client.ts`) — see U1 of the refactor
+plan and § "Post-refactor: AS lives on api.packrat.world" below.
+
+### 4. Migrate API env-var names: `BETTER_AUTH_*` → `PACKRAT_*` (2026-05-25)
+
+The API package was renamed off framework-specific env-var names so the
+backend secrets carry a `PACKRAT_*` namespace consistent with the rest of
+the monorepo (MCP and CLI already used `PACKRAT_API_URL`):
+
+| Legacy name (accepted as fallback) | New canonical name |
+|---|---|
+| `BETTER_AUTH_SECRET` | `PACKRAT_AUTH_SECRET` |
+| `BETTER_AUTH_URL` | `PACKRAT_API_URL` |
+
+The zod schema in `packages/api/src/utils/env-validation.ts` accepts BOTH
+names during the rolling migration — set EITHER one in each pair and the
+canonical `PACKRAT_*` field is resolved at validation time. Consumer code
+reads `env.PACKRAT_AUTH_SECRET` / `env.PACKRAT_API_URL` only.
+
+**Operator migration steps (per environment — `--env prod` first, then
+`--env dev`):**
+
+```bash
+# 1) Add the new-name secrets with the SAME VALUES as today. CF Worker
+# secrets are write-only — you cannot read back the current value via
+# `wrangler secret`. Either pull from your password manager / 1Password,
+# OR rotate to a fresh value and accept that every Better Auth session +
+# every HS256 admin JWT is invalidated (users + admins must re-login
+# once; no data loss). The URL value is non-secret: `https://api.packrat.world`
+# in prod, `http://localhost:8787` in dev.
+
+wrangler secret put PACKRAT_AUTH_SECRET --env prod # value: current BETTER_AUTH_SECRET, or fresh random
+wrangler secret put PACKRAT_API_URL --env prod # value: https://api.packrat.world
+
+# 2) Deploy the API. The transitional schema now reads PACKRAT_* first,
+# falling back to BETTER_AUTH_* if PACKRAT_* is missing — both code
+# paths are exercised here, so no downtime.
+
+# 3) Verify the API came up cleanly (no zod validation errors in
+# `wrangler tail --env prod`, /api/health returns 200).
+
+# 4) Once you've verified, delete the legacy secrets:
+wrangler secret delete BETTER_AUTH_SECRET --env prod
+wrangler secret delete BETTER_AUTH_URL --env prod
+```
+
+**A follow-up PR will remove the `BETTER_AUTH_*` schema fallback.** Until
+that PR ships, you can leave the legacy secrets in place or delete them
+per step 4. The schema accepts either configuration.
+
+**Why this matters:** `PACKRAT_AUTH_SECRET` signs both Better Auth sessions
+AND the legacy HS256 admin JWTs used by `apps/admin`. Keep the VALUE
+identical across the rename — rotating the value would invalidate every
+existing admin token. The rename is name-only; the bytes stay the same.
+
+## U5 admin scope model
+
+The MCP Worker advertises three coarse-grained OAuth scopes (see
+`packages/mcp/src/scopes.ts` and `metadata.ts`):
+
+| Scope | Visible tools |
+| ----- | ------------- |
+| `mcp:read` | read tools only (`packrat_get_*`, `packrat_list_*`, `packrat_search_*`, `packrat_find_*`, `packrat_extract_*`, `packrat_preview_*`, `packrat_whoami`) |
+| `mcp:write` | read + write tools (everything not classified `admin`) |
+| `mcp:admin` | read + write + every `packrat_admin_*` tool + the four explicit overrides `packrat_execute_sql_query` / `packrat_get_database_schema` / `packrat_generate_pack_template_from_url` / `packrat_create_app_pack_template` (the last two added in U7) |
+
+`mcp:admin` is granted ONLY when:
+
+1. The client requested `mcp:admin` in `/authorize`, AND
+2. The authenticated user's Better Auth session resolves to
+ `user.role === 'ADMIN'` at `/callback` time.
+
+A non-admin user who requests `mcp:admin` does not receive it — the
+authorization completes successfully but the granted-scope set is
+stripped of `mcp:admin`. Per RFC 6749 §3.3 the granted scope must be a
+subset of the requested scope, so a client that didn't request
+`mcp:admin` will never receive it even for an admin user.
+
+### Per-grant role lookup, fail-closed
+
+The role lookup at `/callback` calls Better Auth via the API
+(`/api/auth/get-session`) with a **5-second** `AbortSignal.timeout`.
+Any failure path — timeout, non-2xx response, malformed body,
+network error, role !== ADMIN — drops the request to "non-admin"
+scope set. This keeps the OAuth flow usable for read/write users
+during Better Auth degradation; admin scope is only granted on an
+unambiguous positive role check.
+
+The lookup is NOT cached across `/callback` invocations: every
+authorization re-checks the role, so a user whose admin role was
+revoked between sessions cannot keep getting `mcp:admin` on the
+next grant.
+
+### Contrast: removed parallel admin path
+
+U5 deleted the prior `admin_login` MCP tool and the
+`X-PackRat-Admin-Token` request header. Admins no longer need to
+perform a runtime tool-mediated handshake to access admin tools;
+they re-authorize the MCP client with `mcp:admin` in the requested
+scope set and the scope is granted automatically if their Better
+Auth role permits it.
+
+On the API side (`packages/api/src/routes/admin/index.ts`), the
+`adminAuthGuard` was extended to accept Better Auth session bearers
+whose `user.role === 'ADMIN'` in addition to the legacy HS256
+`packrat-admin` JWT. The HS256 path is retained for back-compat
+with `apps/admin`. See the security note in that file's docstring:
+accepting Better Auth bearers means a stolen admin session is now
+also a path to `/admin/*`. This is the intended trade-off — admin
+session theft has always been catastrophic, and consolidating on a
+single revocation surface (the Better Auth session table) is the
+simplification the change buys.
+
+### U5 consumer audit
+
+Grep audit (2026-05-22) across `apps/`, `packages/`, `docs/`,
+`scripts/`, `.github/workflows/`, `README*` for the removed
+identifiers:
+
+| Identifier | Hits outside `docs/plans/` | Resolution |
+| ---------- | -------------------------- | ---------- |
+| `X-PackRat-Admin-Token` | **0** | Header was MCP-internal; no consumer ever shipped. |
+| `admin_login` (MCP tool name) | 1 in `packages/mcp/src/tools/auth.ts` (historical-context comment) + 1 in `packages/mcp/src/tools/packTemplates.ts` (live tool description) | Comment retained as removal documentation. The tool description was updated to reference `mcp:admin` scope. |
+| `admin/login` (API route) | 1 in `apps/admin/app/login/page.tsx` | Unrelated — this is the API `POST /admin/login` HS256-JWT path used by the admin SPA. Path A of the dual-mechanism guard preserves it. |
+| `adminToken` / `getAdminToken` | 0 in `packages/mcp/` | Field removed from `Props`; client factory no longer takes the parameter. |
+
+No active consumer outside `apps/admin` (which uses the preserved
+HS256 path) was affected by the U5 removal.
+
+## Better Auth trustedOrigins (U6)
+
+The MCP Worker calls Better Auth (in `packages/api`) for password sign-in
+during the OAuth flow. Better Auth rejects calls whose `Origin` is not on
+its `trustedOrigins` list — so `https://mcp.packratai.com` must appear in
+that list, or every MCP-driven sign-in will fail with an untrusted-origin
+error.
+
+> U5 also depends on this: the role lookup at `/callback` calls
+> `/api/auth/get-session`, which Better Auth gates on the same
+> `trustedOrigins` list. If the MCP host is missing from
+> `trustedOrigins`, admin scope grants will fail closed (correctly —
+> the role check fails — but for the wrong reason).
+
+`trustedOrigins` is configured in **two files that drift independently**:
+
+| File | Purpose | Line |
+| ---- | ------- | ---- |
+| `packages/api/src/auth/index.ts` | Runtime (per-isolate) config | search `trustedOrigins:` |
+| `packages/api/src/auth/auth.config.ts` | CLI / `bunx auth generate` static config | search `trustedOrigins:` |
+
+Both must include `https://mcp.packratai.com`. If you edit one, edit the
+other in the same commit. The factory pattern that splits them is
+documented in
+[`docs/solutions/developer-experience/better-auth-cli-cloudflare-worker-factory-2026-05-02.md`](../solutions/developer-experience/better-auth-cli-cloudflare-worker-factory-2026-05-02.md).
+
+### Schema regen reminder
+
+Per the same learning doc, after editing `auth.config.ts` you should run:
+
+```bash
+cd packages/api
+bunx auth generate --config src/auth/auth.config.ts
+```
+
+to keep the generated schema in sync. The U6 change only touches
+`trustedOrigins` — which is not a schema-affecting field — so a regen is
+not required to ship U6. Run it on the next deploy that does touch a
+schema-affecting field (an `additionalFields` change, a new plugin, etc.).
+
+### Forcing isolate rotation after a deploy
+
+Better Auth is memoized in a per-isolate singleton (`authCache` in
+`packages/api/src/auth/index.ts`). Existing isolates already running when
+a deploy lands will keep the old `trustedOrigins` list until they're
+rotated. Force a rotation by deploying a no-op env change (e.g. bumping
+a benign var) so MCP sign-ins start succeeding immediately rather than
+waiting on natural isolate churn.
+
+## CORS allowlist on /.well-known/oauth-protected-resource (U6)
+
+Post-refactor, the MCP worker only serves the **protected-resource**
+metadata endpoint at `/.well-known/oauth-protected-resource`. The
+authorization-server metadata (`/.well-known/oauth-authorization-server`)
+now lives on `api.packrat.world` because the AS itself runs there.
+
+The PRM endpoint accepts cross-origin GET and OPTIONS requests **only**
+from:
+
+- `https://claude.ai`
+- `https://claude.com`
+
+Everything else gets the response unmodified (default-deny). The
+allowlist + GET annotation + OPTIONS short-circuit all live in
+`packages/mcp/src/cors.ts` (`applyCorsHeaders`), invoked by the outer
+fetch wrapper in `index.ts`.
+
+If Anthropic adds new origins (e.g. a future Claude domain), update the
+`WELL_KNOWN_ALLOWED_ORIGINS` set in `cors.ts` and the corresponding test
+in `__tests__/auth.test.ts`.
+
+## U7 tool surface
+
+### `packrat_*` namespace
+
+Every user-callable MCP tool is namespaced with the `packrat_` prefix. This
+prevents collisions when a user installs multiple connectors in Claude
+(e.g. another connector also exposing a `get_pack` tool would clash without
+the prefix). Admin tools keep the legacy `admin_` prefix on top of the
+namespace, so they read as `packrat_admin_*`.
+
+There are no backwards-compatible aliases — the v1 connector-store
+listing breaks pre-rename tool names by design. The scope classifier in
+`packages/mcp/src/scopes.ts` accepts both shapes (`admin_*` and
+`packrat_admin_*`) so the U5 gating contract doesn't depend on U7 having
+shipped, but the live surface only emits the prefixed form.
+
+### Annotation policy — every flag set explicitly
+
+Every tool registration sets `title`, `readOnlyHint`, `idempotentHint`,
+and `openWorldHint` on the `annotations` object. Write tools (anything
+with `readOnlyHint: false`) additionally set `destructiveHint`.
+
+We do **not** rely on SDK defaults. The MCP SDK's `destructiveHint`
+default is `true`, which forces a confirmation prompt on every tool
+call — including reads — if `readOnlyHint` is also unset. The catalog
+test in `packages/mcp/src/__tests__/annotations.test.ts` fails the
+build if any tool ships without explicit values for every annotation.
+
+Classification rules (codified in the catalog test):
+
+| Pattern | `readOnlyHint` | `destructiveHint` | `openWorldHint` |
+| --- | --- | --- | --- |
+| `packrat_get_*` / `packrat_list_*` / `packrat_search_*` / `packrat_whoami` | true | (unset) | false for internal data; true for `packrat_web_search`, `packrat_get_weather`, `packrat_extract_url_content`, `packrat_preview_alltrails_url`, `packrat_search_weather_*`, etc. |
+| `packrat_create_*` / `packrat_update_*` / `packrat_submit_*` / `packrat_record_*` / `packrat_add_*` | false | false (additive) | false |
+| `packrat_delete_*` / `packrat_remove_*` / `packrat_admin_hard_delete_*` / `packrat_admin_delete_*` | false | true | false |
+| `packrat_toggle_*` | false | false (additive — flips state) | false |
+| `packrat_analyze_*` / `packrat_identify_*` / `packrat_analyze_pack_image` | false | false | false |
+| `packrat_generate_pack_template_from_url` | false | false | true (reaches TikTok/YouTube) |
+
+### Split tools
+
+The pre-rename `create_pack_template` accepted an `is_app_template`
+boolean that switched between user-level and admin-only behaviour. Per
+the U7 plan's "Key Technical Decisions" and the security-lens
+doc-review finding, U7 split this into two tools so a single boolean
+parameter never decides between safe and unsafe operations:
+
+| New tool | Behaviour | Visibility |
+| --- | --- | --- |
+| `packrat_create_pack_template` | `is_app_template` forced to `false`. Creates a personal template visible only to the signed-in user. | All write+admin scopes (`mcp:write`, `mcp:admin`). |
+| `packrat_create_app_pack_template` | `is_app_template` forced to `true`. Creates a curated app template visible to all users. | `mcp:admin` only — listed in `EXPLICIT_ADMIN` in `scopes.ts`. |
+
+### `EXPLICIT_ADMIN` overrides — U7 additions
+
+The `ADMIN_OVERRIDES` set in `packages/mcp/src/scopes.ts` lists tool
+names whose prefix doesn't match the admin convention but whose blast
+radius warrants admin-only visibility. U7 added two new entries on top
+of the existing two D3-finding overrides:
+
+| Tool | Why explicit-admin |
+| --- | --- |
+| `packrat_execute_sql_query` (carry-over from U5 / D3) | Raw DB SELECT access — over-grant risk. |
+| `packrat_get_database_schema` (carry-over from U5 / D3) | Exposes the DB shape; admin-only data leakage prevention. |
+| `packrat_generate_pack_template_from_url` (U7) | API enforces admin on `user.role`; MCP hides it from non-admin sessions so `tools/list` matches what the user can actually call. |
+| `packrat_create_app_pack_template` (U7) | Admin variant of the split create-template tool; the `admin_` prefix isn't in the name (would otherwise read as "admin: create"), so the override is the only gate. |
+
+Each override is listed twice in `ADMIN_OVERRIDES` — once without the
+`packrat_` prefix and once with — so the classifier handles both
+pre- and post-U7 naming and the override semantics survive a future
+naming refactor.
+
+## U8 output envelopes
+
+### Error envelope convention
+
+Every recoverable tool failure flows through `errResponse(code, message, retryable)`
+in `packages/mcp/src/client.ts` and surfaces as:
+
+```jsonc
+{
+ "isError": true,
+ "content": [{ "type": "text", "text": "" }],
+ "structuredContent": {
+ "error": {
+ "code": "api_error" | "network_error" | "unauthorized" | "forbidden" |
+ "not_found" | "conflict" | "validation_error" | "rate_limited" |
+ "tool_error",
+ "message": "",
+ "retryable": true | false
+ }
+ }
+}
+```
+
+`call()` maps API responses to codes deterministically:
+
+| Origin | `code` | `retryable` |
+| -------------------------- | ------------------- | ----------- |
+| Thrown / network error | `network_error` | true |
+| HTTP 401 | `unauthorized` | false |
+| HTTP 403 | `forbidden` | false |
+| HTTP 404 | `not_found` | false |
+| HTTP 409 | `conflict` | false |
+| HTTP 422 | `validation_error` | false |
+| HTTP 429 | `rate_limited` | true |
+| HTTP 5xx | `api_error` | true |
+| Other non-success | `api_error` | false |
+
+Protocol violations — unknown method, malformed JSON-RPC params, bad
+argument types — are reserved for the SDK to surface as JSON-RPC errors
+(`-32602`, `-32600`, etc.). Tool handlers must never throw to signal a
+recoverable failure; throw is for "the model gave us something we can't
+parse at all". `call()` catches inside-handler throws and converts them
+to `network_error` to make the asymmetry safe.
+
+### 150 000-char response cap + truncation
+
+Per Anthropic's connector-store documentation, Claude.ai and Claude
+Desktop truncate tool results at ~150 000 characters. We truncate
+server-side so we control the marker text and don't waste bandwidth:
+
+- The cap is `RESPONSE_SIZE_LIMIT_CHARS = 150_000` in `client.ts`.
+- `ok()` runs every payload through `truncateForResponse` before
+ formatting. If `JSON.stringify(data, null, 2).length` exceeds the cap,
+ the text content is sliced to fit and a `\n[truncated: response
+ exceeded 150k chars]` marker is appended.
+- On truncation we **drop `structuredContent`** even when the caller
+ opted in — the truncated text is no longer valid JSON, so emitting it
+ as `structuredContent` would fail the SDK's outputSchema validation.
+- Truncation is **not** flagged as `isError: true` — it's a response-
+ shape concern, not a failure. The marker is sufficient for the model
+ to detect the cutoff and request a narrower scope on its next turn.
+
+### Pagination clamp + cursor convention
+
+List-style tools that previously advertised `limit ≤ 200` now clamp to
+`PAGINATION_LIMIT_MAX = 50` server-side. The clamp is **silent**:
+caller-supplied `limit > 50` is rounded down without erroring, so a
+model that ignores the published cap still gets a successful response
+on a recoverable mistake.
+
+| Tool | Pagination cursor surface |
+| ------------------------------------------ | ------------------------- |
+| `packrat_list_packs` (U8) | MCP envelope `{ data, nextOffset }`; `nextOffset` is null at end of list. |
+| `packrat_list_trips` (U8) | Same MCP envelope. |
+| `packrat_admin_list_users` | API native `{ data, total, limit, offset }`; walk via next `offset`. |
+| `packrat_admin_list_packs` | Same as above. |
+| `packrat_admin_list_catalog` | Same as above. |
+| `packrat_admin_list_trail_condition_reports` | Same as above. |
+| `packrat_admin_search_trails` | API native `{ trails, hasMore, offset, limit }`. |
+| `packrat_search_gear_catalog` | API native `page`-based pagination; `limit` clamped. |
+| `packrat_admin_analytics_top_brands` | `limit` clamped. |
+| `packrat_admin_analytics_etl_jobs` | `limit` clamped. |
+| `packrat_admin_analytics_etl_failure_summary` | `limit` clamped. |
+| `packrat_admin_analytics_etl_job_failures` | `limit` clamped. |
+
+The `withNextOffset` helper in `client.ts` is the canonical
+no-cursor-from-API fallback: it returns
+`{ data: items, nextOffset: items.length >= limit ? offset + items.length : null }`
+so the model always sees the same shape regardless of which list tool
+it called.
+
+### Structured output (Tier 1)
+
+The MCP spec 2025-06-18 allows tools to declare an `outputSchema` and
+emit `structuredContent` alongside the text content block. Clients that
+adopt the new shape (Claude Code, future Claude.ai versions) can
+consume the structured payload directly; clients that don't still see
+the JSON-stringified text fallback. The SDK validates emitted
+`structuredContent` against the declared schema before send — a schema
+mismatch is a runtime error, not a silent shape drift.
+
+Tier 1 (shipped in U8 — these tools declare an `outputSchema` and call
+`ok(..., { structured: true })` or `call(..., { structured: true })`):
+
+| Tool | Schema |
+| --- | --- |
+| `packrat_whoami` | `WhoAmIOutputSchema` (`{ success?, user }`) |
+| `packrat_get_pack` | `PackWithItemsSchema` |
+| `packrat_list_packs` | `{ data: Pack[], nextOffset }` |
+| `packrat_get_trip` | `TripSchema` |
+| `packrat_list_trips` | `{ data: Trip[], nextOffset }` |
+| `packrat_get_weather` | `GetWeatherOutputSchema` (WeatherAPI passthrough) |
+| `packrat_admin_stats` | `AdminStatsSchema` |
+| `packrat_admin_analytics_active_users` | `ActiveUsersSchema` |
+| `packrat_admin_analytics_catalog_overview` | `CatalogOverviewSchema` |
+| `packrat_admin_analytics_growth` | `z.array(GrowthPointSchema)` (declared) |
+| `packrat_admin_analytics_activity` | `z.array(ActivityPointSchema)` (declared) |
+| `packrat_admin_analytics_pack_breakdown` | `z.array(BreakdownItemSchema)` (declared) |
+
+Schemas live in `packages/mcp/src/output-schemas.ts`. They re-use
+`@packrat/schemas` wherever a response shape is already modeled in the
+API contract — single source of truth. Tests in
+`packages/mcp/src/__tests__/output-schemas.test.ts` round-trip every
+schema and assert each Tier 1 tool's `_registeredTools` entry carries
+an `outputSchema` value.
+
+### Tier 2 deferral (follow-up unit)
+
+The remaining read tools emit text-only output today. Their API
+response shapes either aren't modeled in `@packrat/schemas` yet or
+require non-trivial derivation from Eden Treaty's inferred types.
+Lifting them to Tier 1 is a follow-up unit; the catalogue test still
+asserts the annotation invariants on all of these so the surface
+doesn't drift in the meantime.
+
+Tier 2 categories (representative — not exhaustive):
+
+- All `packs.items.*` mutations and the bare `*_items` reads
+ (`packrat_get_pack_item`, `packrat_list_pack_items`).
+- Catalog read paths beyond `packrat_search_gear_catalog`
+ (`packrat_get_catalog_item`, `packrat_similar_catalog_items`,
+ `packrat_semantic_gear_search`, `packrat_compare_gear_items`,
+ `packrat_list_gear_categories`).
+- All `tools/feed.ts`, `tools/trail-conditions.ts`,
+ `tools/trails.ts`, `tools/alltrails.ts`, `tools/guides.ts`,
+ `tools/knowledge.ts`, `tools/seasons.ts`, `tools/wildlife.ts`,
+ `tools/upload.ts`, `tools/packTemplates.ts`, `tools/ai.ts`.
+- `tools/user.ts` — `packrat_get_profile`, `packrat_update_profile`
+ (overlap with `packrat_whoami` shape; can be lifted in the same
+ follow-up).
+- Admin list/get tools that aren't analytics-bucket Tier 1 above:
+ `packrat_admin_list_users`, `packrat_admin_list_packs`,
+ `packrat_admin_list_catalog`, `packrat_admin_get_trail`,
+ `packrat_admin_get_trail_geometry`,
+ `packrat_admin_list_trail_condition_reports`,
+ `packrat_admin_search_trails`,
+ `packrat_admin_analytics_catalog_prices`,
+ `packrat_admin_analytics_catalog_embeddings`.
+- `tools/weather.ts` beyond `packrat_get_weather`
+ (`packrat_search_weather_location`,
+ `packrat_search_weather_by_coordinates`,
+ `packrat_get_weather_forecast`).
+
+Tracking sketch for a follow-up:
+
+1. Inventory each Tier 2 tool's API endpoint and pull the Treaty
+ inferred response type into `output-schemas.ts`.
+2. Where Treaty loses the array element shape (the recurring pattern
+ here is admin routes whose response is declared with Elysia's
+ `t.Unsafe`), declare the schema fresh against the route's
+ underlying SQL projection.
+3. Add the schema to the Tier 1 table in this runbook; add a
+ round-trip test and a cross-check entry in `output-schemas.test.ts`.
+
+## U9 resources surface
+
+The MCP Worker exposes the following resources. Templated resources
+carry `list:` providers wherever it makes sense, so MCP clients can
+enumerate the signed-in user's data via `resources/list` rather than
+having to guess IDs.
+
+| URI | Shape | List provider | mimeType | Notes |
+| ---------------------------------- | --------- | ------------- | ------------------- | ----- |
+| `packrat://packs/{packId}` | template | yes | `application/json` | Lists user's packs (no public packs in the enumeration). |
+| `packrat://trips/{tripId}` | template | yes | `application/json` | Lists user's trips. |
+| `packrat://catalog/{itemId}` | template | yes (capped) | `application/json` | List capped at `CATALOG_LIST_CAP = 25` to avoid context-blowing on the multi-thousand-item catalog. |
+| `packrat://catalog/categories` | static | n/a | `application/json` | Pre-U9; preserved. |
+| `packrat://search?q={query}` | template | no | `application/json` | Delegates to the gear-catalog text-search endpoint. Returns up to 20 hits as JSON. No list provider (queries are inherently parameterised). |
+| `packrat://glossary` | static | n/a | `text/markdown` | Domain vocabulary (pack/trip/weight/trail/scope terms). Reviewers see this in the resource catalog; Claude reads it once early in a session. |
+
+### Why a glossary resource
+
+Reviewer-facing: Anthropic's reviewers downrank "thin connectors" that
+expose only CRUD calls. A glossary resource doubles as
+domain-knowledge documentation a reviewer can browse without leaving
+the resource catalog.
+
+Model-facing: Claude burns tool calls (and turns) re-learning that
+"base weight" excludes consumables, that an "AT thru-hiker" walks the
+Appalachian Trail, etc. A single static markdown read at session start
+shortcuts that. The glossary content lives in
+`packages/mcp/src/glossary.ts` and is exported as
+`GLOSSARY_MARKDOWN` so the resource handler stays a one-line return.
+
+### List-provider error handling (degrade, don't propagate)
+
+A thrown error inside any list callback would break the SDK's
+`resources/list` aggregator for **every** template at once. So all
+three list providers (`pack`, `trip`, `catalog_item`) wrap their
+callbacks in `safeList()` which swallows the error, logs a warning to
+`console.warn`, and returns an empty array. The catalog, glossary,
+and other resources stay readable even while one provider is degraded
+(network blip, auth race at session start, API outage).
+
+U15 will replace `console.warn` here with the structured logger; the
+contract is otherwise stable.
+
+### Catalog list cap (25)
+
+The full PackRat catalog runs to thousands of items. Listing all of
+them on every `resources/list` call would burn megabytes of context
+for marginal value. `CATALOG_LIST_CAP = 25` is one screen of resource
+entries in Claude.ai's resource browser; the model can still page
+deeper via `packrat://search?q=...` or the
+`packrat_search_gear_catalog` / `packrat_semantic_gear_search` tools.
+
+Bumping the cap is cheap (single constant in `resources.ts`); revisit
+if reviewer feedback says the initial surface is too narrow.
+
+### Error envelope on resource reads
+
+Resource read failures throw `McpError` (from
+`@modelcontextprotocol/sdk/types.js`) so the SDK converts them to
+proper JSON-RPC errors. Pre-U9, the read handlers returned errors as
+JSON content blocks with no error flag — clients couldn't tell apart
+"successful read of a JSON document that describes an error" from
+"the read itself failed". U9 fixes that:
+
+| Upstream status | JSON-RPC code |
+| --------------- | ------------------------ |
+| 4xx (404, etc.) | `-32602` (InvalidParams) |
+| 5xx / network | `-32603` (InternalError) |
+
+The `ReadResourceResult` type in MCP SDK 1.29 does NOT have an
+`isError` field (unlike `CallToolResult`), which is why the resource
+path diverges from the tool-call envelope U8 hardened — for resources
+the JSON-RPC layer carries the error, not the result body.
+
+## U10 elicitations
+
+PackRat's MCP server prompts the user via MCP `elicitation/create` before
+firing irreversible / high-blast-radius admin operations. The blast
+radius is intentionally limited — only six tools elicit, matching the
+plan's "destructive admin + ambiguous input" stance.
+
+### Gated tools and confirmation tokens
+
+| Tool | Confirmation field | Required string |
+| ------------------------------------------------- | ------------------ | ---------------- |
+| `packrat_admin_hard_delete_user` | User ID | the target user_id (verbatim) |
+| `packrat_admin_delete_pack` | Confirmation | `DELETE` |
+| `packrat_admin_delete_catalog_item` | Confirmation | `DELETE` |
+| `packrat_admin_delete_trail_condition_report` | Confirmation | `DELETE` |
+| `packrat_create_app_pack_template` | Confirmation | `PUBLISH` |
+| `packrat_generate_pack_template_from_url` | Confirmation | `GENERATE` |
+
+For `packrat_admin_hard_delete_user` we ask the operator to retype the
+user_id rather than a fixed token because the admin API has no GET-by-id
+endpoint to enrich the prompt with the username/email pre-deletion
+(`packages/api/src/routes/admin/index.ts` only exposes `/users-list` and
+the DELETE itself). Retyping the id keeps the prompt deliberate without
+introducing a fragile pre-read call. If a future API unit adds the GET
+endpoint, swap the confirmation token to the username.
+
+### agents@0.13 contract — `{ relatedRequestId }` is required
+
+The U2 dependency bump pulled `agents` to `^0.13.2`. The 0.13 release
+added a required second argument to `McpAgent.elicitInput`:
+
+```ts
+elicitInput(
+ params: { message: string; requestedSchema: unknown },
+ options?: { relatedRequestId?: RequestId },
+): Promise;
+```
+
+Without `{ relatedRequestId: extra.requestId }`, the elicitation request
+routes to a non-existent SSE stream and rejects with
+`Elicitation request timed out` after the SDK's 60-second timeout —
+silently from the user's perspective (no prompt ever appears).
+
+Both helpers in `packages/mcp/src/elicit.ts` (`confirmAction`,
+`chooseFromList`) always pass this option, sourcing `requestId` from the
+tool handler's second argument (`extra: RequestHandlerExtra`).
+`packages/mcp/src/__tests__/elicit.test.ts` asserts every call site
+passes the option, so a future helper that forgets it fails CI rather
+than failing silently in prod.
+
+### Fallback for clients without elicitation support
+
+When the connecting client (e.g. a custom MCP harness, or an older
+Claude Desktop build) never advertised the `elicitation` capability in
+its `initialize` handshake, the MCP SDK's
+`Server.assertCapabilityForMethod` throws:
+
+> `Client does not support elicitation (required for elicitation/create)`
+
+The helpers catch this exact substring (plus the agents SDK's
+`No active connections available for elicitation`, which fires when the
+SSE stream has dropped) and return `reason: 'unsupported'`. Each gated
+tool maps that into a structured error envelope:
+
+| Helper reason | `structuredContent.error.code` | `retryable` |
+| ------------- | ------------------------------ | ----------- |
+| `cancelled` | `user_cancelled` | false |
+| `mismatch` | `confirmation_mismatch` | false |
+| `timeout` | `confirmation_timeout` | true |
+| `unsupported` | `elicitation_unsupported` | false |
+
+The destructive API call is NOT fired in any of those branches. The
+tool-handler tests in `packages/mcp/src/__tests__/tools-admin.test.ts`
+assert that explicitly — the spy on the underlying Treaty endpoint sees
+zero `delete`/`post` invocations on the cancel / mismatch / unsupported
+paths.
+
+### Ambiguous-search elicitation — deferred
+
+The plan flagged `packrat_alltrails_search` as a possible candidate for
+`chooseFromList`-style disambiguation. We deferred this because:
+
+- `packrat_preview_alltrails_url` is the only alltrails tool today, and
+ it takes a single URL — there's no multi-result step where the user
+ has to pick between candidates.
+- `packrat_search_trails` already returns a list of trails plus their
+ OSM IDs, and the established pattern (`search_trails` →
+ `get_trail(osm_id)` → `get_trail_geometry(osm_id)`) puts the
+ disambiguation step squarely in front of the model + user with the
+ IDs in hand. Layering an elicitation on top would duplicate that
+ choice and add a round-trip without changing the outcome.
+
+The `chooseFromList` helper is implemented, tested, and ready to wire
+in the moment a real ambiguity surface arrives (likely a future
+trail-name fuzzy-search endpoint). This is a connector-store nice-to-
+have rather than a blocker, per the plan.
+
+### Where the helpers live
+
+`packages/mcp/src/elicit.ts` — `confirmAction`, `chooseFromList`, and
+the `ElicitCapable` / `ElicitAgent` structural types. Designed to be
+called with `(agent, extra, opts)` where `agent` is the live
+`PackRatMCP` instance (which extends `McpAgent` and inherits
+`elicitInput`) and `extra` is the second argument the SDK passes to
+every tool handler.
+
+`AgentContext.elicitInput` is optional (see `packages/mcp/src/types.ts`)
+so unit tests can construct an agent stub without standing up a Durable
+Object — both helpers short-circuit to `reason: 'unsupported'` when the
+method is missing, mirroring the live-client missing-capability path.
+
+## U12 legal pages
+
+Anthropic's Software Directory Policy treats a missing or incomplete privacy
+policy as an immediate-rejection cause. Both URLs below are reviewer-loaded
+during connector intake; the MCP `/health` JSON now references them so the
+listing surface, the worker, and the brand domain stay in lockstep.
+
+### Canonical URLs
+
+| Page | URL | Source |
+| ---- | --- | ------ |
+| Terms of Service | `https://packratai.com/terms-of-service` | `apps/landing/app/terms-of-service/page.tsx` |
+| Privacy Policy | `https://packratai.com/privacy-policy` | `apps/landing/app/privacy-policy/page.tsx` |
+
+The footer on every landing page surfaces both via
+`siteConfig.footerLinks.legal` (`apps/landing/config/site.ts`); the support
+contact (`hello@packratai.com`) is exposed via the new `siteConfig.support`
+field on the same config.
+
+### Privacy Policy — MCP addendum
+
+The Privacy Policy includes a "MCP Connector & Third-Party Clients" section
+that covers, at minimum:
+
+- OAuth refresh tokens stored at rest in Cloudflare KV (encrypted by KV); 60-
+ minute access tokens; 30-day rotating refresh tokens.
+- What MCP clients see (only the scopes the user approved) and explicit
+ callout that `mcp:admin` is restricted to PackRat admins.
+- What MCP clients do NOT see (passwords; conversation content sent to MCP
+ clients).
+- Retention: grants deleted automatically when the refresh token expires, or
+ immediately on revocation.
+- Third-party clients (e.g. Claude.ai) — their own privacy policy governs
+ their handling of PackRat data.
+- Deletion path: account settings or `hello@packratai.com`.
+
+If you add a new MCP data flow, update this section first — reviewers and
+end users will read the Privacy Policy before they read the source.
+
+### `/health` JSON references these URLs
+
+`PackRatAuthHandler` (`packages/mcp/src/auth.ts`) now emits the legal +
+support URLs from `/` and `/health`:
+
+```jsonc
+{
+ "status": "ok",
+ "service": "PackRat MCP",
+ "version": "",
+ "transport": "streamable-http",
+ "endpoint": "/mcp",
+ "docs": "https://packratai.com/mcp",
+ "terms": "https://packratai.com/terms-of-service",
+ "privacy": "https://packratai.com/privacy-policy",
+ "support": "mailto:hello@packratai.com"
+}
+```
+
+The auth.test.ts `/health` test asserts the three new fields; if you change
+either URL, update both the JSON and the test in one commit so the listing
+intake and the worker advertisement never drift.
+
+### TODO (operator): jurisdiction in the Terms of Service
+
+`apps/landing/app/terms-of-service/page.tsx` ships with a placeholder
+governing-law / venue clause (Delaware, US federal + state courts) and a
+`{/* TODO(operator): set jurisdiction */}` marker at that paragraph. Replace
+it with the chosen jurisdiction once legal review completes. The smoke test
+in `apps/landing/__tests__/legal.pages.test.ts` asserts the TODO marker is
+still present — remove that assertion in the same commit that resolves the
+TODO, so the marker can't be silently lost.
+
+## U13 listing artifacts
+
+The artifacts a Claude Connector Store reviewer interacts with — public
+docs page, brand assets, the favicon Anthropic probes for domain
+ownership, the reviewer test account — all land in U13. This section
+documents where each one lives and how to refresh it.
+
+### Public docs page
+
+URL: . Source:
+[`apps/landing/app/mcp/page.tsx`](../../apps/landing/app/mcp/page.tsx).
+The page is an RSC route in the landing site (`apps/landing`), styled
+to match the existing privacy/terms pages (same container width, same
+Tailwind tokens — no new component vocabulary).
+
+Information architecture: hero → 3-step Claude.ai quickstart → scopes
+table → 3 example prompts (read, multi-tool plan, write with
+elicitation) → tool catalog (grouped by domain) → resources →
+privacy & security → reviewer test account pointer → footer pointers
+to the dev README, plan, and this runbook. Per the doc-review D6
+finding, the catalog is **not** a flat 103-tool dump — it groups by
+domain (Packs, Trips, Trails, Gear & Catalog, Admin & Analytics, …)
+so reviewers and end-users can scan in chunks.
+
+### Catalog regen
+
+The public docs page reads its tool catalog from
+`apps/landing/data/mcp-catalog.json`. **Rerun the dump after any tool
+surface change** (new tool, rename, annotation tweak, scope
+re-classification):
+
+```bash
+bun packages/mcp/scripts/dump-catalog.ts
+```
+
+Commit the regenerated JSON in the same PR as the tool change so
+`packratai.com/mcp` stays in lockstep with the live worker. The script
+uses the same recursive-Proxy stub as the U7 annotations test
+(`packages/mcp/src/__tests__/annotations.test.ts`), so it picks up
+every tool the worker registers without needing a Cloudflare runtime.
+
+If the script exits with `dump-catalog: zero tools registered`, the
+MCP SDK's internal `_registeredTools` field shape probably changed —
+update both the dump script and the annotations test to use the new
+accessor; they walk the same field.
+
+### Brand assets
+
+| Asset | Path | Notes |
+| --- | --- | --- |
+| MCP connector mark (SVG, 256×256 viewBox) | [`apps/landing/public/mcp-logo.svg`](../../apps/landing/public/mcp-logo.svg) | Used by the public docs page and listing materials. The MCP worker itself no longer renders any branded UI (the login page lived on the worker pre-refactor; the consent page now lives on api.packrat.world — see U1 of the 2026-05-25 refactor plan). If the brand mark changes, update this SVG and the favicon in the same commit so the listing surfaces don't drift. |
+| 1024×1024 PNG fallback for the directory listing | not in repo — render from `mcp-logo.svg` at submission time | Operator action; tracked in `docs/mcp/submission-packet.md` § "Logo / favicon checklist". |
+| Favicon (32×32 .ico) at the OAuth host | served at `https://mcp.packratai.com/favicon.ico` by the worker | Implementation: [`packages/mcp/src/favicon.ts`](../../packages/mcp/src/favicon.ts) (see "Favicon at OAuth domain" below). |
+| Favicon at the brand domain | `apps/landing/public/favicon.ico` and `apps/landing/public/PackRat.ico` (legacy filename still referenced by `apps/landing/lib/metadata.ts`) | Both files exist for compat; the worker's embedded favicon is sourced from `favicon.ico`. |
+
+### Favicon at OAuth domain (Anthropic domain-ownership probe)
+
+Anthropic's domain-ownership verification probe hits
+`mcp.packratai.com/favicon.ico` — **not** the landing site at
+`packratai.com/favicon.ico`. The two domains are distinct from
+Cloudflare's perspective, so the worker has to own the route.
+
+Chosen mechanism (U13): embed the .ico as a base64 string at build
+time. `packages/mcp/src/favicon.ts` exports `faviconResponse()`
+which returns a `Response` with `Content-Type: image/x-icon`,
+`Cache-Control: public, max-age=86400, immutable`, and a fresh
+buffer per call. The route is wired up in
+`packages/mcp/src/auth.ts` (`PackRatAuthHandler.fetch` —
+`/favicon.ico` branch, immediately after `/health`).
+
+Why embedded vs. a runtime fetch to the landing site:
+- **Self-contained.** The worker has no extra binding and no
+ cross-domain hop on cold start; the probe always succeeds.
+- **Small.** ~4.2 KiB binary, ~5.7 KiB base64 — negligible bundle
+ overhead.
+- **No race on cold start.** A runtime fetch to `packratai.com`
+ during a worker boot could 502 if the landing site is in the
+ middle of a deploy; the embed avoids that failure mode entirely.
+
+Refresh contract: if the brand icon changes, copy the new file to
+`apps/landing/public/favicon.ico`, regenerate the base64 with
+`base64 -w 0 < apps/landing/public/favicon.ico`, and paste the
+result into `FAVICON_ICO_BASE64` in `packages/mcp/src/favicon.ts`.
+The favicon test (`packages/mcp/src/__tests__/favicon.test.ts`)
+asserts the `.ico` magic bytes and a non-zero size, so a
+copy-paste mistake fails CI loudly.
+
+## U14 rate limiting
+
+PackRat's MCP Worker rate-limits authenticated tool calls via a single
+Cloudflare Workers Rate Limiting binding:
+
+| Surface | Backed by | Keyed by | Default budget |
+| ------- | --------- | -------- | -------------- |
+| Authenticated tool calls | Workers Rate Limiting binding `MCP_TOOLS_RL` | `${userId}:${toolName}` | 60 calls / 60s |
+| Anonymous AS endpoints (`/authorize`, `/token`, `/register` on api.packrat.world) | **Zone-level WAF Rate Limiting Rules on the API host** (operator-applied; see TODO below) | client IP | 100 r/s/IP (target) |
+
+The binding configuration lives in
+[`packages/mcp/wrangler.jsonc`](../../packages/mcp/wrangler.jsonc) under the
+`rate_limiting` block — present in both the top-level/dev base and the
+`env.prod` and `env.dev` blocks. Block-key conventions follow
+`packages/api/wrangler.jsonc:44`: the block is `rate_limiting` (not
+`ratelimits`) and the per-binding field is `binding` (not `name`).
+
+### Binding source change, key shape unchanged
+
+Post-refactor, the **binding** (`MCP_TOOLS_RL`) and **key shape**
+(`${userId}:${toolName}`) are unchanged. What changed is the source of
+`userId`: the prior implementation read it from the OAuthProvider `props`
+object (populated by the U5 `/callback` bridge); the new implementation
+reads it from the JWT `sub` claim returned by `verifyMcpToken`. Same
+counter independence, same budget, same envelope on exceed.
+
+### Per-user/per-tool counter independence
+
+`MCP_TOOLS_RL.limit({ key: '${userId}:${toolName}' })` runs **before** every
+authenticated tool handler. The key shape makes counters independent across
+both axes:
+
+- One user spamming `packrat_get_pack` does NOT consume their own
+ `packrat_list_trips` budget.
+- Two different users both hitting `packrat_get_pack` do NOT share a
+ counter — each user gets their own 60/60s slot.
+
+On exceed, the wrapper short-circuits the handler and returns the canonical
+U8 envelope `errResponse('rate_limited', 'Rate limit exceeded; try again in
+a moment.', true)` — `retryable: true` so the model knows it can back off
+and retry. The handler itself never runs.
+
+### Dev fallback
+
+When `env.MCP_TOOLS_RL` is undefined (local `vitest`, some `wrangler dev`
+configurations), the call site returns "allowed" without consulting the
+binding. Production deploys always bind it via `wrangler.jsonc`; the
+fallback exists so onboarding engineers don't need a bound rate-limit
+namespace to run the unit suite.
+
+### Fail-open on binding error
+
+`checkRateLimit` in `packages/mcp/src/rate-limit.ts` swallows binding-side
+exceptions and returns `true`. The trade-off is documented at the call
+site: a brief over-allow window during a Cloudflare-side rate-limit-API
+hiccup is preferable to a hard outage of the MCP surface. U15
+observability lets us alert on the error volume.
+
+### KV-purge cron — removed
+
+The previous `triggers.crons: ["0 4 * * *"]` block and the
+`runScheduledPurge` handler are both gone post-refactor. The AS now lives
+on `api.packrat.world` via `@better-auth/oauth-provider`, which handles
+its own expiry / cleanup against the API's Postgres + `AUTH_KV`. No MCP
+worker-side cron is needed.
+
+### TODO (operator): zone-level WAF Rate Limiting Rules on api.packrat.world
+
+The anonymous OAuth endpoints (`/api/auth/oauth/register`,
+`/api/auth/oauth/authorize`, `/api/auth/oauth/token`) live on the API host
+now. Apply WAF Rate Limiting Rules on the `packrat.world` zone (or via
+Terraform) for that host:
+
+| Path expression | Rule | Action |
+| ------------------------------------------------------ | ----------------- | -------- |
+| `http.request.uri.path contains "/api/auth/oauth/"` | > 100 r/s per IP | Block 1m |
+
+100 r/s is generous for legitimate use: a Claude.ai user starting a fresh
+connection issues at most 3-4 requests across these endpoints. Tune
+downward after observing real traffic for a week. Add an explicit
+*allow* rule above the limits for Anthropic's IP ranges if reviewer
+probes get blocked during intake — Anthropic publishes the ranges in
+the connector-store docs.
+
+### Refreshing the binding budget
+
+The 60/60s default is configured in `wrangler.jsonc` under the
+`rate_limiting` block. To change it:
+
+1. Edit `simple.limit` and `simple.period` in the top-level, `env.prod`,
+ and `env.dev` blocks.
+2. `wrangler deploy --env prod`.
+3. Update `docs/mcp/runbook.md` (this section) so the docs match the
+ live config.
+
+Changes take effect immediately on the next request after deploy — no
+binding-side state to migrate.
+
+### Reviewer test account
+
+Credentials and the populated-data list live in
+[`docs/mcp/submission-packet.md`](./submission-packet.md) § 4. The
+file ships with `TODO (operator)` placeholders; the operator fills
+them in **only** for the form-submission session and does **not**
+commit the populated values to the repo.
+
+The public docs page at `packratai.com/mcp` deliberately tells
+reviewers the credentials are not on the public page and points
+them at the submission-packet doc (which Anthropic receives via the
+form, not via a public link).
+
+### Footer link
+
+`apps/landing/config/site.ts` adds `MCP Connector` to
+`siteConfig.footerLinks.product` so the landing site's footer
+exposes the public docs page. The landing-site smoke tests cover
+the legal links; the MCP page itself is RSC-rendered and shipped
+without a separate vitest assertion (the catalog JSON is the
+build-time contract).
+
+---
+
+## U15 observability
+
+The MCP Worker emits structured JSON logs via `console.log/warn/error`.
+Workers Logs ingests them as structured events, and a Cloudflare-dashboard
+**OTel pipeline** forwards them to Sentry's OTLP endpoint. There is NO
+in-process Sentry SDK in the worker — by design (smaller bundle, no
+SDK-version drift, no need to handle SDK initialisation in the DO
+constructor).
+
+### Operator TODO: enable the OTel → Sentry pipeline
+
+Required dashboard click-path (do once per environment, after the U1
+`SENTRY_DSN` secret is set):
+
+1. **Cloudflare dashboard** → Workers & Pages → `packrat-mcp` (or
+ `packrat-mcp-dev`).
+2. **Observability** → **Telemetry** → **Add destination** →
+ **OTLP**.
+3. Endpoint: the Sentry OTLP ingest URL for your project (find it in
+ Sentry → Settings → Projects → packrat-mcp → Client Keys (DSN) → use
+ the "OTLP" tab).
+4. Authentication: **Headers** → add `x-sentry-auth: sentry_key=` (the public key is the segment of the DSN before `@`).
+5. **Resource attributes** (recommended): `service.name=mcp`,
+ `deployment.environment=prod` (or `dev`).
+6. **Sampling**: 100% on `WARN`/`ERROR`; 5% on `INFO` (cost guardrail).
+7. Save. The pipeline activates within ~1 minute. Verify by triggering a
+ known WARN (e.g. `curl -X POST https://mcp.packratai.com/mcp` with no
+ Authorization header — this emits `mcp.auth.jwt.denied
+ reason=missing_bearer`) and watching Sentry's Issues view.
+
+The `SENTRY_DSN` secret (set as a placeholder by U1) is **not** read by
+the worker. It's surfaced in the runbook so operators have one canonical
+place to look for the DSN value when configuring the pipeline; the
+worker's logs reach Sentry exclusively via the OTLP pipeline.
+
+### Log shape
+
+Every log line is a single JSON object on one line:
+
+```json
+{
+ "ts": "2026-05-22T04:00:00.000Z",
+ "level": "info" | "warn" | "error" | "debug",
+ "msg": "human-readable message",
+ "correlationId": "ray-or-uuid-or-cron:timestamp",
+ "service": "mcp",
+ "...": "additional structured fields (allowlisted)"
+}
+```
+
+`ts` is ISO-8601 UTC. `level` is the canonical lowercase severity.
+`correlationId` and `service` are pinned on every line so Workers Logs
+filters can pivot on them without per-call instrumentation.
+
+### Correlation IDs
+
+Each inbound request receives a correlation ID at the top of the outer
+`fetch` wrapper (`packages/mcp/src/index.ts`):
+
+- Prefers the `cf-ray` header (every Cloudflare-fronted request has one,
+ and the value matches the upstream zone log so an operator can pivot
+ between Workers Logs / Sentry / the Cloudflare dashboard for the same
+ request).
+- Falls back to `crypto.randomUUID()` for off-CF tests or the rare
+ upstream-strip case.
+- Stashed on the Request via a per-request `WeakMap` so deep handlers
+ (the JWT verification path in `token-verify.ts`, the `/health`
+ handler, etc.) can read it via `getCorrelationId(request)` without
+ plumbing the id through every function signature. **Not
+ AsyncLocalStorage** — Workers ALS support is still gated behind a
+ compatibility flag we don't set.
+- Echoed on every outbound response as `X-Correlation-Id: ` so the
+ caller can quote it when reporting issues.
+
+For code paths without an inbound Request (today only the scheduled
+cron sweep), `syntheticCorrelationId('cron')` mints `cron:`.
+
+### Audit log shape
+
+Admin tool invocations emit a structured audit line via
+`audit(logger, '', { actor, target, outcome, ... })`:
+
+```json
+{
+ "ts": "...",
+ "level": "info",
+ "msg": "mcp.audit.admin_hard_delete_user",
+ "action": "admin_hard_delete_user",
+ "actor": { "userId": "...", "scopes": ["mcp:admin", "mcp:write"] },
+ "target": { "type": "user", "id": "u-42" },
+ "outcome": "success" | "failure" | "declined",
+ "error": { "code": "...", "retryable": false }, // failure / declined only
+ "correlationId": "session:",
+ "service": "mcp"
+}
+```
+
+The `mcp.audit.` prefix on `msg` is the operator-facing namespace filter
+for Sentry / Workers Logs. Six tools currently audit:
+
+- `packrat_admin_hard_delete_user`
+- `packrat_admin_delete_pack`
+- `packrat_admin_delete_catalog_item`
+- `packrat_admin_delete_trail_condition_report`
+- `packrat_create_app_pack_template` (PUBLISH gate)
+- `packrat_generate_pack_template_from_url` (GENERATE gate)
+
+`outcome: 'declined'` is used when the U10 elicitation surface returned
+`confirmed: false` — the action did not run, but the intent was made
+known to the server and is recorded with the canonical error code
+(`user_cancelled`, `confirmation_mismatch`, `confirmation_timeout`,
+`elicitation_unsupported`).
+
+### Auth-failure WARN logs
+
+The MCP worker is a pure protected resource post-refactor — token
+issuance lives on `api.packrat.world`. The remaining auth-side WARN
+surface on this worker is JWT validation:
+
+| Surface | `msg` | `reason` values |
+| -------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------- |
+| `POST /mcp` (JWT validation) | `mcp.auth.jwt.denied` | `missing_bearer`, `bad_scheme`, `invalid_token`, `expired`, `bad_audience`, `bad_issuer`, `jwks_fetch_failed` |
+
+Better Auth's OAuth-provider plugin emits its own structured errors on
+the API side (see the API package's observability surface); reviewer
+auth-failure analysis spans both workers.
+
+### Redaction policy — no tokens, no PII, default-deny field allowlist
+
+`packages/mcp/src/observability.ts` exports `scrubFields()`, which every
+log line passes through before emit. The policy is **default-deny on a
+top-level allowlist** (not a denylist):
+
+- Allowed top-level keys: `correlationId`, `service`, `ts`, `level`,
+ `msg`, `requestId`, `method`, `path`, `statusCode`, `duration`,
+ `iteration`, `iterations`, `done`, `code`, `description`, `reason`,
+ `retryable`, `oauthCode`, `oauthStatus`, `action`, `outcome`, `actor`,
+ `target`, `error`, `grantsChecked`, `grantsPurged`, `tokensChecked`,
+ `tokensPurged`, `cap`, `tool`, `toolName`.
+- `actor` allows nested `userId`, `scopes`.
+- `target` allows nested `type`, `id`.
+- `error` allows nested `code`, `message`, `retryable`.
+- **Anything else collapses to `'[redacted]'`** with the key preserved
+ (so triage can see "the caller tried to log X but it was scrubbed").
+- Functions are dropped entirely.
+
+What is **never** logged: `betterAuthToken`, `props`, OAuth `code`,
+bearer tokens, refresh tokens, passwords, email addresses, IP addresses,
+full URLs (only bounded path/origin is okay), the request/response body,
+the user's typed elicitation answer.
+
+To add a field to the allowlist, edit `TOP_LEVEL_ALLOWLIST` in
+`observability.ts`. **Every addition is a code-review event** — that's
+the property we want for telemetry hygiene.
+
+### Operator TODO: confirm Sentry routing
+
+After enabling the OTel pipeline, verify end-to-end:
+
+1. `curl -i -X POST https://mcp.packratai.com/mcp` (no Authorization).
+2. The response includes `X-Correlation-Id: ` and 401 +
+ `WWW-Authenticate: Bearer resource_metadata=...`.
+3. `wrangler tail --env prod --format pretty | grep jwt.denied`
+ shows `{"ts":...,"level":"warn","msg":"mcp.auth.jwt.denied",
+ "correlationId":"","reason":"missing_bearer",...}`.
+4. Sentry Issues view receives a matching event tagged
+ `service.name=mcp`, `correlationId=`, with the message
+ `mcp.auth.jwt.denied`.
+
+If steps 3 and 4 don't align within ~30 seconds, the OTel pipeline is
+mis-configured (most often: missing `x-sentry-auth` header or a typo
+in the OTLP endpoint).
+
+---
+
+## U16 /health + /status
+
+Two unauthenticated read-only endpoints reviewers (and uptime probes)
+hit to verify the Worker is healthy and to read its public metadata.
+
+### `/health` — real dependency probe
+
+`GET /health` (and `GET /`, which dispatches to the same handler) probes
+the single upstream dependency (the API host that also serves the AS
+metadata + JWKS) and returns 200 only when it succeeds:
+
+| Probe | Mechanism | Pass = `'ok'`, fail = `'down'` |
+| ----- | ---------------------------------------------------------- | ------------------------------- |
+| API | `fetch(env.PACKRAT_API_URL + '/health')` with 3s timeout | `res.ok` (HTTP 2xx) |
+
+The API probe hits the PackRat API's root `/health` endpoint
+(`packages/api/src/index.ts:86`), **not** `/api/health` — Elysia mounts
+the meta route at the worker root, so the canonical URL is
+`${PACKRAT_API_URL}/health`. If we ever move the API to a versioned
+path prefix, this URL needs to update in lockstep.
+
+The prior `OAUTH_KV.list` probe is removed — the MCP worker no longer
+binds KV.
+
+Response body shape (stable — reviewers parse this):
+
+```json
+{
+ "status": "ok" | "degraded",
+ "service": "packrat-mcp",
+ "version": "",
+ "transport": "streamable-http",
+ "endpoint": "/mcp",
+ "docs": "https://packratai.com/mcp",
+ "terms": "https://packratai.com/terms-of-service",
+ "privacy": "https://packratai.com/privacy-policy",
+ "support": "mailto:hello@packratai.com",
+ "probes": { "api": "ok" | "down" }
+}
+```
+
+HTTP status: 200 when the probe is `'ok'`, 503 otherwise. The
+legal/support URLs (U12) are surfaced on **both** the healthy and
+degraded responses so a reviewer curling `/health` during an incident
+still finds the contact surface.
+
+### Cache strategy — 10s isolate-local
+
+The probe result is cached in an isolate-local module slot
+(`packages/mcp/src/auth.ts → healthCache`) for 10 seconds. Trade-offs:
+
+- **Why cache at all?** Without it, an external uptime monitor polling
+ every 5s would synthesize 12 API fetch calls/minute per isolate —
+ easy to miss as a load source. 10s keeps the steady-state probe rate
+ ≤6/min/isolate.
+- **Why 10 seconds?** Short enough that a real outage surfaces within
+ one cache-window of when it began (no reviewer waits 30s for /health
+ to flip red). Long enough that consecutive uptime probes hit the
+ cache.
+- **Why per-isolate (not Worker-wide)?** A shared cache would mean an
+ extra fetch round-trip on every probe — defeating the point of
+ caching. Per-isolate scales with the isolate pool (single digits for
+ our traffic shape) so worst-case the dependency surface sees ≤N
+ probes/10s where N is the pool size.
+- **Module-level `let healthCache`** (not WeakMap / LRU) is deliberate:
+ the cache holds exactly one entry, and the simplest possible
+ eviction story keeps future refactors honest. The
+ `__resetHealthCacheForTests` helper is exported for vitest only —
+ production code never calls it.
+
+### Incident response
+
+The `probes` field tells you which dependency tripped:
+
+```bash
+curl -s https://mcp.packratai.com/health | jq
+# {"status":"degraded", ..., "probes":{"api":"down"}}
+# ^^^^^^^ → PackRat API outage
+```
+
+The degraded path also emits a WARN-level structured log:
+
+```bash
+wrangler tail --env prod --format pretty | grep mcp.health.degraded
+# {"ts":"...","level":"warn","msg":"mcp.health.degraded","reason":"api_down","statusCode":503,...}
+```
+
+`reason` is `api_down`. The healthy path is silent so external uptime
+probes don't fill Workers Logs with noise. If the probe fails, escalate
+to the API on-call (the same probe failure also breaks JWT validation,
+since `token-verify.ts` fetches JWKS from the same host).
+
+### `/status` — public-safe extended metadata
+
+`GET /status` returns a static metadata block — no upstream calls, no
+503 path. Reviewers use this to verify a deployed Worker matches the
+version + scope catalog they were promised.
+
+```json
+{
+ "service": "packrat-mcp",
+ "version": "",
+ "transport": "streamable-http",
+ "endpoint": "/mcp",
+ "scopes_supported": ["mcp:read", "mcp:write", "mcp:admin"],
+ "docs": "https://packratai.com/mcp",
+ "terms": "https://packratai.com/terms-of-service",
+ "privacy": "https://packratai.com/privacy-policy",
+ "support": "mailto:hello@packratai.com",
+ "deployId": "" | "unknown"
+}
+```
+
+**No secrets ever**: the response only contains version + scopes +
+public URLs + the Cloudflare deploy id. Adding a new field requires a code review
+that explicitly notes the field is non-sensitive — the auth.test.ts
+suite asserts a denylist of secret-looking keys is absent so a
+careless refactor that surfaces `env` more broadly regresses visibly.
+
+### `deployId` — no operator action needed
+
+`/status` surfaces `deployId` from `env.CF_VERSION_METADATA.id` — the
+Cloudflare `version_metadata` binding declared in `wrangler.jsonc`. The
+runtime injects it on every deploy, so there is **nothing to set** at
+deploy time: no `--var`, no CI step. It behaves identically under
+`wrangler deploy` and Cloudflare Workers Builds.
+
+`id` is the Cloudflare version UUID; Workers Builds maps it back to the
+originating git commit in its dashboard. When the binding is absent
+(`wrangler dev`, vitest) `/status` returns `deployId: "unknown"` —
+expected for local, and harmless. A prod hostname returning `unknown`
+means the `version_metadata` binding was dropped from the config.
+
+### CORS interaction
+
+Neither `/health` nor `/status` is annotated by the U6 CORS handler
+(`applyCorsHeaders` short-circuits on a `/.well-known/` prefix check —
+see `packages/mcp/src/cors.ts:48`). Reviewers curl them directly so no
+CORS dance is needed; if Claude.ai ever needed to fetch them
+cross-origin, the allowlist would have to extend.
+
+Neither endpoint requires auth — they're explicitly public surfaces. JWT
+validation only fires on `/mcp` (the MCP transport endpoint).
+
+---
+
+## U17 CI + integration tests
+
+MCP uses the repository's shared CI gates rather than a bespoke PR
+workflow:
+
+- `.github/workflows/checks.yml` runs repo-wide Biome, custom lint rules,
+ unsafe-cast checks, route-auth checks, and `bun check-types`.
+- `.github/workflows/coverage.yml` runs the MCP test suite with coverage
+ (`bun run --cwd packages/mcp test --coverage`) and includes it in the
+ ratchet.
+- `.github/workflows/api-tests.yml` runs the API suite, including the
+ auth and admin guard tests that protect the OAuth/Admin side of the MCP
+ contract.
+
+`packages/mcp` still has a local `check-types` script
+(`tsc --noEmit`). It now runs in ~1 GB / a few seconds: the
+`tool()`/`prompt()` wrappers (`src/registerTool.ts`) erase the SDK's
+`registerTool`/`registerPrompt` generics against `never`, so the
+recursive Zod-shape instantiation that used to push tsc past 14 GB is
+gone.
+
+### Prod deploy — Cloudflare-native (no bespoke workflow)
+
+There is no `mcp-deploy.yml`. The MCP Worker deploys the same way the API
+Worker does — **Cloudflare Workers Builds** (the git-connected build in the
+Cloudflare dashboard): connect the `packrat-mcp` Worker to this repo, set
+the deploy command to `bun run --cwd packages/mcp deploy`
+(`wrangler deploy --minify`), and CF rebuilds + deploys on the configured
+branch. The shared PR gates above are what keep tested code flowing to
+prod; there is no deploy-time re-run of the suite.
+
+`deployId` on `/status` comes from the `version_metadata` binding
+automatically (see § "`deployId` — no operator action needed") — no
+`--var`, no SHA-stamping step, no tagged-commit resolution.
+
+**Manual fallback** (operator, from `packages/mcp`):
+
+```bash
+wrangler deploy --env prod # prod → mcp.packratai.com
+bun run deploy:dev # dev → packrat-mcp-dev
+```
+
+Because deploys are no longer tag-triggered, there is no `mcp-v*` tag
+convention and no `CLOUDFLARE_API_TOKEN` / `CLOUDFLARE_ACCOUNT_ID` repo
+secrets to provision for MCP. Workers Builds carries its own Cloudflare
+auth; a manual `wrangler deploy` uses the operator's local `wrangler login`.
+
+Both secrets must be set at the **repository** level (not the
+environment level — the deploy workflow doesn't use a GitHub
+Environment object, intentionally, to keep the trigger surface
+small).
+
+### Tag convention
+
+```bash
+# Bump version in packages/mcp/package.json + src/constants.ts (single
+# source of truth — they MUST match; `auth.test.ts` asserts this).
+git commit -am "chore(mcp): bump to v2.1.0"
+git tag mcp-v2.1.0
+git push origin main mcp-v2.1.0 # tag push triggers the deploy
+```
+
+Pre-deploy checklist (run locally before pushing the tag):
+
+- `bun run --cwd packages/mcp test` — 1,123 tests must pass.
+- Verify `version` in `packages/mcp/package.json` matches
+ `ServiceMeta.Version` in `packages/mcp/src/constants.ts`.
+
+### vitest-pool-workers integration suite — current state
+
+`packages/mcp/vitest.workspace.ts` declares two projects:
+
+- `mcp-unit` — Node-environment tests for pure modules (the existing
+ 1,123-test surface). Fast; no workerd.
+- `mcp-integration` — wired but tests currently deferred as
+ `it.todo`. The harness boots cleanly (`bun run --cwd packages/mcp
+ test:integration` discovers all four integration files); the only
+ reason real assertions don't run is the upstream blocker below.
+
+**Why deferred:** the Worker entrypoint transitively imports the MCP
+SDK, which loads `ajv@^8` at module-eval time. `ajv` does
+`require('./refs/data.json')`, and workerd's CJS module-fallback path
+treats JSON content as JS code — the worker won't boot inside
+vitest-pool-workers until one of two upstream fixes lands:
+
+1. vitest-pool-workers' `handleModuleFallbackRequest` learns to apply
+ user-supplied `modulesRules` to bare JSON requires (currently the
+ rules array is only applied via the vite RPC patch, not the
+ workerd-side resolution chain).
+2. The MCP SDK accepts an injected `jsonSchemaValidator` we can stub
+ in tests — bypassing `ajv` entirely.
+
+Until then the `it.todo` placeholders in
+`packages/mcp/src/__tests__/integration/*.test.ts` preserve the
+contract intent and `vitest run` reports the deferred-todo count so
+the gap stays visible. Unit-level coverage of every deferred contract
+exists in the corresponding `../*.test.ts` files (well-known →
+`metadata.test.ts`, health/status → `auth.test.ts`, JWT validation →
+`token-verify.test.ts`). The previous DCR-gate integration entry is
+gone — DCR was deleted in U3+U4 of the 2026-05-25 refactor.
+
+**First-invocation note (for when the integration tests light up):**
+`@cloudflare/vitest-pool-workers` downloads `workerd` on first run
+(~30s, one-time per machine + version). Subsequent runs are warm.
+
+### Miniflare bindings for the deferred integration suite
+
+Post-refactor (2026-05-25) the MCP worker no longer binds KV at all —
+`OAUTH_KV` and `MCP_INITIAL_ACCESS_TOKEN` are gone. The integration
+config (`packages/mcp/vitest.integration.config.ts`) accordingly carries
+**no KV stubs and no DCR-token stub**; the only required binding when
+the suite eventually swaps back to `defineWorkersProject` is
+`PACKRAT_API_URL` (so `verifyMcpToken` can fetch the JWKS — either
+against a mock-fetch or a locally-running API worker). The Durable
+Object + rate-limit bindings come from `wrangler.jsonc` unchanged.
+
+**No live Cloudflare creds are needed for the test run** — miniflare
+synthesises the DO + RL bindings in-process, and the JWKS fetch is the
+only outbound dependency to mock.
+
+---
+
+## U18 submission packet + readiness script
+
+The last unit of the connector-store readiness plan ships two operator
+surfaces: a programmatic pre-submission probe and a fully-resolved
+submission packet document. Together they replace the "operator reads
+13 different runbook sections and ad-hoc curls each one" pattern with a
+single command + a single doc.
+
+### `bun packages/mcp/scripts/submission-readiness.ts` — cross-origin probe
+
+Default target is production. Post-refactor the AS and RS live on
+different origins, so the legacy `--url` flag is gone — pass
+`--rs-url` (MCP resource server) and `--as-url` (Better Auth AS) as
+separate args when probing a non-prod environment. The script is
+**a deployed-server probe** — it cannot run before both workers are
+deployed, and it never mutates state.
+
+```bash
+# Default: probes https://mcp.packratai.com (RS), https://api.packrat.world (AS),
+# and https://packratai.com (brand). Reads the catalog from apps/landing/data/mcp-catalog.json.
+bun packages/mcp/scripts/submission-readiness.ts
+
+# Against staging
+bun packages/mcp/scripts/submission-readiness.ts \
+ --rs-url https://packrat-mcp-dev..workers.dev \
+ --as-url https://packrat-api-dev..workers.dev
+
+# CI / machine-readable
+bun packages/mcp/scripts/submission-readiness.ts --json
+```
+
+Exit codes: `0` = every check passed; `1` = at least one check failed;
+`2` = bad CLI args. Default output is colour-coded one-line-per-check
+plus an `N passed / M warned / K failed` summary; `--json` emits a
+structured report suitable for piping into a CI job.
+
+#### The checks at a glance
+
+| # | What it asserts | Host | Failure recovery |
+| - | --- | --- | --- |
+| 1 | TLS + custom domain reachability — `GET /` returns 200 over HTTPS on the right host | RS | DNS not propagated; cert not provisioned; worker not deployed |
+| 2 | `/mcp` returns 401 with `WWW-Authenticate: Bearer resource_metadata=..., scope=...` (RFC 9728 §5.1) | RS | `index.ts` outer fetch wiring drifted; PRM URL stale |
+| 3 | `/.well-known/oauth-protected-resource` has `resource`, `authorization_servers`, all 4 scopes, `bearer_methods_supported: ['header']` | RS | `packages/mcp/src/metadata.ts` drifted from the plan |
+| 4 | `/.well-known/oauth-authorization-server` advertises `S256`, `authorization_code`, `refresh_token`, `code` | AS | `@better-auth/oauth-provider` config drift; `allowPlainCodeChallengeMethod` flipped on |
+| 5 | Pre-registered Claude client present in the AS `oauthClient` table — **always WARN** (no public client-list endpoint) | AS | Re-run `cd packages/api && bun run db:seed:oauth-clients` (idempotent — no-op if already registered) or inspect the `oauthClient` table directly |
+| 6 | `/favicon.ico` returns 200 image/x-icon with the .ico magic bytes (Anthropic's domain-ownership probe) | RS | `packages/mcp/src/favicon.ts` corrupted; re-embed per the U13 contract |
+| 7 | `packratai.com/mcp` renders with `PackRat`, `Claude.ai`, `scope` text present | brand | Landing site deploy failed; route 404'd |
+| 8 | `/privacy-policy` and `/terms-of-service` return 200 AND contain `mcp` or `connector` | brand | Legal pages missing the MCP addendum — Anthropic immediate-reject cause |
+| 9 | `/health` JSON includes `support: mailto:hello@packratai.com` | RS | U12 mapping drifted |
+| 10 | `/health` returns `status: 'ok'` with `probes.api: ok` | RS | The API dependency is degraded; check `wrangler tail` |
+| 10b | `/status` advertises `scopes_supported` with all 4 PackRat scopes | RS | U16 metadata drifted |
+| 11 | Every tool in the catalog has `title` + `readOnlyHint` + `destructiveHint` (when not read-only) | local | Re-run `bun packages/mcp/scripts/dump-catalog.ts`; the U7 annotations test should have caught this |
+| 12 | Tool descriptions contain no forbidden marketing words (`revolutionary`, `AI-powered` as a value claim, etc.) | local | Edit the offending description in `packages/mcp/src/tools/*.ts`; re-dump catalog |
+
+The prior `dcr_gate` check (probe `POST /register` for 401) is **gone**:
+post-refactor the MCP worker has no `/register` route and the AS has
+`allowDynamicClientRegistration: false`, so there's nothing to probe.
+
+#### Honest gaps in automation
+
+- **Check 5** (pre-registered Claude client) cannot be automated:
+ `@better-auth/oauth-provider` does not expose a public client-list
+ endpoint and DCR is disabled, so the script always emits a WARN
+ pointing at the seed script + the `oauthClient` table. Verify
+ manually by re-running
+ `cd packages/api && bun run db:seed:oauth-clients` (idempotent —
+ no-op if already registered) or by querying the `oauthClient` table
+ directly. This is the only check that does not assert by default.
+- WAF rule audits are not probed — they require a non-Cloudflare-egress
+ client to test, which a Worker-side script cannot synthesize. See
+ § "TODO (operator): zone-level WAF Rate Limiting Rules" above.
+
+### Catalog source for checks 12 and 13
+
+The two catalog-shape checks read from
+`apps/landing/data/mcp-catalog.json` (dumped by U13's
+`scripts/dump-catalog.ts`). If the catalog file is missing or stale,
+re-run the dump first:
+
+```bash
+bun packages/mcp/scripts/dump-catalog.ts
+bun packages/mcp/scripts/submission-readiness.ts
+```
+
+Override the catalog path with `--catalog /tmp/other-catalog.json` if
+you need to probe an older snapshot.
+
+### Unit tests
+
+The check primitives are pure and have a comprehensive unit suite at
+`packages/mcp/src/__tests__/submission-readiness.test.ts` (62 tests).
+The shared coverage workflow runs them alongside the rest of the MCP test
+surface. If a check's output shape ever drifts (new severity level,
+renamed status string), this suite fails loudly so the formatter, the
+readiness probe, and this runbook stay in lockstep.
+
+### Submission packet doc
+
+[`docs/mcp/submission-packet.md`](./submission-packet.md) is the
+operator's filing reference. It contains:
+
+- The form URL ().
+- A field-by-field mapping (every Anthropic form field → the
+ copy-pasteable PackRat value).
+- The 13-check pre-submission checklist with manual-verification
+ fallbacks.
+- The reviewer test account setup runbook.
+- The known-limitations / explicitly-deferred section (SSO, integration
+ `it.todo` cases, Tier 2 outputSchema tools, WAF rules, OTel pipeline).
+- The rejection-recovery playbook (same-day fixable vs. multi-day
+ re-architect).
+
+The operator does not commit the populated reviewer credentials to the
+repo — the doc carries `TODO (operator)` placeholders.
+
+### Operator check
+
+Run the readiness probe directly after the production deploy is live:
+
+```bash
+bun packages/mcp/scripts/submission-readiness.ts
+```
+
+For staging or other non-prod targets, pass explicit hosts:
+
+```bash
+bun packages/mcp/scripts/submission-readiness.ts \
+ --rs-url https://staging-mcp.example.com \
+ --as-url https://staging-api.example.com \
+ --brand-domain https://staging-packratai.example.com
+```
+
+The job exits 0 on green / 1 on red so the workflow surfaces a clear
+status badge. Re-run after every deploy that touches metadata, scope,
+or annotation surfaces.
+
+---
+
+## Common operations
+
+### Deploy
+
+```bash
+# Dev (manual)
+bun run deploy:dev
+
+# Prod — Cloudflare Workers Builds deploys on push (like the API).
+# Manual fallback (no --var needed; deployId comes from version_metadata):
+wrangler deploy --env prod
+```
+
+### Tail logs
+
+```bash
+wrangler tail --env prod --format pretty
+```
+
+### Rotate `PACKRAT_API_URL`
+
+```bash
+wrangler secret put PACKRAT_API_URL --env prod
+# Forces the JWKS cache on the next request to re-fetch from the new URL.
+# Use a benign env var bump alongside (per § "Forcing isolate rotation
+# after a deploy") so existing isolates rotate immediately rather than
+# waiting on natural isolate churn.
+```
+
+## Post-refactor dev verification (R11 gate)
+
+Before tagging the prod release that lands the Better Auth OAuth consolidation
+(plan: [`docs/plans/2026-05-25-001-refactor-mcp-auth-onto-better-auth-plan.md`](../plans/2026-05-25-001-refactor-mcp-auth-onto-better-auth-plan.md)),
+the operator manually installs the connector in a real Claude.ai account
+against the dev deploy URLs to confirm the cross-origin AS flow works
+end-to-end. Anthropic has documented but unfixed issues with cross-origin
+discovery in Claude.ai (`anthropics/claude-ai-mcp#82, #248, #291` —
+closed-as-not-planned); this checklist catches them before prod.
+
+The unit + integration tests cannot prove this works — the deferred
+`it.todo` cases (per § "vitest-pool-workers integration suite — current
+state" above) are blocked on an upstream ajv module-resolution fix, and
+even when they light up they exercise the worker boundary, not Claude.ai's
+actual discovery client. **This manual install IS the integration test
+for the refactor.**
+
+### Operator steps
+
+1. Deploy to dev manually — `bun run deploy:dev` from `packages/mcp`
+ (and the equivalent for the API worker) ships the current commit to
+ `packrat-mcp-dev` + `packrat-api-dev`. Keep prod deploys (Workers
+ Builds on the configured branch, or a manual `wrangler deploy --env
+ prod`) until after this dev gate passes.
+2. Open `https://claude.ai` in a fresh browser profile (no PackRat cookies
+ from a prior session — the AS-domain switch should be visible in the
+ address bar).
+3. Settings → Connectors → Add custom connector → URL:
+ `https://packrat-mcp-dev..workers.dev/mcp` (or whatever dev
+ URL the deploy assigns).
+4. Walk through the OAuth flow. Expected:
+ - Claude fetches `/.well-known/oauth-protected-resource` from the dev MCP.
+ - Reads `authorization_servers: ["https://packrat-api-dev..workers.dev"]`
+ (or whatever the dev API URL is).
+ - Fetches AS metadata from the dev API root
+ (`/.well-known/oauth-authorization-server`).
+ - Opens a browser to the dev API's `/oauth2/authorize`.
+ - User sees the branded consent page (PackRat logo, Claude as the
+ client name, scope checkboxes).
+5. Sign in with the reviewer test account credentials (§ 4 of
+ [`docs/mcp/submission-packet.md`](./submission-packet.md)).
+6. Approve the consent screen. Confirm the scope list shows only the
+ four MCP scopes (or fewer if the test account isn't admin — `mcp:admin`
+ should be absent for non-admin users).
+7. Confirm redirect back to Claude.ai succeeds without an error toast.
+8. In Claude, ask a simple `mcp:read` prompt: *"List the packs I have on
+ PackRat."* Confirm a tool call fires and returns expected output.
+9. Ask a `mcp:write` prompt: *"Create a new pack called 'Dev Verification
+ Test'."* Confirm the write succeeds.
+10. **Test account with admin role:** ask a `mcp:admin` prompt that confirms
+ admin tools are visible. **Test account without admin role:** confirm
+ admin tools are absent from `tools/list`.
+11. Wait at least 65 minutes (longer than the 60-min access token TTL) and
+ confirm refresh-token grant happens transparently — another tool call
+ works without re-consent.
+
+### Failure mode catalog
+
+If any step fails, escalate per the plan's HLD "Cross-origin failure-mode
+catalog" table. Realistic fallback path if Claude.ai's cross-origin
+discovery is broken: reverse-proxy the AS endpoints onto
+`mcp.packratai.com` (documented as a follow-up plan, **not built** in this
+refactor).
+
+Common failure modes to look for:
+
+- **CORS preflight failure on `/.well-known/oauth-authorization-server`
+ from `https://claude.ai`** → API worker missing the AS host in its CORS
+ allowlist for the well-known prefix. Fix on the API side.
+- **Authorization header stripped on cross-origin redirect** → Claude.ai
+ proxy stripping `Authorization` between the AS callback and the MCP
+ worker. Catchable by inspecting the network panel in DevTools. No
+ workaround within MCP/AS — fall back to the reverse-proxy plan.
+- **`invalid_client` at `/oauth2/token`** → seed script wasn't run for
+ this dev env, or the dev client_id Claude is using doesn't match.
+ Re-run `cd packages/api && bun run db:seed:oauth-clients` against
+ the dev DB.
+- **`invalid_audience` or 401 from MCP after a successful token grant** →
+ the AS isn't sending `resource` correctly, so an opaque token was
+ issued instead of a JWT. Inspect the granted access token; if it's
+ not a JWT (no three `.`-separated base64 segments), the AS is wrong.
+- **Refresh-token rejection at the 65-min boundary** → Better Auth
+ rotation policy diverged from Claude's expectation. Capture the
+ rejection's `error` field and escalate.
+
+### Tag prod on green
+
+If verification passes: tag `mcp-vX.Y.Z` and CI deploys to prod. After the
+prod deploy lands, run the operator cleanup per § "Deprovision the legacy
+OAUTH_KV namespaces + DCR secret" above.
+
+## Known issues / environment notes
+
+- **`tsc --noEmit` (i.e. `bun run check-types`) OOMs on machines under ~16 GB
+ RAM.** The MCP SDK's type surface is large; combined with the package's
+ own types, type-checking needs `NODE_OPTIONS=--max-old-space-size=16384`
+ or a workstation with more headroom. **Type validation is the CI pipeline's
+ job** (U17); locally, rely on `bun test` (which runs vitest on the unit
+ surface) and let CI catch type regressions.
+
+## See also
+
+- [`packages/mcp/.dev.vars.example`](../../packages/mcp/.dev.vars.example) — required env vars
+- [`packages/mcp/wrangler.jsonc`](../../packages/mcp/wrangler.jsonc) — env / route / binding structure
+- [The implementation plan](../plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md)
diff --git a/docs/mcp/submission-packet.md b/docs/mcp/submission-packet.md
new file mode 100644
index 0000000000..bfb72c65e5
--- /dev/null
+++ b/docs/mcp/submission-packet.md
@@ -0,0 +1,423 @@
+# PackRat MCP — Anthropic Connector Store submission packet
+
+Operator-facing packet that captures every field the Anthropic submission
+form asks for, plus the reviewer test account and the pre-submission
+checklist. **This document is the source of truth the operator
+copy-pastes from when filing the form.** Do not publish it; reviewer
+credentials live here and the public docs page at
+[packratai.com/mcp](https://packratai.com/mcp) explicitly points
+reviewers back to this file (which Anthropic receives via the form, not
+the public site).
+
+> **Status: ready for submission (U18).** Every code-side artifact is
+> shipped; the placeholders below marked **TODO (operator)** are the
+> handful of values the operator resolves at submission time (test
+> account credentials, PNG render of the SVG logo, the actual filing
+> date / acknowledgment thread reference, the jurisdiction in the ToS).
+
+---
+
+## 0. Filing checklist (do this in order)
+
+1. Confirm the worker is **deployed to prod** (`mcp.packratai.com` returns
+ HTTP 200 with HTTPS) — see [`runbook.md`](./runbook.md) §
+ "Domains & environments".
+2. Run the **submission-readiness probe** (U18, updated by U7 for the
+ cross-origin AS architecture) and confirm `12/13 passed` (with 1 WARN
+ — see below):
+ ```bash
+ bun packages/mcp/scripts/submission-readiness.ts
+ ```
+ The probe targets two distinct hosts: `mcp.packratai.com` (resource
+ server) and `api.packrat.world` (authorization server, hosting
+ `@better-auth/oauth-provider`). All non-WARN checks must pass before
+ filing. The check 5 WARN (Claude pre-registration) is expected and
+ acceptable: the AS exposes no public client-list endpoint, so the
+ probe always WARNs and points operators at
+ [`packages/api/src/db/seed-claude-oauth-client.ts`](../../packages/api/src/db/seed-claude-oauth-client.ts)
+ (the idempotent DB-seed script that pre-registers Claude as a trusted
+ OAuth client in the `oauthClient` table).
+3. Prepare the **reviewer test account** (§ 4 below) and verify the demo
+ prompts work end-to-end.
+4. **Logo PNGs are pre-rendered** and committed under `apps/landing/public/`:
+ - `mcp-logo-1024.png` (24 KB) — attach to the submission form
+ - `mcp-logo-512.png` (9 KB) — retina favicon fallback
+ - `mcp-logo-256.png` (3.6 KB) — listing thumbnail
+ Render command (run only if the SVG changes):
+ ```bash
+ node -e "
+ const sharp=require('sharp'),fs=require('fs');
+ const svg=fs.readFileSync('apps/landing/public/mcp-logo.svg');
+ for (const size of [1024,512,256])
+ sharp(svg,{density:600}).resize(size,size).png()
+ .toFile(\`apps/landing/public/mcp-logo-\${size}.png\`).then(i=>console.log(size,i.size));
+ "
+ ```
+5. Sign in to with the
+ `hello@packratai.com` Google account (or whichever account owns the
+ listing).
+6. Paste each field verbatim from § 2 below. Attach the PNG logo,
+ reviewer credentials, and the example prompts.
+7. After filing, record the submission date and Anthropic's
+ acknowledgment thread in § 1 below.
+
+---
+
+## 1. Submission form
+
+- **Form URL:** (Anthropic's
+ Claude Connector Store submission form; same URL the plan's U18
+ references).
+ - If the form 404s, check Anthropic's [Submitting to the Connectors
+ Directory](https://claude.com/docs/connectors/building/submission)
+ docs for the current canonical URL; Anthropic has rotated it before.
+- **Submission email:** `hello@packratai.com` (the operator filing the
+ form).
+- **Submission date (TODO — operator):** fill in when filed.
+- **Anthropic acknowledgment thread (TODO — operator):** record the
+ acknowledgment message-id or subject line so future follow-ups have a
+ durable anchor.
+
+---
+
+## 2. Field-by-field mapping
+
+The form fields below are derived from Anthropic's documented submission
+flow (`Building Connectors → Submitting to the Connectors Directory`)
+as of plan-drafting. Update the field labels in this table if Anthropic
+changes the form. Each row is the value the operator pastes verbatim.
+
+| Form field | Value | Source / notes |
+| --- | --- | --- |
+| Connector name | `PackRat` | Single brand string; matches the `serverInfo.name` emitted by the Worker. |
+| Tagline (≤ 80 chars) | `Plan trips, build packs, check weather — from any MCP client.` | Public docs page hero (`apps/landing/app/mcp/page.tsx`). |
+| Short description (≤ 150 chars) | `PackRat is a free outdoor adventure planner — packs, trips, trails, gear, weather — connected to Claude via MCP.` | 141 chars. |
+| Long description (≤ 500 chars) | See "Description draft" below. | ≈ 470 chars; trim further if the form caps lower. |
+| Category (primary) | `Productivity` | Anthropic's published category taxonomy as of plan-drafting; PackRat is a planning/productivity tool first and an outdoor tool second. **TODO (operator):** confirm the exact category strings against the live form before submitting. |
+| Category (secondary) | `Travel & Outdoor` (or `Lifestyle` if Travel/Outdoor is unavailable) | Best-fit; confirm against the live taxonomy. |
+| Connector URL (Server URL) | `https://mcp.packratai.com/mcp` | Production Streamable HTTP endpoint. Probed by submission-readiness check 2. The OAuth Authorization Server lives on `https://api.packrat.world` and is reachable via the PRM discovery chain (`mcp.packratai.com/.well-known/oauth-protected-resource` → `authorization_servers: ["https://api.packrat.world"]` → `api.packrat.world/.well-known/oauth-authorization-server`); no separate AS form field is needed. |
+| OAuth callback URLs (allowlist) | `https://claude.ai/api/mcp/auth_callback` `https://claude.com/api/mcp/auth_callback` | Pre-registered into the `oauthClient` table via [`packages/api/src/db/seed-claude-oauth-client.ts`](../../packages/api/src/db/seed-claude-oauth-client.ts) (run with `cd packages/api && bun run db:seed:oauth-clients`; idempotent — re-runs are safe). DCR is disabled at the AS (`allowDynamicClientRegistration: false`); the seed script is the only registration path. See [`runbook.md`](./runbook.md) § "Deprovision the legacy OAUTH_KV namespaces + DCR secret" for the operator setup. |
+| Scopes advertised | `mcp:read`, `mcp:write`, `mcp:admin` | From `packages/mcp/src/metadata.ts` (`SCOPES_SUPPORTED`). Probed by submission-readiness checks 3 and 11b. |
+| Default scopes Claude.ai should request | `mcp:read`, `mcp:write` | Admin scope is operator-controlled; never requested by default. |
+| Privacy policy URL | `https://packratai.com/privacy-policy` | U12; the MCP addendum lives under the "MCP Connector & Third-Party Clients" section. Probed by check 9. |
+| Terms of Service URL | `https://packratai.com/terms-of-service` | U12. **TODO (operator):** confirm the jurisdiction TODO has been resolved if your legal review requires it (see [`runbook.md`](./runbook.md) § "TODO (operator): jurisdiction in the Terms of Service"). |
+| Public documentation URL | `https://packratai.com/mcp` | U13. Probed by check 8. |
+| Support contact (email) | `hello@packratai.com` | Same as `siteConfig.support.email`; advertised on `/health` (check 10). |
+| Support contact (URL) | `https://packratai.com/mcp#privacy--security` | Anchor on the public docs page. |
+| Logo / icon (SVG) | `apps/landing/public/mcp-logo.svg` | U13 vector mark. |
+| Logo / icon (1024×1024 PNG) | `apps/landing/public/mcp-logo-1024.png` — pre-rendered from the SVG; attach this file to the form. | Anthropic's form requires a raster fallback for the directory tile. |
+| Favicon (32×32 .ico) at OAuth domain | `https://mcp.packratai.com/favicon.ico` | Served by the Worker — [`packages/mcp/src/favicon.ts`](../../packages/mcp/src/favicon.ts). Anthropic's domain-ownership probe targets this exact URL (check 7). |
+| Reviewer test account | See § 4 below. | Provide via the form's reviewer-credentials field. |
+| Example prompts (≥ 3) | See § 5 below. | Verbatim from the U13 public docs page. |
+| Pricing | `Free` | PackRat MCP is included with a free PackRat account; no paid tier exists. |
+| Listed user audience | `Outdoor / adventure / travel planners; gear-heads; ultralight backpackers; thru-hikers` | One-line audience descriptor; operators can refine if the form asks for a more specific demographic. |
+
+### Description draft
+
+> PackRat is a free outdoor adventure planner — packs, trips, trails, gear, weather, and a community feed. The PackRat MCP connector lets Claude (or any MCP-capable client) read and write your PackRat data on your behalf: list packs, build a multi-day trip, compare gear by weight, check the forecast, and post trail-condition updates. Built on Streamable HTTP with OAuth 2.1 + PKCE, audience-bound tokens, and per-scope tool gating. Free with a PackRat account.
+
+(≈ 470 chars — trim further if the form caps lower.)
+
+---
+
+## 3. Pre-submission verification checklist
+
+Anthropic's documented intake heuristics, mapped to the
+`submission-readiness.ts` checks. The script runs all of these in one
+invocation; this table is the human-readable expansion of what each
+check covers.
+
+| # | Check | Host | Readiness-script ID | How to verify manually if needed |
+| - | --- | --- | --- | --- |
+| 1 | Streamable HTTP at `mcp.packratai.com/mcp` reachable over HTTPS | RS | `tls_reachability` | `curl -i https://mcp.packratai.com/` |
+| 2 | `/mcp` returns 401 with RFC 9728 `WWW-Authenticate: Bearer resource_metadata=...` | RS | `streamable_http_auth` | `curl -i -X POST https://mcp.packratai.com/mcp -d '{}'` |
+| 3 | `/.well-known/oauth-protected-resource` (RFC 9728) is valid JSON with all 4 scopes AND `authorization_servers` points at the AS | RS | `protected_resource_metadata` | `curl -s https://mcp.packratai.com/.well-known/oauth-protected-resource \| jq` |
+| 4 | `/.well-known/oauth-authorization-server` (RFC 8414) has `code_challenge_methods_supported: ["S256"]` (no `"plain"`) and the right grants | AS | `authorization_server_metadata` | `curl -s https://api.packrat.world/.well-known/oauth-authorization-server \| jq` |
+| 5 | Pre-registered Claude client present in the AS `oauthClient` table (always WARNs — no public list endpoint) | AS | `claude_client_registration` | Re-run `cd packages/api && bun run db:seed:oauth-clients` (idempotent — no-op if already registered) or query the table directly |
+| 6 | `/favicon.ico` on the MCP domain returns 200 image/x-icon with .ico magic bytes (Anthropic's domain-ownership probe target) | RS | `favicon_oauth_domain` | `curl -sI https://mcp.packratai.com/favicon.ico` |
+| 7 | Public docs page renders with PackRat / Claude.ai / scope copy | brand | `public_docs_page` | Visit in a browser |
+| 8 | Privacy + Terms reachable AND contain MCP-specific copy | brand | `privacy_and_terms` | `curl -s https://packratai.com/privacy-policy \| grep -i 'mcp\|connector'` |
+| 9 | `/health` advertises a `support: mailto:hello@packratai.com` contact | RS | `support_contact` | `curl -s https://mcp.packratai.com/health \| jq .support` |
+| 10 | `/health` returns `{ status: 'ok', probes: { ... all green } }` | RS | `health_status` | `curl -s https://mcp.packratai.com/health \| jq` |
+| 10b | `/status` advertises `scopes_supported` with all 4 PackRat scopes | RS | `status_endpoint` | `curl -s https://mcp.packratai.com/status \| jq .scopes_supported` |
+| 11 | Every tool has `title` + `readOnlyHint` (+ `destructiveHint` when not read-only) | local | `tool_annotations` | `bun packages/mcp/scripts/dump-catalog.ts` then inspect `apps/landing/data/mcp-catalog.json` |
+| 12 | Tool descriptions contain no forbidden marketing words | local | `tool_descriptions_non_promotional` | Read the descriptions in `apps/landing/data/mcp-catalog.json` |
+
+The prior `dcr_gate` check (probe `POST /register` for 401) is **deleted**:
+post-refactor the MCP worker has no `/register` route and the AS has
+`allowDynamicClientRegistration: false`, so there's nothing to probe.
+
+"Host" column legend:
+- **RS** = `mcp.packratai.com` (the MCP Streamable HTTP resource server)
+- **AS** = `api.packrat.world` (the OAuth Authorization Server hosted by `@better-auth/oauth-provider` on the API worker)
+- **brand** = `packratai.com` (the landing site)
+- **local** = a filesystem file (the dumped tool catalog in `apps/landing/data/mcp-catalog.json`)
+
+**Additional manual checks (not automated):**
+
+- WAF Rate Limiting Rules on `packratai.com` don't block Anthropic's
+ OAuth discovery probes. See [`runbook.md`](./runbook.md) § "TODO
+ (operator): zone-level WAF Rate Limiting Rules". If reviewer probes
+ get blocked during intake, add an explicit allow rule above the rate
+ limits for Anthropic's published IP ranges.
+- Token endpoint accepts `application/x-www-form-urlencoded` (default
+ OAuthProvider behaviour; verify with a one-shot
+ `curl -d 'grant_type=...' https://mcp.packratai.com/token` if the
+ reviewer flags it).
+- The reviewer test account in § 4 has been signed into at least once
+ via Claude.ai's "Add custom connector" flow end-to-end.
+
+---
+
+## 4. Reviewer test account
+
+Anthropic's reviewers need a fully-populated account they can sign into
+without friction. Generate dedicated credentials (do **not** reuse the
+operator's account) and populate the listed data before filing the form.
+
+> **TODO (operator):** the credentials block below is intentionally
+> blank in the committed file. Fill it in **only** in your local copy
+> when preparing the form submission; do not commit the populated
+> values to the repo. Use a password manager + paste into the form
+> directly.
+
+```text
+Reviewer test account
+---------------------
+Email: TODO (operator) — e.g. mcp-reviewer@packratai.com
+Password: TODO (operator) — generate via 1Password / equivalent
+Account URL: https://packratai.com (sign in via app or web)
+Role: standard user (NOT admin — reviewers should not see admin tools by default)
+Created on: TODO (operator)
+Expires: TODO (operator) — recommend re-rotating after each review cycle
+```
+
+### Reviewer test account setup runbook
+
+Run this once per submission cycle (the operator's one-time setup; not
+committed to the repo):
+
+1. **Create the account.** Sign up at with the
+ reviewer email. Use a unique, strong password from a password
+ manager — the password is shared with Anthropic's reviewers via the
+ form, so do not reuse it anywhere else.
+2. **Confirm the email.** Click the confirmation link in the inbox.
+3. **Do NOT grant admin role.** The role defaults to `USER`; leave it
+ there. The connector store reviews the non-admin experience.
+4. **Populate the data set described under "Pre-populated data" below.**
+ Use the mobile app or the admin UI to add the packs / trips / feed
+ posts. Aim for ~15 minutes of real-feeling data — enough that the
+ example prompts in § 5 return non-empty results.
+5. **Sanity-check via Claude.ai.** Open Claude.ai → Settings →
+ Connectors → Add custom connector → enter
+ `https://mcp.packratai.com/mcp`. Sign in with the reviewer
+ credentials. Approve the `mcp:read` + `mcp:write` scopes. Run each
+ example prompt in § 5 in order; confirm each returns a useful answer.
+6. **Sign out + sign in again** to confirm the password persists.
+7. **Paste the credentials into the form's reviewer-instructions field**
+ along with the first-run instructions below.
+
+### Pre-populated data the reviewer should see
+
+Populate the test account with realistic data so the example prompts in
+§ 5 work end-to-end. Use the mobile app or admin UI to create:
+
+- **Packs (≥ 3)**:
+ - "Big 3 — Wind Rivers 3-day": shelter (tent), sleep system (bag +
+ pad), pack (frame pack). Add 8–10 items with realistic weights so
+ `packrat_compare_gear_items` has substance to compare.
+ - "Day hike — kit": water, snacks, layer, first-aid, headlamp.
+ - "Winter overnight": include a stove + fuel + insulated layer.
+- **Trips (≥ 1)**:
+ - "Wind River Range — 3 day" with a future date and a real
+ destination (e.g. Cirque of the Towers coords).
+- **Feed posts (≥ 1)**: a public trip recap post with a photo if
+ convenient.
+- **Trail-condition reports (≥ 1, optional)**: lets
+ `packrat_list_my_trail_reports` return a non-empty list.
+
+### First-run instructions for the reviewer
+
+Include this verbatim in the form's reviewer-instructions field:
+
+> 1. Install PackRat as a custom connector in Claude.ai (Settings →
+> Connectors → Add custom connector). URL:
+> `https://mcp.packratai.com/mcp`.
+> 2. When prompted to sign in, use the credentials above.
+> 3. Approve the requested scopes (`mcp:read`, `mcp:write`).
+> 4. Run the example prompts in the order listed in the public docs:
+> .
+> 5. To revoke the connection: PackRat app → Settings → MCP → Revoke,
+> or remove the connector from Claude.ai.
+
+---
+
+## 5. Demo prompt checklist
+
+These mirror the three prompts on the public docs page
+(`apps/landing/app/mcp/page.tsx`). Anthropic asks reviewers to exercise
+each one; the operator should verify they work end-to-end against the
+reviewer account before filing.
+
+### Prompt 1 — Read-only (packs + gear comparison)
+
+> "What's in my Big 3 right now? Suggest one swap to drop a pound."
+
+**Tools exercised:** `packrat_list_packs`, `packrat_list_pack_items`,
+`packrat_compare_gear_items`, optionally `packrat_search_gear_catalog`.
+
+**Expected behavior:** Claude lists the user's packs, picks the
+"Big 3" pack (or asks which one if ambiguous), surfaces shelter + sleep
++ pack with weights, and proposes one lighter substitute pulled from
+the gear catalog.
+
+**Operator verification (pre-submission):** run the prompt; confirm no
+destructive tools fire, no `isError: true` envelopes appear, response
+stays under the 150 000-char cap.
+
+### Prompt 2 — Multi-tool plan (trip + weather + trail conditions + pack)
+
+> "Plan a 3-day trip to the Wind River Range next weekend; build the pack, check the weather, and flag any trail closures."
+
+**Tools exercised:** `packrat_search_trails`, `packrat_get_weather`,
+`packrat_list_my_trail_reports`, `packrat_create_trip`,
+`packrat_create_pack`.
+
+**Expected behavior:** Claude composes a plan touching at least 4 tool
+surfaces. The trip + pack writes succeed; weather returns a forecast for
+the next-weekend dates; trail reports filter to any reports tagged to
+the route.
+
+**Operator verification (pre-submission):** confirm the `create_trip`
+and `create_pack` writes land in the test account (refresh the app /
+admin UI to spot them).
+
+### Prompt 3 — Write with elicitation (admin-style confirmation)
+
+> "Find a TikTok ultralight loadout I saw at and import it as a personal template."
+
+**Tools exercised:** `packrat_extract_url_content`,
+`packrat_generate_pack_template_from_url` (admin-only), with fallback
+to `packrat_create_pack_template` for non-admin users.
+
+**Expected behavior:** Claude attempts the import. Because the test
+account is non-admin, `packrat_generate_pack_template_from_url` is not
+visible — Claude either says so or falls back to
+`packrat_create_pack_template`, which triggers an MCP **elicitation**
+asking the user to type a confirmation token before the template is
+created. This is the reviewer-facing demonstration of the elicitation
+pattern.
+
+**Operator verification (pre-submission):** confirm the elicitation
+prompt appears in Claude.ai's UI; type the confirmation token and
+verify the template lands; mistype the token and verify the tool
+returns `isError: true` with code `confirmation_mismatch` and no write
+occurred.
+
+---
+
+## 6. Logo / favicon checklist
+
+| Asset | Path | Status |
+| --- | --- | --- |
+| MCP logo (SVG, 256×256 viewBox) | `apps/landing/public/mcp-logo.svg` | Shipped (U13). |
+| MCP logo (1024×1024 PNG) | `apps/landing/public/mcp-logo-1024.png` — pre-rendered. | Pre-rendered + committed; no operator action. |
+| Favicon (32×32 .ico) at OAuth host | `https://mcp.packratai.com/favicon.ico` — served via [`packages/mcp/src/favicon.ts`](../../packages/mcp/src/favicon.ts) (embedded base64 of `apps/landing/public/favicon.ico`). | Shipped (U13). |
+| Favicon at brand domain | `https://packratai.com/PackRat.ico` (legacy filename used in `apps/landing/lib/metadata.ts`); also available at `/favicon.ico` since U13. | Shipped. |
+
+---
+
+## 7. Known limitations / explicitly-deferred
+
+The submission proceeds with these items in deferral. Each is documented
+honestly so reviewers (and future operators) see the scope.
+
+| Item | Status | Where to look |
+| --- | --- | --- |
+| Google + Apple SSO on the OAuth consent flow | **Deferred** — Better Auth supports the social providers on `api.packrat.world`; surfacing them on the MCP consent page is a follow-up on the AS side, not the MCP side. Post-refactor the sign-in surface is fully owned by Better Auth, so adding SSO is a flag flip on the API plus a UI change to the consent page (`packages/api/src/consent-page.ts`), not the cross-origin re-architecture it used to require. | `packages/api/src/auth/index.ts` (Better Auth plugin config); `packages/api/src/consent-page.ts` (consent UI). |
+| 21 `vitest-pool-workers` integration tests | **Deferred (U17)** — workerd's CJS fallback rejects `ajv@^8`'s `require('./refs/data.json')`. Tracked as `it.todo` placeholders so the deferred contracts stay visible in test output. | `packages/mcp/src/__tests__/integration/*.test.ts`; unit-level coverage of each deferred contract lives in the sibling `*.test.ts` files. |
+| Tier 2 output-schema tools | **Deferred (U8)** — every read tool outside the curated Tier 1 set (`packrat_whoami`, `packrat_get_pack`, etc.) emits text-only output today. Annotations are enforced; structured output is the follow-up. | `packages/mcp/src/output-schemas.ts`; the list of Tier 2 categories is in [`runbook.md`](./runbook.md) § "U8 output envelopes → Tier 2 deferral". |
+| `apps/admin` MCP-integration tests | **Deferred** — `apps/admin` does not depend on the MCP Worker (the dual-mechanism admin guard preserves its HS256 path). No test coverage needed for U18. | `packages/api/src/routes/admin/index.ts` (admin guard); `apps/admin/app/login/page.tsx` (HS256 path). |
+| Zone-level WAF Rate Limiting Rules on the AS endpoints (`/oauth2/authorize`, `/oauth2/token`, `/.well-known/oauth-authorization-server`) — these live on `api.packrat.world` post-refactor | **TODO (operator)** — applied via the Cloudflare dashboard or Terraform, not code. | [`runbook.md`](./runbook.md) § "TODO (operator): zone-level WAF Rate Limiting Rules". |
+| OTel → Sentry pipeline | **TODO (operator)** — dashboard click-path documented; one-time setup per environment. | [`runbook.md`](./runbook.md) § "U15 observability → Operator TODO: enable the OTel → Sentry pipeline". |
+| Per-feature/per-tool fine-grained scopes (e.g. `mcp:trails:read`) | Out of scope per the plan; v1 ships with the four coarse scopes only. | The plan's "Scope Boundaries → Deferred to Follow-Up Work" section. |
+| "MCP Apps" surface (screenshots, declared link origins) | Out of scope per the plan; v1 submits as a Remote MCP / Directory listing. | Same plan section. |
+
+---
+
+## 8. Rejection-recovery playbook
+
+Anthropic's reviewers typically respond within ~2 weeks. Categorise any
+rejection by what it implicates so the response time matches the fix
+scope. (The taxonomy below mirrors the doc-review adversarial finding
+attached to the plan.)
+
+### Same-day fixable (text/asset edits, no deploy)
+
+| Cause | Fix |
+| --- | --- |
+| Description marked "vague" / "promotional" | Edit `apps/landing/app/mcp/page.tsx` + the short description in § 2 above; re-submit. No code deploy needed. |
+| Logo or favicon resolution / aspect-ratio issue | Re-render the SVG at the requested size; resubmit. The favicon served from the Worker only changes if `apps/landing/public/favicon.ico` is regenerated AND the base64 in `packages/mcp/src/favicon.ts` is bumped (see [`runbook.md`](./runbook.md) § "Refresh contract"). |
+| Reviewer test account locked / data sparse | Reset the password; re-populate per § 4; resubmit. |
+| Privacy / Terms link 404 | Confirm `apps/landing` deploy is green; redeploy if needed. |
+
+### Same-day fixable (code edit + tag push, < 1 hour)
+
+| Cause | Fix |
+| --- | --- |
+| Tool annotation missing (the #1 cause per Anthropic's docs) | The U7 catalog test (`packages/mcp/src/__tests__/annotations.test.ts`) would have caught this — investigate why CI passed. Add the annotation, re-run `bun packages/mcp/scripts/dump-catalog.ts`, commit, push `mcp-v` tag. |
+| Tool description triggers content policy | Edit the description in `packages/mcp/src/tools/*.ts`, re-dump the catalog, re-tag. |
+| Scope copy not specific enough | Edit `packages/mcp/src/scopes.ts` (descriptions are stable strings) and the docs page; re-tag. |
+| `/health` returns degraded | Check `wrangler tail --env prod` for the `mcp.health.degraded` log line; resolve the underlying KV or API outage. |
+
+### Multi-day to re-architect
+
+| Cause | Fix |
+| --- | --- |
+| OAuth callback URL allowlist incomplete | Add the new redirect URI to `CLAUDE_REDIRECT_URIS` in `packages/api/src/db/seed-claude-oauth-client.ts`, then re-run `cd packages/api && bun run db:seed:oauth-clients` (idempotent — updates the existing `oauthClient` row). Both currently-known callbacks (`claude.ai`, `claude.com`) are pre-registered. |
+| Audience binding rejected | The U2 OAuth provider upgrade + U3 metadata wiring should satisfy this; if not, audit `packages/mcp/src/metadata.ts` `canonicalResourceUrl` and confirm it matches the metadata's `resource` value exactly. |
+| WAF blocking Anthropic discovery probes | Add explicit allow rule for Anthropic's published IP ranges on `/.well-known/*` and `/mcp`. |
+| Connector rejected for category / audience mismatch | Re-classify per Anthropic's suggested category; update § 2. |
+| Architectural rejection (e.g. demand for SSO before listing) | Schedule the deferred U11 SSO follow-up; the cookie-domain blocker is documented in [`runbook.md`](./runbook.md) § "U11 login UX → What was NOT wired and why". |
+
+If the rejection is something **not** in the published taxonomy, treat
+it as a learning event:
+
+1. Reply to the rejection thread with concrete questions
+ (`hello@packratai.com` → Anthropic).
+2. Once resolved, write a `docs/solutions/` entry capturing the surprise
+ so the next connector submission benefits from the learning. The
+ plan's documentation plan calls this out explicitly: "connector-store
+ submission retro (Phase 5)".
+
+---
+
+## 9. Post-submission
+
+- Monitor `hello@packratai.com` for the Anthropic review thread; typical
+ turnaround is ~2 weeks per the plan's reference.
+- Once approved, write a `docs/solutions/` retro covering what surprised
+ you about the review process so the next connector submission
+ benefits from the institutional learning.
+- The deployed Worker is now in the "spec-immutable" regime — every
+ tool surface change fires `notifications/tools/list_changed` and the
+ `serverInfo` version bumps. Avoid changing tool input schemas in place;
+ add a new tool name instead.
+
+---
+
+## 10. See also
+
+- [`docs/mcp/runbook.md`](./runbook.md) — operator runbook (deploy,
+ secrets, scope model, login security, observability, readiness
+ script).
+- [`packages/mcp/README.md`](../../packages/mcp/README.md) —
+ developer-facing README.
+- [`packages/mcp/scripts/submission-readiness.ts`](../../packages/mcp/scripts/submission-readiness.ts)
+ — the cross-origin pre-submission probe (12 numbered checks plus the
+ 10b `/status` cross-check; updated by U7 for the AS-on-`api.packrat.world`
+ architecture).
+- [`apps/landing/app/mcp/page.tsx`](../../apps/landing/app/mcp/page.tsx)
+ — public docs page rendered at `packratai.com/mcp`.
+- [`docs/plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md`](../plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md)
+ — the implementation plan.
diff --git a/docs/plans/2026-05-20-001-fix-etl-pipeline-workflows-migration-plan.md b/docs/plans/2026-05-20-001-fix-etl-pipeline-workflows-migration-plan.md
index 62ed13acf1..3cb295e25f 100644
--- a/docs/plans/2026-05-20-001-fix-etl-pipeline-workflows-migration-plan.md
+++ b/docs/plans/2026-05-20-001-fix-etl-pipeline-workflows-migration-plan.md
@@ -296,8 +296,8 @@ Scheduled (CF Cron Trigger or scheduled workflow):
**Files:**
- Modify: `packages/db/src/schema.ts` (add columns to `etlJobs`; UNIQUE constraint on `catalogItemEtlJobs`)
-- Create: `packages/api/drizzle/0048_etl_workflow_columns.sql`
-- Create: `packages/api/drizzle/meta/0048_snapshot.json` (generated)
+- Create: a drizzle-kit-generated migration in `packages/api/drizzle/` (keep its random name; never rename the generated file)
+- Create: the matching snapshot in `packages/api/drizzle/meta/` (generated alongside the migration)
- Modify: `packages/api/drizzle/meta/_journal.json` (generated)
- Test: `packages/api/test/db-schema-etl.test.ts` (new — assert columns exist with expected defaults)
@@ -331,6 +331,7 @@ Scheduled (CF Cron Trigger or scheduled workflow):
- Error path: Re-running the migration is a no-op (Drizzle's migration log handles this).
**Verification:**
+- `cd packages/api && bunx drizzle-kit check` passes (validates the generated snapshot chain is internally consistent) — required before merge.
- `bun run --cwd packages/api db:migrate` applies cleanly against a fresh Docker Postgres + against a Postgres seeded with current-prod-shape `etl_jobs` rows.
- `bun lint:custom` passes.
- `bun test:api:unit` includes the new schema test and it passes.
@@ -386,7 +387,7 @@ Scheduled (CF Cron Trigger or scheduled workflow):
- `chunkCsvForR2`: producer-side row-boundary alignment with parallel 64KB peek reads (closes audit P1 #3/#4/#5 + the previously-flagged producer CPU budget concern). Returns `Array<{ chunkIndex, chunksTotal, byteStart, byteEnd }>` plus the captured `etag` + `lastModified`.
- Producer endpoint writes `etl_jobs` row with `source_etag`, `source_last_modified`, `workflow_instance_id`; then `env.ETL_WORKFLOW.create({ id: \`${source}-${filename}\`, params: { jobId, objectKey, source, scraperRevision, chunks } })`. The deterministic instance ID prevents duplicate triggers for the same file (Workflows rejects duplicate IDs).
- Producer's `?engine=queue` branch keeps the old `queueCatalogETL` flow for rollback. Removed in the Phase 1 cleanup PR after one week of bake.
-- Test uses Workflows' test harness (`@cloudflare/vitest-pool-workers`) or mocks the `step` object directly with an in-memory implementation that exercises memoization.
+- Test uses Workflows' test harness under the `@cloudflare/vitest-pool-workers` pool (required for all API unit tests per repo guidelines) with an implementation that exercises memoization.
**Patterns to follow:**
- Workflows quickstart: .
diff --git a/docs/plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md b/docs/plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md
new file mode 100644
index 0000000000..e1eac2484a
--- /dev/null
+++ b/docs/plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md
@@ -0,0 +1,992 @@
+---
+title: "feat: PackRat MCP Connector Store readiness"
+type: feat
+status: active
+date: 2026-05-22
+---
+
+# feat: PackRat MCP Connector Store readiness
+
+## Summary
+
+Close the gap between today's PackRat MCP Worker and the bar Anthropic enforces for the Claude Connector Store / Software Directory: a custom-domain Streamable HTTP server with OAuth 2.1 + PKCE S256 + RFC 8707 audience binding, RFC 9728 + RFC 8414 discovery metadata, scope-based admin gating (no parallel admin-token path), annotated tools, structured outputs and elicitations where they help, a branded login page with the existing Better Auth Google/Apple SSO, unified privacy/terms/support pages, rate-limiting and observability, and a reviewer-ready submission packet. This plan does not build net-new tools or rewrite the API — it hardens what exists and ships the listing artifacts a reviewer will inspect.
+
+---
+
+## Problem Frame
+
+The packrat MCP Worker (`packages/mcp`) was built as a thin Eden/Hono RPC façade over `@packrat/api`, with OAuth 2.1 wired via `@cloudflare/workers-oauth-provider` and a Durable-Object-backed `McpAgent`. It works, but it was shaped for "an MCP server we run for our own clients" — not for "a public connector that Anthropic's reviewers and end users will install through Claude.ai's directory". The submission bar (HTTPS custom domain, RFC 9728 metadata, audience-bound tokens, tool annotations, prompt-injection hygiene, privacy policy, branded consent, support contact, working reviewer test account, ≥3 example prompts) is well-specified by Anthropic and the MCP 2025-11-25 authorization spec, and the bulk of the gap is concrete and small per item — but spread across deployment config, OAuth surface, ~104 tools, login UX, public docs, observability, and CI/CD. Without a sequenced plan this fragments across many half-shipped PRs; with one, it should be a focused 4-phase push.
+
+A prior plan, `docs/plans/2026-04-30-feat-better-auth-migration-plan.md`, is the architectural parent of the current MCP. It is marked `status: completed` but several of its Phase-3 checkboxes (custom domain, DCR initial-access-token, `mcp.packratai.com` in `trustedOrigins`, OAuth scope design, pre-registering Claude as a trusted client) shipped only partially. This plan explicitly closes those open items as part of its work.
+
+---
+
+## Requirements
+
+- R1. The MCP server is reachable at a stable custom HTTPS subdomain owned by PackRat (e.g. `https://mcp.packratai.com`), with CA-signed TLS, and Streamable HTTP at `/mcp`.
+- R2. OAuth 2.1 + PKCE S256 + RFC 8707 audience binding is enforced; tokens are audience-bound to the MCP server; access tokens are short-lived; refresh tokens rotate.
+- R3. `/.well-known/oauth-protected-resource` (RFC 9728) and `/.well-known/oauth-authorization-server` (RFC 8414) are served and accurate, including `code_challenge_methods_supported: ["S256"]` and `scopes_supported`.
+- R4. Dynamic client registration is either disabled and replaced by admin-issued clients, or gated by an initial access token; in both cases the Claude callback hosts `https://claude.ai/api/mcp/auth_callback` and `https://claude.com/api/mcp/auth_callback` are explicitly allowlisted.
+- R5. Admin tools are gated by an OAuth scope (`mcp:admin`), not by the parallel `X-PackRat-Admin-Token` header or the `admin_login` tool, which are removed.
+- R6. Every user-callable tool carries the MCP annotations Anthropic requires: `title`, `readOnlyHint`, and — when `readOnlyHint` is false — `destructiveHint`; `idempotentHint` and `openWorldHint` are set honestly where applicable.
+- R7. Tool names are namespaced (`packrat_*`), have no read-vs-write switches in a single parameter, and use valid JSON Schemas with bounded result sizes and pagination on list-style tools.
+- R8. Resources expand beyond ID-based lookups: list providers for the user's packs/trips, a search resource template, and a static `packrat://glossary` resource describing domain terms.
+- R9. Destructive admin tools and ambiguous-input tools use MCP elicitations to confirm intent and disambiguate.
+- R10. The login page presents PackRat branding, Google and Apple SSO buttons (via the existing Better Auth social providers), a password-reset path, the requesting client's name, and links to terms, privacy, and support.
+- R11. A public, HTTPS Privacy Policy and Terms of Service exist on a single canonical domain; a public support contact (email and URL) is surfaced from `/health`, the login page, and the listing.
+- R12. Public MCP docs exist (`packages/mcp/README.md`, a public docs page on the landing site) with a connection guide, the full tool catalog with annotations, ≥3 example prompts, and a reviewer test account.
+- R13. Rate limiting is in place at both the Worker layer (per-user, per-tool) and the zone layer (anonymous endpoints), plus a KV `purgeExpiredData` cron.
+- R14. Errors are observable: Sentry via OTel pipeline, structured logging on the OAuth surface, an `onError` hook on `OAuthProvider`, audit logs for admin actions, and a real `/health` that probes KV + API.
+- R15. CI runs lint/type-check/test for `packages/mcp` on every PR and deploys on a tag, including integration tests against `@cloudflare/vitest-pool-workers` that cover the OAuth flow and scope-based tool gating.
+- R16. A submission packet is assembled for Anthropic's Google Form (description, category, callback URLs, test account, prompts, logo, favicon, support URL), pre-submission validation passes, and the form is filed.
+
+---
+
+## Scope Boundaries
+
+- No new tools beyond the existing ~104; no rewrite of the API or `packages/api-client`.
+- No deeper rewrite of the OAuth provider, MCP SDK, or Cloudflare Agents SDK — adopt their current patterns and bump versions, do not fork.
+- No mobile/web app changes outside what landing-site Privacy/Terms/MCP-docs pages require.
+- No expansion of admin capabilities or new admin tools — only the gating mechanism changes.
+- No App Store / Play Store / Vercel-style submissions; the only target is the Anthropic Claude Connector Store.
+- No SLO contract beyond "best-effort 99.5%"; no paid support channel; no enterprise/tenant tiers.
+
+### Deferred to Follow-Up Work
+
+- Per-feature/per-tool fine-grained scopes (e.g., `mcp:trails:read`, `mcp:packs:write`): the v1 listing ships with `mcp`, `mcp:read`, `mcp:write`, and `mcp:admin` only; finer scopes are a follow-up once Anthropic and users provide feedback.
+- "MCP Apps" surface (Anthropic's app-style listing with screenshots and `ui/open-link`): v1 submits as a Remote MCP / Directory listing; pursuing the richer MCP Apps surface (screenshots, declared link origins, app-style chrome) is a follow-up after the first listing is approved.
+- DO-backed per-tenant quota counters: skipped in v1; revisit if abuse patterns demand it.
+- SSO buttons on the MCP login page (conditional fallback per U11 if integration cost is higher than the marginal-cost estimate above): defer to a follow-up PR after the listing is approved.
+- Postgres-backed session storage (Agents SDK v0.13 experimental): not adopted; SQLite-backed DO is fine for v1.
+- Promotion to Anthropic's "Prebuilt Integrations" tier — not a self-serve path; out of scope.
+
+---
+
+## Context & Research
+
+### Relevant Code and Patterns
+
+- `packages/mcp/src/index.ts` — `PackRatMCP` DO + `OAuthProvider` config; current admin-gating, feature-flag, and bearer-fallback paths.
+- `packages/mcp/src/auth.ts` — `/authorize`, `/login` (GET/POST), `/callback`, `/health`; the dev-grade login page and missing CSRF/Origin/rate-limit story.
+- `packages/mcp/src/client.ts` — `call()`, `ok()`, `errMessage()` helpers; the only tested file. The error envelope here is what scope-gated tool failures will need to flow through.
+- `packages/mcp/src/constants.ts` — `ServiceMeta` (currently `'1.0.0'`, stale) and `WorkerRoute` (target for adding `.well-known/*` paths).
+- `packages/mcp/src/tools/*.ts` — 18 tool registration modules totalling ~104 tools; the annotation, naming, structured-output, and pagination changes land here.
+- `packages/mcp/src/resources.ts` — 4 templated resources, all by ID; the list-provider/search/glossary work extends this file.
+- `packages/mcp/src/prompts.ts` — 4 prompts that hard-reference tool names; needs sync after tool renames.
+- `packages/mcp/wrangler.jsonc` — `__TODO_OAUTH_KV_*_ID__` placeholders, no `routes` block, no `env.prod`, redundant migrations.
+- `packages/api/src/auth/index.ts` — Better Auth setup (lines 106-131); Google + Apple social providers are already configured. `trustedOrigins` (line 158) does NOT include `mcp.packratai.com` — add it.
+- `apps/landing/app/privacy-policy/page.tsx` — existing privacy policy on `packratai.com`; needs (a) MCP-specific addendum and (b) domain unification with the MCP `/health` `docs` URL.
+- `apps/landing/config/site.ts` — footer + support contact (`mailto:hello@packratai.com`); only "Privacy" is in the legal section, "Terms" is missing.
+- `docs/plans/2026-04-30-feat-better-auth-migration-plan.md` — architectural parent; its Phase 3 unchecked items (DCR, scope design, custom domain, trustedOrigins) become this plan's targets.
+- `docs/plans/2026-04-15-001-refactor-hono-rpc-foundation-plan.md` — global 500 error contract pattern; mirror in MCP error envelope so tool errors don't double-wrap.
+
+### Institutional Learnings
+
+- `docs/solutions/developer-experience/better-auth-cli-cloudflare-worker-factory-2026-05-02.md` — when changing Better Auth scope/plugin config, regenerate the schema via `bunx auth generate --config src/auth/auth.config.ts`. The MCP `mcp:admin` scope addition is unlikely to touch the schema (it's an OAuth provider concept, not a Better Auth role), but plugin or `additionalFields` changes in lockstep with this plan must update both `auth/index.ts` and `auth/auth.config.ts`.
+- No `docs/solutions/` entries exist for Cloudflare custom domains, Workers observability, Turnstile/WAF, MCP server design, or any prior marketplace submission. This is greenfield institutional territory — the connector-store push should produce `docs/solutions/` entries for: custom-domain promotion runbook, observability stack decision, rate-limit split, and "first connector-store submission" retro.
+
+### External References
+
+- [Anthropic — Building Connectors](https://claude.com/docs/connectors/building) — Streamable HTTP, OAuth scopes, callback URLs, capabilities.
+- [Anthropic — Submitting to the Connectors Directory](https://claude.com/docs/connectors/building/submission) — submission form, rejection reasons (annotations ~30%, missing privacy = immediate reject, OAuth callback allowlist).
+- [Anthropic Software Directory Policy](https://support.claude.com/en/articles/13145358-anthropic-software-directory-policy) — banned categories, content rules, ≥3 example prompts, domain ownership.
+- [MCP Authorization spec 2025-11-25](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization) — RFC 8414, 7591, 9728, 8707; `WWW-Authenticate: Bearer resource_metadata` requirement; PKCE S256; no token passthrough.
+- [MCP Security Best Practices 2025-11-25](https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices) — Origin validation, session ID binding (`:`), confused-deputy mitigation.
+- [MCP Tools spec 2025-06-18](https://modelcontextprotocol.io/specification/2025-06-18/server/tools) — `outputSchema` / `structuredContent`, `isError` for execution errors, annotation semantics.
+- [@cloudflare/workers-oauth-provider README](https://github.com/cloudflare/workers-oauth-provider) — `disallowPublicClientRegistration`, `allowPlainPKCE: false`, `resourceMetadata`, `onError`, `purgeExpiredData`, `createClient`.
+- [cloudflare/ai demos/remote-mcp-github-oauth](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-github-oauth) — the canonical reference; `oauth:state:${randomUUID}` keys, `__Host-` cookies, conditional tool registration.
+- [Workers Rate Limiting binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/) — per-key 10s/60s windows; key by `${userId}:${toolName}`.
+- [Cloudflare Workers Observability — OTel/Sentry](https://nerdleveltech.com/cloudflare-workers-observability-workers-logs-sentry-tutorial) — current Cloudflare guidance for Sentry on Workers (OTel pipeline, not Tail Workers).
+
+---
+
+## Key Technical Decisions
+
+- **Custom domain `mcp.packratai.com`.** Aligns with the Better Auth migration plan, gives reviewers a stable, brand-aligned URL, and matches what the OAuth provider's `resourceMetadata.resource` field will advertise to Claude. Reject the `*.workers.dev` shortcut — known reviewer red flag.
+- **Domain unification: `packratai.com` is the canonical brand domain.** The landing site already lives there with the privacy policy. The MCP `/health` will reference `https://packratai.com/docs/mcp`. The MCP server itself stays at `mcp.packratai.com`. We do *not* try to migrate the landing site domain in this plan — too much blast radius.
+- **OAuth scopes: `mcp`, `mcp:read`, `mcp:write`, `mcp:admin`.** Coarse-grained four-level model. `mcp` retained as backwards-compatible umbrella for currently-registered clients. `mcp:admin` becomes the gate for all admin tools; the `admin_login` tool and `X-PackRat-Admin-Token` header path are removed entirely (admin users acquire the admin scope at OAuth time via a backend-issued grant, not via a runtime tool call). Finer-grained per-domain scopes are deferred.
+- **DCR posture: dual mechanism.** Configure `clientRegistrationEndpoint: '/register'` AND wire `MCP_INITIAL_ACCESS_TOKEN` enforcement in the `defaultHandler` (per the workers-oauth-provider README's gating pattern), AND pre-register both `claude.ai` and `claude.com` callback hosts via `env.OAUTH_PROVIDER.createClient()` from an admin route so Claude.ai users hit a pre-approved client and can skip the consent screen.
+- **MCP SDK version line: stay on `1.x`.** v2.0 is alpha (Apr 2026) and changes error semantics (`-32602` for unknown tools instead of `isError`). Bump to `^1.29.0` and pin transitively so it stays aligned with `agents@^0.13.2`.
+- **OAuth provider version: `^0.7.0`.** The currently-installed `0.4.0` already exposes `onError`, `resourceMetadata`, `disallowPublicClientRegistration`, and `createClient` — so U3/U4 are not blocked on a bump. The real reasons to upgrade: `purgeExpiredData` (required by U14's KV cron), Client ID Metadata Document (CIMD) support, and incidental security/bug fixes shipped in 0.5/0.6/0.7. Treat the bump as U14's dependency, not U3's.
+- **Tool annotations: explicit on every tool, not relying on defaults.** Defaults are dangerous for reviewers — `destructiveHint` defaults to `true`, so a read-only tool that omits the annotation gets a confirmation prompt. Set every flag explicitly.
+- **Tool naming: `packrat_*` prefix on all user tools.** Prevents collisions with other installed connectors. Admin tools keep their `admin_*` prefix but additionally get the namespace, becoming `packrat_admin_*`. Pre-existing names without the prefix are removed entirely (no backwards-compatible aliases — this is a connector-store v1 break that ships before any public listing).
+- **Replace manual `tools/list_changed` emission with SDK's built-in.** Use the `RegisteredTool` handle's `.enable()/.disable()` (already does it) and `this.server.sendToolListChanged()` for explicit cases. Removes a parallel code path we have to maintain.
+- **Error envelope: dual signal.** Recoverable tool failures return `{ content: [...], isError: true, structuredContent: { error: { code, message } } }` to satisfy both LLM-readable text and structured consumers. Protocol-level failures (bad args, unknown tool) throw and let the SDK surface JSON-RPC errors.
+- **Rate-limit split.** Workers Rate Limiting binding keyed by `${props.userId}:${toolName}` at 60/60s for authenticated tool calls. Zone-level WAF Rate Limiting Rules at ~100/s/IP on `/register`, `/authorize`, `/token` for anonymous endpoints. No DO-backed limiter in v1.
+- **Observability stack: Sentry via OTel pipeline + Workers Logs.** Configure the OTel pipeline in the Cloudflare dashboard (no code), use `onError` on `OAuthProvider` for explicit OAuth error capture, structured-log every admin action with a correlation ID. Skip Tail Workers and Logpush.
+- **SSO included.** Google and Apple are already configured in Better Auth (`packages/api/src/auth/index.ts:106-131`); the MCP login page just renders buttons that initiate the Better Auth social flow and route the callback back through OAuth state. Marginal cost, large reviewer-perception gain.
+- **Elicitations: limited blast radius.** Only used where they directly help — destructive admin tools (confirm-delete) and ambiguous search (resolve which `trail` the user means). Not added speculatively across the whole catalog.
+- **Glossary as a resource, not a tool.** Static `packrat://glossary` resource describing pack/trip/gear/trail terminology, so Claude can read it once into context and stop fumbling vocabulary — and reviewers see a thoughtful resource catalog beyond CRUD.
+
+---
+
+## Open Questions
+
+### Resolved During Planning
+
+- **DCR open or gated?** Gate via `MCP_INITIAL_ACCESS_TOKEN` AND pre-register Claude's callback URLs. Hybrid approach matches the OAuth provider's grain and removes the open-`/register` finding.
+- **Admin gating mechanism?** OAuth scope `mcp:admin`, not the parallel admin-token path. Confirmed during scope dialogue with the user.
+- **SSO in v1?** Yes — Better Auth providers already exist, MCP login page just needs UI.
+- **Per-tool fine-grained scopes (`mcp:trails:read` etc.)?** Deferred to a follow-up; v1 ships with four coarse scopes.
+- **Tool namespace?** `packrat_*` prefix on every user tool; remove unprefixed names without compatibility aliases (pre-listing break).
+- **MCP SDK major: stay on 1.x or jump to 2.0 alpha?** Stay on `^1.29.0` for connector submission.
+- **Custom domain choice?** `mcp.packratai.com`.
+- **Landing-site domain unification?** Defer the full `packrat.world ↔ packratai.com` reconciliation; align the MCP `/health` `docs` URL with the landing site's actual domain (`packratai.com`) and stop there.
+
+### Deferred to Implementation
+
+- Exact wording of the legal/privacy MCP addendum — drafted during U12; reviewed by anyone with legal context the team designates.
+- Exact list of tools that warrant elicitations (beyond the 5-6 destructive admin tools that are obvious from U10's scenarios) — discovered while writing the integration tests.
+- Whether to migrate the `admin_login` tool's job (one-off admin JWT exchange) onto a `mcp:admin`-scope `whoami_admin` resource or simply remove it without replacement — decided in U5 once the scope-issuance path is built.
+- Whether to bind Claude's pre-registered client to a specific `audience` value or accept default — discovered during U4 when calling `createClient()`.
+- Whether to emit Workers Analytics Engine events for per-tool metrics (rather than relying on Sentry events) — decided in U15 once the volume estimate is clearer.
+
+---
+
+## High-Level Technical Design
+
+> *This illustrates the intended approach and is directional guidance for review, not implementation specification. The implementing agent should treat it as context, not code to reproduce.*
+
+### Connector flow after this plan lands
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant U as User
+ participant C as Claude.ai
+ participant M as MCP Worker mcp.packratai.com
+ participant B as Better Auth packratai.com API
+ participant S as Sentry/OTel
+
+ Note over C,M: Discovery
+ C->>M: GET /.well-known/oauth-protected-resource
+ M-->>C: { authorization_servers: ["https://mcp.packratai.com"], resource: ".../mcp", scopes: [...] }
+ C->>M: GET /.well-known/oauth-authorization-server
+ M-->>C: { code_challenge_methods_supported: ["S256"], scopes_supported: [...], ... }
+
+ Note over C,M: Authorization (pre-registered client; PKCE S256; RFC 8707 resource)
+ C->>M: GET /authorize?client_id=claude&scope=mcp+mcp:read+mcp:write&resource=mcp.packratai.com&code_challenge=...
+ M->>U: Branded /login (Google / Apple / email+password, terms/privacy/support links)
+ alt SSO
+ U->>B: Sign in with Google/Apple
+ B-->>M: Better Auth session token (via callback)
+ else Email+password
+ U->>M: POST /login (Origin-checked, rate-limited)
+ M->>B: POST /api/auth/sign-in/email
+ B-->>M: session token + userId + roles
+ end
+ M->>M: Determine OAuth scopes from user role (admins get mcp:admin)
+ M-->>C: /callback redirect with auth code
+
+ C->>M: POST /token (PKCE verifier, resource=mcp.packratai.com)
+ M-->>C: access_token (audience-bound) + refresh_token (rotating)
+
+ Note over C,M: Tool calls (per-user/per-tool rate-limited; structuredContent)
+ C->>M: POST /mcp tools/call packrat_get_pack { packId }
+ M->>M: Check scopes; check rate-limit ${userId}:${toolName}
+ M->>S: structured log + Sentry breadcrumb
+ M-->>C: { content: [...], structuredContent: {...}, isError: false }
+
+ Note over C,M: Tool-list updates after scope change
+ M->>C: notifications/tools/list_changed (SDK auto-emit on .enable()/.disable())
+```
+
+### Scope-to-tool gating model
+
+| Token scopes | Visible tool prefixes | Notes |
+|---|---|---|
+| `mcp` | all read tools (`packrat_get_*`, `packrat_list_*`, `packrat_search_*`) | Back-compat umbrella for any client registered before scope split |
+| `mcp:read` | `packrat_get_*`, `packrat_list_*`, `packrat_search_*` | Same as `mcp` but explicit |
+| `mcp:write` | all `mcp:read` + `packrat_create_*`, `packrat_update_*`, `packrat_delete_*` (with destructiveHint), `packrat_submit_*` | Default scope Claude.ai requests |
+| `mcp:admin` | all `mcp:write` + `packrat_admin_*` (28 tools) | Only granted to users with admin role at sign-in |
+
+Gating uses the SDK's `.enable()/.disable()` on the `RegisteredTool` handle. `init()` registers everything; a per-session "scope filter" pass disables anything the granted scopes don't authorize, and emits `notifications/tools/list_changed` automatically.
+
+---
+
+## Output Structure
+
+```
+packages/mcp/
+ src/
+ auth.ts # rewritten: SSO buttons, CSRF, origin check, rate limit, password-reset link, structured /health
+ glossary.ts # NEW: static glossary content
+ metadata.ts # NEW: RFC 9728/8414 metadata customization, well-known wiring
+ scopes.ts # NEW: scope constants + scope-to-tool gating logic
+ rate-limit.ts # NEW: Workers Rate Limiting binding wrapper
+ observability.ts # NEW: structured logger + Sentry/OTel helpers
+ index.ts # rewritten: scope-based gating replaces admin token path; new well-known + telemetry wiring
+ resources.ts # extended: list providers, search template, glossary resource
+ prompts.ts # updated: refer to renamed packrat_* tools
+ tools/ # every file touched for annotations + naming + outputSchema + elicitations
+ admin.ts # elicitInput on destructive ops
+ packs.ts, trips.ts, ... # annotations, naming, output schemas
+ auth.ts # admin_login removed; whoami stays
+ __tests__/
+ auth.test.ts # NEW: OAuth flow + login form + SSO redirect
+ scopes.test.ts # NEW: scope-based gating
+ annotations.test.ts # NEW: every tool has required annotations
+ resources.test.ts # NEW: list providers + glossary
+ elicitations.test.ts # NEW: destructive tool confirmations
+ integration/ # NEW dir: @cloudflare/vitest-pool-workers
+ oauth-flow.test.ts
+ tool-gating.test.ts
+ well-known.test.ts
+ wrangler.jsonc # rewritten: env.prod, custom domain route, rate-limit binding, cron, real KV IDs
+ README.md # NEW: connection guide, tool catalog, example prompts, reviewer test account
+
+apps/landing/app/
+ mcp/page.tsx # NEW: public docs page (connection, tools, examples)
+ terms-of-service/page.tsx # NEW
+ privacy-policy/page.tsx # extended: MCP addendum (data scopes, OAuth tokens, retention)
+
+apps/landing/config/site.ts # extended: Terms in legal block; MCP support contact
+
+docs/mcp/ # NEW: deeper internal-facing MCP docs (architecture, runbook)
+ README.md
+ runbook.md
+ submission-packet.md # the artifacts assembled in U17
+
+.github/workflows/
+ mcp-test.yml # NEW: lint/type-check/test/integration on PR
+ mcp-deploy.yml # NEW: deploy on tag
+
+docs/solutions/ # NEW entries written *after* each phase
+ conventions/mcp-tool-annotations-2026-MM-DD.md
+ tooling-decisions/mcp-observability-stack-2026-MM-DD.md
+ tooling-decisions/cloudflare-rate-limit-split-2026-MM-DD.md
+ conventions/mcp-custom-domain-promotion-2026-MM-DD.md
+```
+
+---
+
+## Implementation Units
+
+### U1. Production deploy configuration
+
+**Goal:** Make the MCP Worker actually deployable to production at `mcp.packratai.com` with real KV namespaces, custom domain route, an explicit `env.prod`, and unified version/identity across `package.json`, `McpServer`, `ServiceMeta`, and `/health`.
+
+**Requirements:** R1
+
+**Dependencies:** None
+
+**Files:**
+- Modify: `packages/mcp/wrangler.jsonc`
+- Modify: `packages/mcp/package.json` (version alignment)
+- Modify: `packages/mcp/src/constants.ts` (`ServiceMeta` derives from `package.json`)
+- Modify: `packages/mcp/src/index.ts` (`McpServer({ version })` reads from `ServiceMeta`)
+- Modify: `packages/mcp/src/auth.ts` (`/health` returns `ServiceMeta.Version`, not a hardcoded string)
+- Create: `packages/mcp/.dev.vars.example` updates documenting all required secrets
+- Create: `docs/mcp/runbook.md` (deploy + secret rotation steps)
+
+**Approach:**
+- Create real Cloudflare KV namespaces for prod + dev via `wrangler kv namespace create`. Replace both `__TODO_OAUTH_KV_*_ID__` placeholders. Keep `preview_id` on dev only.
+- Add a `routes` block binding the Worker to `mcp.packratai.com/*` (production) with `custom_domain: true`. Document the DNS CNAME / route configuration in the runbook.
+- Add an explicit `env.prod` block with the worker name `packrat-mcp` so `wrangler deploy --env prod` is unambiguous; top-level config becomes the dev base.
+- Centralize the version string: import it from `package.json` (TS allows `import pkg from '../package.json' with { type: 'json' }`), expose as `ServiceMeta.Version`, and use everywhere — kills the four-way drift.
+- Document every required secret (`PACKRAT_API_URL`, `MCP_INITIAL_ACCESS_TOKEN`, optional `MCP_FEATURE_FLAGS`, Sentry DSN once U15 lands) in `.dev.vars.example` and `docs/mcp/runbook.md`.
+
+**Patterns to follow:**
+- `cloudflare/agents-starter/wrangler.jsonc` for the canonical multi-env shape.
+- `packages/api/wrangler.jsonc` for any PackRat-specific conventions already followed by the API Worker.
+
+**Test scenarios:**
+- Happy path: `wrangler deploy --env prod --dry-run` succeeds with real KV IDs and the route block.
+- Edge case: `wrangler dev` against `env.dev` still mounts at the local URL and serves `/health`.
+- Happy path: `/health` JSON includes the version from `package.json`, not `1.0.0`.
+- Test expectation: a small unit test on `ServiceMeta.Version === pkg.version` to lock the drift down.
+
+**Verification:**
+- A dry-run prod deploy is clean.
+- `/health` on dev returns the package.json version.
+- `docs/mcp/runbook.md` lists every step a fresh engineer needs to deploy.
+
+---
+
+### U2. Dependency bumps and elicitation audit
+
+**Goal:** Bring `@modelcontextprotocol/sdk`, `@cloudflare/workers-oauth-provider`, and `agents` to current stable, audit for breaking-change-driven code changes (especially elicitation routing in Agents 0.13).
+
+**Requirements:** R2, R6, R9
+
+**Dependencies:** U1 (deploy stability so a failed bump can be reverted cleanly)
+
+**Files:**
+- Modify: `packages/mcp/package.json` (`@modelcontextprotocol/sdk` → `^1.29.0`; `@cloudflare/workers-oauth-provider` → `^0.7.0`; `agents` → `^0.13.2`)
+- Modify: `bun.lock`
+- Modify: `packages/mcp/src/index.ts` (any constructor-arg or capability-shape adjustments)
+- Modify: `packages/mcp/src/tools/*.ts` (only where existing `elicitInput` calls exist — likely none today)
+
+**Approach:**
+- Bump in one commit; let TypeScript surface the breaking changes via `bun check-types`.
+- Per the framework research, audit `elicitInput` call sites for v0.13's required `{ relatedRequestId: extra.requestId }` argument. There are no current call sites, but lock the convention in test scaffolding for U10.
+- Verify the bundled `@modelcontextprotocol/sdk` inside `agents@0.13.2` matches the top-level pinned version (single SDK instance is required).
+- Re-run all existing tests + lint + type-check; do not add new test scenarios in this unit — coverage of new behavior lives in the units that depend on it.
+
+**Patterns to follow:**
+- `bun upgrade --filter @packrat/mcp` for the bump itself.
+- Existing dependency-bump plans in `docs/plans/2026-04-14-chore-finalize-dependabot-consolidation-plan.md` for any project-specific conventions.
+
+**Test scenarios:**
+- Happy path: `bun test --filter @packrat/mcp` passes unchanged.
+- Happy path: `bun check-types` passes.
+- Edge case: a fresh `bun install` resolves to a single `@modelcontextprotocol/sdk` version in the workspace (no duplicate copies).
+
+**Verification:**
+- Lockfile shows a single resolved version of MCP SDK.
+- Existing tests still pass; type-check is clean.
+
+---
+
+### U3. RFC 9728 + RFC 8414 metadata wiring
+
+**Goal:** Serve accurate, customized OAuth metadata at both `.well-known/*` endpoints with the custom domain as the resource, ensure `code_challenge_methods_supported: ["S256"]` and `scopes_supported` advertise correctly, and emit `WWW-Authenticate: Bearer resource_metadata="…"` on 401 from `/mcp`.
+
+**Requirements:** R3, R4
+
+**Dependencies:** U1, U2
+
+**Files:**
+- Create: `packages/mcp/src/metadata.ts`
+- Modify: `packages/mcp/src/index.ts` (pass `resourceMetadata` option to `OAuthProvider`; add 401 `WWW-Authenticate` header in `mcpApiHandler` failure paths)
+- Modify: `packages/mcp/src/constants.ts` (add `.well-known/*` paths to `WorkerRoute`)
+- Test: `packages/mcp/src/__tests__/integration/well-known.test.ts`
+
+**Approach:**
+- Provider already auto-emits both endpoints; override only the resource URL to match the custom domain: `resourceMetadata: { resource: 'https://mcp.packratai.com/mcp', authorization_servers: ['https://mcp.packratai.com'], scopes_supported: ['mcp', 'mcp:read', 'mcp:write', 'mcp:admin'], bearer_methods_supported: ['header'], resource_name: 'PackRat MCP' }`.
+- Advertise all four scopes in `OAuthProvider.scopesSupported` (visible in `/.well-known/oauth-authorization-server`).
+- Update `mcpApiHandler.fetch` (or thread through the OAuth provider's `apiHandler` flow) to set `WWW-Authenticate: Bearer resource_metadata="https://mcp.packratai.com/.well-known/oauth-protected-resource", scope="mcp"` on every 401.
+
+**Test scenarios:**
+- Happy path: `GET /.well-known/oauth-protected-resource` returns JSON with `resource`, `authorization_servers`, `scopes_supported`.
+- Happy path: `GET /.well-known/oauth-authorization-server` returns `code_challenge_methods_supported: ["S256"]` (without it, MCP clients refuse to proceed per spec).
+- Error path: A request to `/mcp` with no token returns 401 with `WWW-Authenticate` containing `resource_metadata=...` and `scope=...`.
+- Integration: With the worker running locally, an MCP Inspector connection auto-discovers both endpoints and the scopes list.
+
+**Verification:**
+- An MCP client can complete metadata discovery against the local worker with no manual config.
+- `curl` on both `.well-known/*` returns the customized resource URL.
+
+---
+
+### U4. Lock down dynamic client registration + pre-register Claude
+
+**Goal:** Ensure `/register` is not open to the public, AND pre-register both Claude callback URLs as trusted clients so users skip the consent screen on first connect.
+
+**Requirements:** R4
+
+**Dependencies:** U3
+
+**Files:**
+- Modify: `packages/mcp/src/index.ts` (intercept `/register` in `PackRatAuthHandler` to enforce `Authorization: Bearer `; set `disallowPublicClientRegistration: true`)
+- Modify: `packages/mcp/src/auth.ts` (`/register` interception logic; new `/admin/clients` endpoint requiring `mcp:admin` scope that calls `env.OAUTH_PROVIDER.createClient()`)
+- Create: `packages/mcp/scripts/register-claude-clients.ts` (one-shot script run by an operator; reads `MCP_INITIAL_ACCESS_TOKEN`, registers both `https://claude.ai/api/mcp/auth_callback` and `https://claude.com/api/mcp/auth_callback`)
+- Test: `packages/mcp/src/__tests__/auth.test.ts` (new — register flow)
+
+**Approach:**
+- In `PackRatAuthHandler.fetch`, before the route table, intercept `POST /register`. If `Authorization: Bearer ` is missing or mismatched, return 401 with the standard `WWW-Authenticate` header.
+- Pass `disallowPublicClientRegistration: true` to `OAuthProvider` for defense-in-depth.
+- Add an admin-scoped Worker route `POST /admin/clients` that calls `env.OAUTH_PROVIDER.createClient({ redirectUris: [...], clientName, ... })` and returns the issued client ID + secret. Protected by the `mcp:admin` scope (U5 dependency landed by the time this is callable, but the route can be authored now with a temporary check).
+- The `register-claude-clients.ts` script is run once by an operator with the initial access token, pre-registering both Claude callback URLs and pinning the client name to "Claude" so the consent page (if shown) is recognizable.
+
+**Test scenarios:**
+- Error path: `POST /register` with no Authorization header returns 401 + `WWW-Authenticate`.
+- Error path: `POST /register` with wrong bearer returns 401.
+- Happy path: `POST /register` with the matching initial access token returns 201 + client credentials.
+- Happy path: `POST /admin/clients` from a `mcp:admin` token registers a client; from a `mcp:read` token returns 403.
+- Integration: After running `register-claude-clients.ts`, the OAuth flow from `claude.ai` does not show a consent screen.
+
+**Verification:**
+- `/register` returns 401 to unauthenticated clients.
+- Two pre-registered clients exist in KV after running the script.
+
+---
+
+### U5. OAuth scope model + scope-based admin gating
+
+**Goal:** Define four scopes (`mcp`, `mcp:read`, `mcp:write`, `mcp:admin`), grant `mcp:admin` only to users with the admin role at sign-in, gate every admin tool on the granted scope, and remove the parallel `admin_login` tool and `X-PackRat-Admin-Token` header path entirely.
+
+**Requirements:** R5, R6
+
+**Dependencies:** U2, U3, U4, U6 (Better Auth `trustedOrigins` must contain `mcp.packratai.com` *before* U5's `/callback` handler issues role-based scope grants via `getAuth(env).api.getSession()` — otherwise the session lookup is rejected as untrusted-origin. U5 and U6 can also land in a single atomic PR; either approach satisfies the constraint.)
+
+**Files:**
+- Create: `packages/mcp/src/scopes.ts` (scope constants, `getVisibleTools(scopes): string[]`, scope-to-tool mapping)
+- Modify: `packages/mcp/src/index.ts` (remove `registerAdminTool`, `setAdminToken`, `syncAdminToolVisibility`, `BEARER_REGEX` admin header path; add scope-aware tool gating in `init`)
+- Modify: `packages/mcp/src/auth.ts` (after Better Auth sign-in, look up user role; if admin, include `mcp:admin` in granted scopes via `completeAuthorization({ scope, ... })`)
+- Modify: `packages/mcp/src/types.ts` (`Props.adminToken` removed; `Props.scopes: string[]` added)
+- Modify: `packages/mcp/src/client.ts` (`createMcpClients` no longer takes `getAdminToken`; the `admin` Treaty client uses the same `getUserToken` bearer as the user client — the API enforces admin role on the bearer)
+- Modify: `packages/mcp/src/tools/admin.ts` (use `agent.server.registerTool` then `.disable()` if `mcp:admin` not in granted scopes; remove `admin_login`)
+- Modify: `packages/mcp/src/tools/auth.ts` (remove `admin_login`; keep `whoami`, `logout`)
+- Modify: every other `packages/mcp/src/tools/*.ts` (use the scope-aware registration helper for read vs. write classification)
+- Modify: `packages/api/src/routes/admin/index.ts` (extend `adminAuthGuard` — and any sibling admin route guard — to also accept a Better Auth bearer whose `user.role === 'ADMIN'`, in addition to the existing HS256 `packrat-admin` JWT; the JWT path stays as a back-compat alternative for the legacy `apps/admin` flow but is no longer the only mechanism)
+- Modify: `packages/api/src/routes/admin/__tests__/` (extend existing admin auth tests to cover the Better Auth admin-role acceptance path)
+- Test: `packages/mcp/src/__tests__/scopes.test.ts` (gating matrix)
+- Test: extend `packages/api/src/routes/admin/__tests__/` (admin role bearer acceptance, non-admin bearer rejection)
+
+**Approach:**
+- `scopes.ts` declares the four scope strings and exports a `classifyTool(name): 'read'|'write'|'admin'` plus a `visibleScopes(name): Set` function. Tool names declare their classification via a registration-helper wrapper (`agent.registerReadTool`, `agent.registerWriteTool`, `agent.registerAdminTool`) that records the classification. **Classify `packrat_execute_sql_query` and `packrat_get_database_schema` as `admin` explicitly** — they don't match the read prefix pattern and exposing them to `mcp:read`/`mcp:write` is a data-access over-grant (per doc-review finding D3).
+- During `init()`, all tools are registered. After `init()`, the agent reads `props.scopes` (set at OAuth time) and disables every tool whose classification isn't covered.
+- The Better Auth API exposes a `user.role` field; in the `/callback` handler, after the sign-in completes, look it up via `getAuth(env).api.getSession()` and append `mcp:admin` to `granted` scopes if the user is an admin.
+- **Admin authentication on the API side: unify on the Better Auth bearer.** Per the resolved D1 decision, the API's `adminAuthGuard` is extended to accept *either* (a) the legacy HS256 `packrat-admin` JWT — kept for back-compat with `apps/admin` — *or* (b) a Better Auth bearer whose session resolves to `user.role === 'ADMIN'`. The MCP Worker uses path (b) exclusively: admin tools just send the same Better Auth bearer as user tools, and the API gates them by role. This removes the need for MCP to mint or hold a parallel admin JWT, eliminates the `getAdminToken` Treaty hook, and removes `BETTER_AUTH_SECRET` from MCP's required-secrets list.
+- The `requested_scopes` parameter from Claude is intersected with the user's eligible scopes; clients can request `mcp:admin` but only admin users receive it. Document this in `docs/mcp/runbook.md`.
+- The `admin_login` tool and the `X-PackRat-Admin-Token` header path are deleted, not soft-disabled. Audit the `tools/admin.ts` registrations to ensure none rely on the removed mechanism. Run a concrete grep across `apps/`, `packages/`, `docs/`, `scripts/`, `.github/workflows/` for any consumer of `admin_login` / `X-PackRat-Admin-Token` and record the audit result in `docs/mcp/runbook.md` before merging.
+
+**Test scenarios:**
+- Happy path: A token with `["mcp:read"]` lists only `packrat_get_*` / `packrat_list_*` / `packrat_search_*` tools.
+- Happy path: A token with `["mcp:read", "mcp:write"]` adds create/update/delete tools.
+- Happy path: A token with `["mcp:read", "mcp:write", "mcp:admin"]` adds `packrat_admin_*`.
+- Edge case: A token with the legacy `["mcp"]` umbrella scope lists read tools (back-compat).
+- Error path: Calling `packrat_admin_hard_delete_user` with `mcp:write` only returns the MCP "tool not found" error (because it's disabled), not 401 from the API.
+- Error path: A request with the (removed) `X-PackRat-Admin-Token` header has no effect on tool visibility.
+- Integration: After OAuth completes for an admin user, `tools/list` includes admin tools; for a non-admin user, it does not.
+
+**Verification:**
+- The `admin_login` tool no longer appears in `tools/list`.
+- The `X-PackRat-Admin-Token` header is never read.
+- All admin tools are gated by `mcp:admin` scope, verified by scope-matrix test.
+
+---
+
+### U6. Better Auth integration repair + login form security
+
+**Goal:** Add `mcp.packratai.com` to Better Auth's `trustedOrigins`; add CORS headers on `.well-known/*` (and `/mcp` only for the hosts that need it); harden the `/login` POST with Origin validation, a CSRF nonce distinct from the OAuth state key, and a rate limit; map Better Auth's rate-limit / locked / invalid-password responses to distinct error messages.
+
+**Requirements:** R2, R10, R13, R14
+
+**Dependencies:** U2 (the runtime/static `trustedOrigins` edits in this unit are independent of U5; U5 in turn depends on U6's `trustedOrigins` repair landing first or in the same PR)
+
+**Files:**
+- Modify: `packages/api/src/auth/index.ts` (add `https://mcp.packratai.com` to `trustedOrigins` at line 158)
+- Modify: `packages/api/src/auth/auth.config.ts` (add `https://mcp.packratai.com` to the static `trustedOrigins` list at line 74 in lockstep with the runtime change above; without this, `bunx auth generate` will run against a drifted config and any tooling that reads the static config will be wrong about which origins are trusted). Per `docs/solutions/developer-experience/better-auth-cli-cloudflare-worker-factory-2026-05-02.md`, regenerate the Better Auth schema after this edit.
+- Modify: `packages/mcp/src/auth.ts` (CSRF nonce in a `__Host-PR_CSRF` cookie; Origin check on `/login` POST; rate-limit hook via U14's binding once landed, stubbed with a placeholder check until then; distinguish API-side 429 / 423 / 401 responses)
+- Modify: `packages/mcp/src/index.ts` (CORS allowlist for `claude.ai` + `claude.com` on `.well-known/*` paths)
+- Test: extend `packages/mcp/src/__tests__/auth.test.ts`
+
+**Approach:**
+- The Better Auth instance is per-isolate-singleton per `packages/api/src/auth/index.ts` (memoized in `authCache`). Adding `mcp.packratai.com` to `trustedOrigins` is a one-line config change; the singleton cache will be rebuilt on the next isolate spin-up after deploy.
+- Run `bunx auth generate --config src/auth/auth.config.ts` per the documented learning to ensure schema parity (no schema change expected, but it's the prescribed checkpoint).
+- CSRF: at `/authorize`, set a `__Host-PR_CSRF` cookie containing a UUID; embed the same UUID in a hidden form field. On POST, compare cookie vs. form field; reject mismatches with a clear error.
+- Origin check: reject `/login` POSTs whose Origin header is not `https://mcp.packratai.com` (production) or the dev origin.
+- CORS: a static handler in `index.ts` adds `Access-Control-Allow-Origin` for the two Anthropic hosts on `GET .well-known/*`. Other endpoints default-deny.
+- Map Better Auth responses: `429` → "Too many attempts, please wait", `423` → "Account locked, check your email", `401` → "Invalid email or password". Today they collapse to one generic message.
+
+**Test scenarios:**
+- Happy path: A POST to `/login` with valid Origin + matching CSRF cookie/field + correct credentials proceeds.
+- Error path: POST with mismatched CSRF cookie/field returns 400 + a CSRF-specific error.
+- Error path: POST from a third-party Origin returns 403.
+- Error path: When Better Auth returns 429, the login page shows the rate-limit-specific error.
+- Error path: When Better Auth returns 423, the login page shows the locked-account error.
+- Integration: `GET /.well-known/oauth-protected-resource` from `https://claude.ai` returns the metadata with `Access-Control-Allow-Origin: https://claude.ai`.
+- Integration: The API `getAuth()` factory cache is invalidated on next isolate boot and the new `trustedOrigins` takes effect.
+
+**Verification:**
+- The login page rejects forged form posts.
+- CORS preflight for `.well-known/*` succeeds from Claude origins.
+- Better Auth no longer rejects MCP-originated sign-in calls.
+
+---
+
+### U7. Tool annotations + naming + collision audit
+
+**Goal:** Every user-callable tool carries `title`, `readOnlyHint`, and (when not read-only) `destructiveHint` / `idempotentHint`. Every tool name is `packrat_*` (admin tools become `packrat_admin_*`). Read-vs-write parameters are never collapsed into a single tool — split any that exist.
+
+**Requirements:** R6, R7
+
+**Dependencies:** U5
+
+**Files:**
+- Modify: every file under `packages/mcp/src/tools/*.ts`
+- Modify: `packages/mcp/src/prompts.ts` (update tool name references)
+- Create: `packages/mcp/src/__tests__/annotations.test.ts` (catalog test that enumerates all registered tools and asserts every one has the required annotations and a `packrat_` prefix)
+
+**Approach:**
+- Walk every `registerTool` call. For each tool, set:
+ - `title`: a human-readable title (e.g., "Get Pack", "List My Trips", "Hard-Delete User").
+ - `readOnlyHint`: true for any tool whose name starts `get_/list_/search_/find_`.
+ - `destructiveHint`: true for any tool whose name starts `delete_/hard_delete_/remove_/clear_`, or that's annotated as such in a prior audit.
+ - `idempotentHint`: true for idempotent reads + idempotent writes (PATCH-shaped updates).
+ - `openWorldHint`: false for tools that only touch PackRat data; true for `web_search`, `extract_url_content`, `get_weather`, `alltrails_*`, etc.
+- Rename: prefix every tool with `packrat_`. Update all `prompts.ts` references in lockstep.
+- Audit for read/write collapse: spot-check `tools/admin.ts` (`admin_set_user_role` etc.), `tools/feed.ts`, `tools/catalog.ts`. If any tool's input has an `action: "read"|"write"` switch, split into two tools.
+- The catalog test reads `agent.server`'s registered tool map and fails the build on missing annotations.
+
+**Test scenarios:**
+- Happy path (catalog test): every registered tool has a `title`, every tool has `readOnlyHint` set explicitly, every non-read-only tool has `destructiveHint` set explicitly.
+- Happy path: every tool name matches `/^packrat_/`.
+- Edge case: a "list" tool with default pagination has `readOnlyHint: true` and returns no more than the documented page size (verified in U8).
+- Edge case: `packrat_admin_hard_delete_user` has `readOnlyHint: false`, `destructiveHint: true`, `idempotentHint: true`.
+- Edge case: `packrat_web_search` has `openWorldHint: true`; `packrat_get_pack` has `openWorldHint: false`.
+
+**Verification:**
+- The annotation catalog test passes; build fails on any missing annotation.
+- All tool names are prefixed.
+- `prompts.ts` references resolve.
+
+---
+
+### U8. Output envelope hardening: structuredContent + isError + pagination
+
+**Goal:** JSON-returning tools advertise an `outputSchema` and emit `structuredContent`; recoverable failures use `isError: true` content blocks (not thrown exceptions); list-style tools paginate; tool descriptions are factual, non-promotional, with stable response-size budgets.
+
+**Requirements:** R6, R7
+
+**Dependencies:** U7
+
+**Files:**
+- Modify: `packages/mcp/src/client.ts` (`ok()` accepts an optional `structuredContent`; `errMessage()` and `call()` consistently return `{ isError: true, content: [{ type: 'text', ... }], structuredContent: { error: { code, message, retryable } } }`)
+- Modify: every `packages/mcp/src/tools/*.ts` (add `outputSchema` for tools returning structured JSON; pass structured shape through `ok()`)
+- Modify: tools with list-style outputs to enforce `limit ≤ 50` server-side and surface a `nextCursor` field
+- Test: extend `packages/mcp/src/__tests__/client.test.ts`
+
+**Approach:**
+- Update `ok(data, opts?)` to additionally emit `structuredContent: data` (mirroring the text content's JSON.stringify) when an output schema is registered. Backward-compatible — old callers continue to work.
+- For each tool with a recognizable response shape (`packrat_get_pack`, `packrat_list_packs`, `packrat_search_trails`, ...), declare a Zod `outputSchema` and pass it to `registerTool`. The SDK validates `structuredContent` against it.
+- For failures, replace any unhelpful `throw new Error(...)` inside tool handlers with `isError: true` returns whose `structuredContent.error` carries `{ code: 'api_error', message, retryable }`. Reserve thrown errors for protocol-level violations (bad args, unknown tool — let the SDK surface them).
+- Cap response size: enforce `JSON.stringify(...).length < 150_000` per `Building Connectors` doc; truncate with a marker if exceeded. This matters for `packrat_list_packs`, `packrat_admin_list_users`, `packrat_search_*`.
+- Pagination: enforce `limit ≤ 50` server-side; surface `nextCursor` and document it in the tool description. Caller-supplied `limit` requests > 50 are clamped silently.
+- Rewrite any promotional-sounding tool description ("revolutionary AI-powered..." etc.) to factual prose. The `repo-research-analyst` audit flagged a few candidates.
+
+**Test scenarios:**
+- Happy path: `packrat_get_pack` returns both `content` (text JSON) and `structuredContent` matching the registered schema.
+- Error path: An API 500 surfaces as `{ isError: true, structuredContent.error.code: "api_error" }`, not a thrown exception.
+- Edge case: A `packrat_list_packs` call with `limit: 500` is clamped to 50 and includes a `nextCursor`.
+- Edge case: A response larger than 150k chars is truncated with a `[truncated]` marker and an `isError: false` (truncation isn't an error, but the LLM should know).
+- Edge case: Calling a tool with a missing required arg returns a JSON-RPC `-32602` (from the SDK), not `isError: true`.
+
+**Verification:**
+- Catalog test enumerates tools that have `outputSchema` and verifies they emit `structuredContent`.
+- No tool throws raw errors from its handler.
+
+---
+
+### U9. Resources expansion + glossary
+
+**Goal:** Add `list:` providers for user packs/trips, a search resource template, a static `packrat://glossary` resource. Reviewers see a thoughtful catalog beyond ID lookups; Claude can read domain vocabulary once into context.
+
+**Requirements:** R8
+
+**Dependencies:** U7
+
+**Files:**
+- Create: `packages/mcp/src/glossary.ts` (the glossary content as a typed constant — pack/base weight/big-3/layering/FKT/AT/PCT/etc.)
+- Modify: `packages/mcp/src/resources.ts` (add list providers via `resource.list` returning the current user's resources; add `packrat://search?q=...` template; add `packrat://glossary` static resource)
+- Modify: `packages/mcp/src/prompts.ts` (reference the glossary resource where it helps)
+- Test: `packages/mcp/src/__tests__/resources.test.ts`
+
+**Approach:**
+- `resource.list` is called by MCP clients to discover available resources. Add it to the templated resources so Claude can enumerate the user's packs/trips by name.
+- Add a `packrat://search?q=...` resource template that resolves a free-text query against the user's data (delegates to existing search tools server-side).
+- `packrat://glossary` is a static `text/markdown` resource (≤ 50 KB) imported from `glossary.ts`. Reviewers see it as a domain-knowledge artifact.
+- For each resource, return errors as `{ isError: true, ... }`-shaped content (consistent with U8) rather than success-with-error-body (the current bug per the audit).
+
+**Test scenarios:**
+- Happy path: `resources/list` returns the four templated resources + the glossary + the search template.
+- Happy path: Reading `packrat://packs/list` returns the user's pack list (delegated to `packrat_list_packs`).
+- Happy path: Reading `packrat://glossary` returns the markdown body with `mimeType: text/markdown`.
+- Edge case: Reading a missing pack ID returns `isError: true` not a success-with-error-body.
+- Edge case: The glossary resource fits within MCP response size limits.
+
+**Verification:**
+- An MCP Inspector run shows the glossary, the list providers, and the search template alongside the existing ID-lookup resources.
+
+---
+
+### U10. Elicitations on destructive admin + ambiguous tools
+
+**Goal:** Wire `McpAgent.elicitInput()` (with the v0.13-required `{ relatedRequestId }`) into a small set of high-blast-radius admin tools and a couple of ambiguous-search tools. Confirmation dialogs make the difference between "Claude executed an irreversible delete" and "Claude paused, asked, and the user said yes".
+
+**Requirements:** R9
+
+**Dependencies:** U5, U7, U8
+
+**Files:**
+- Modify: `packages/mcp/src/tools/admin.ts` (elicitations on `packrat_admin_hard_delete_user`, `packrat_admin_delete_pack`, `packrat_admin_delete_trip`, `packrat_admin_set_user_role`, and `packrat_admin_clear_feed` if present)
+- Modify: `packages/mcp/src/tools/trails.ts` and `packages/mcp/src/tools/alltrails.ts` (elicitations on ambiguous-match search results)
+- Test: `packages/mcp/src/__tests__/elicitations.test.ts`
+
+**Approach:**
+- For each destructive admin tool, wrap the handler so it first calls `elicitInput({ message: "Confirm hard-delete of user X — type the username to proceed", requestedSchema: { type: 'object', properties: { confirmation: { type: 'string' } }, required: ['confirmation'] } }, { relatedRequestId: extra.requestId })`. If the response doesn't echo the target, return `isError: true` with a "cancelled" message.
+- For ambiguous trail search (`packrat_alltrails_search` returning >1 match), elicit the user's choice via `requestedSchema: { type: 'string', enum: candidateNames }`.
+- Pass `relatedRequestId: extra.requestId` per the Agents 0.13 contract; without it the elicitation routes to a non-existent SSE stream and times out silently.
+- Document the elicitation conventions in `docs/mcp/runbook.md` (when to add elicitations, the required `relatedRequestId` pattern).
+
+**Test scenarios:**
+- Happy path: A user calls `packrat_admin_hard_delete_user`, the elicitation fires with a confirmation prompt, the user types the correct username, the delete proceeds.
+- Error path: The user mistypes the confirmation; the tool returns `isError: true` and does not call the API.
+- Error path: The user declines the elicitation; the tool returns a cancelled response without side effects.
+- Edge case: An MCP client that doesn't support elicitations gets a clear error message ("This tool requires user confirmation; your client does not support elicitations") rather than a silent timeout.
+- Integration: The elicitation message routes through the originating POST stream (verified via the test client receiving the response on the same connection).
+
+**Verification:**
+- Destructive admin tools cannot run without user confirmation.
+- Ambiguous searches converge to a single user-chosen result.
+
+---
+
+### U11. Branded login page + SSO buttons + UX polish
+
+**Goal:** Replace the dev-grade login form with a branded page: PackRat logo, Google + Apple SSO buttons (initiating the existing Better Auth social flow), email/password fallback, a password-reset link, the requesting client's name, and explicit terms/privacy/support links.
+
+**Requirements:** R10, R11
+
+**Dependencies:** U6
+
+**Files:**
+- Modify: `packages/mcp/src/auth.ts` (`loginPage()` rewritten; new `/login/google` and `/login/apple` redirect handlers that initiate the Better Auth social flow with the MCP state key threaded through `redirect_to`)
+- Create: `packages/mcp/src/login-page.ts` (the HTML body — kept readable, no template engine)
+- Modify: `packages/api/src/auth/index.ts` — confirm the Better Auth `redirect_to` allowlist permits the MCP callback (`https://mcp.packratai.com/callback/social`)
+- Test: extend `packages/mcp/src/__tests__/auth.test.ts`
+
+**Approach:**
+- The login page renders three options: "Sign in with Google", "Sign in with Apple", or email/password. SSO buttons POST to `/login/google` (and `/login/apple`), which redirects to Better Auth's `/api/auth/sign-in/social?provider=google&callbackURL=https://mcp.packratai.com/callback/social&state=...`.
+- A new `/callback/social` handler validates the returned session and threads it back through the existing `completeAuthorization` flow (mirroring email+password).
+- The page surfaces the OAuth client name from the `OAuthRequest` (`client.clientName` if available) — "Claude is requesting access to your PackRat account".
+- Footer links: Terms (U12), Privacy (U12), Support (`mailto:hello@packratai.com` or a status page).
+- Add a "Forgot your password?" link that opens Better Auth's password-reset endpoint in a new tab.
+- Accessibility: ``, skip link, `role="alert"` on error region, labelled buttons.
+- **SSO is conditional on cost.** Better Auth's Google + Apple providers are already wired in the API, so the marginal cost is the MCP-side button + `/callback/social` round-trip and the Better Auth `callbackURL` allowlist update. If that integration surfaces real complexity at implementation time (e.g., state-key threading through Better Auth's social `callbackURL` parameter turns out non-trivial, or Apple's `appBundleIdentifier` audience handling collides with the web flow), ship email+password only and move SSO to *Deferred to Follow-Up Work* — the branding/copy/password-reset/legal-links polish on its own is enough for the listing reviewer bar.
+
+**Test scenarios:**
+- Happy path: Page renders with Google + Apple + email/password options visible and accessible.
+- Happy path: Clicking "Sign in with Google" redirects to Better Auth's social endpoint with the right callback URL and state.
+- Happy path: After successful social sign-in, the callback completes the OAuth flow with the same `props.userId` shape as email+password.
+- Edge case: The page renders the client name when present in the `OAuthRequest`; falls back to "an MCP client" when missing.
+- Edge case: All three links (Terms, Privacy, Support) work and use HTTPS.
+- Error path: A returning failed-social-sign-in shows a clear error and stays on the page.
+
+**Verification:**
+- A reviewer using a fresh Claude account can sign in via Google in one click.
+- The page has PackRat branding and looks production-grade.
+- Lighthouse / axe smoke pass.
+
+---
+
+### U12. Public legal + support pages, domain alignment
+
+**Goal:** Publish Terms of Service alongside the existing Privacy Policy on the canonical domain (`packratai.com`); extend the Privacy Policy with an MCP-specific addendum (data scopes, OAuth token storage, retention, deletion path); surface a working support contact (email + URL) consistently across MCP `/health`, the login page, and the listing.
+
+**Requirements:** R11
+
+**Dependencies:** None (parallel to the worker units)
+
+**Files:**
+- Create: `apps/landing/app/terms-of-service/page.tsx`
+- Modify: `apps/landing/app/privacy-policy/page.tsx` (MCP addendum: what scopes mean; that PackRat stores OAuth refresh tokens encrypted in KV; data retention; how to revoke; reviewer test-account note)
+- Modify: `apps/landing/config/site.ts` (`legal: [..., { title: 'Terms', href: '/terms-of-service' }]`; add a `support` field with the canonical mailto + URL)
+- Modify: `packages/mcp/src/auth.ts` (`/health` JSON includes `support_url`, `privacy_url`, `terms_url`, all on `packratai.com`)
+
+**Approach:**
+- Draft Terms of Service that explicitly cover MCP usage: scope grant, rate limits, abuse policy, refund / no-refund language, jurisdiction.
+- Add a Privacy Policy addendum section explaining MCP data flows: OAuth tokens stored encrypted at rest in Cloudflare KV; tool calls relayed to the PackRat API; no conversation logging; per-user deletion via the existing account-deletion flow.
+- Add the `support` config so the landing site footer surfaces the same contact MCP advertises.
+- Pin every URL the MCP advertises to `packratai.com` (not `packrat.world`); the worker remains at `mcp.packratai.com` but documentation lives on the brand domain.
+
+**Test scenarios:**
+- Happy path: `GET /terms-of-service` returns 200 with full ToS body.
+- Happy path: `GET /privacy-policy` returns 200 including the new MCP addendum.
+- Happy path: `GET https://mcp.packratai.com/health` references `https://packratai.com/docs/mcp`, `.../privacy-policy`, `.../terms-of-service`.
+- Test expectation: A landing-site smoke test asserts the footer renders both legal links.
+
+**Verification:**
+- All three URLs return 200.
+- The `/health` JSON URLs all resolve to the published pages.
+
+---
+
+### U13. Public docs page, README, listing artifacts
+
+**Goal:** Author the MCP-facing documentation a Connector Store reviewer will need: a public docs page on the landing site, a `packages/mcp/README.md` describing connection + tool catalog + example prompts, branded logo/favicon assets, and a reviewer test account.
+
+**Requirements:** R12
+
+**Dependencies:** U7, U8, U9, U10, U11, U12
+
+**Files:**
+- Create: `apps/landing/app/mcp/page.tsx` (public connection guide, tool catalog with annotations + descriptions, example prompts)
+- Create: `packages/mcp/README.md` (internal/developer-facing version of the same content + dev setup)
+- Create: `apps/landing/public/mcp-logo.svg` (+ a 1024×1024 PNG fallback)
+- Create / verify: `apps/landing/public/favicon.ico` (used for Anthropic's domain-ownership verification)
+- Create: `docs/mcp/README.md`, `docs/mcp/submission-packet.md` (operator-facing)
+- Modify: `apps/landing/config/site.ts` (add MCP nav link)
+- Test: a landing-site smoke test for `/mcp` route
+
+**Approach:**
+- The public docs page covers: what the connector does, how to install it in Claude.ai, the scopes it requests, the tool catalog (auto-generated from a static dump of `tools/list` is cleanest — script in `packages/mcp/scripts/dump-catalog.ts`), example prompts, and a link to the reviewer test account onboarding instructions.
+- ≥3 example prompts covering different tool surfaces (one read-only, one write, one with elicitation) per the Software Directory Policy.
+- The reviewer test account: a pre-provisioned PackRat account with sample packs/trips/feed posts; credentials documented in `docs/mcp/submission-packet.md` (excluded from public docs but provided to Anthropic via the form).
+- Logo: a vector PackRat mark + a 1024×1024 PNG fallback.
+- Favicon must be served at the same domain as the OAuth server (`mcp.packratai.com/favicon.ico`) so Anthropic's verification probe succeeds — either copy from the landing site or add a tiny static route in the MCP worker.
+
+**Test scenarios:**
+- Happy path: `apps/landing/app/mcp/page.tsx` renders with the tool catalog, scopes, and example prompts visible.
+- Happy path: `packages/mcp/README.md` lints clean (markdown lint).
+- Test expectation: smoke test for `/mcp` route returns 200 with the catalog text visible.
+- Happy path: `GET https://mcp.packratai.com/favicon.ico` returns a 200 with `image/x-icon` (so Anthropic's domain check succeeds).
+
+**Verification:**
+- A Claude reviewer can reach a public docs page, install the connector via OAuth, find ≥3 example prompts, and use the test account.
+- Favicon verifies at the OAuth domain.
+
+---
+
+### U14. Rate limiting + KV cron purge
+
+**Goal:** Per-user/per-tool authenticated rate limits via the Workers Rate Limiting binding (60/60s); anonymous DoS protection at the zone via WAF Rate Limiting Rules; periodic KV cleanup via `oauthProvider.purgeExpiredData`.
+
+**Requirements:** R13
+
+**Dependencies:** U2
+
+**Files:**
+- Modify: `packages/mcp/wrangler.jsonc` (add `rate_limiting` binding `MCP_TOOLS_RL`; add `triggers.crons` for the KV purge)
+- Create: `packages/mcp/src/rate-limit.ts` (thin wrapper around the binding; returns a 429-equivalent `isError: true` tool response when triggered)
+- Modify: `packages/mcp/src/index.ts` (wire `MCP_TOOLS_RL.limit({ key: `${props.userId}:${toolName}` })` into the tool dispatch path; add the `scheduled()` handler for the KV cron)
+- Modify: `packages/mcp/src/types.ts` (`Env.MCP_TOOLS_RL: RateLimit`)
+- Document: zone-level WAF Rate Limiting Rules in `docs/mcp/runbook.md` (operator-applied via the dashboard or `terraform`)
+- Test: extend `packages/mcp/src/__tests__/integration/tool-gating.test.ts`
+
+**Approach:**
+- Add the binding under the `rate_limiting` block in `wrangler.jsonc` (matching the existing `packages/api/wrangler.jsonc:44` convention): `"rate_limiting": [{ "binding": "MCP_TOOLS_RL", "namespace_id": "1", "simple": { "limit": 60, "period": 60 } }]`. Note: the block key is `rate_limiting` (not `ratelimits`) and the field is `binding` (not `name`) — both must match the existing API package precedent or wrangler will reject the config.
+- Wrap tool handlers so each call invokes `MCP_TOOLS_RL.limit({ key: ... })` first; on limit-exceeded, return `{ isError: true, structuredContent: { error: { code: 'rate_limited', retryAfter: 60 } } }`.
+- Add a `scheduled()` export to the Worker that runs daily and calls `env.OAUTH_PROVIDER.purgeExpiredData({ batchSize: 100 })`; configure via `triggers.crons: ["0 4 * * *"]`.
+- Document the zone-level rules in the runbook: 100 r/s per IP on `/authorize`, `/token`, `/register`. These are dashboard-configured (or, optionally, Terraform).
+
+**Test scenarios:**
+- Happy path: 60 sequential calls to `packrat_get_pack` succeed; the 61st within the window returns `rate_limited`.
+- Edge case: Different `userId`s have independent counters.
+- Edge case: Different tool names for the same `userId` have independent counters.
+- Happy path: The `scheduled()` handler runs without throwing; mocked `purgeExpiredData` is called with `{ batchSize: 100 }`.
+- Edge case: A user with 1000 expired KV entries gets them swept in multiple cron passes (test asserts `result.done === false` on first pass, `done === true` after enough passes).
+
+**Verification:**
+- A burst test triggers `rate_limited` predictably.
+- Manual `wrangler tail` after a cron tick shows the purge log line.
+
+---
+
+### U15. Observability: Sentry/OTel + structured logging + audit
+
+**Goal:** Pipe MCP Worker telemetry to Sentry via Cloudflare's OTel pipeline; emit structured logs with a correlation ID per request; capture OAuth errors via the provider's `onError`; audit-log every admin tool invocation.
+
+**Requirements:** R14
+
+**Dependencies:** U5, U6
+
+**Files:**
+- Create: `packages/mcp/src/observability.ts` (`createLogger`, correlation-ID extraction, `withCorrelation()` wrapper)
+- Modify: `packages/mcp/src/index.ts` (`onError` on `OAuthProvider` → log + capture; correlation ID injection at the top of every request)
+- Modify: `packages/mcp/src/auth.ts` (structured logs at each OAuth step; never log tokens or props)
+- Modify: `packages/mcp/src/tools/admin.ts` (every admin tool emits an audit log with `{ correlationId, userId, action, targetId, ts }`)
+- Document: how to enable the OTel→Sentry pipeline in the Cloudflare dashboard in `docs/mcp/runbook.md`
+- Test: `packages/mcp/src/__tests__/observability.test.ts`
+
+**Approach:**
+- `createLogger({ correlationId })` returns a typed logger that emits JSON via `console.log` (picked up by Workers Logs and forwarded to Sentry via the dashboard-configured OTel pipeline — no code-level Sentry SDK needed).
+- A `correlationId` is read from `cf-ray` or generated per request, then propagated through tool handlers (via `agent` field or `AsyncLocalStorage` — pick at implementation time).
+- Wire `onError({ code, description, status })` on `OAuthProvider` to call the logger at `warn` level; never log the request body or props.
+- Every admin tool wraps its handler with an audit log emitter that captures the action and target IDs (not the response body).
+
+**Test scenarios:**
+- Happy path: A failed OAuth `/token` exchange surfaces a `warn` log with `oauth.invalid_grant` + status + correlation ID, no token bodies.
+- Happy path: A successful `packrat_admin_hard_delete_user` emits an audit log entry with the action and target user ID.
+- Error path: A tool handler throwing an unexpected error surfaces an `error` log with the correlation ID and the stack — no sensitive args logged.
+- Edge case: A `props` object is never present in any log entry (asserted via a global log spy in the test).
+
+**Verification:**
+- A `wrangler tail` against dev shows correlation-ID-tagged logs with no leaked tokens.
+- The Sentry dashboard receives errors after the OTel pipeline is enabled.
+
+---
+
+### U16. Real `/health` + status endpoint
+
+**Goal:** Replace the trivial `/health` with a real one that probes KV reachability and the PackRat API; expose a `/status` endpoint with the version, build SHA, scopes supported, and which features are enabled.
+
+**Requirements:** R14
+
+**Dependencies:** U1, U3, U15
+
+**Files:**
+- Modify: `packages/mcp/src/auth.ts` (`/health` checks KV `OAUTH_KV.list({ limit: 1 })`, `fetch(env.PACKRAT_API_URL + '/api/health')`; `/status` returns extended metadata)
+- Modify: `packages/mcp/src/constants.ts` (add `/status` to `WorkerRoute`)
+- Test: extend `packages/mcp/src/__tests__/auth.test.ts`
+
+**Approach:**
+- `/health` returns 200 only if both probes succeed; 503 if either fails. Body includes per-probe status (`{ kv: 'ok', api: 'ok' }`).
+- `/status` returns a public-safe metadata block: `version` (from package.json), `commitSha` (injected via wrangler `vars`), `scopes_supported`, `transport`, `docs`. No secrets, no internal config.
+- Cache the health-probe result for 10 seconds to avoid hammering KV/API.
+
+**Test scenarios:**
+- Happy path: Both probes succeed; `/health` returns 200 with `{ kv: 'ok', api: 'ok' }`.
+- Error path: KV is unreachable (mocked); `/health` returns 503 with `{ kv: 'down', api: 'ok' }`.
+- Error path: API health probe returns 500; `/health` returns 503 with `{ kv: 'ok', api: 'down' }`.
+- Happy path: `/status` returns the public metadata block.
+
+**Verification:**
+- A reviewer can `curl /health` and `curl /status` and get useful, accurate JSON.
+
+---
+
+### U17. CI: tests, type-check, deploy, integration suite
+
+**Goal:** GitHub Actions runs `bun check-types`, `bun lint`, and `bun test --filter @packrat/mcp` (including integration tests via `@cloudflare/vitest-pool-workers`) on every PR; deploys to prod via `wrangler deploy --env prod` on a tag.
+
+**Requirements:** R15
+
+**Dependencies:** U1, U6, U7, U8
+
+**Files:**
+- Create: `.github/workflows/mcp-test.yml`
+- Create: `.github/workflows/mcp-deploy.yml`
+- Modify: `packages/mcp/vitest.config.ts` (drop the coverage exclusions for the real risk surface; add a separate `integration` workspace using `@cloudflare/vitest-pool-workers`)
+- Create: `packages/mcp/src/__tests__/integration/` directory (covered by the per-unit test files above)
+- Modify: `packages/mcp/package.json` (`test:integration` script)
+
+**Approach:**
+- `mcp-test.yml` triggers on PRs touching `packages/mcp/**`; runs `bun install`, `bun check-types`, `bun lint`, `bun test --filter @packrat/mcp` (unit + integration). Integration tests use `@cloudflare/vitest-pool-workers` with a miniflare-backed KV + DO.
+- `mcp-deploy.yml` triggers on tags matching `mcp-v*`; runs `bun install`, `bun test --filter @packrat/mcp`, and `wrangler deploy --env prod` using a `CLOUDFLARE_API_TOKEN` repo secret.
+- Drop the vitest coverage exclusions for `src/index.ts`, `src/tools/**`, `src/resources.ts`, `src/prompts.ts`, `src/auth.ts` — the per-unit tests above bring real coverage.
+- Document the deploy-token issuance and rotation in `docs/mcp/runbook.md`.
+
+**Test scenarios:**
+- Happy path: A PR touching `packages/mcp/**` triggers the workflow; all jobs pass.
+- Edge case: A PR not touching `packages/mcp/**` does not trigger.
+- Happy path: A tag push to `mcp-v2.1.0` triggers the deploy job; `wrangler deploy --env prod` is invoked.
+- Test expectation: integration test `oauth-flow.test.ts` runs the full discover→authorize→token→tool-call path against miniflare.
+
+**Verification:**
+- The first PR after this lands shows the new checks in the GitHub UI.
+- A tagged release deploys cleanly to prod.
+
+---
+
+### U18. Submission packet + pre-submission validation + file submission
+
+**Goal:** Assemble the Anthropic submission packet (name, description, category, callback URLs, test account, prompts, logo, favicon, support contact); run Anthropic's pre-submission checklist; file via the Google Form.
+
+**Requirements:** R16
+
+**Dependencies:** U1 through U17
+
+**Files:**
+- Create: `docs/mcp/submission-packet.md` (the full operator runbook: every field's exact value, copy-pasteable)
+- Modify: `docs/mcp/README.md` (link to submission packet)
+
+**Approach:**
+- Walk Anthropic's pre-submission checklist:
+ - Streamable HTTP at `mcp.packratai.com/mcp` — verify.
+ - OAuth 2.1, PKCE S256, RFC 8707, well-known endpoints — verify with the integration tests + MCP Inspector.
+ - Both Claude callback URLs allowlisted — verify in KV via `wrangler kv key list --namespace-id ... | grep client`.
+ - Every tool has the required annotations — verify via the catalog test.
+ - Privacy policy + Terms of Service URLs return 200, on the verified domain — verify.
+ - Favicon at the OAuth domain returns 200 — verify.
+ - ≥3 example prompts ready, each exercising different tools — verify.
+ - Reviewer test account populated with realistic data — verify by signing in.
+ - WAF doesn't block Anthropic's OAuth discovery probes — explicit allow rule for Claude UA + IP range if known.
+ - Token endpoint accepts `application/x-www-form-urlencoded` — verify (the OAuth provider does this by default).
+- Run `claude plugin validate` (per Anthropic's docs) against the deployed Worker.
+- File the form at with the packet contents.
+- The packet doc explicitly lists the form field → packet value mapping so the operator filing the form doesn't miss anything.
+
+**Test scenarios:**
+- Test expectation: none — this unit is an operator runbook, not code. The verification is the submission itself.
+
+**Verification:**
+- Anthropic acknowledges receipt; the connector enters the ~2-week review queue. Successful approval is out of scope for this plan but is the natural endpoint.
+
+---
+
+## System-Wide Impact
+
+- **Interaction graph:** The MCP Worker still calls the PackRat API; the API still calls Better Auth. New seams: the MCP Worker now reads user role from Better Auth to decide scope grants (U5/U6); the MCP Worker now ratelimits via a Cloudflare Workers binding (U14); the MCP Worker now emits to Sentry via the OTel pipeline (U15). The landing site (`apps/landing`) gains an MCP docs page and a Terms page.
+- **Error propagation:** Tool-execution errors flow through the new `{ isError: true, structuredContent.error }` envelope; protocol errors propagate as JSON-RPC `-32602` automatically; OAuth errors propagate via `onError → Sentry`. Audit logs accompany every admin action.
+- **State lifecycle risks:** Removing the `X-PackRat-Admin-Token` header path breaks any existing client that uses it — confirmed no public clients depend on this. Removing the `admin_login` tool similarly. The KV cron sweeps both expired OAuth state and expired grants — safe because the OAuth provider uses TTLs.
+- **API surface parity:** The PackRat API (`packages/api`) is touched only for `trustedOrigins` and (potentially) `auth.config.ts` regeneration; no API tools change. The Expo app, the web app, and admin UI are not affected.
+- **Integration coverage:** The new integration tests in U17 cover the OAuth flow end-to-end (something no test does today); scope-based gating; well-known metadata; and the rate-limiter trigger.
+- **Unchanged invariants:** The 60+ tools' user-facing semantics do not change — only their names (prefix), annotations (added), error envelopes (formalized), and output schemas (added). The API client (`@packrat/api-client`) is not modified.
+
+---
+
+## Risks & Dependencies
+
+| Risk | Likelihood | Impact | Mitigation |
+|---|---|---|---|
+| Removing `admin_login` / `X-PackRat-Admin-Token` breaks an internal client | Low | Med | Audit `apps/admin` and any internal scripts before merging U5; pre-flight communicate the change. |
+| Renaming all tools (`packrat_*` prefix) breaks any pinned tool reference in a Claude saved chat | Low | Low | Renames happen before any Connector Store listing exists publicly; no upstream consumer is locked in. Document the change in the README. |
+| `mcp.packratai.com` DNS / cert provisioning takes longer than expected | Med | Med | Start DNS work in U1 in parallel with code; verify TLS via `curl -v` before proceeding. |
+| Anthropic's reviewers reject the listing for an unforeseen reason | Med | Low | Pre-submission validation in U18 plus the published rejection-reason taxonomy (annotations, missing privacy, OAuth callback allowlist, vague descriptions, mixed safe/unsafe params) cover the top causes. A first rejection is recoverable within days. |
+| Better Auth singleton cache hides a `trustedOrigins` change in deployed isolates | Low | Med | After deploy, force isolate rotation (a no-op env change deploy); add an assertion in CI that `trustedOrigins` includes the expected hosts. |
+| Workers Rate Limiting binding hits its 1000-keys cap under abuse | Low | Med | Keyed by `${userId}:${toolName}` — bounded by `unique_users × tools`. With ~104 tools and v1 user count this is well under the cap. Re-evaluate at v2. |
+| The `agents` SDK v0.13 `relatedRequestId` requirement is missed somewhere | Med | Med | The U10 test scaffolding asserts every elicitation passes `relatedRequestId`; the catalog-shape pattern repeats across new tools. |
+| OAuth provider version 0.7 surfaces an unforeseen breaking change | Med | Med | U2 is sequenced first; full unit + integration suite must pass before proceeding. Roll back to ^0.6 if necessary — the metadata/cron features can wait one cycle. |
+| Privacy policy / ToS lack legal review | Med | Low | The plan acknowledges this in Open Questions; operator decides whether to gate U18 on legal sign-off. |
+| WAF rules block Anthropic's discovery probes silently | Med | High (rejection cause #9) | Explicit allow rule for the Claude origins on `.well-known/*` and `/mcp`; integration test exercises the path. |
+| Coverage threshold (95% on `client.ts`) drops as new code lands | Low | Low | Update `vitest.config.ts` thresholds in U17 to apply to the broader surface, not just `client.ts`. |
+
+---
+
+## Dependencies / Prerequisites
+
+- Cloudflare DNS access for `mcp.packratai.com` subdomain.
+- Two Cloudflare KV namespaces (prod + dev) created via `wrangler kv namespace create`.
+- `MCP_INITIAL_ACCESS_TOKEN` and any new secrets set via `wrangler secret put` (or Cloudflare dashboard) for the prod and dev environments.
+- Sentry project + OTel ingest URL (configured in the Cloudflare dashboard, not in code).
+- A reviewer test PackRat account, fully populated with sample data.
+- Branding assets: PackRat logo (SVG + 1024×1024 PNG), favicon.
+
+---
+
+## Phased Delivery
+
+### Phase 1 — Auth and OAuth Hardening (U1, U2, U3, U4, U5, U6)
+The blocking changes that make the server a valid OAuth-conformant MCP. Ships first; tests cover OAuth flow end-to-end. After this phase, a private (non-listed) connection from `claude.ai` works.
+
+### Phase 2 — Tool Surface Quality (U7, U8, U9, U10)
+The changes Anthropic's reviewers will probe most: annotations, naming, structured outputs, resources, elicitations. After this phase, the catalog passes Anthropic's tool-quality bar.
+
+### Phase 3 — Listing UX & Public Surface (U11, U12, U13)
+The user-visible polish: branded login with SSO, public legal pages, public docs, branding assets, reviewer test account. After this phase, the listing is presentable.
+
+### Phase 4 — Operational Hardening (U14, U15, U16, U17)
+Production posture: rate limits, observability, real health, CI/CD. After this phase, ongoing maintenance is sustainable.
+
+### Phase 5 — Submission (U18)
+Pre-submission validation, packet assembly, form submission. Single operator-driven unit.
+
+---
+
+## Documentation Plan
+
+- `packages/mcp/README.md` — connection guide, tool catalog with annotations, example prompts, dev setup.
+- `apps/landing/app/mcp/page.tsx` — public-facing docs page; the listing's "Documentation" URL.
+- `apps/landing/app/terms-of-service/page.tsx` — new ToS.
+- `apps/landing/app/privacy-policy/page.tsx` — extend with MCP addendum.
+- `docs/mcp/README.md` + `docs/mcp/runbook.md` + `docs/mcp/submission-packet.md` — operator runbooks.
+- After each phase, write a `docs/solutions/` entry: tool-annotation conventions (Phase 2); observability stack (Phase 4); rate-limit split (Phase 4); custom-domain promotion (Phase 1); connector-store submission retro (Phase 5).
+- Mark `docs/plans/2026-04-30-feat-better-auth-migration-plan.md` Phase 3 unchecked items as closed-by-reference in this plan.
+
+---
+
+## Operational / Rollout Notes
+
+- The MCP custom-domain provisioning has no dev-prod rollout — it's a one-shot DNS + Worker route change. Schedule during low-traffic window in case TLS provisioning takes a few minutes.
+- The `admin_login` removal (U5) is a breaking change for any internal admin who used it directly. Communicate in the team channel before merge; provide the new "acquire admin scope via OAuth re-consent" path in the runbook.
+- The tool-prefix rename (U7) is a breaking change for any pre-listing internal MCP user. Same communication plan; the renames happen before public listing exists, so no external user is affected.
+- The KV purge cron runs at 04:00 UTC daily; surface the timestamp in observability so the first few runs can be checked.
+- Once submitted (U18), monitor `mcp-review@anthropic.com` and the operator's email for review feedback. Typical turnaround is ~2 weeks; rejections are usually fixable in a same-day patch.
+- Post-listing, treat the production server as immutable in the spec sense — `notifications/tools/list_changed` fires on any tool surface change, and the version in `serverInfo` bumps. Avoid changing tool input schemas in place — add a new tool name instead.
+
+---
+
+## Sources & References
+
+- **Origin (architectural parent):** `docs/plans/2026-04-30-feat-better-auth-migration-plan.md`
+- Related plan: `docs/plans/2026-04-15-001-refactor-hono-rpc-foundation-plan.md` (global error envelope)
+- Related plan: `docs/plans/2026-04-14-feat-finish-elysia-migration-pr-2083-plan.md` (API error-handling context)
+- Institutional learning: `docs/solutions/developer-experience/better-auth-cli-cloudflare-worker-factory-2026-05-02.md`
+- Anthropic: [Building Connectors](https://claude.com/docs/connectors/building), [Submission](https://claude.com/docs/connectors/building/submission), [Software Directory Policy](https://support.claude.com/en/articles/13145358-anthropic-software-directory-policy), [Software Directory Terms](https://support.claude.com/en/articles/13145338-anthropic-software-directory-terms), [Custom Connectors](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp)
+- MCP: [Authorization spec 2025-11-25](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization), [Security Best Practices](https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices), [Tools spec 2025-06-18](https://modelcontextprotocol.io/specification/2025-06-18/server/tools)
+- RFCs: [8414 (AS metadata)](https://datatracker.ietf.org/doc/html/rfc8414), [7591 (DCR)](https://datatracker.ietf.org/doc/html/rfc7591), [9728 (Protected Resource metadata)](https://datatracker.ietf.org/doc/html/rfc9728), [8707 (Resource Indicators)](https://www.rfc-editor.org/rfc/rfc8707.html)
+- Cloudflare: [workers-oauth-provider](https://github.com/cloudflare/workers-oauth-provider), [remote-mcp-github-oauth reference](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-github-oauth), [Rate Limiting binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/), [Workers Logs](https://developers.cloudflare.com/workers/observability/logs/workers-logs/), [Build a Remote MCP Server](https://developers.cloudflare.com/agents/guides/remote-mcp-server/)
+- Submission writeups: [sunpeak — Connector Directory Submission](https://sunpeak.ai/blogs/claude-connector-directory-submission/), [sunpeak — Connector Tool Design](https://sunpeak.ai/blogs/claude-connector-tool-design/)
diff --git a/docs/plans/2026-05-25-001-refactor-mcp-auth-onto-better-auth-plan.md b/docs/plans/2026-05-25-001-refactor-mcp-auth-onto-better-auth-plan.md
new file mode 100644
index 0000000000..a7073942b8
--- /dev/null
+++ b/docs/plans/2026-05-25-001-refactor-mcp-auth-onto-better-auth-plan.md
@@ -0,0 +1,758 @@
+---
+title: "refactor: Consolidate MCP OAuth onto Better Auth OAuth Provider plugin"
+type: refactor
+status: active
+date: 2026-05-25
+---
+
+# refactor: Consolidate MCP OAuth onto Better Auth OAuth Provider plugin
+
+## Summary
+
+Move the PackRat MCP Worker off `@cloudflare/workers-oauth-provider` onto `@better-auth/oauth-provider` (the modern, non-deprecated Better Auth OAuth 2.1 plugin) hosted in the existing `packages/api` worker. The MCP and Better Auth OAuth machinery converge on Better Auth, eliminating the duplicated OAuth state machine on the MCP side; the legacy HS256 admin-JWT path used by `apps/admin` stays as documented back-compat. The MCP becomes a pure protected resource that validates JWT access tokens locally against Better Auth's JWKS. Built on top of the current 22-commit `plan/mcp-connector-store-readiness` branch — the connector-store readiness work (tools, annotations, output envelopes, resources, elicitations, rate limits, observability, CI, listing artifacts) all carries forward unchanged; only the OAuth machinery on both workers gets rewritten.
+
+---
+
+## Problem Frame
+
+The current MCP Worker runs its own OAuth 2.1 authorization server via `@cloudflare/workers-oauth-provider`, on top of which we layered: custom DCR gating with a pre-shared bearer (U4), a custom Better Auth `/callback` bridge to look up `user.role` and grant `mcp:admin` (U5), a `trustedOrigins` repair so the MCP could call Better Auth's `/sign-in/email` (U6), a branded login page (U11). This works but the architectural cost is two parallel auth systems: every feature (passkeys, MFA, social provider, scope, rate-limit policy) has to be considered twice; the `/callback` role bridge is glue code papering over the split; admin role checks happen via a synchronous Better Auth HTTP call on every OAuth grant.
+
+Mid-session research discovered Better Auth (v1.6.11) ships first-class MCP support — the `mcp` and `oidcProvider` plugins in core, plus the newer separate `@better-auth/oauth-provider` package that's the actively-maintained replacement for the now-deprecated bundled plugins. The plan eliminates the duplication by hosting the OAuth AS in Better Auth and reducing the MCP Worker to a pure protected resource.
+
+A prior plan (`docs/plans/2026-04-30-feat-better-auth-migration-plan.md`) explicitly considered and rejected this architecture in April for cross-origin discovery brittleness. Two things changed: (1) Better Auth's MCP support matured (it didn't exist in April), and (2) Anthropic's connector troubleshooting docs now explicitly support and document the cross-origin AS pattern. The refactor re-litigates that decision deliberately.
+
+---
+
+## Requirements
+
+- R1. `mcp.packratai.com` validates JWT access tokens locally against `api.packrat.world`'s JWKS (no per-request HTTP introspection round-trip).
+- R2. OAuth 2.1 + PKCE S256 + RFC 8707 audience binding is enforced; tokens are audience-bound to `https://mcp.packratai.com/mcp`; access tokens are short-lived; refresh tokens rotate with proper invalidation of the prior token. **Spike-confirmed**: `validAudiences` enforces RFC 8707 strictly (`checkResource` throws 400 `invalid_request` for unknown audiences). JWT tokens are issued only when the client sends a `resource` parameter AND `disableJwtPlugin` is unset/false — Claude.ai MUST send `resource` per the MCP spec; verify empirically in U9 dev verification (regression guard: a request without `resource` receives an opaque token, not a JWT, which breaks the cross-worker JWKS validation architecture).
+- R3. `/.well-known/oauth-authorization-server` (RFC 8414) is served at the root path on `https://api.packrat.world` (NOT `/api/auth/.well-known/...`); `/.well-known/oauth-protected-resource` (RFC 9728) is served at the root path on `https://mcp.packratai.com` and advertises `authorization_servers: ["https://api.packrat.world"]`. The `issuer` claim in the AS metadata exactly matches the URL the metadata is fetched from.
+- R4. Claude is pre-registered as a trusted OAuth client in Better Auth — both `https://claude.ai/api/mcp/auth_callback` and `https://claude.com/api/mcp/auth_callback` allowlisted, `type: 'public'` (PKCE-only, no shared secret), end users still see the consent screen. The plugin does NOT expose a `trustedClients` config array (per doc-review inspection of the installed package source — that was an outdated assumption from external docs); registration happens via the plugin's `POST /oauth2/create-client` endpoint or a DB seed against the `oauthClient` table. Mechanism choice is a planning-time decision (see Open Questions).
+- R5. The four MCP scopes (`mcp`, `mcp:read`, `mcp:write`, `mcp:admin`) are declared in `@better-auth/oauth-provider`'s scope catalog. `mcp:admin` is granted only when the authenticated user has `role === 'ADMIN'`. **Enforcement mechanism** (verified by spike against the actual plugin source — see `docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md`): a custom `consentPage` URL is registered with the plugin; the page server-side reads the user's role and POSTs a filtered `scope` field to `/oauth2/consent` (which accepts a reduced subset of the originally-requested scopes — first-class plugin behavior). Non-admin users requesting `mcp:admin` end up with a JWT that does NOT carry the scope. **Defense in depth**: the MCP worker also re-checks `user.role` via the PackRat API for any `mcp:admin`-scoped tool call (cached 5s, fail-closed). Both ship; the consentPage is the user-facing primary, the RS re-check is the safety net.
+- R6. The MCP Worker's `@cloudflare/workers-oauth-provider` dependency and every line of the OAuth state machine it required (handleAuthorize, handleLogin*, handleCallback, dcrRegisterGate, CSRF/Origin helpers, isAdminUser bridge, grantedScopesFor, login-page.ts, scheduled.ts purgeExpiredData cron, register-claude-clients.ts script) is deleted; only the protected-resource surface (well-known metadata, JWT validation, /health, /status, /mcp, /favicon.ico, CORS for Claude origins) remains.
+- R7. `MCP_OAUTH_KV` bindings and namespaces (`MCP_OAUTH_KV` prod `0ac2e23bb4f04dc5a39cfd3d7bc900e0`, `MCP_OAUTH_KV_dev` `be554ba7448c4c13a48e85d9a0cdabc8`) and the `MCP_INITIAL_ACCESS_TOKEN` secret are removed from `wrangler.jsonc`; namespaces deprovisioned via `wrangler kv namespace delete`. The KV-purge cron is removed.
+- R8. Every preserved component continues working: scope filter in `init()` (now sourced from JWT `scope` claim), Workers Rate Limiting binding `MCP_TOOLS_RL` keyed `${userId}:${toolName}` (now from JWT `sub`), audit logs with `actor: { userId, scopes }`, all 103 `packrat_*` tools + annotations, structured outputs + isError + pagination, resources + glossary, elicitations on destructive admin tools, `/health` probing KV+API, `/status` advertising scopes, favicon at OAuth domain, all submission-readiness probes pass against the new architecture.
+- R9. `apps/admin`'s legacy HS256 admin-JWT path is preserved (the U5 dual-path `adminAuthGuard` in `packages/api/src/routes/admin/index.ts` still accepts both an HS256 `packrat-admin` JWT and a Better Auth bearer where `user.role === 'ADMIN'`). No migration of `apps/admin` in this plan.
+- R10. JWT access tokens are signed via Better Auth's `jwt()` plugin (already installed) using its JWKS — same `jwks` table that today serves `/api/auth/jwks`. Stale-while-revalidate caching on the MCP side, with single-retry on stale `kid` per the April plan's documented commitment.
+- R11. Dev-environment verification gate: before the prod cutover, an operator manually installs the connector in a real Claude.ai account against the dev deploy URLs (`packrat-mcp-dev.workers.dev` + `packrat-api-dev.workers.dev`) and confirms the full OAuth → initialize → tool-call flow works end-to-end. If verification fails, fallback to reverse-proxying AS endpoints onto `mcp.packratai.com` is documented but not built unless needed.
+- R12. All MCP unit tests pass after refactor (current baseline: 1134 tests across 17 unit + 4 integration files). New JWKS-cache + JWT-validation unit tests added. Tests tightly coupled to deleted code (auth.test.ts OAuth-state machine tests, login-page.test.ts, scheduled.test.ts) are removed; surviving tests are kept.
+
+---
+
+## Scope Boundaries
+
+- No new dedicated auth worker. Better Auth stays in `packages/api`. (Re-locked from prior dialogue.)
+- No DB switch. Neon Postgres + Drizzle + `AUTH_KV` namespace stays.
+- No `apps/admin` migration off the legacy HS256 JWT path.
+- No custom-branded OIDC consent UI in v1. Better Auth's default consent screen, served at `https://api.packrat.world`, is the v1 UX. Reviewer-perception polish deferred.
+- No changes to tool implementations, descriptions, annotations, resources, glossary, elicitations, listing artifacts, branding, legal pages.
+- No new social providers (Google + Apple already in Better Auth; SSO buttons on the deleted MCP login page are gone with it).
+- No production deploy from this plan. CI deploys on tag push (operator action). Local validation is vitest only — no `wrangler deploy` invoked from any unit.
+
+### Deferred to Follow-Up Work
+
+- ~~Custom-branded OIDC consent UI~~ — **promoted to in-scope** in U1 after the spike (`docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md`) confirmed it doubles as the scope-filtering mechanism. We're already building consent UI for `mcp:admin` gating (R5); branding it in the same pass is incremental work. Lifted from Future Considerations.
+- **`apps/admin` migration off HS256 admin JWT**: defer until the SPA is rewritten or has a clear ownership owner; the dual-path guard preserves back-compat indefinitely.
+- **MCP SSO via Better Auth social providers**: the U11 deferral is now structurally implementable (the OAuth flow lives entirely on `api.packrat.world`, so the cookie-domain blocker between `packratai.com` and `packrat.world` no longer applies to MCP login). Wire SSO buttons on Better Auth's default consent screen if/when reviewers ask — but defer the work itself.
+- **Per-feature scope refinement** (`mcp:trails:read`, `mcp:packs:write`, etc.): the four coarse scopes ship; finer granularity defers per the original connector-store plan.
+- **JWKS rotation policy + key-rollover runbook**: Better Auth's `jwks` table supports rotation but the project has no documented operator procedure for rolling keys. Defer; document the steady-state assumption (one key, no rotation) until needed.
+- **Migration of any production OAuth grants in `MCP_OAUTH_KV`**: no live grants exist today (the connector hasn't deployed to prod). If grants exist by execution time, document that they invalidate atomically with the AS swap — Claude users re-authorize.
+- **`better-auth-cloudflare@^0.3.0`**: this package is in `packages/api/package.json` but has zero imports anywhere in the source tree (verified via grep). Remove during U1 as a one-line cleanup; not a separate unit.
+
+---
+
+## Context & Research
+
+### Relevant Code and Patterns
+
+- `packages/api/src/auth/index.ts` (lines 25-169) — Better Auth runtime instance, per-isolate `WeakMap`-cached singleton (`authCache`), full plugin set (`bearer`, `jwt`, `admin`, `expo`), social providers, rate-limit config (`window: 60, max: 100`, secondary-storage), `trustedOrigins` (currently includes `https://mcp.packratai.com` from **prior-plan U6**; this refactor REMOVES that entry — the MCP worker no longer calls Better Auth sign-in endpoints directly).
+- `packages/api/src/auth/auth.config.ts` (lines 22-80) — static CLI config that must stay in lockstep with `index.ts` for schema generation. Documented drift hazard.
+- `packages/api/src/index.ts` (lines 122-128) — Cloudflare `fetch` handler intercepts `/api/auth/**` before Elysia, calls `getAuth(env)`, returns `auth.handler(request)`. The mount point for the new OAuth provider's endpoints.
+- `packages/db/src/schema.ts` (lines 25-108) — current Better Auth tables (`users`, `session`, `account`, `verification`, `jwks`). NO `oauthApplication`/`oauthAccessToken`/`oauthConsent` tables — adding the plugin requires a new migration.
+- `packages/api/auth-schema.ts` — drift artifact at the API package root, parallel to `packages/db/src/schema.ts`. Generated by Better Auth CLI; not imported. Either delete or sync during U1.
+- `packages/api/src/routes/admin/index.ts` (lines 168-205) — `adminAuthGuard` with the dual-path (HS256 JWT OR Better Auth bearer with role check). Preserved unchanged.
+- `packages/mcp/src/index.ts` (lines 75-555) — `PackRatMCP` Durable Object, outer fetch wrapper, OAuthProvider config block, `mcpApiHandler` wrapper, `scheduled()` handler. The outer fetch shrinks substantially; the OAuthProvider config block + apiHandler + scheduled all delete.
+- `packages/mcp/src/auth.ts` (1095 lines) — the bulk to delete. Survivors: `handleHealth`, `handleStatus`, `__resetHealthCacheForTests`, `PUBLIC_LINKS`. Everything else (OAuth state machine, CSRF, Origin checks, dcrRegisterGate, role bridge, `betterAuthErrorCopy`, `checkLoginRateLimit`) deletes.
+- `packages/mcp/src/metadata.ts` — `buildResourceMetadata` (still served by MCP for RFC 9728) keeps its shape; `authorization_servers` value changes from `https://mcp.packratai.com` to `https://api.packrat.world`. `SCOPES_SUPPORTED` constant stays (still advertised). `unauthorizedResponse` + `buildWwwAuthenticateHeader` stay.
+- `packages/mcp/src/scopes.ts` — pure functions, transport-agnostic. Survives unchanged; gets re-bound via different input source (JWT `scope` claim, not `props.scopes`).
+- `packages/mcp/wrangler.jsonc` — `kv_namespaces[].OAUTH_KV` (both prod + dev), `triggers.crons`, `MCP_INITIAL_ACCESS_TOKEN` secret all removed. `rate_limiting`, `durable_objects`, `custom_domain`, `observability` all stay.
+
+### Institutional Learnings
+
+- `docs/solutions/developer-experience/better-auth-cloudflare-worker-factory-2026-05-02.md` — Better Auth CLI requires a static `auth.config.ts` that mirrors the runtime config because per-request factories can't be statically imported. Schema regen via `bunx auth generate --config src/auth/auth.config.ts`. **Directly applies to U1**: adding `@better-auth/oauth-provider` is a plugin addition; the static config file must mirror exactly or schema generation diverges from runtime.
+- `docs/plans/2026-04-30-feat-better-auth-migration-plan.md` — architectural parent. Decisions to preserve: (1) per-isolate `authCache` singleton pattern with isolate-rotation discipline on deploy (`docs/mcp/runbook.md` "Forcing isolate rotation"), (2) KV rate-limit windows ≥ 60s (Cloudflare KV TTL floor), (3) `trustedOrigins` in both `index.ts` and `auth.config.ts`, (4) Apple per-isolate client-secret JWT signing. Decision to **re-litigate**: this plan rejected cross-origin AS as "more brittle"; this refactor reverses that decision and verifies empirically in dev (R11).
+- `docs/plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md` — connector-store readiness, completed. Every U7-U18 surface must keep working. The auth-surface units (U3-U6) get superseded.
+- `docs/mcp/runbook.md` — operator-facing reality of the connector-store work. Heavy rewrites in U8: the DCR gating contract section deletes, login form security section deletes (U6 work goes away), KV provisioning section rewrites, OTel pipeline + custom domain sections stay.
+- No prior `docs/solutions/` entries for: OIDC providers on Cloudflare Workers, JWKS cache patterns with stale-while-revalidate, cross-domain OAuth (RFC 9728 cross-origin), `@better-auth/oauth-provider` plugin usage. This refactor is greenfield institutional territory and should produce 2-3 new `docs/solutions/` entries when it lands.
+
+### External References
+
+- [Better Auth OAuth 2.1 Provider docs](https://better-auth.com/docs/plugins/oauth-provider) — the new package's reference. Configuration shape, `trustedClients`, `validAudiences`, `customAccessTokenClaims({user, scopes, resource, client})`, `formatRefreshToken`, per-client `require_pkce`, refresh rotation with old-token invalidation.
+- [Better Auth MCP plugin docs](https://better-auth.com/docs/plugins/mcp) — bundled `mcp` plugin reference; we're NOT using this directly but it confirms the deprecation track and the `createMcpAuthClient` HTTP-introspection alternative we're choosing to avoid.
+- [@better-auth/oauth-provider on npm](https://www.npmjs.com/package/@better-auth/oauth-provider) — package metadata. Latest 1.6.x track.
+- [MCP Authorization spec 2025-11-25](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization) — RFC 8414 + 9728 + 8707 requirements; the `WWW-Authenticate: Bearer resource_metadata="..."` 401 contract; `issuer` claim must match the metadata-fetch URL; PKCE S256 mandatory.
+- [Anthropic Connector troubleshooting](https://claude.com/docs/connectors/building/troubleshooting) — explicit blessing of cross-origin AS pattern + warning about WAF blocking discovery probes from Anthropic's egress range + redirect-loses-Authorization-header trap.
+- [anthropics/claude-ai-mcp#82, #248, #291, #11814] — closed-as-not-planned issues about Claude.ai cross-origin AS bugs. Real but unconfirmed-current; the R11 dev verification gate catches them.
+- [better-auth#5496] — "OIDC plugin sets incorrect issuer at non-root basePath" — fixed pre-1.6.11, verify token `iss` claim during U1.
+- [better-auth#9654] — `verifyAccessToken` passes raw `jose` errors through; wrap try/catch and map to 401.
+- [better-auth#6423] — expired OAuth tokens not auto-deleted; track for cleanup cron in follow-up if needed.
+
+---
+
+## Key Technical Decisions
+
+- **Use `@better-auth/oauth-provider` (separate npm package), NOT the bundled `oidcProvider`/`mcp` plugins.** The bundled plugins are `@deprecated` in `better-auth@1.6.11`'s own source. Going "all in on Better Auth's docs" means going on the actively-maintained package. The new package adds: real RFC 8707 audience binding (`validAudiences`), proper refresh rotation (with `oauthRefreshToken` table tracking), per-client PKCE config, JWT-signable access tokens (default — no opt-in flag required; the relevant option is `disableJwtPlugin?: boolean` which defaults to `false`). Note: `customAccessTokenClaims` is NOT a scope-reduction hook (inspection-confirmed); scope-gating mechanism is a planning decision (see Open Questions / R5).
+- **JWT access tokens, signed via the `jwt()` plugin's JWKS, validated locally on the MCP worker via `jose.createRemoteJWKSet` + stale-while-revalidate cache.** Avoids per-request HTTP introspection round-trip (~50ms latency saved per MCP call). Matches the April plan's documented JWKS caching commitment.
+- **Discovery endpoints mounted at root via `@better-auth/oauth-provider`'s metadata helpers.** Better Auth defaults to subpath (`/api/auth/.well-known/...`); RFC 5785 + MCP clients expect root (`/.well-known/...`). The package exports the AS-side helpers as `oauthProviderAuthServerMetadata` and `oauthProviderOpenIdConfigMetadata` (verified via doc-review inspection of `dist/index.d.mts:64`); the protected-resource metadata helper does NOT ship from the AS-side package — keep the existing `packages/mcp/src/metadata.ts` `buildResourceMetadata` for that (it's served by the MCP worker anyway, which is the architecturally correct location per RFC 9728).
+- **Pre-register Claude via DB seed against the `oauthClient` table (NOT a plugin config — `trustedClients` doesn't exist).** `allowDynamicClientRegistration: false` everywhere; both Claude callback URLs are seeded with `type: 'public'` (PKCE-only) into the `oauthClient` table at deploy time via a one-shot script that calls `auth.api.createOAuthClient(...)`. Operator script analog to the deleted `register-claude-clients.ts` but targeting Better Auth's admin endpoint instead of workers-oauth-provider's. Document in U1.
+- **Admin-scope gating mechanism is a planning-time decision (see R5).** `customAccessTokenClaims` only spreads into JWT claims; the scope field is overwritten downstream — confirmed by inspection of `dist/index.mjs:339-363`. Two viable enforcement paths: (a) custom `consentPage` that pre-filters scopes before `/oauth2/consent` is called, (b) resource-server re-check of `user.role` for any `mcp:admin`-scoped call from the MCP worker (defense-in-depth always-on; primary if no consent UI built). The plan ships path (b) unconditionally and adds path (a) if branded consent UI lands in U1 — see Open Questions.
+- **Audience binding pinned to `https://mcp.packratai.com/mcp`.** Plugin's `validAudiences: ['https://mcp.packratai.com/mcp']` rejects tokens minted for any other audience. MCP worker validates `aud` claim during JWT verification. Spec-correct RFC 8707.
+- **Build refactor first, verify in dev before prod tag.** Standard sequence — develop locally, validate via vitest, deploy to dev via CI tag-push, operator manually installs in real Claude.ai against dev URLs to confirm cross-origin flow works. Prod tag only after dev verification.
+- **All local validation via vitest; no `wrangler deploy` invoked from any unit.** Per user constraint. CI handles deploys.
+- **Cutover is clean — no feature-flag, no parallel mounting.** Delete `workers-oauth-provider` machinery in the same arc of commits that adds Better Auth's OAuth provider. Rollback via `git revert` of the merge. Zero deployed OAuth grants exist today, so no migration cost.
+- **`better-auth-cloudflare@^0.3.0` dead code removed.** Listed in deps, zero imports. One-line cleanup during U1.
+
+---
+
+## Open Questions
+
+### Resolved During Planning
+
+- **Which Better Auth package?** `@better-auth/oauth-provider` (new). Confirmed by user direction.
+- **Cross-origin verification posture?** Build first, verify in dev pre-cutover. Confirmed.
+- **Auth-server topology?** Stays in `packages/api`. Confirmed earlier — no new auth worker.
+- **Consent UI?** **Custom branded `consentPage`** (promoted from deferred to in-scope after spike). Doubles as the scope-filter mechanism. See `docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md`.
+- **Admin scope gating mechanism?** Custom `consentPage` filters at grant time (POSTs reduced scope to `/oauth2/consent` — first-class plugin behavior); MCP worker re-checks role on `mcp:admin` calls as defense-in-depth. Both ship in U1/U2.
+- **`apps/admin` migration?** Out of scope. Dual-path `adminAuthGuard` stays.
+- **`better-auth-cloudflare` package?** Dead code, delete during U1.
+- **`trustedClients` config?** Doesn't exist (spike-verified); pre-register Claude via `auth.api.createOAuthClient` seed script.
+- **Schema tables?** Four (`oauthClient`, `oauthAccessToken`, `oauthRefreshToken`, `oauthConsent`) — `oauthRefreshToken` was missing from the original plan; spike caught it.
+- **JWT vs opaque tokens?** JWT default; only issued when `resource` parameter present (spike finding §Q4). Claude.ai sends `resource` per spec; U9 verifies.
+
+### Deferred to Implementation
+
+- **Exact path the `@better-auth/oauth-provider` plugin uses for its endpoints** — likely `/api/auth/oauth2/authorize` and `/api/auth/oauth2/token` per Better Auth conventions, but verify against the installed package's docs at implementation time and update the runbook accordingly.
+- **JWKS cache backend** — Workers Cache API (`caches.default`) vs. KV-backed vs. isolate-local LRU. Pick at implementation time based on the actual JWKS payload size + rotation cadence; isolate-local is cheapest if rotation is rare.
+- **Stale-while-revalidate retry mechanics** — exact code shape for "JWT signature failed → fetch JWKS once via `ctx.waitUntil` → retry verification → if still failing, 401 with `error: token_expired`". Implementer's call.
+- **Final issuer URL** — `https://api.packrat.world` vs `https://api.packrat.world/api/auth` depending on what `@better-auth/oauth-provider` v1.6.x advertises after the basePath fixes (issue #5496). Verify the `iss` claim in a real issued token matches what the AS metadata's `issuer` field says.
+- **Reverse-proxy fallback shape** if dev verification fails — sketch only documented; build only if needed. Likely a per-route proxy on the MCP worker fronting `/.well-known/oauth-authorization-server` + `/oauth2/authorize` + `/oauth2/token` against `api.packrat.world`.
+- **D5 — JWT audience mismatch for MCP→API proxied tool calls.** Three options on the table: (a) extend `validAudiences` to accept both `https://mcp.packratai.com/mcp` and `https://api.packrat.world` so the same JWT is accepted by both; (b) mint a separate API-audience token alongside the MCP token; (c) MCP holds a separate API credential per user (Better Auth bearer fetched via session). Pick at U2 implementation time when proxied call shape is concrete.
+- ~~`customAccessTokenClaims` scope-reduction behavior~~ — **resolved by spike**: confirmed claims-only (cannot reduce scope); using `consentPage` mechanism instead. See `docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md` §Q1-Q2.
+
+---
+
+## High-Level Technical Design
+
+> *This illustrates the intended approach and is directional guidance for review, not implementation specification. The implementing agent should treat it as context, not code to reproduce.*
+
+### Architecture diff
+
+**Before (current state, post-connector-store-readiness):**
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant U as User
+ participant C as Claude.ai
+ participant M as MCP Worker mcp.packratai.com (AS + RS)
+ participant K as MCP_OAUTH_KV
+ participant A as API Worker api.packrat.world (Better Auth IdP only)
+
+ C->>M: GET /.well-known/oauth-protected-resource
+ M-->>C: { authorization_servers: ["https://mcp.packratai.com"] }
+ C->>M: /authorize → /login → /callback (OAuth state in MCP_OAUTH_KV)
+ M->>A: POST /api/auth/sign-in/email
+ A-->>M: session token + userId
+ M->>A: GET /api/auth/get-session (role lookup for mcp:admin)
+ A-->>M: { user: { role: 'ADMIN' } }
+ M->>K: store OAuth grant
+ M-->>C: opaque access_token + refresh_token
+ C->>M: POST /mcp + Authorization: Bearer
+ M->>K: lookup grant
+ M-->>C: tool response
+```
+
+**After (this plan):**
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant U as User
+ participant C as Claude.ai
+ participant M as MCP Worker mcp.packratai.com (RS only)
+ participant A as API Worker api.packrat.world (AS via @better-auth/oauth-provider)
+
+ Note over C,M: Cross-origin discovery (RFC 9728)
+ C->>M: GET /.well-known/oauth-protected-resource
+ M-->>C: { authorization_servers: ["https://api.packrat.world"] }
+ C->>A: GET /.well-known/oauth-authorization-server
+ A-->>C: { issuer, authorization_endpoint, token_endpoint, jwks_uri, scopes_supported }
+
+ Note over C,A: OAuth on api.packrat.world (single origin for entire flow)
+ C->>A: /oauth2/authorize?client_id=claude&scope=mcp+mcp:read+mcp:write&resource=https://mcp.packratai.com/mcp&code_challenge=...
+ A->>U: Better Auth default consent screen
+ U->>A: approve
+ A-->>C: redirect to claude.ai/api/mcp/auth_callback?code=...
+ C->>A: POST /oauth2/token + PKCE verifier + resource=https://mcp.packratai.com/mcp
+ A->>A: customAccessTokenClaims: if user.role !== 'ADMIN', strip mcp:admin
+ A-->>C: JWT access_token (aud=mcp/, iss=api/, scope="mcp:read mcp:write") + rotating refresh_token
+
+ Note over C,M: Tool calls (per-call JWT validation, no network round-trip)
+ C->>M: POST /mcp + Authorization: Bearer
+ M->>M: jose.jwtVerify(JWT, jwks) — JWKS cached SWR from api.packrat.world/api/auth/jwks
+ M->>M: assert iss + aud + exp; extract sub + scopes
+ M-->>C: tool response
+```
+
+### Scope-to-tool gating model (unchanged from the prior plan's U5 — `packages/mcp/src/scopes.ts`; this plan changes only the input source)
+
+| Token scopes | Visible tool prefixes | Notes |
+|---|---|---|
+| `mcp` | read tools | back-compat umbrella; `customAccessTokenClaims` includes by default |
+| `mcp:read` | read tools | |
+| `mcp:write` | read + write tools | |
+| `mcp:admin` | read + write + admin tools | only granted when `user.role === 'ADMIN'` (enforced via `customAccessTokenClaims`) |
+
+Source of `props.scopes`: today, OAuthProvider injects from KV grants → `Props` schema. After: outer fetch wrapper parses JWT `scope` claim → builds equivalent `Props` shape → DO `init()` reads `props.scopes` unchanged.
+
+### Cross-origin failure-mode catalog
+
+The R11 dev verification gate exists because these are real risks:
+
+| Symptom in Claude.ai install | Likely root cause | Mitigation |
+|---|---|---|
+| Claude shows generic "OAuth failed" without ever reaching api.packrat.world | CORS preflight on `POST /mcp` from `claude.ai` origin failing | U2 outer fetch wrapper allowlists `https://claude.ai` and `https://claude.com` for `Access-Control-Allow-Origin` + exposes `WWW-Authenticate` |
+| OAuth completes but Claude shows "Authorization with the MCP server failed" | The MCP returns `301/302` redirect after install, dropping `Authorization` header | Ensure `mcp.packratai.com/mcp` returns 401 (not 302) when token missing; same for any redirect path |
+| Claude ignores `authorization_endpoint` from AS metadata (issue #82) | Claude.ai bug with non-`/authorize` paths on cross-origin AS | Try Better Auth's default endpoint paths; if rejected, mount aliases at `/authorize` and `/token` on `api.packrat.world` root |
+| `initialize` never sent after OAuth (issue #291) | CORS-on-POST-/mcp + missing `Access-Control-Expose-Headers: mcp-session-id` | Confirm CORS exposes both `WWW-Authenticate` and `mcp-session-id` |
+| Token validation 500s instead of 401 on bad token | `jose.jwtVerify` throws raw error; not caught and mapped (issue #9654) | U2 wraps verify call in try/catch, maps to 401 + WWW-Authenticate |
+| Discovery probe from Anthropic egress blocked at zone | WAF / Bot Fight Mode on `api.packrat.world` blocking unknown user agents | Explicit allow rule for `/.well-known/*` paths; document in runbook |
+
+---
+
+## Implementation Units
+
+### U1. Install `@better-auth/oauth-provider`, configure plugin, regenerate schema
+
+**Goal:** Add the new OAuth provider plugin to Better Auth on the API worker, configure it with the four MCP scopes + Claude pre-registration + audience binding + admin-scope gating, generate the new database tables.
+
+**Requirements:** R2, R3, R4, R5, R9, R10
+
+**Dependencies:** None
+
+**Files:**
+- Modify: `packages/api/package.json` (add `@better-auth/oauth-provider@^1.6.0` to dependencies; remove `better-auth-cloudflare@^0.3.0` from devDependencies — dead code per repo audit)
+- Modify: `packages/api/src/auth/index.ts` (add the plugin to `plugins: [...]`; **remove** `'https://mcp.packratai.com'` from `trustedOrigins` — the MCP worker no longer calls Better Auth sign-in endpoints directly after this refactor, so the trusted-origin entry expands CORS/CSRF bypass surface unnecessarily. CORS for MCP-originated traffic to specific routes can be handled per-route via Elysia's CORS plugin if needed.)
+- Modify: `packages/api/src/auth/auth.config.ts` (mirror the plugin config in the static CLI surface — lockstep per `docs/solutions/developer-experience/better-auth-cloudflare-worker-factory-2026-05-02.md`; also mirror the `trustedOrigins` removal of `'https://mcp.packratai.com'`)
+- Modify: `packages/db/src/schema.ts` (add the **four** new tables: `oauthClient` (NOT `oauthApplication` — that's the bundled OIDC plugin's name), `oauthAccessToken`, `oauthRefreshToken`, `oauthConsent` — copy shape from `packages/api/auth-schema.ts` after regen. The `oauthRefreshToken` table is required for R2's refresh-token rotation; omitting it breaks refresh grants at first attempt per doc-review inspection of the plugin source)
+- Modify: `packages/api/src/index.ts` (mount `oauthProviderAuthServerMetadata` and `oauthProviderOpenIdConfigMetadata` helpers at root paths `/.well-known/oauth-authorization-server` and `/.well-known/openid-configuration` — replaces Better Auth's default subpath mount for these specific endpoints. Note: protected-resource metadata helper does NOT ship from the AS-side package; that's served by the MCP worker via the existing `buildResourceMetadata` in `packages/mcp/src/metadata.ts`)
+- Create: `packages/api/src/auth/consent-page.ts` (server-rendered branded consent page registered as `consentPage: '/oauth/consent'` in the plugin config; reads `client_id`, `scope`, `code` query params; server-side checks current user's Better Auth session role; filters `mcp:admin` from the displayed scope set for non-admins so the user can't approve a scope they're not eligible for; renders PackRat-branded consent UI with logo, client name from the `oauthClient` record's `name`/`logo_uri` fields, scope-by-scope description, and the four URI links (`policy_uri` → privacy, `tos_uri` → terms, `client_uri` → docs); POSTs to `/api/auth/oauth2/consent` with the approved filtered `scope` field per the plugin's first-class scope-reduction mechanism — see spike findings in `docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md`)
+- Create: `packages/api/src/auth/__tests__/consent-page.test.ts` (assertions: non-admin requesting `mcp:admin` sees that scope absent from the form; POST with filtered scope causes the issued JWT to omit `mcp:admin`; admin sees and can approve all four scopes; CSRF protection inherits from Better Auth session middleware on `/oauth2/consent`)
+- Create: `packages/api/drizzle/.sql` (drizzle-kit migration emitted by `bun run db:generate`)
+- Delete: `packages/api/auth-schema.ts` (drift artifact at API package root, parallel to `packages/db/src/schema.ts`, not imported anywhere; remove after copying the new tables into the real schema)
+- Test: `packages/api/test/oauth-provider.test.ts` (new — discovery doc shape, trustedClients are visible, /authorize redirects correctly)
+
+**Approach:**
+- Install the plugin. Configure with: `scopes: ['openid', 'profile', 'email', 'offline_access', 'mcp', 'mcp:read', 'mcp:write', 'mcp:admin']`; `requirePKCE: true`; `allowPlainCodeChallengeMethod: false`; `allowDynamicClientRegistration: false`; `validAudiences: ['https://mcp.packratai.com/mcp']`; `consentPage: '/oauth/consent'`; `loginPage: '/sign-in'` (or wherever Better Auth's sign-in page lives in the API). **JWT access tokens are the default** (option name is `disableJwtPlugin?: boolean`, default `false` — leave unset). **Critical**: JWT tokens are only issued when the client sends a `resource` parameter (spike-verified `isJwtAccessToken = audience && !disableJwtPlugin`); Claude.ai sends `resource` per MCP spec, but verify in U9. `trustedClients` is NOT a valid config option (verified by spike); use the seed mechanism in the next bullet instead.
+- Pre-register Claude via DB seed: create a one-shot script at `packages/api/scripts/seed-claude-oauth-client.ts` that calls `auth.api.createOAuthClient({ headers: , body: { redirect_uris: ['https://claude.ai/api/mcp/auth_callback', 'https://claude.com/api/mcp/auth_callback'], token_endpoint_auth_method: 'none', grant_types: ['authorization_code', 'refresh_token'], response_types: ['code'], client_name: 'Claude', scope: 'openid profile email offline_access mcp mcp:read mcp:write', logo_uri: 'https://packratai.com/mcp-logo-256.png', policy_uri: 'https://packratai.com/privacy-policy', tos_uri: 'https://packratai.com/terms-of-service' } })`. The `redirect_uris` field uses the API's snake_case wire shape; the schema column is `redirectUris` (camel-case) — both are correct depending on the layer. The four client-metadata URI fields (`logo_uri`, `client_uri`, `policy_uri`, `tos_uri`) are load-bearing for the consent screen — they're what users read during install.
+- **Admin-scope gating is primarily at consent time, defended-in-depth at the resource server.** The custom `consentPage` (new file in this unit) reads the user's role from the Better Auth session and POSTs a filtered `scope` field to `/oauth2/consent` — the plugin natively accepts a reduced subset (spike-verified, see `docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md` §Q2). Non-admin users requesting `mcp:admin` receive a JWT without it. The MCP worker's `verifyMcpToken` also re-checks `user.role` via a cached Better Auth `getSession` call (5s timeout, fail-closed) for any tool call where `mcp:admin` appears in the JWT scope — defense-in-depth backstop against a misconfigured consent page or a stolen admin JWT.
+- Schema regen flow per `CLAUDE.md` "Migration discipline": edit both `auth/index.ts` and `auth/auth.config.ts` in lockstep; run `cd packages/api && bunx auth generate --config src/auth/auth.config.ts`; review the generated `packages/api/auth-schema.ts`; copy the four new tables (`oauthClient`, `oauthAccessToken`, `oauthRefreshToken`, `oauthConsent` — `oauthRefreshToken` is required for R2's refresh-token rotation) into `packages/db/src/schema.ts`; run `cd packages/api && bun run db:generate`; **do not rename the generated SQL file**; run `bunx drizzle-kit check`.
+- Mount discovery at root: in `packages/api/src/index.ts`'s fetch dispatcher, intercept `GET /.well-known/oauth-authorization-server` and `GET /.well-known/oauth-protected-resource` before Elysia, call Better Auth's `oAuthDiscoveryMetadata(auth)` and `oAuthProtectedResourceMetadata(auth)` helpers respectively. RFC 5785 requires these at root; Better Auth's default mount under `/api/auth/.well-known/...` doesn't satisfy clients.
+- Verify in test: the AS metadata `issuer` claim equals `https://api.packrat.world` (or whatever URL the metadata is served from — they MUST match per spec).
+
+**Patterns to follow:**
+- Per-isolate `authCache` singleton stays (lines 22, 26, 167 of `packages/api/src/auth/index.ts`); the new plugin gets captured into the singleton at first request per isolate. Document the isolate-rotation requirement for the deploy in U7.
+- Schema additions follow the existing Better Auth section in `packages/db/src/schema.ts` (after line 102 `jwks`).
+- `bunx drizzle-kit check` is the validation gate per `CLAUDE.md`.
+
+**Test scenarios:**
+- Happy path: `GET https://api.packrat.world/.well-known/oauth-authorization-server` returns JSON with `issuer: "https://api.packrat.world"`, `code_challenge_methods_supported: ["S256"]`, `scopes_supported` includes all four MCP scopes plus the standard OIDC scopes, `authorization_endpoint` and `token_endpoint` on `api.packrat.world`.
+- Happy path: a registered trusted client `claude-ai` appears when calling `auth.api.listOAuthClients()` (or equivalent); the redirect URL list contains both Claude callback URLs.
+- Edge case: requesting `mcp:admin` as a non-admin user — assert that the access token's `scope` claim does NOT contain `mcp:admin` after the `customAccessTokenClaims` hook fires. If empirically the hook doesn't reduce scopes, this test red-flags the gap so the implementer falls back to a custom consent page.
+- Edge case: requesting `mcp:admin` as an admin user — token contains it.
+- Error path: requesting an unsupported scope (e.g., `mcp:nonsense`) returns `invalid_scope` error.
+- Integration: a full PKCE S256 authorization-code flow against the deployed dev instance (via `mcp-cli` or `@modelcontextprotocol/inspector`) issues a JWT access token whose `aud` claim equals exactly `https://mcp.packratai.com/mcp` and whose `iss` matches the AS metadata `issuer`. (Marked `it.todo` if vitest-pool-workers still has the ajv blocker per U17 of the prior plan; otherwise live.)
+
+**Verification:**
+- `cd packages/api && bunx drizzle-kit check` is green.
+- `cd packages/api && bun run test:unit` shows the OAuth provider discovery test passing.
+- A reviewer can `curl` the well-known URL from outside Cloudflare and see the discovery JSON.
+
+---
+
+### U2. MCP-side JWT validation infrastructure (JWKS cache + verify helper)
+
+**Goal:** Build the protected-resource validation surface — a JWKS-aware token verifier with stale-while-revalidate caching, fail-closed semantics, RFC 8707 audience claim enforcement, and the integration seam the U3 deletion expects.
+
+**Requirements:** R1, R2, R10
+
+**Dependencies:** U1 (the JWKS endpoint at `api.packrat.world/api/auth/jwks` must serve the same keys that signed the JWTs)
+
+**Files:**
+- Create: `packages/mcp/src/token-verify.ts` (the JWKS cache + JWT verify wrapper)
+- Create: `packages/mcp/src/__tests__/token-verify.test.ts` (unit tests against fixture JWTs)
+- Modify: `packages/mcp/package.json` (add `jose@^6.x` — verify version against Workers compat date; Better Auth uses jose internally so it's likely already in the workspace tree)
+
+**Approach:**
+- The verifier exposes a single function: `async verifyMcpToken(token: string, env: Env): Promise<{ sub: string; scopes: string[]; token: string } | null>`. Returns `null` on any verification failure (caller maps to 401 with `WWW-Authenticate`).
+- Internally: `jose.createRemoteJWKSet(new URL('https://api.packrat.world/api/auth/jwks'), { cacheMaxAge: 600_000 })` (10-minute cache); call `jose.jwtVerify(token, jwks, { issuer: 'https://api.packrat.world', audience: 'https://mcp.packratai.com/mcp', algorithms: ['ES256', 'RS256'] })`.
+- Stale-while-revalidate retry: on first `jose.errors.JWSSignatureVerificationFailed` (possible stale JWKS cache after key rotation), fire `ctx.waitUntil(jwks.coolingDown(0))` to force refresh, then retry verification once. On second failure, return `null`. Per the April plan's documented commitment.
+- Wrap `jose.jwtVerify` in try/catch — any thrown error returns `null` (per issue better-auth#9654, raw thrown errors break the WWW-Authenticate-driven discovery retry).
+- Extract `payload.sub` and `payload.scope` (space-separated string per RFC 6749 §3.3) → split → return as `scopes: string[]`. Return the raw token alongside for the legacy `betterAuthToken` field in `Props` (used by `packages/mcp/src/client.ts` to forward as Bearer to the PackRat API for proxied calls).
+
+**Execution note:** Build the verifier test-first with fixture JWTs (use `jose.SignJWT` to mint test tokens against an in-memory key). The verifier is the most security-critical surface in the refactor; correctness via tests before integration.
+
+**Technical design:**
+
+```
+function makeJwksCache(env: Env, ctx: ExecutionContext):
+ jwks ← jose.createRemoteJWKSet('${PACKRAT_API_URL}/api/auth/jwks', { cacheMaxAge: 10min })
+ return jwks
+
+async function verifyMcpToken(token, env, ctx):
+ try:
+ { payload } ← jose.jwtVerify(token, jwks, {
+ issuer: 'https://api.packrat.world',
+ audience: 'https://mcp.packratai.com/mcp',
+ algorithms: ['ES256','RS256'],
+ })
+ return { sub: payload.sub, scopes: payload.scope?.split(' ') ?? [], token }
+ catch e:
+ if e is signature error AND first try:
+ ctx.waitUntil(jwks.reload())
+ retry once
+ return null
+```
+
+Frame: directional guidance, not implementation specification. The implementing agent should treat this as context, not code to reproduce.
+
+**Patterns to follow:**
+- Better Auth's own client uses `jose` — mirror the version and import shape (`import { jwtVerify, createRemoteJWKSet } from 'jose'`).
+- Existing pattern: `packages/mcp/src/metadata.ts`'s `unauthorizedResponse` helper — call it from the outer fetch wrapper when `verifyMcpToken` returns null.
+
+**Test scenarios:**
+- Happy path: a JWT signed by a test JWKS key, with valid `iss`, `aud`, `exp`, returns `{ sub, scopes, token }`.
+- Happy path: scopes are correctly split from space-separated string.
+- Edge case: token with no `scope` claim returns `scopes: []`.
+- Edge case: token with `aud` as array (rather than string) including the MCP audience verifies successfully (RFC 7519 allows both).
+- Error path: token with wrong `iss` returns `null`.
+- Error path: token with wrong `aud` returns `null`.
+- Error path: expired token returns `null`.
+- Error path: token signed with an unknown key returns `null` after one retry (stale-while-revalidate exercised).
+- Error path: malformed JWT (not three base64 segments) returns `null` without throwing.
+- Error path: token signed with `alg: none` returns `null` (algorithm allowlist enforced).
+- Integration: real `api.packrat.world/api/auth/jwks` endpoint reachable from the test environment returns a JWKS document `jose` accepts. (May be `it.todo` if integration-test infrastructure is still blocked.)
+
+**Verification:**
+- `bun run test --filter @packrat/mcp` shows the new token-verify suite passing.
+- A real token issued by a U1-configured dev API instance can be verified by this helper end-to-end (manual smoke).
+
+---
+
+### U3. Rewrite MCP outer fetch wrapper; delete `workers-oauth-provider` machinery
+
+**Goal:** Replace the OAuthProvider-based outer fetch wrapper in `packages/mcp/src/index.ts` with a thin dispatcher that does JWT validation on `/mcp`, serves the well-known + favicon + health + status routes directly, and delegates `/mcp` to the Durable Object. Delete every line of OAuth state machinery (auth.ts handlers, login-page.ts, scheduled.ts, register-claude-clients.ts) and the `@cloudflare/workers-oauth-provider` dependency.
+
+**Requirements:** R3, R6
+
+**Dependencies:** U2 (the JWT verifier is the replacement for OAuthProvider's apiHandler gate)
+
+**Files:**
+- Modify: `packages/mcp/package.json` (remove `@cloudflare/workers-oauth-provider`; remove `magic-regexp` — its only consumers were the CSRF-cookie regexes in `auth.ts` deleted in this unit and the escapeHtml regexes in `login-page.ts` deleted in this unit, leaving zero remaining usages)
+- Modify: `packages/mcp/src/index.ts` (rewrite the default export: drop OAuthProvider config block lines ~431-499, drop `mcpApiHandler` wrapper lines ~383-412, drop `dcrRegisterGate` call, drop `scheduled` arm; new outer fetch dispatcher: route `/.well-known/oauth-protected-resource` to a static handler, `/health` + `/status` + `/favicon.ico` to surviving auth.ts handlers, `OPTIONS *` for CORS preflight from Claude origins, default to `/mcp` → JWT-validate via `verifyMcpToken` → build `Props` → forward to DO; `Props` shape stays the same so DO consumers don't change)
+- Modify: `packages/mcp/src/auth.ts` (delete: `handleAuthorize`, `handleLoginGet`, `handleLoginPost`, `handleCallback`, `dcrRegisterGate`, `extractBearer`, `timingSafeEqual`, `csrfEqual`, `isOriginAcceptable`, `parseCookieHeader`, `buildCsrfSetCookie`, `betterAuthErrorCopy`, `checkLoginRateLimit`, `isAdminUser`, `grantedScopesFor`, `PackRatAuthHandler`, KV-key helpers `oauthStateKey`/`sessionKey`/`csrfKey`, all `magic-regexp` imports tied to deleted helpers, all `OAUTH_KV` references. Keep: `handleHealth`, `handleStatus`, `__resetHealthCacheForTests`, `PUBLIC_LINKS`, `serviceMetadata`. The file should be a small module exporting health/status handlers + the public-links constant.)
+- Modify: `packages/mcp/src/metadata.ts` (change `authorization_servers` value in `buildResourceMetadata` from `https://mcp.packratai.com` to `https://api.packrat.world` — this is the load-bearing one-line change connector-store-readiness submission depends on)
+- Modify: `packages/mcp/src/types.ts` (drop `Env.OAUTH_KV`, drop `Env.OAUTH_PROVIDER`, drop `Env.MCP_INITIAL_ACCESS_TOKEN`; keep `Env.MCP_TOOLS_RL`, `Env.MCP_FEATURE_FLAGS`, `Env.MCP_COMMIT_SHA`, `Env.PACKRAT_API_URL`, `Env.PackRatMCP`; `Props` shape unchanged but `betterAuthToken` is now the validated JWT)
+- Delete: `packages/mcp/src/login-page.ts` (entire file)
+- Delete: `packages/mcp/src/scheduled.ts` (entire file)
+- Delete: `packages/mcp/scripts/register-claude-clients.ts` (entire file)
+- Modify: `packages/mcp/src/cors.ts` (comment cleanup: refs to OAuthProvider context are stale; substance correct)
+- Modify: `packages/mcp/src/client.ts` (comment cleanup: ref to OAuthProvider-injected bearer is stale)
+
+**Approach:**
+- The outer fetch wrapper is the only auth surface that survives on the MCP. Sketch of the new dispatcher (directional, not specification):
+ - `OPTIONS *` from `https://claude.ai`/`claude.com` Origin → 204 with CORS headers (preflight handling already lives in `cors.ts`; reuse).
+ - `GET /.well-known/oauth-protected-resource` → static JSON from `buildResourceMetadata(env)`; the `authorization_servers` value now points at `api.packrat.world`.
+ - `GET /favicon.ico` → existing `faviconResponse()`.
+ - `GET /health` → existing `handleHealth(request, env)`.
+ - `GET /status` → existing `handleStatus(request, env)`.
+ - `POST /mcp` (or anything starting with `/mcp`) → extract `Authorization: Bearer `; `verifyMcpToken(token, env, ctx)`; if `null`, return `unauthorizedResponse(env)` (401 with `WWW-Authenticate`); else build `Props = { betterAuthToken: token, userId: result.sub, scopes: result.scopes }` and delegate to the Durable Object via the same SDK pattern OAuthProvider used (`McpAgent.serve('/mcp').fetch` or similar — check `agents@^0.13.2` API).
+ - Anything else: 404.
+- The DO `PackRatMCP` class (lines 75-353 of `index.ts`) stays unchanged in shape — `props` arrives via the same `ctx.props` channel the SDK uses, just sourced from the JWT instead of OAuthProvider grants. The `init()` scope filter, `getAuditContext`, `currentUserId`, rate-limit binding wrapper all consume `this.props.userId` and `this.props.scopes` exactly as today.
+- `metadata.ts` change is the load-bearing one for connector-store correctness — the AS URL Claude discovers MUST match the URL where the AS metadata is served. Update + verify.
+
+**Patterns to follow:**
+- The existing CORS + `WWW-Authenticate` infrastructure stays (U6 work). Reuse `cors.ts`'s `applyCorsHeaders` and `metadata.ts`'s `unauthorizedResponse`.
+- DO delegation pattern: study how the current `mcpApiHandler` calls `mcpDoHandler.fetch(...)` — same pattern, fewer header manipulations (no admin-token header injection since admin is now JWT scope).
+
+**Test scenarios:**
+- Happy path: `GET /.well-known/oauth-protected-resource` returns JSON with `authorization_servers: ["https://api.packrat.world"]` (the load-bearing change).
+- Happy path: `POST /mcp` with a valid JWT calls the DO and returns the DO's response.
+- Error path: `POST /mcp` with no bearer returns 401 + `WWW-Authenticate: Bearer resource_metadata="https://mcp.packratai.com/.well-known/oauth-protected-resource"`.
+- Error path: `POST /mcp` with invalid bearer (wrong issuer, wrong audience, expired) returns 401.
+- Error path: `POST /mcp` with bearer that throws inside `jose` returns 401 (not 500 — guards against issue better-auth#9654).
+- Edge case: `OPTIONS /mcp` from `Origin: https://claude.ai` returns 204 with `Access-Control-Allow-Origin`, `Access-Control-Expose-Headers: WWW-Authenticate, mcp-session-id`, `Access-Control-Allow-Methods: POST, OPTIONS`.
+- Edge case: `OPTIONS /mcp` from `Origin: https://evil.example` does NOT get `Access-Control-Allow-Origin` set.
+- Edge case: `/.well-known/oauth-protected-resource` includes the `scopes_supported` from `metadata.ts` (all four MCP scopes).
+- Integration: `GET /favicon.ico` returns 200 + image/x-icon with .ico magic bytes (existing U13 test survives unchanged).
+
+**Verification:**
+- `bun run test --filter @packrat/mcp` — surviving tests still pass (auth.test.ts has been trimmed to /health, /status, PUBLIC_LINKS only; see U6).
+- `git ls-files packages/mcp/src/auth.ts` → file exists but is ~10% of its prior size.
+- `git ls-files packages/mcp/src/login-page.ts packages/mcp/src/scheduled.ts packages/mcp/scripts/register-claude-clients.ts` → all return no output (files deleted).
+- `grep -r '@cloudflare/workers-oauth-provider' packages/mcp/` → returns nothing.
+
+---
+
+### U4. Re-bind `props.userId` + `props.scopes` from JWT claims (plumbing migration)
+
+**Goal:** Update the `Props` source-of-truth across the Durable Object's consumers — every place that reads `this.props.userId` or `this.props.scopes` now reads the JWT-validated claim shape — without changing the consumer code itself (the Props shape stays identical, only the source changes).
+
+**Requirements:** R8
+
+**Dependencies:** U3 (the outer fetch wrapper builds the Props shape)
+
+**Files:**
+- Modify: `packages/mcp/src/index.ts` (`PropsSchema` Zod schema validation — `betterAuthToken: z.string()`, `userId: z.string()`, `scopes: z.array(z.string())` — unchanged shape, just the source documentation in the comments updates)
+- Modify: `packages/mcp/src/index.ts` (`State` interface — drop `adminToken` if any lingering reference exists; the interface should already be `{ authToken: string }` after U5 of the prior plan)
+- Verify: `packages/mcp/src/index.ts` (`getAuditContext()`, `currentUserId()`, `applyScopeFilter(props.scopes)`, `installToolRegistrationProxy` rate-limit key — all consume `this.props.userId` / `this.props.scopes` unchanged; only the upstream source changed)
+- Verify: `packages/mcp/src/tools/admin.ts` (admin audit logs `actor: { userId, scopes }` — unchanged)
+- Verify: `packages/mcp/src/tools/packTemplates.ts` (audit logs — unchanged)
+- Verify: `packages/mcp/src/scopes.ts` (pure functions, unchanged)
+- Test: extend `packages/mcp/src/__tests__/scopes.test.ts` to assert the scope filter still works when scopes come from a JWT-shaped Props object (use a fixture Props instead of a Better Auth callback)
+
+**Approach:**
+- This unit is mostly a verification + comment-update pass. The Props shape stays the same; the U3 outer fetch wrapper produces the same object, just from a different upstream. Consumers don't care.
+- The only "rewire" is at the construction point (U3) and the validation schema (this unit). Make sure the Zod schema's documentation reflects the new source.
+- For tests: the test pattern shifts from mocking OAuthProvider's `propsResult.data` to constructing a Props directly from a JWT claim shape. The scope-filter test was previously testing "OAuthProvider injects scopes → init() filters tools"; now it tests "JWT scope claim → init() filters tools". Same matrix, different fixture.
+
+**Execution note:** characterization-first. Before changing anything, run the existing scope-filter tests against the current code to lock down the expected behavior; then assert the same matrix holds after the source change. This unit's risk is invisible behavior change.
+
+**Patterns to follow:**
+- The `Props` shape is the contract. Don't change it; don't add fields; don't remove fields. Source change only.
+
+**Test scenarios:**
+- Happy path: a Props built from a JWT claim with `scope: 'mcp:read mcp:write'` filters tools to read + write (same matrix the scope-filter test covered before).
+- Happy path: a Props with `scope: 'mcp:admin'` shows admin tools.
+- Edge case: empty scope claim → fail-closed (no tools visible). Matches `scopes.ts`'s `getVisibleTools(empty)` returning all-false.
+- Edge case: `mcp` (umbrella, back-compat) scope shows read tools only. Matches U5 scope model.
+- Edge case: `userId` from JWT `sub` is correctly forwarded to rate-limit key, audit log actor, `currentUserId()`.
+- Error path: PropsSchema rejection (missing field) surfaces as 401 from the outer fetch wrapper, not a 500.
+
+**Verification:**
+- All scope-related tests pass under the new source.
+- The rate-limit binding test (existing) confirms key shape `${userId}:${toolName}` still works.
+- The audit log allowlist test (existing, U15) confirms `actor.userId` and `actor.scopes` flow through unredacted.
+
+---
+
+### U5. Strip KV bindings, cron, and `MCP_INITIAL_ACCESS_TOKEN` from `wrangler.jsonc`; document namespace deprovisioning
+
+**Goal:** Remove the MCP-side KV binding (no longer used), the `triggers.crons` block (`purgeExpiredData` is gone), and the `MCP_INITIAL_ACCESS_TOKEN` secret (DCR is gone). Operator-side: deprovision the two `MCP_OAUTH_KV` namespaces and remove the secret from Cloudflare via dashboard / wrangler CLI (post-merge, not in any unit).
+
+**Requirements:** R7
+
+**Dependencies:** U3 (no MCP code path references `OAUTH_KV` or `MCP_INITIAL_ACCESS_TOKEN` after U3 lands)
+
+**Files:**
+- Modify: `packages/mcp/wrangler.jsonc` (delete `kv_namespaces[].OAUTH_KV` from top-level and from `env.prod` and from `env.dev`; delete `triggers.crons` from top-level and both envs; delete the comment block referencing the KV setup recipe; update the header comment to drop `MCP_INITIAL_ACCESS_TOKEN` from the required-secrets list)
+- Modify: `packages/mcp/.dev.vars.example` (delete `MCP_INITIAL_ACCESS_TOKEN=...` line + surrounding comment block)
+- Modify: `docs/mcp/runbook.md` (rewrite § "One-time operator setup → 1. KV namespaces" — change from "create and bind" to "deprovision once stale code is removed"; document `wrangler kv namespace delete ` for both `0ac2e23bb4f04dc5a39cfd3d7bc900e0` (prod) and `be554ba7448c4c13a48e85d9a0cdabc8` (dev); delete § "3. Set secrets per environment → MCP_INITIAL_ACCESS_TOKEN"; delete § "4. Pre-register Claude as a trusted OAuth client (U4)" — replaced by Better Auth's `trustedClients` config baked at deploy time; delete § "DCR gating contract (U4)" entirely; delete § "Login form security (U6)" entirely (form is gone); delete § "CORS allowlist on /.well-known/* (U6)" — wait, KEEP this one, CORS on well-known still applies; the well-known endpoint still lives on MCP)
+- Add to `docs/mcp/runbook.md`: new § "AS lives on api.packrat.world (post-refactor)" describing the cross-origin discovery flow, the JWKS endpoint, the `customAccessTokenClaims` admin-gating mechanism, and the trustedClients config location
+
+**Approach:**
+- Code-side: 6-8 line deletions across `wrangler.jsonc` + `.dev.vars.example`. Mechanical.
+- Doc-side: the runbook needs substantial rewrites — about half its content becomes stale or wrong after this refactor. Keep the structure (Domains, One-time setup, Common operations, Known issues) but rewrite the auth-specific subsections to reflect the new architecture.
+- Operator action documented BUT NOT performed in any unit: post-merge, after CI deploys the new code, operator runs `wrangler kv namespace delete ` for both KV namespaces and `wrangler secret delete MCP_INITIAL_ACCESS_TOKEN --env prod` + `--env dev` to clean up Cloudflare state. The runbook records the commands so the operator doesn't have to look them up.
+
+**Test scenarios:**
+- Test expectation: none -- pure config/doc change. The actual binding removal is verified by the U3 verification step (`grep '@cloudflare/workers-oauth-provider' packages/mcp/`) — if the code doesn't reference the binding, the binding can be safely removed from config.
+
+**Verification:**
+- `packages/mcp/wrangler.jsonc` no longer contains `OAUTH_KV` or `triggers.crons` or `MCP_INITIAL_ACCESS_TOKEN`.
+- Runbook reads coherently for an operator unfamiliar with the prior architecture — the deleted sections don't leave dangling references.
+
+---
+
+### U6. Rewrite + delete tests tightly coupled to deleted OAuth machinery
+
+**Goal:** Bring the MCP test suite back to green after the deletions in U3. Delete tests against gone code; rewrite tests whose fixtures were tied to OAuthProvider; preserve every test against code that survives (~80% of the 1134 unit tests).
+
+**Requirements:** R12
+
+**Dependencies:** U3 (the deletions are complete), U4 (the Props source change is settled)
+
+**Files:**
+- Delete: `packages/mcp/src/__tests__/login-page.test.ts` (entire — login-page.ts is gone)
+- Delete: `packages/mcp/src/__tests__/scheduled.test.ts` (entire — scheduled.ts is gone)
+- Delete: `packages/mcp/src/__tests__/integration/dcr-gate.test.ts` (entire — dcrRegisterGate is gone)
+- Modify: `packages/mcp/src/__tests__/auth.test.ts` (trim from 1238 lines to ~150-200 lines — keep ONLY: `handleHealth` tests (probe behavior, cache, both-probes-green, KV-down, API-down, 503 mapping), `handleStatus` tests (full block, scopes_supported, commitSha, secret-denylist), `PUBLIC_LINKS` consistency tests, the `/favicon.ico` route smoke test. Delete: every dcrRegisterGate test, every handleAuthorize/handleLoginPost/handleCallback test, every CSRF test, every Origin-check test, every betterAuthErrorCopy mapping test, every isAdminUser test, every grantedScopesFor test, every checkLoginRateLimit test (the function is gone; the U14 binding stays but its key wrapper moves to test-friendly location))
+- Modify: `packages/mcp/src/__tests__/rate-limit.test.ts` (drop the `loginRateLimitKey` tests — function is gone; keep `toolRateLimitKey` tests since the binding stays + key shape stays)
+- Modify: `packages/mcp/src/__tests__/observability.test.ts` (drop fixtures that mock `env.OAUTH_KV` since OAUTH_KV is gone from Env; the redaction tests and audit log tests survive)
+- Modify: `packages/mcp/src/__tests__/scopes.test.ts` (rewrite test setup to construct Props from JWT-claim fixtures instead of OAuthProvider grants; the assertion matrix stays the same — every scope combination still produces the same visible-tool set)
+- Modify: `packages/mcp/src/__tests__/submission-readiness.test.ts` (update the probe URLs: AS metadata now on `api.packrat.world/.well-known/oauth-authorization-server`, NOT `mcp.packratai.com/.well-known/oauth-authorization-server`; PRM still on `mcp.packratai.com/.well-known/oauth-protected-resource` but its `authorization_servers` value asserts `api.packrat.world`; DCR-gate probe test deleted; trustedClients probe added (verify Claude appears in registered clients via a discovery-list call))
+- Modify: `packages/mcp/src/__tests__/integration/well-known.test.ts` (update the `authorization_servers` URL assertion; the `it.todo` stubs stay deferred per the U17 ajv blocker)
+- Modify: `packages/mcp/src/__tests__/integration/oauth-flow.test.ts` (already `it.todo` — update the descriptions to reflect the cross-origin AS flow; flow now goes through `api.packrat.world`)
+- Modify: `packages/mcp/src/__tests__/metadata.test.ts` (update the `authorization_servers` URL assertion in `buildResourceMetadata` tests)
+- Verify (no changes): `annotations.test.ts` (758 tests), `output-schemas.test.ts` (38), `resources.test.ts` (25), `elicit.test.ts` (20), `tools-admin.test.ts` (19), `favicon.test.ts` (6), `enums.test.ts` (13), `constants.test.ts` (19), `client.test.ts` (n/a or 67 — check) — all should pass without modification
+
+**Approach:**
+- Run the existing test suite first; capture which tests fail. Most failures will be in the files above; deletions and rewrites address them.
+- The Props-source change (U4) means scope test fixtures shift from `OAuthProvider's propsResult.data.scopes` to `JWT.payload.scope.split(' ')`. The assertion matrix doesn't change — same scope combinations → same visible tools.
+- After the rewrites: baseline should be ~900-1000 unit tests (down from 1134 because the 4 deleted files removed ~200-250 tests of code that's gone). Add the new ~25-50 tests from U2 (token-verify) and U1 (oauth-provider configuration) and the total lands in the same neighborhood as today.
+
+**Test scenarios:**
+- This is a test-rewrite unit; its "scenarios" are the meta-assertion that ALL surviving tests pass after the refactor. Specifically:
+ - Pre-refactor baseline: 1134 unit tests, 17 files, 4 integration files (most `it.todo`'d).
+ - Post-refactor target: ≥900 unit tests passing, 0 failures. New unit tests from U1 + U2 bring total back to ~1000+.
+ - The annotations catalog test still asserts every tool has `title`, `readOnlyHint`, etc. — no regression on U7's work.
+ - The output-schemas tests still validate every tier-1 tool's structured output shape — no regression on U8.
+ - The resources tests still validate the glossary + list providers + search template — no regression on U9.
+ - The elicitations tests still validate the destructive-tool confirmation flow — no regression on U10.
+
+**Verification:**
+- `cd packages/mcp && bun run test` is green.
+- `git diff --stat HEAD~1 packages/mcp/src/__tests__/` shows the expected file deletions + size reductions.
+
+---
+
+### U7. Update CI workflows + `submission-readiness.ts` script for the new architecture
+
+**Goal:** Keep the U17 CI workflows (PR test + tag deploy) working post-refactor; update the `submission-readiness.ts` script (U18) so the 13-check probe targets the new AS host.
+
+**Requirements:** R3, R8, R11
+
+**Dependencies:** U1, U2, U3, U5 (the deployable state of the refactor must be settled)
+
+**Files:**
+- Modify: `.github/workflows/mcp-test.yml` (path filters stay correct — `packages/mcp/**`, `packages/api-client/**`, `packages/api/src/auth/**`, `packages/api/src/routes/admin/**`; the "Re-run API auth + admin guard tests" step at line 74-75 becomes more critical post-refactor since the API now owns the AS; possibly add `packages/db/src/schema.ts` to the path filters since the schema migration touches it)
+- Modify: `.github/workflows/mcp-deploy.yml` (drop the `MCP_INITIAL_ACCESS_TOKEN` operator-setup callout in the workflow comments; the deploy step itself doesn't change)
+- Modify: `.github/workflows/mcp-readiness.yml` (the workflow_dispatch trigger stays; inputs unchanged; the script it runs targets the new URLs per the next bullet)
+- Modify: `packages/mcp/scripts/submission-readiness.ts` (the 13-check probe — update check #3 and #4 to probe `https://api.packrat.world/.well-known/oauth-authorization-server` instead of `https://mcp.packratai.com/.well-known/oauth-authorization-server`; check #6 (DCR gate) is deleted entirely — DCR is gone; check #5 (Claude pre-registration) probes the AS host now; check #8 (public docs URL on packratai.com) stays; all other checks stay structurally similar with URL host updates where applicable; the `--claude-client-id` arg is no longer needed since trustedClients are baked into the AS config — remove from the CLI surface)
+- Modify: `packages/mcp/src/__tests__/submission-readiness.test.ts` (per U6, already includes this; this unit just confirms the test passes against the new script behavior)
+- Modify: `docs/mcp/submission-packet.md` (update the field-by-field mapping: "Server URL" stays at `https://mcp.packratai.com/mcp`, "AS URL" is implicit in the `.well-known/oauth-protected-resource` document so no separate field; "OAuth callback URLs" stay at the two Claude domains but the registration mechanism changes from "run register-claude-clients.ts" to "baked into Better Auth trustedClients config"; the operator-checklist § "Once the worker is deployed and MCP_INITIAL_ACCESS_TOKEN is set" deletes its second clause)
+
+**Approach:**
+- Mechanical updates following the architecture change. The 13-check shape stays largely intact; the URLs and one check (DCR) shift.
+- The most important re-verification: check #4 (`code_challenge_methods_supported: ["S256"]` advertised in AS metadata) now probes `api.packrat.world` — if `@better-auth/oauth-provider` advertises `["S256", "plain"]` despite our `allowPlainCodeChallengeMethod: false` config, the probe catches it.
+
+**Test scenarios:**
+- Happy path: running `bun packages/mcp/scripts/submission-readiness.ts --url https://mcp.packratai.com` against a fully-deployed refactor returns 13/13 passed.
+- Edge case: a misconfigured AS that advertises `["S256", "plain"]` triggers the PKCE check failure with a clear message.
+- Edge case: a misconfigured PRM that points `authorization_servers` at the wrong host triggers the cross-reference check failure.
+- Integration: the workflow_dispatch trigger on `mcp-readiness.yml` runs the script against an operator-provided URL and uploads the JSON report as an artifact.
+
+**Verification:**
+- A dry run of the readiness script against a hypothetical post-refactor deployment passes 13/13 (modulo `--url` parameter pointing at a real instance).
+
+---
+
+### U8. Update landing-site MCP docs + runbook + submission packet for the new architecture
+
+**Goal:** Bring the user-facing docs (landing page, runbook, submission packet) in line with the post-refactor architecture so reviewers + operators + future engineers see a consistent story.
+
+**Requirements:** R8
+
+**Dependencies:** U1, U2, U3, U5, U7 (the actual architecture must be settled before the docs describe it)
+
+**Files:**
+- Modify: `apps/landing/app/mcp/page.tsx` (rewrite § "Quickstart" to describe the install flow: Claude.ai → Settings → Connectors → Add custom connector → URL: `https://mcp.packratai.com/mcp` → Claude redirects to `api.packrat.world` for OAuth → consent → back to Claude → done. Add a note about cross-origin AS for technical reviewers who notice the domain switch during install)
+- Modify: `apps/landing/app/mcp/page.tsx` § "Scopes" — copy stays factually identical (four scopes, mcp:admin admin-only), but mention the granting mechanism in passing ("admin scope is granted server-side based on PackRat user role")
+- Modify: `docs/mcp/runbook.md` per U5 (this unit confirms the doc rewrite is coherent end-to-end; the previous unit modified specific sections)
+- Modify: `docs/mcp/submission-packet.md` per U7 (this unit confirms the packet reads correctly for an operator filing the form)
+- Modify: `packages/mcp/README.md` (update the OAuth architecture section: AS lives on `api.packrat.world` via Better Auth's `@better-auth/oauth-provider`; MCP is a pure protected resource validating JWTs via JWKS; remove the four-scopes-and-DCR section paragraph and replace with the new architecture)
+- Modify: `docs/mcp/README.md` (architecture diagram update: cross-origin AS+RS pattern, Better Auth as AS)
+
+**Approach:**
+- Doc-rewrite unit. Coherence and consistency check. Pull the architecture diagram (the mermaid sequence diagram from this plan's HLD) into the public docs page as a visual aid.
+- Ensure no dangling references to `MCP_OAUTH_KV`, `MCP_INITIAL_ACCESS_TOKEN`, `register-claude-clients.ts`, or `dcrRegisterGate` anywhere in `docs/` or in any README.
+
+**Test scenarios:**
+- Test expectation: none -- pure documentation update. Verified by a coherence read after merging.
+- Lightweight assertion: grep `docs/` `packages/mcp/README.md` `apps/landing/app/mcp/` for the stale terms above; expect zero hits.
+
+**Verification:**
+- `grep -rE 'MCP_OAUTH_KV|MCP_INITIAL_ACCESS_TOKEN|dcrRegisterGate|register-claude-clients' docs/ packages/mcp/README.md apps/landing/app/mcp/` returns no results.
+- A reviewer reading `docs/mcp/runbook.md` end-to-end sees a coherent operator narrative without architectural contradictions.
+
+---
+
+### U9. Dev verification: operator manually installs in real Claude.ai against dev deploy
+
+**Goal:** Validate the cross-origin AS flow works against a real Claude.ai account before tagging the prod release. This is the R11 gate — the dev verification posture the user explicitly chose over pre-flight smoke testing.
+
+**Requirements:** R11
+
+**Dependencies:** U1, U2, U3, U4, U5, U6, U7, U8 — every code-side unit must be merged so CI can deploy the full refactor to dev
+
+**Files:**
+- Modify: `docs/mcp/submission-packet.md` § "Pre-submission verification" — add a "Step 0: dev verification" subsection describing the manual install flow the operator runs before tagging prod
+
+**Approach:**
+
+This unit is operator-driven; no code lands. The plan documents the verification checklist the operator follows.
+
+Operator runs:
+1. Tag a dev release (`git tag mcp-v3.0.0-rc.1 && git push --tags`) — CI deploys to `packrat-mcp-dev` + `packrat-api-dev` via the existing U17 deploy workflow.
+2. Open `https://claude.ai` in a fresh browser profile.
+3. Settings → Connectors → Add custom connector → URL: `https://packrat-mcp-dev..workers.dev/mcp` (or whatever dev URL the deploy assigns).
+4. Walk through the OAuth flow. Expected flow per the HLD mermaid: Claude → MCP dev → 401+WWW-Authenticate → Claude fetches PRM from MCP → reads `authorization_servers` → fetches AS metadata from API dev → opens browser to `https://packrat-api-dev..workers.dev/.../authorize` (or wherever Better Auth dev mounts).
+5. Sign in with the reviewer test account credentials from `docs/mcp/submission-packet.md` § 4.
+6. Approve the consent screen.
+7. Confirm redirect back to Claude.
+8. In Claude.ai, ask a simple prompt that exercises a `mcp:read` tool: *"List the packs I have on PackRat."*
+9. Confirm a tool call fires and returns expected output.
+10. Ask a `mcp:write` prompt: *"Create a new pack called 'Dev Verification Test'."*
+11. Confirm the write succeeds.
+12. If the test account has admin role: ask a `mcp:admin` prompt that confirms admin tools are visible. If not admin: confirm admin tools are absent from `tools/list`.
+13. Wait at least 65 minutes (longer than 60-min access token TTL) and confirm refresh-token grant happens transparently — another tool call works without re-consent.
+
+If any step fails, the operator escalates per the runbook's "Cross-origin failure-mode catalog" table (this plan's HLD section).
+
+If verification passes: operator tags `mcp-v3.0.0` and CI deploys to prod.
+
+If verification fails: operator does NOT tag prod. The plan's deferred fallback (reverse-proxy AS endpoints onto `mcp.packratai.com`) becomes a follow-up plan.
+
+**Patterns to follow:**
+- The R11 verification is documented in `docs/mcp/submission-packet.md` so an operator can re-run it on any future re-deploy or on rotation.
+
+**Test scenarios:**
+- Test expectation: none -- this is an operator runbook unit. The verification IS the test. Pass/fail is binary: did Claude.ai successfully install + call tools against the cross-origin AS?
+- Optional: a recorded video / screenshot of the successful install flow attached to the PR description, for reviewer reference.
+
+**Verification:**
+- Operator confirms in chat / commit message that 13/13 steps passed against dev before tagging prod.
+- If any step failed, a follow-up plan is filed for the reverse-proxy fallback.
+
+---
+
+## System-Wide Impact
+
+- **Interaction graph:**
+ - **Removed:** MCP → Better Auth `/sign-in/email` (login flow), MCP → Better Auth `/get-session` (role lookup), MCP → KV (OAuth grants storage), MCP → KV (CSRF nonces), MCP → KV (session storage), MCP `scheduled()` → `purgeExpiredData` cron.
+ - **Added:** Claude.ai → API `/.well-known/oauth-authorization-server` (discovery), Claude.ai → API `/oauth2/authorize` (auth code flow), Claude.ai → API `/oauth2/token` (token exchange + refresh), MCP → API `/api/auth/jwks` (JWKS fetch, cached 10min SWR).
+ - **Unchanged:** MCP → PackRat API for tool data (Bearer JWT forwarded), API admin guard still accepts dual-path bearers (HS256 legacy + Better Auth role-check), `apps/admin` → API `/admin/login` HS256 flow.
+- **Error propagation:**
+ - MCP-side JWT validation failures: 401 + `WWW-Authenticate: Bearer resource_metadata="..."` so Claude triggers re-auth. Never 500 from a malformed token (per better-auth#9654 mitigation).
+ - API-side OAuth provider failures: standard OAuth 2.1 error envelope (`error: invalid_request`, etc.). Better Auth's plugin handles these natively.
+ - Cross-origin failures during install: caught by U9 dev verification before prod; fallback plan to reverse-proxy AS endpoints documented but not built.
+- **State lifecycle risks:**
+ - KV deprovisioning (U5 operator step) must happen AFTER code drops the binding (U3). Reverse order = runtime errors on every MCP request.
+ - Schema migration (U1) must run BEFORE code deploys reference the new tables. The drizzle-kit migration is idempotent; running it pre-deploy is safe.
+ - Existing connector-store-readiness OAuth grants in `MCP_OAUTH_KV` invalidate atomically when the AS swap happens. No users today; document for completeness.
+- **API surface parity:** `apps/admin` HS256 path unaffected; its `adminAuthGuard` dual-path stays. Mobile/web apps already use Better Auth bearer for API auth — unchanged.
+- **Integration coverage:** U9 is the integration scenario that mocks can't prove. Vitest-pool-workers integration tests are still blocked by the ajv issue (per U17 of the prior plan); the operator manual install IS the integration test for this refactor.
+- **Unchanged invariants:** 103 `packrat_*` tool registrations + their annotations (U7), output envelope shape `{ content, structuredContent, isError }` (U8), 6 resource URIs (U9), elicitation contract on 6 destructive admin tools (U10), Workers Rate Limiting binding `MCP_TOOLS_RL` + key shape `${userId}:${toolName}` (U14), structured logger + audit log shapes (U15), `/health` + `/status` JSON shapes (U16), all 21 deferred `it.todo` integration tests (U17), submission packet doc structure (U18). Every U7-U18 surface of the prior plan keeps working bit-for-bit.
+
+---
+
+## Risks & Dependencies
+
+| Risk | Likelihood | Impact | Mitigation |
+|---|---|---|---|
+| Claude.ai cross-origin AS install fails (issues #82/#248/#291) | Med | High | R11 dev verification gate catches before prod tag; fallback to reverse-proxy AS endpoints onto MCP host documented but not built |
+| `@better-auth/oauth-provider`'s `customAccessTokenClaims` doesn't actually reduce granted scopes when returning fewer | Med | Med | U1 test scenario red-flags this empirically; fallback is custom consent page that pre-filters scopes (more work, documented in Open Questions) |
+| Better Auth schema regen produces unexpected changes to existing tables | Med | Med | `bunx drizzle-kit check` is the gate; the generated migration is reviewed line-by-line before commit per `CLAUDE.md` discipline; backup plan is hand-curating the 3 new tables in `schema.ts` and skipping the regen |
+| JWKS rotation breaks MCP validation mid-flight | Low | Med | SWR cache + single-retry on stale `kid` per April plan's commitment; if both fail, 401 with `error: token_expired` triggers client re-auth |
+| WAF/Bot Management on `api.packrat.world` blocks Anthropic discovery probes | Med | High (rejection cause) | Explicit allow rule for `/.well-known/*` and `/oauth2/*` paths from any UA documented in runbook; operator applies pre-submission |
+| Existing OAuth state in `MCP_OAUTH_KV` causes confusion during cutover | Low | Low | Zero deployed grants today (per audit); deprovision namespaces post-code-drop |
+| `better-auth-cloudflare@^0.3.0` is silently load-bearing (audit missed an import) | Low | Low | The repo audit grep returned zero imports; if a future import surfaces, fail-loud at install time |
+| `auth.config.ts` drift from `index.ts` during the plugin addition | Med | Med | Documented learning + this plan's U1 explicitly calls out lockstep; doc-review or CI lint can add a future check |
+| Per-isolate `authCache` retains stale config across deploy | Low | Med | Force isolate rotation via a benign env var bump on deploy; runbook step |
+| Test rewrites in U6 miss a surviving behavior and drop coverage | Med | Med | Characterization-first: run existing tests pre-change to capture matrix; assert same matrix post-change; reviewer spot-checks coverage report diff |
+| Cross-origin domain in consent URL ("api.packrat.world" not "packratai.com") confuses reviewers | Med | Low | Document in submission packet; consent screen branding is a deferred follow-up if flagged |
+
+---
+
+## Dependencies / Prerequisites
+
+- `@better-auth/oauth-provider@^1.6.x` published on npm and compatible with `better-auth@1.6.11` (verified via npm listing during research).
+- Cloudflare API token + account ID already configured for CI (from U17 operator setup).
+- `BETTER_AUTH_SECRET` stable through the refactor — rotating it would invalidate the HS256 admin JWT path used by `apps/admin`.
+- Anthropic's connector-store submission docs continue to bless cross-origin AS pattern (verified via research; subject to change without notice).
+- Operator availability for the U9 dev verification step.
+
+---
+
+## Phased Delivery
+
+### Phase 1 — API-side OAuth provider (U1)
+Lands the OAuth provider plugin on `api.packrat.world` with schema migration. After this phase, the AS exists and is discoverable, but the MCP worker still runs its own AS in parallel. No live cutover yet — Claude.ai is still installed against the old MCP-as-AS architecture (if anyone had installed it pre-tagging).
+
+### Phase 2 — MCP-side JWT validation (U2)
+Lands the protected-resource validation infrastructure. The MCP worker can NOW validate JWTs issued by the new AS, but the outer fetch wrapper still routes through the old OAuthProvider.
+
+### Phase 3 — Cutover (U3, U4)
+The atomic deletion + replacement arc. After this phase merges, the MCP worker no longer has `@cloudflare/workers-oauth-provider` — it's a pure protected resource. The old AS endpoints (handleAuthorize, /login, /callback) return 404.
+
+### Phase 4 — Cleanup (U5, U6, U7, U8)
+Wrangler config trim, test rewrites, CI + readiness-script updates, doc rewrites. No behavioral changes; the system already works after Phase 3.
+
+### Phase 5 — Verification (U9)
+Operator dev install + verification before tagging prod. The R11 gate.
+
+---
+
+## Documentation Plan
+
+- `docs/mcp/runbook.md` — heavy rewrites (U5 + U8): deprovision KV section, rewrite OAuth architecture description, drop DCR + login form sections, add JWKS + cross-origin AS section.
+- `docs/mcp/submission-packet.md` — field/value updates (U7), § "pre-submission verification" expanded with the R11 manual install steps (U9).
+- `apps/landing/app/mcp/page.tsx` — Quickstart copy update (U8) describing the cross-origin install flow + AS domain awareness.
+- `packages/mcp/README.md` — architecture section rewrite (U8).
+- After the plan lands, write 2-3 `docs/solutions/` entries: (a) "Better Auth OAuth Provider on Cloudflare Workers — config patterns" (b) "Cross-origin OAuth: protected-resource + AS on separate workers" (c) "JWKS cache with stale-while-revalidate on Cloudflare Workers". These document the institutional learnings the connector-store plan flagged as greenfield.
+
+---
+
+## Operational / Rollout Notes
+
+- **No `wrangler deploy` from any unit in this plan** per user constraint. All deploys go through CI on tag push.
+- **Tagging sequence:** dev release (`mcp-v3.0.0-rc.1`) → CI deploys to dev → operator runs U9 verification → tag prod release (`mcp-v3.0.0`) → CI deploys to prod.
+- **Isolate rotation after prod deploy:** force a benign env-var change to rotate isolates, ensuring the new per-isolate `authCache` instances pick up the new plugin config. Document in runbook.
+- **WAF allowlist before submission:** operator confirms `/.well-known/*` and `/oauth2/*` paths on `api.packrat.world` are not blocked by Bot Management for unknown UAs (Anthropic egress range).
+- **Namespace deprovisioning timing:** AFTER prod deploy, AFTER U9 confirms the new architecture works. Operator runs `wrangler kv namespace delete ` for both namespaces. Per the runbook recipe.
+- **Rollback:** `git revert` of the merge commit, re-tag, CI re-deploys old code. No KV state to restore (the old MCP_OAUTH_KV namespaces are deprovisioned in the cleanup step; if rollback is needed BEFORE deprovisioning, the namespaces are still there with zero data; if AFTER, the rollback would require re-creating the namespaces — document the timing in the runbook).
+- **`BETTER_AUTH_SECRET` stability:** do not rotate during this refactor. Rotating invalidates `apps/admin`'s HS256 admin JWT path.
+
+---
+
+## Alternative Approaches Considered
+
+- **Use Better Auth's bundled `oidcProvider` + `mcp` plugins (not the separate `@better-auth/oauth-provider` package).** Faster to wire (no new dependency); the `mcp` plugin auto-mounts the `.well-known/*` endpoints. **Rejected** because: (1) bundled `oidcProvider` is `@deprecated` in `better-auth@1.6.11`'s own source; (2) bundled plugin issues opaque tokens, forcing per-request HTTP introspection from MCP to API (~50ms latency per call) instead of local JWKS validation; (3) no RFC 8707 audience binding support (the MCP spec requires it); (4) no `customAccessTokenClaims` hook (would require custom consent page to gate `mcp:admin`); (5) partial refresh-token rotation (old tokens not invalidated). Net: shipping on the deprecated plugin means a follow-up migration within 6 months anyway, plus more code to write up front for the consent page workaround.
+- **Stay on `@cloudflare/workers-oauth-provider` indefinitely.** Zero migration cost. **Rejected** because the duplication tax across every future auth feature (passkeys, MFA, social providers, new scopes) compounds, and the U5 `/callback` role-lookup bridge is load-bearing glue between two OAuth systems that should be one.
+- **Extract Better Auth to its own dedicated worker (`auth.packratai.com`).** Cleaner bounded context; auth scales independently. **Rejected** by user direction (avoid multiplying Drizzle connections / DB bindings). Deferred to a follow-up if auth load ever genuinely diverges from API load.
+- **Use Better Auth as identity-only + keep workers-oauth-provider as AS but consolidate the role-lookup bridge.** Half-measure — keeps both systems but reduces duplication slightly. **Rejected** because it doesn't actually solve the duplication problem; the `/callback` bridge is symptomatic, not root cause.
+- **Parallel-mount (feature-flag) the new AS alongside the old during transition.** Safer rollback window. **Rejected** because zero live OAuth grants exist; clean cutover is simpler and `git revert` provides rollback. Adds two-system complexity for no real benefit.
+- **Pre-flight smoke test the cross-origin Claude.ai flow before any refactor work.** Lowest risk of architectural blocker. **Rejected** by user direction in favor of build-first-then-verify; standard ce-work sequence.
+
+---
+
+## Future Considerations
+
+- **Custom-branded consent screen** on `api.packrat.world` — if Anthropic reviewers flag the domain mismatch between `api.packrat.world` (visible during consent) and `packratai.com` (brand), a follow-up PR builds a branded consent template via `@better-auth/oauth-provider`'s `consentPage` option. The U11 deferral notes apply.
+- **MCP SSO via Better Auth social providers** — structurally unblocked by this refactor. The U11 cookie-domain blocker disappears (OAuth flow lives on `api.packrat.world`; the social-provider redirect lands at the same origin). SSO buttons can be added to Better Auth's consent screen in a follow-up.
+- **JWKS rotation policy** — needs operator procedure documentation when key rotation becomes operationally necessary (annually or on suspected compromise). Steady state is one key, no rotation.
+- **Migrate `apps/admin` off HS256 to OIDC** — deferred indefinitely. When `apps/admin` is rewritten, the dual-path `adminAuthGuard` simplifies to Better-Auth-only.
+- **Per-feature scope refinement** (`mcp:trails:read`, etc.) — defer until users + Anthropic provide feedback that coarse scopes are limiting.
+- **`@better-auth/oauth-provider`'s `clientPrivileges` callback** — richer per-action gating beyond scope; possibly useful for "this client can manage its own resources but not others" patterns if PackRat ever supports third-party integrations.
+
+---
+
+## Sources & References
+
+- **Connector-store readiness plan (architectural parent):** `docs/plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md`
+- **Prior Better Auth migration plan:** `docs/plans/2026-04-30-feat-better-auth-migration-plan.md` (documents the rejected Option A this refactor reverses)
+- **Better Auth CLI factory pattern learning:** `docs/solutions/developer-experience/better-auth-cli-cloudflare-worker-factory-2026-05-02.md`
+- **Runbook (heavy rewrite target):** `docs/mcp/runbook.md`
+- **Submission packet (field-value update target):** `docs/mcp/submission-packet.md`
+- Better Auth OAuth 2.1 Provider plugin docs:
+- Better Auth MCP plugin docs (deprecated path; we're going around):
+- `@better-auth/oauth-provider` on npm:
+- MCP Authorization spec 2025-11-25:
+- Anthropic connector troubleshooting (cross-origin AS guidance):
+- Anthropic connector submission docs:
+- Known Claude.ai cross-origin AS issues: `anthropics/claude-ai-mcp` #82, #248, #291; `anthropics/claude-code` #11814
+- Better Auth issuer fix at non-root basePath: `better-auth/better-auth` #5496 (fixed pre-1.6.11)
+- Better Auth `verifyAccessToken` error mapping: `better-auth/better-auth` #9654 (work around in U2)
+- RFCs: [8414](https://datatracker.ietf.org/doc/html/rfc8414) (AS metadata), [9728](https://datatracker.ietf.org/doc/html/rfc9728) (Protected Resource metadata), [8707](https://www.rfc-editor.org/rfc/rfc8707.html) (Resource Indicators / audience binding), [7591](https://datatracker.ietf.org/doc/html/rfc7591) (DCR — not using but referenced for spec correctness)
+- `jose` JWT library: (the `createRemoteJWKSet` + `jwtVerify` API)
diff --git a/docs/runbooks/etl-pipeline.md b/docs/runbooks/etl-pipeline.md
index 784525a865..58fa01c966 100644
--- a/docs/runbooks/etl-pipeline.md
+++ b/docs/runbooks/etl-pipeline.md
@@ -6,7 +6,7 @@ new runs; anyone debugging why the catalog isn't updating.
## Architecture at a glance
-```
+```text
Scraper → R2 object (packrat-scrapy-bucket)
│
▼
@@ -65,6 +65,7 @@ curl -X POST 'https://packrat-api.orange-frost-d665.workers.dev/api/catalog/etl?
```
Response:
+
```json
{
"message": "Catalog ETL workflow triggered",
@@ -115,6 +116,7 @@ The retry endpoint:
4. Calls `env.ETL_WORKFLOW.create(...)` with the chunks
Response:
+
```json
{
"success": true,
@@ -146,6 +148,7 @@ correctly handles quoted multi-line fields, unlike raw `\n` counting), and
writes the result to `etl_jobs.verified_row_count` + `etl_jobs.verified_at`.
Response:
+
```json
{
"success": true,
diff --git a/package.json b/package.json
index 5ffbbaac14..0f9875b5bc 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
"format": "biome format --write",
"format:package-json": "bun scripts/format/sort-package-json.ts",
"preinstall": "bun run configure:deps",
- "postinstall": "bun run lefthook && bun run env",
+ "postinstall": "bun run lefthook && bun run env && bun run --cwd packages/consent-ui build",
"ios": "cd apps/expo && bun ios",
"lefthook": "lefthook install",
"lint": "biome check --write",
diff --git a/packages/api-client/src/index.ts b/packages/api-client/src/index.ts
index 058f160b64..d7bcdc4f28 100644
--- a/packages/api-client/src/index.ts
+++ b/packages/api-client/src/index.ts
@@ -1,5 +1,9 @@
import { treaty } from '@elysiajs/eden';
-import type { App } from '@packrat/api';
+// Import from `@packrat/api/app` (the JSX-free Elysia contract), NOT the worker
+// entry `@packrat/api`. The entry mounts the server-rendered OAuth consent page
+// (@kitajs/html), whose JSX types would otherwise leak into every consumer of
+// this client (packages/mcp, apps/*) via the `App` type.
+import type { App } from '@packrat/api/app';
import { isObject, isString } from '@packrat/guards';
/**
diff --git a/packages/api/README.md b/packages/api/README.md
index c5d080ed39..ee3e58c67f 100644
--- a/packages/api/README.md
+++ b/packages/api/README.md
@@ -1,18 +1,74 @@
-To install dependencies:
+# @packrat/api
+
+Elysia on Cloudflare Workers. Drizzle ORM against Neon Postgres.
+
+## Develop
+
```sh
bun install
+bun run dev # wrangler dev -e=dev → http://localhost:8787
+```
+
+## Test
+
+```sh
+bun run test # full suite (requires docker-compose postgres up)
+bun run test:unit # unit-only, no DB
```
-To run:
+## Database
+
```sh
-bun run dev
+bun run db:generate # drizzle-kit generate (after editing schema)
+cd packages/api && bunx drizzle-kit check # verify the generated snapshot chain (run before migrate)
+bun run db:migrate # apply pending migrations to NEON_DATABASE_URL
```
-open http://localhost:8787
+### Seeds
+
+All four seeders use `drizzle-seed` as the tool surface (`.refine()` with
+`f.default()` / `f.valuesFromArray()`). drizzle-seed has no native upsert,
+so the three production-shape seeds gate their `seed()` call on an
+explicit existence check — re-runs are safe in any environment.
+
+| Command | Script | Purpose |
+|---|---|---|
+| `bun run db:seed` | `src/db/seed.ts` | Featured Pack templates (6 curated app templates, 164 items) |
+| `bun run db:seed:e2e-user` | `src/db/seed-e2e-user.ts` | E2E test user (reads `E2E_TEST_EMAIL` / `E2E_TEST_PASSWORD`; refreshes password on re-run) |
+| `bun run db:seed:oauth-clients` | `src/db/seed-claude-oauth-client.ts` | Pre-register Claude as an OAuth client (run once per env after deploy) |
+
+One dev-only seed (drizzle-seed's randomized fake-data mode — for local
+development + QA only):
+
+| Command | Script | Purpose |
+|---|---|---|
+| `bun run db:seed:dev` | `src/db/seed-dev.ts` | Populate a fresh local DB with ~50 users, 150 packs, 1500 items, 100 catalog items, 80 posts, 200 comments — randomized via drizzle-seed's `f.fullName()` / `f.email()` / `f.loremIpsum()` |
+
+`db:seed:dev` **TRUNCATEs the affected tables before inserting** (per
+`drizzle-seed`'s default behavior). It **hard-refuses** to run against a
+Neon-hosted URL — no override flag — so a stray prod run cannot wipe user
+data. The seed RNG is fixed (`seed=42`) so re-runs produce the same content.
+
+Typical onboarding flow against the docker-compose test DB:
+
+```sh
+cd packages/api
+docker compose -f docker-compose.test.yml up -d # if not running
+NEON_DATABASE_URL=postgres://test_user:test_password@localhost:5432/packrat_test \
+ bun run db:migrate
+NEON_DATABASE_URL=postgres://test_user:test_password@localhost:5432/packrat_test \
+ bun run db:seed:dev
+```
+
+## Deploy
+
+CI handles deploys via wrangler. Operator runbook lives at
+[`docs/mcp/runbook.md`](../../docs/mcp/runbook.md) (covers env-var setup,
+secret rotation, JWKS rotation, and the
+`BETTER_AUTH_*` → `PACKRAT_*` migration steps).
## AI Billing
AI-backed routes and services use Cloudflare AI Gateway when `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_AI_GATEWAY_ID`, and `CLOUDFLARE_API_TOKEN` are configured. Direct provider keys such as `OPENAI_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`, and `PERPLEXITY_API_KEY` are still required for fallback and rollback.
The root `.env.local` is copied into `packages/api/.dev.vars` by `bun install` / `bun run env`. See `../../docs/runbooks/ai-gateway-unified-billing.md` for the production setup and fallback runbook.
-# packrat-v2-api
diff --git a/packages/api/auth-schema.ts b/packages/api/auth-schema.ts
deleted file mode 100644
index 196dc5f4d3..0000000000
--- a/packages/api/auth-schema.ts
+++ /dev/null
@@ -1,110 +0,0 @@
-import { relations } from 'drizzle-orm';
-import { boolean, index, pgTable, text, timestamp } from 'drizzle-orm/pg-core';
-
-export const user = pgTable('user', {
- id: text('id').primaryKey(),
- name: text('name').notNull(),
- email: text('email').notNull().unique(),
- emailVerified: boolean('email_verified').default(false).notNull(),
- image: text('image'),
- createdAt: timestamp('created_at').defaultNow().notNull(),
- updatedAt: timestamp('updated_at')
- .defaultNow()
- .$onUpdate(() => /* @__PURE__ */ new Date())
- .notNull(),
- role: text('role').default('USER').notNull(),
- banned: boolean('banned').default(false),
- banReason: text('ban_reason'),
- banExpires: timestamp('ban_expires'),
- first_name: text('first_name').notNull(),
- last_name: text('last_name').notNull(),
- avatar_url: text('avatar_url').notNull(),
- password_hash: text('password_hash').notNull(),
-});
-
-export const session = pgTable(
- 'session',
- {
- id: text('id').primaryKey(),
- expiresAt: timestamp('expires_at').notNull(),
- token: text('token').notNull().unique(),
- createdAt: timestamp('created_at').defaultNow().notNull(),
- updatedAt: timestamp('updated_at')
- .$onUpdate(() => /* @__PURE__ */ new Date())
- .notNull(),
- ipAddress: text('ip_address'),
- userAgent: text('user_agent'),
- userId: text('user_id')
- .notNull()
- .references(() => user.id, { onDelete: 'cascade' }),
- impersonatedBy: text('impersonated_by'),
- },
- (table) => [index('session_userId_idx').on(table.userId)],
-);
-
-export const account = pgTable(
- 'account',
- {
- id: text('id').primaryKey(),
- accountId: text('account_id').notNull(),
- providerId: text('provider_id').notNull(),
- userId: text('user_id')
- .notNull()
- .references(() => user.id, { onDelete: 'cascade' }),
- accessToken: text('access_token'),
- refreshToken: text('refresh_token'),
- idToken: text('id_token'),
- accessTokenExpiresAt: timestamp('access_token_expires_at'),
- refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
- scope: text('scope'),
- password: text('password'),
- createdAt: timestamp('created_at').defaultNow().notNull(),
- updatedAt: timestamp('updated_at')
- .$onUpdate(() => /* @__PURE__ */ new Date())
- .notNull(),
- },
- (table) => [index('account_userId_idx').on(table.userId)],
-);
-
-export const verification = pgTable(
- 'verification',
- {
- id: text('id').primaryKey(),
- identifier: text('identifier').notNull(),
- value: text('value').notNull(),
- expiresAt: timestamp('expires_at').notNull(),
- createdAt: timestamp('created_at').defaultNow().notNull(),
- updatedAt: timestamp('updated_at')
- .defaultNow()
- .$onUpdate(() => /* @__PURE__ */ new Date())
- .notNull(),
- },
- (table) => [index('verification_identifier_idx').on(table.identifier)],
-);
-
-export const jwks = pgTable('jwks', {
- id: text('id').primaryKey(),
- publicKey: text('public_key').notNull(),
- privateKey: text('private_key').notNull(),
- createdAt: timestamp('created_at').notNull(),
- expiresAt: timestamp('expires_at'),
-});
-
-export const userRelations = relations(user, ({ many }) => ({
- sessions: many(session),
- accounts: many(account),
-}));
-
-export const sessionRelations = relations(session, ({ one }) => ({
- user: one(user, {
- fields: [session.userId],
- references: [user.id],
- }),
-}));
-
-export const accountRelations = relations(account, ({ one }) => ({
- user: one(user, {
- fields: [account.userId],
- references: [user.id],
- }),
-}));
diff --git a/packages/api/drizzle/0049_even_lizard.sql b/packages/api/drizzle/0049_even_lizard.sql
new file mode 100644
index 0000000000..73f01f6d4a
--- /dev/null
+++ b/packages/api/drizzle/0049_even_lizard.sql
@@ -0,0 +1,93 @@
+CREATE TABLE "oauthAccessToken" (
+ "id" text PRIMARY KEY NOT NULL,
+ "token" text,
+ "client_id" text NOT NULL,
+ "session_id" text,
+ "user_id" text,
+ "reference_id" text,
+ "refresh_id" text,
+ "expires_at" timestamp NOT NULL,
+ "created_at" timestamp NOT NULL,
+ "scopes" jsonb NOT NULL,
+ CONSTRAINT "oauthAccessToken_token_unique" UNIQUE("token")
+);
+--> statement-breakpoint
+CREATE TABLE "oauthClient" (
+ "id" text PRIMARY KEY NOT NULL,
+ "client_id" text NOT NULL,
+ "client_secret" text,
+ "disabled" boolean DEFAULT false,
+ "skip_consent" boolean,
+ "enable_end_session" boolean,
+ "subject_type" text,
+ "scopes" jsonb,
+ "user_id" text,
+ "created_at" timestamp,
+ "updated_at" timestamp,
+ "name" text,
+ "uri" text,
+ "icon" text,
+ "contacts" jsonb,
+ "tos" text,
+ "policy" text,
+ "software_id" text,
+ "software_version" text,
+ "software_statement" text,
+ "redirect_uris" jsonb NOT NULL,
+ "post_logout_redirect_uris" jsonb,
+ "token_endpoint_auth_method" text,
+ "grant_types" jsonb,
+ "response_types" jsonb,
+ "public" boolean,
+ "type" text,
+ "require_pkce" boolean,
+ "reference_id" text,
+ "metadata" jsonb,
+ CONSTRAINT "oauthClient_client_id_unique" UNIQUE("client_id")
+);
+--> statement-breakpoint
+CREATE TABLE "oauthConsent" (
+ "id" text PRIMARY KEY NOT NULL,
+ "client_id" text NOT NULL,
+ "user_id" text,
+ "reference_id" text,
+ "scopes" jsonb NOT NULL,
+ "created_at" timestamp NOT NULL,
+ "updated_at" timestamp NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "oauthRefreshToken" (
+ "id" text PRIMARY KEY NOT NULL,
+ "token" text NOT NULL,
+ "client_id" text NOT NULL,
+ "session_id" text,
+ "user_id" text NOT NULL,
+ "reference_id" text,
+ "expires_at" timestamp NOT NULL,
+ "created_at" timestamp NOT NULL,
+ "revoked" timestamp,
+ "auth_time" timestamp,
+ "scopes" jsonb NOT NULL,
+ CONSTRAINT "oauthRefreshToken_token_unique" UNIQUE("token")
+);
+--> statement-breakpoint
+ALTER TABLE "oauthAccessToken" ADD CONSTRAINT "oauthAccessToken_client_id_oauthClient_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."oauthClient"("client_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "oauthAccessToken" ADD CONSTRAINT "oauthAccessToken_session_id_session_id_fk" FOREIGN KEY ("session_id") REFERENCES "public"."session"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "oauthAccessToken" ADD CONSTRAINT "oauthAccessToken_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "oauthAccessToken" ADD CONSTRAINT "oauthAccessToken_refresh_id_oauthRefreshToken_id_fk" FOREIGN KEY ("refresh_id") REFERENCES "public"."oauthRefreshToken"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "oauthClient" ADD CONSTRAINT "oauthClient_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "oauthConsent" ADD CONSTRAINT "oauthConsent_client_id_oauthClient_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."oauthClient"("client_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "oauthConsent" ADD CONSTRAINT "oauthConsent_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "oauthRefreshToken" ADD CONSTRAINT "oauthRefreshToken_client_id_oauthClient_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."oauthClient"("client_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "oauthRefreshToken" ADD CONSTRAINT "oauthRefreshToken_session_id_session_id_fk" FOREIGN KEY ("session_id") REFERENCES "public"."session"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "oauthRefreshToken" ADD CONSTRAINT "oauthRefreshToken_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+CREATE INDEX "oauth_access_token_client_id_idx" ON "oauthAccessToken" USING btree ("client_id");--> statement-breakpoint
+CREATE INDEX "oauth_access_token_session_id_idx" ON "oauthAccessToken" USING btree ("session_id");--> statement-breakpoint
+CREATE INDEX "oauth_access_token_user_id_idx" ON "oauthAccessToken" USING btree ("user_id");--> statement-breakpoint
+CREATE INDEX "oauth_access_token_refresh_id_idx" ON "oauthAccessToken" USING btree ("refresh_id");--> statement-breakpoint
+CREATE INDEX "oauth_client_user_id_idx" ON "oauthClient" USING btree ("user_id");--> statement-breakpoint
+CREATE INDEX "oauth_consent_client_id_idx" ON "oauthConsent" USING btree ("client_id");--> statement-breakpoint
+CREATE INDEX "oauth_consent_user_id_idx" ON "oauthConsent" USING btree ("user_id");--> statement-breakpoint
+CREATE INDEX "oauth_refresh_token_client_id_idx" ON "oauthRefreshToken" USING btree ("client_id");--> statement-breakpoint
+CREATE INDEX "oauth_refresh_token_session_id_idx" ON "oauthRefreshToken" USING btree ("session_id");--> statement-breakpoint
+CREATE INDEX "oauth_refresh_token_user_id_idx" ON "oauthRefreshToken" USING btree ("user_id");
\ No newline at end of file
diff --git a/packages/api/drizzle/meta/0049_snapshot.json b/packages/api/drizzle/meta/0049_snapshot.json
new file mode 100644
index 0000000000..3c7db1827f
--- /dev/null
+++ b/packages/api/drizzle/meta/0049_snapshot.json
@@ -0,0 +1,3025 @@
+{
+ "id": "70588809-032b-41f6-a2c2-e487b844806e",
+ "prevId": "abc127e8-7f28-4a39-9bea-29119e52cb96",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.account": {
+ "name": "account",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "account_id": {
+ "name": "account_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider_id": {
+ "name": "provider_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "access_token_expires_at": {
+ "name": "access_token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_token_expires_at": {
+ "name": "refresh_token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "password": {
+ "name": "password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "account_userId_idx": {
+ "name": "account_userId_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "account_user_id_users_id_fk": {
+ "name": "account_user_id_users_id_fk",
+ "tableFrom": "account",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "account_provider_account_idx": {
+ "name": "account_provider_account_idx",
+ "nullsNotDistinct": false,
+ "columns": ["provider_id", "account_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.catalog_item_etl_jobs": {
+ "name": "catalog_item_etl_jobs",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "catalog_item_id": {
+ "name": "catalog_item_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "etl_job_id": {
+ "name": "etl_job_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "catalog_item_etl_jobs_catalog_item_id_catalog_items_id_fk": {
+ "name": "catalog_item_etl_jobs_catalog_item_id_catalog_items_id_fk",
+ "tableFrom": "catalog_item_etl_jobs",
+ "tableTo": "catalog_items",
+ "columnsFrom": ["catalog_item_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "catalog_item_etl_jobs_etl_job_id_etl_jobs_id_fk": {
+ "name": "catalog_item_etl_jobs_etl_job_id_etl_jobs_id_fk",
+ "tableFrom": "catalog_item_etl_jobs",
+ "tableTo": "etl_jobs",
+ "columnsFrom": ["etl_job_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.catalog_items": {
+ "name": "catalog_items",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "product_url": {
+ "name": "product_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sku": {
+ "name": "sku",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "weight": {
+ "name": "weight",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "weight_unit": {
+ "name": "weight_unit",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "categories": {
+ "name": "categories",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "images": {
+ "name": "images",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "brand": {
+ "name": "brand",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "model": {
+ "name": "model",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rating_value": {
+ "name": "rating_value",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "color": {
+ "name": "color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "size": {
+ "name": "size",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "price": {
+ "name": "price",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "availability": {
+ "name": "availability",
+ "type": "availability",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "seller": {
+ "name": "seller",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "product_sku": {
+ "name": "product_sku",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "material": {
+ "name": "material",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "currency": {
+ "name": "currency",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "condition": {
+ "name": "condition",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "review_count": {
+ "name": "review_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "variants": {
+ "name": "variants",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "techs": {
+ "name": "techs",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "links": {
+ "name": "links",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "reviews": {
+ "name": "reviews",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "qas": {
+ "name": "qas",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "faqs": {
+ "name": "faqs",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "embedding": {
+ "name": "embedding",
+ "type": "vector(1536)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "embedding_idx": {
+ "name": "embedding_idx",
+ "columns": [
+ {
+ "expression": "embedding",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last",
+ "opclass": "vector_cosine_ops"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "hnsw",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "catalog_items_sku_unique": {
+ "name": "catalog_items_sku_unique",
+ "nullsNotDistinct": false,
+ "columns": ["sku"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.comment_likes": {
+ "name": "comment_likes",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "comment_id": {
+ "name": "comment_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "comment_likes_comment_id_post_comments_id_fk": {
+ "name": "comment_likes_comment_id_post_comments_id_fk",
+ "tableFrom": "comment_likes",
+ "tableTo": "post_comments",
+ "columnsFrom": ["comment_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "comment_likes_user_id_users_id_fk": {
+ "name": "comment_likes_user_id_users_id_fk",
+ "tableFrom": "comment_likes",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "comment_likes_comment_id_user_id_unique": {
+ "name": "comment_likes_comment_id_user_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["comment_id", "user_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.etl_jobs": {
+ "name": "etl_jobs",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "etl_job_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "source": {
+ "name": "source",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "filename": {
+ "name": "filename",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "started_at": {
+ "name": "started_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "completed_at": {
+ "name": "completed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "total_processed": {
+ "name": "total_processed",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "total_valid": {
+ "name": "total_valid",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "total_invalid": {
+ "name": "total_invalid",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scraper_revision": {
+ "name": "scraper_revision",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workflow_instance_id": {
+ "name": "workflow_instance_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "total_embedding_failures": {
+ "name": "total_embedding_failures",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "verified_at": {
+ "name": "verified_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "verified_row_count": {
+ "name": "verified_row_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "source_etag": {
+ "name": "source_etag",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "source_last_modified": {
+ "name": "source_last_modified",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "superseded_by_job_id": {
+ "name": "superseded_by_job_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "superseded_at": {
+ "name": "superseded_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "etl_jobs_scraper_revision_idx": {
+ "name": "etl_jobs_scraper_revision_idx",
+ "columns": [
+ {
+ "expression": "scraper_revision",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "etl_jobs_workflow_instance_id_idx": {
+ "name": "etl_jobs_workflow_instance_id_idx",
+ "columns": [
+ {
+ "expression": "workflow_instance_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "etl_jobs_superseded_by_idx": {
+ "name": "etl_jobs_superseded_by_idx",
+ "columns": [
+ {
+ "expression": "superseded_by_job_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "etl_jobs_superseded_by_job_id_etl_jobs_id_fk": {
+ "name": "etl_jobs_superseded_by_job_id_etl_jobs_id_fk",
+ "tableFrom": "etl_jobs",
+ "tableTo": "etl_jobs",
+ "columnsFrom": ["superseded_by_job_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {
+ "etl_jobs_no_self_supersede": {
+ "name": "etl_jobs_no_self_supersede",
+ "value": "\"etl_jobs\".\"superseded_by_job_id\" IS NULL OR \"etl_jobs\".\"superseded_by_job_id\" <> \"etl_jobs\".\"id\""
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.invalid_item_logs": {
+ "name": "invalid_item_logs",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "job_id": {
+ "name": "job_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "errors": {
+ "name": "errors",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "raw_data": {
+ "name": "raw_data",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "row_index": {
+ "name": "row_index",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "invalid_item_logs_job_id_etl_jobs_id_fk": {
+ "name": "invalid_item_logs_job_id_etl_jobs_id_fk",
+ "tableFrom": "invalid_item_logs",
+ "tableTo": "etl_jobs",
+ "columnsFrom": ["job_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.jwks": {
+ "name": "jwks",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_key": {
+ "name": "public_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "private_key": {
+ "name": "private_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.oauthAccessToken": {
+ "name": "oauthAccessToken",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "client_id": {
+ "name": "client_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "session_id": {
+ "name": "session_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "reference_id": {
+ "name": "reference_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_id": {
+ "name": "refresh_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "scopes": {
+ "name": "scopes",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "oauth_access_token_client_id_idx": {
+ "name": "oauth_access_token_client_id_idx",
+ "columns": [
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "oauth_access_token_session_id_idx": {
+ "name": "oauth_access_token_session_id_idx",
+ "columns": [
+ {
+ "expression": "session_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "oauth_access_token_user_id_idx": {
+ "name": "oauth_access_token_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "oauth_access_token_refresh_id_idx": {
+ "name": "oauth_access_token_refresh_id_idx",
+ "columns": [
+ {
+ "expression": "refresh_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "oauthAccessToken_client_id_oauthClient_client_id_fk": {
+ "name": "oauthAccessToken_client_id_oauthClient_client_id_fk",
+ "tableFrom": "oauthAccessToken",
+ "tableTo": "oauthClient",
+ "columnsFrom": ["client_id"],
+ "columnsTo": ["client_id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "oauthAccessToken_session_id_session_id_fk": {
+ "name": "oauthAccessToken_session_id_session_id_fk",
+ "tableFrom": "oauthAccessToken",
+ "tableTo": "session",
+ "columnsFrom": ["session_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "oauthAccessToken_user_id_users_id_fk": {
+ "name": "oauthAccessToken_user_id_users_id_fk",
+ "tableFrom": "oauthAccessToken",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "oauthAccessToken_refresh_id_oauthRefreshToken_id_fk": {
+ "name": "oauthAccessToken_refresh_id_oauthRefreshToken_id_fk",
+ "tableFrom": "oauthAccessToken",
+ "tableTo": "oauthRefreshToken",
+ "columnsFrom": ["refresh_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "oauthAccessToken_token_unique": {
+ "name": "oauthAccessToken_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.oauthClient": {
+ "name": "oauthClient",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "client_id": {
+ "name": "client_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "client_secret": {
+ "name": "client_secret",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "disabled": {
+ "name": "disabled",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false,
+ "default": false
+ },
+ "skip_consent": {
+ "name": "skip_consent",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "enable_end_session": {
+ "name": "enable_end_session",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "subject_type": {
+ "name": "subject_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scopes": {
+ "name": "scopes",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "uri": {
+ "name": "uri",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "icon": {
+ "name": "icon",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "contacts": {
+ "name": "contacts",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "tos": {
+ "name": "tos",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "policy": {
+ "name": "policy",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "software_id": {
+ "name": "software_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "software_version": {
+ "name": "software_version",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "software_statement": {
+ "name": "software_statement",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "redirect_uris": {
+ "name": "redirect_uris",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "post_logout_redirect_uris": {
+ "name": "post_logout_redirect_uris",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "token_endpoint_auth_method": {
+ "name": "token_endpoint_auth_method",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "grant_types": {
+ "name": "grant_types",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "response_types": {
+ "name": "response_types",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "public": {
+ "name": "public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "require_pkce": {
+ "name": "require_pkce",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "reference_id": {
+ "name": "reference_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "metadata": {
+ "name": "metadata",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "oauth_client_user_id_idx": {
+ "name": "oauth_client_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "oauthClient_user_id_users_id_fk": {
+ "name": "oauthClient_user_id_users_id_fk",
+ "tableFrom": "oauthClient",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "oauthClient_client_id_unique": {
+ "name": "oauthClient_client_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["client_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.oauthConsent": {
+ "name": "oauthConsent",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "client_id": {
+ "name": "client_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "reference_id": {
+ "name": "reference_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scopes": {
+ "name": "scopes",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "oauth_consent_client_id_idx": {
+ "name": "oauth_consent_client_id_idx",
+ "columns": [
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "oauth_consent_user_id_idx": {
+ "name": "oauth_consent_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "oauthConsent_client_id_oauthClient_client_id_fk": {
+ "name": "oauthConsent_client_id_oauthClient_client_id_fk",
+ "tableFrom": "oauthConsent",
+ "tableTo": "oauthClient",
+ "columnsFrom": ["client_id"],
+ "columnsTo": ["client_id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "oauthConsent_user_id_users_id_fk": {
+ "name": "oauthConsent_user_id_users_id_fk",
+ "tableFrom": "oauthConsent",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.oauthRefreshToken": {
+ "name": "oauthRefreshToken",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "client_id": {
+ "name": "client_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "session_id": {
+ "name": "session_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "reference_id": {
+ "name": "reference_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "revoked": {
+ "name": "revoked",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "auth_time": {
+ "name": "auth_time",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scopes": {
+ "name": "scopes",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "oauth_refresh_token_client_id_idx": {
+ "name": "oauth_refresh_token_client_id_idx",
+ "columns": [
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "oauth_refresh_token_session_id_idx": {
+ "name": "oauth_refresh_token_session_id_idx",
+ "columns": [
+ {
+ "expression": "session_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "oauth_refresh_token_user_id_idx": {
+ "name": "oauth_refresh_token_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "oauthRefreshToken_client_id_oauthClient_client_id_fk": {
+ "name": "oauthRefreshToken_client_id_oauthClient_client_id_fk",
+ "tableFrom": "oauthRefreshToken",
+ "tableTo": "oauthClient",
+ "columnsFrom": ["client_id"],
+ "columnsTo": ["client_id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "oauthRefreshToken_session_id_session_id_fk": {
+ "name": "oauthRefreshToken_session_id_session_id_fk",
+ "tableFrom": "oauthRefreshToken",
+ "tableTo": "session",
+ "columnsFrom": ["session_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "oauthRefreshToken_user_id_users_id_fk": {
+ "name": "oauthRefreshToken_user_id_users_id_fk",
+ "tableFrom": "oauthRefreshToken",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "oauthRefreshToken_token_unique": {
+ "name": "oauthRefreshToken_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pack_items": {
+ "name": "pack_items",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "weight": {
+ "name": "weight",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "weight_unit": {
+ "name": "weight_unit",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "quantity": {
+ "name": "quantity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 1
+ },
+ "category": {
+ "name": "category",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "consumable": {
+ "name": "consumable",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "worn": {
+ "name": "worn",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pack_id": {
+ "name": "pack_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "catalog_item_id": {
+ "name": "catalog_item_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "deleted": {
+ "name": "deleted",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "is_ai_generated": {
+ "name": "is_ai_generated",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "template_item_id": {
+ "name": "template_item_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "embedding": {
+ "name": "embedding",
+ "type": "vector(1536)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "pack_items_embedding_idx": {
+ "name": "pack_items_embedding_idx",
+ "columns": [
+ {
+ "expression": "embedding",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last",
+ "opclass": "vector_cosine_ops"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "hnsw",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "pack_items_pack_id_packs_id_fk": {
+ "name": "pack_items_pack_id_packs_id_fk",
+ "tableFrom": "pack_items",
+ "tableTo": "packs",
+ "columnsFrom": ["pack_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "pack_items_catalog_item_id_catalog_items_id_fk": {
+ "name": "pack_items_catalog_item_id_catalog_items_id_fk",
+ "tableFrom": "pack_items",
+ "tableTo": "catalog_items",
+ "columnsFrom": ["catalog_item_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "pack_items_user_id_users_id_fk": {
+ "name": "pack_items_user_id_users_id_fk",
+ "tableFrom": "pack_items",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "pack_items_template_item_id_pack_template_items_id_fk": {
+ "name": "pack_items_template_item_id_pack_template_items_id_fk",
+ "tableFrom": "pack_items",
+ "tableTo": "pack_template_items",
+ "columnsFrom": ["template_item_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pack_template_items": {
+ "name": "pack_template_items",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "weight": {
+ "name": "weight",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "weight_unit": {
+ "name": "weight_unit",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "quantity": {
+ "name": "quantity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 1
+ },
+ "category": {
+ "name": "category",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "consumable": {
+ "name": "consumable",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "worn": {
+ "name": "worn",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pack_template_id": {
+ "name": "pack_template_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "catalog_item_id": {
+ "name": "catalog_item_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "deleted": {
+ "name": "deleted",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "pack_template_items_pack_template_id_pack_templates_id_fk": {
+ "name": "pack_template_items_pack_template_id_pack_templates_id_fk",
+ "tableFrom": "pack_template_items",
+ "tableTo": "pack_templates",
+ "columnsFrom": ["pack_template_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "pack_template_items_catalog_item_id_catalog_items_id_fk": {
+ "name": "pack_template_items_catalog_item_id_catalog_items_id_fk",
+ "tableFrom": "pack_template_items",
+ "tableTo": "catalog_items",
+ "columnsFrom": ["catalog_item_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "pack_template_items_user_id_users_id_fk": {
+ "name": "pack_template_items_user_id_users_id_fk",
+ "tableFrom": "pack_template_items",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pack_templates": {
+ "name": "pack_templates",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "category": {
+ "name": "category",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "tags": {
+ "name": "tags",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_app_template": {
+ "name": "is_app_template",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "deleted": {
+ "name": "deleted",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "content_source": {
+ "name": "content_source",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "content_id": {
+ "name": "content_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "local_created_at": {
+ "name": "local_created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "local_updated_at": {
+ "name": "local_updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "pack_templates_user_id_users_id_fk": {
+ "name": "pack_templates_user_id_users_id_fk",
+ "tableFrom": "pack_templates",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.weight_history": {
+ "name": "weight_history",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pack_id": {
+ "name": "pack_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "weight": {
+ "name": "weight",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "local_created_at": {
+ "name": "local_created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "weight_history_user_id_users_id_fk": {
+ "name": "weight_history_user_id_users_id_fk",
+ "tableFrom": "weight_history",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "weight_history_pack_id_packs_id_fk": {
+ "name": "weight_history_pack_id_packs_id_fk",
+ "tableFrom": "weight_history",
+ "tableTo": "packs",
+ "columnsFrom": ["pack_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.packs": {
+ "name": "packs",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "category": {
+ "name": "category",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "template_id": {
+ "name": "template_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_public": {
+ "name": "is_public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "tags": {
+ "name": "tags",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "deleted": {
+ "name": "deleted",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "is_ai_generated": {
+ "name": "is_ai_generated",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "local_created_at": {
+ "name": "local_created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "local_updated_at": {
+ "name": "local_updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "packs_user_id_users_id_fk": {
+ "name": "packs_user_id_users_id_fk",
+ "tableFrom": "packs",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "packs_template_id_pack_templates_id_fk": {
+ "name": "packs_template_id_pack_templates_id_fk",
+ "tableFrom": "packs",
+ "tableTo": "pack_templates",
+ "columnsFrom": ["template_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.post_comments": {
+ "name": "post_comments",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "post_id": {
+ "name": "post_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "content": {
+ "name": "content",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "parent_comment_id": {
+ "name": "parent_comment_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "post_comments_post_id_posts_id_fk": {
+ "name": "post_comments_post_id_posts_id_fk",
+ "tableFrom": "post_comments",
+ "tableTo": "posts",
+ "columnsFrom": ["post_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "post_comments_user_id_users_id_fk": {
+ "name": "post_comments_user_id_users_id_fk",
+ "tableFrom": "post_comments",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "post_comments_parent_comment_id_post_comments_id_fk": {
+ "name": "post_comments_parent_comment_id_post_comments_id_fk",
+ "tableFrom": "post_comments",
+ "tableTo": "post_comments",
+ "columnsFrom": ["parent_comment_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.post_likes": {
+ "name": "post_likes",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "post_id": {
+ "name": "post_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "post_likes_post_id_posts_id_fk": {
+ "name": "post_likes_post_id_posts_id_fk",
+ "tableFrom": "post_likes",
+ "tableTo": "posts",
+ "columnsFrom": ["post_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "post_likes_user_id_users_id_fk": {
+ "name": "post_likes_user_id_users_id_fk",
+ "tableFrom": "post_likes",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "post_likes_post_id_user_id_unique": {
+ "name": "post_likes_post_id_user_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["post_id", "user_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.posts": {
+ "name": "posts",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "caption": {
+ "name": "caption",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "images": {
+ "name": "images",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "posts_user_id_users_id_fk": {
+ "name": "posts_user_id_users_id_fk",
+ "tableFrom": "posts",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.reported_content": {
+ "name": "reported_content",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_query": {
+ "name": "user_query",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ai_response": {
+ "name": "ai_response",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "reason": {
+ "name": "reason",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_comment": {
+ "name": "user_comment",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "reviewed": {
+ "name": "reviewed",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false,
+ "default": false
+ },
+ "reviewed_by": {
+ "name": "reviewed_by",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "reviewed_at": {
+ "name": "reviewed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "reported_content_user_id_users_id_fk": {
+ "name": "reported_content_user_id_users_id_fk",
+ "tableFrom": "reported_content",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "reported_content_reviewed_by_users_id_fk": {
+ "name": "reported_content_reviewed_by_users_id_fk",
+ "tableFrom": "reported_content",
+ "tableTo": "users",
+ "columnsFrom": ["reviewed_by"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.session": {
+ "name": "session",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "ip_address": {
+ "name": "ip_address",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_agent": {
+ "name": "user_agent",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "impersonated_by": {
+ "name": "impersonated_by",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "session_userId_idx": {
+ "name": "session_userId_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "session_user_id_users_id_fk": {
+ "name": "session_user_id_users_id_fk",
+ "tableFrom": "session",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "session_token_unique": {
+ "name": "session_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.trail_condition_reports": {
+ "name": "trail_condition_reports",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "trail_name": {
+ "name": "trail_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "trail_region": {
+ "name": "trail_region",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "surface": {
+ "name": "surface",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "overall_condition": {
+ "name": "overall_condition",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "hazards": {
+ "name": "hazards",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'[]'::jsonb"
+ },
+ "water_crossings": {
+ "name": "water_crossings",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "water_crossing_difficulty": {
+ "name": "water_crossing_difficulty",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "photos": {
+ "name": "photos",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'[]'::jsonb"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "trip_id": {
+ "name": "trip_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "deleted": {
+ "name": "deleted",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "local_created_at": {
+ "name": "local_created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "local_updated_at": {
+ "name": "local_updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "trail_condition_reports_user_id_idx": {
+ "name": "trail_condition_reports_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "trail_condition_reports_active_created_idx": {
+ "name": "trail_condition_reports_active_created_idx",
+ "columns": [
+ {
+ "expression": "deleted",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": false,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "trail_condition_reports_trail_name_idx": {
+ "name": "trail_condition_reports_trail_name_idx",
+ "columns": [
+ {
+ "expression": "trail_name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "trail_condition_reports_trip_id_idx": {
+ "name": "trail_condition_reports_trip_id_idx",
+ "columns": [
+ {
+ "expression": "trip_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "where": "\"trail_condition_reports\".\"trip_id\" IS NOT NULL",
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "trail_condition_reports_user_id_users_id_fk": {
+ "name": "trail_condition_reports_user_id_users_id_fk",
+ "tableFrom": "trail_condition_reports",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "trail_condition_reports_trip_id_trips_id_fk": {
+ "name": "trail_condition_reports_trip_id_trips_id_fk",
+ "tableFrom": "trail_condition_reports",
+ "tableTo": "trips",
+ "columnsFrom": ["trip_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.trips": {
+ "name": "trips",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "start_date": {
+ "name": "start_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "end_date": {
+ "name": "end_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "location": {
+ "name": "location",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pack_id": {
+ "name": "pack_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "trail_osm_id": {
+ "name": "trail_osm_id",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "local_created_at": {
+ "name": "local_created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "local_updated_at": {
+ "name": "local_updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "deleted": {
+ "name": "deleted",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "trips_user_id_users_id_fk": {
+ "name": "trips_user_id_users_id_fk",
+ "tableFrom": "trips",
+ "tableTo": "users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "trips_pack_id_packs_id_fk": {
+ "name": "trips_pack_id_packs_id_fk",
+ "tableFrom": "trips",
+ "tableTo": "packs",
+ "columnsFrom": ["pack_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.users": {
+ "name": "users",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email_verified": {
+ "name": "email_verified",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "role": {
+ "name": "role",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'USER'"
+ },
+ "banned": {
+ "name": "banned",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false,
+ "default": false
+ },
+ "ban_reason": {
+ "name": "ban_reason",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ban_expires": {
+ "name": "ban_expires",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "first_name": {
+ "name": "first_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_name": {
+ "name": "last_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "avatar_url": {
+ "name": "avatar_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "password_hash": {
+ "name": "password_hash",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "preferences": {
+ "name": "preferences",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'{}'::jsonb"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "users_email_unique": {
+ "name": "users_email_unique",
+ "nullsNotDistinct": false,
+ "columns": ["email"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.verification": {
+ "name": "verification",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "identifier": {
+ "name": "identifier",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "verification_identifier_idx": {
+ "name": "verification_identifier_idx",
+ "columns": [
+ {
+ "expression": "identifier",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
diff --git a/packages/api/drizzle/meta/_journal.json b/packages/api/drizzle/meta/_journal.json
index fe75b8572b..45bc9f7f24 100644
--- a/packages/api/drizzle/meta/_journal.json
+++ b/packages/api/drizzle/meta/_journal.json
@@ -351,6 +351,13 @@
"when": 1780945594870,
"tag": "0048_sturdy_felicia_hardy",
"breakpoints": true
+ },
+ {
+ "idx": 49,
+ "version": "7",
+ "when": 1781241903101,
+ "tag": "0049_even_lizard",
+ "breakpoints": true
}
]
}
diff --git a/packages/api/package.json b/packages/api/package.json
index a47f0b77f8..0585932f2a 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -28,7 +28,9 @@
"db:generate": "drizzle-kit generate --config=drizzle.config.ts",
"db:migrate": "bun run ./migrate.ts",
"db:seed": "bun run ./src/db/seed.ts",
+ "db:seed:dev": "bun run ./src/db/seed-dev.ts",
"db:seed:e2e-user": "bun run ./src/db/seed-e2e-user.ts",
+ "db:seed:oauth-clients": "bun run ./src/db/seed-claude-oauth-client.ts",
"deploy": "wrangler deploy --minify",
"deploy:dev": "wrangler deploy --minify -e=dev",
"dev": "wrangler dev -e=dev",
@@ -48,12 +50,14 @@
"@ai-sdk/perplexity": "^3.0.29",
"@aws-sdk/client-s3": "~3.787.0",
"@aws-sdk/s3-request-presigner": "~3.787.0",
+ "@better-auth/oauth-provider": "1.6.11",
"@cloudflare/containers": "^0.0.30",
"@elysiajs/cors": "catalog:",
"@elysiajs/eden": "catalog:",
"@elysiajs/openapi": "catalog:",
"@mozilla/readability": "^0.6.0",
"@neondatabase/serverless": "catalog:",
+ "@packrat/consent-ui": "workspace:*",
"@packrat/constants": "workspace:*",
"@packrat/db": "workspace:*",
"@packrat/env": "workspace:*",
@@ -74,7 +78,7 @@
"elysia": "catalog:",
"google-auth-library": "catalog:",
"gray-matter": "catalog:",
- "jose": "^5.9.6",
+ "jose": "^6.0.0",
"linkedom": "^0.18.11",
"nodemailer": "^6.10.0",
"pg": "catalog:",
@@ -95,9 +99,9 @@
"@types/ws": "^8.5.14",
"@vitest/coverage-v8": "catalog:",
"better-auth": "catalog:",
- "better-auth-cloudflare": "^0.3.0",
"concurrently": "^8.2.2",
"drizzle-orm": "catalog:",
+ "drizzle-seed": "^0.3.1",
"miniflare": "^4.20260515.0",
"typed-htmx": "^0.3.1",
"vitest": "catalog:",
diff --git a/packages/api/src/app.ts b/packages/api/src/app.ts
index fcf9b22664..393b2a73be 100644
--- a/packages/api/src/app.ts
+++ b/packages/api/src/app.ts
@@ -1,7 +1,16 @@
+/**
+ * The PackRat API as an Elysia app - the typed contract exported as `App` and
+ * consumed by `@packrat/api-client` (Eden Treaty).
+ *
+ * This module is deliberately JSX-free. The browser-facing OAuth consent page
+ * is mounted on the runtime worker in `index.ts`, not here, so it stays out of
+ * `App` and does not pull JSX types into every Eden consumer.
+ */
+
import { cors } from '@elysiajs/cors';
import { routes } from '@packrat/api/routes';
import { packratOpenApi } from '@packrat/api/utils/openapi';
-import { captureApiException } from '@packrat/api/utils/sentry';
+import { captureApiException, setRequestId } from '@packrat/api/utils/sentry';
import { Elysia } from 'elysia';
import { CloudflareAdapter } from 'elysia/adapter/cloudflare-worker';
@@ -61,48 +70,58 @@ export function corsPreflightResponse(request: Request): Response | null {
});
}
-export const app = new Elysia({ adapter: CloudflareAdapter })
+export const appBase = new Elysia({ adapter: CloudflareAdapter })
.use(
cors({
credentials: true,
- origin: (request) => {
- const origin = request.headers.get('Origin');
- return isAllowedCorsOrigin(origin);
- },
+ origin: (request) => isAllowedCorsOrigin(request.headers.get('Origin')),
allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key'],
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
}),
)
.use(packratOpenApi)
- .onError(({ error, code, request }) => {
+ .derive(({ request, set }) => {
+ const requestId = request.headers.get('cf-ray') ?? crypto.randomUUID();
+ setRequestId(requestId);
+ set.headers['x-request-id'] = requestId;
+ return { requestId };
+ })
+ .onError(({ error, code, request, route, path }) => {
+ const requestId = request?.headers.get('cf-ray') ?? 'unknown';
if (code !== 'VALIDATION' && code !== 'PARSE' && code !== 'NOT_FOUND') {
captureApiException({
- error: error,
- operation: 'elysia.onError',
+ error,
+ operation: route ? `route ${request?.method ?? ''} ${route}`.trim() : 'elysia.onError',
tags: {
error_code: String(code),
method: request?.method ?? 'UNKNOWN',
- path: request ? new URL(request.url).pathname : 'UNKNOWN',
+ route: route ?? 'UNKNOWN',
+ request_id: requestId,
+ },
+ extra: {
+ errorCode: String(code),
+ httpStatus: 500,
+ path: path ?? (request ? new URL(request.url).pathname : 'UNKNOWN'),
},
- extra: { errorCode: String(code), httpStatus: 500 },
});
}
+ const headers = { 'Content-Type': 'application/json', 'X-Request-Id': requestId };
if (code === 'VALIDATION' || code === 'PARSE') {
- return new Response(JSON.stringify({ error: 'Validation failed' }), {
+ return new Response(JSON.stringify({ error: 'Validation failed', requestId }), {
status: 400,
- headers: { 'Content-Type': 'application/json' },
+ headers,
});
}
if (code === 'NOT_FOUND') {
- return new Response(JSON.stringify({ error: 'Not found' }), {
+ return new Response(JSON.stringify({ error: 'Not found', requestId }), {
status: 404,
- headers: { 'Content-Type': 'application/json' },
+ headers,
});
}
- return new Response(JSON.stringify({ error: 'Internal server error' }), {
+ return new Response(JSON.stringify({ error: 'Internal server error', requestId }), {
status: 500,
- headers: { 'Content-Type': 'application/json' },
+ headers,
});
})
.get('/', () => 'PackRat API is running!', {
@@ -114,4 +133,4 @@ export const app = new Elysia({ adapter: CloudflareAdapter })
.use(routes)
.compile();
-export type App = typeof app;
+export type App = typeof appBase;
diff --git a/packages/api/src/auth/__tests__/auth.helpers.test.ts b/packages/api/src/auth/__tests__/auth.helpers.test.ts
index fa08d228f0..4e60a711c3 100644
--- a/packages/api/src/auth/__tests__/auth.helpers.test.ts
+++ b/packages/api/src/auth/__tests__/auth.helpers.test.ts
@@ -31,7 +31,7 @@ describe('verifyPasswordCompat()', () => {
mocks.bcryptCompare.mockResolvedValue(true);
const result = await verifyPasswordCompat({ hash: '$2a$10$abc', password: 'pw' });
expect(mocks.bcryptCompare).toHaveBeenCalledWith('pw', '$2a$10$abc');
- expect(mocks.verifyPassword).not.toHaveBeenCalled();
+ expect(mocks.verifyPassword).toHaveBeenCalledTimes(0);
expect(result).toBe(true);
});
@@ -45,15 +45,15 @@ describe('verifyPasswordCompat()', () => {
it('uses bcrypt for $2y$ hashes', async () => {
mocks.bcryptCompare.mockResolvedValue(true);
await verifyPasswordCompat({ hash: '$2y$10$hash', password: 'pw' });
- expect(mocks.bcryptCompare).toHaveBeenCalled();
- expect(mocks.verifyPassword).not.toHaveBeenCalled();
+ expect(mocks.bcryptCompare).toHaveBeenCalledWith('pw', '$2y$10$hash');
+ expect(mocks.verifyPassword).toHaveBeenCalledTimes(0);
});
it('uses better-auth verifyPassword for non-bcrypt hashes', async () => {
mocks.verifyPassword.mockResolvedValue(true);
const result = await verifyPasswordCompat({ hash: 'argon2:somehash', password: 'pw' });
expect(mocks.verifyPassword).toHaveBeenCalledWith('argon2:somehash', 'pw');
- expect(mocks.bcryptCompare).not.toHaveBeenCalled();
+ expect(mocks.bcryptCompare).toHaveBeenCalledTimes(0);
expect(result).toBe(true);
});
@@ -77,7 +77,7 @@ describe('generateAppleClientSecret()', () => {
it('returns null when APPLE_PRIVATE_KEY is not set', async () => {
const result = await generateAppleClientSecret({ APPLE_PRIVATE_KEY: '' } as never);
expect(result).toBeNull();
- expect(mocks.importPKCS8).not.toHaveBeenCalled();
+ expect(mocks.importPKCS8).toHaveBeenCalledTimes(0);
});
it('returns a signed JWT string on success', async () => {
diff --git a/packages/api/src/auth/__tests__/consent-page.test.ts b/packages/api/src/auth/__tests__/consent-page.test.ts
new file mode 100644
index 0000000000..767f86c8ca
--- /dev/null
+++ b/packages/api/src/auth/__tests__/consent-page.test.ts
@@ -0,0 +1,355 @@
+/**
+ * Unit tests for the OAuth consent page renderer + handler.
+ *
+ * Coverage targets (from U1 plan):
+ * - admin user sees ALL approvable scopes including mcp:admin
+ * - non-admin user has mcp:admin filtered out of the form
+ * - unauthenticated request redirects to /api/auth/sign-in
+ * - unknown client_id returns 404
+ * - missing client_id returns 400
+ * - rendered HTML carries the expected anti-clickjacking + content-type headers
+ */
+
+import { type ConsentPageData, renderConsentPage } from '@packrat/consent-ui';
+import { Elysia } from 'elysia';
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+
+// ── Route-level test setup ────────────────────────────────────────────────
+//
+// The unit-test config runs in plain Node — importing `@packrat/api/index`
+// (the full app) pulls in @cloudflare/containers which extends a Workers-only
+// base class. To exercise the /oauth/consent Elysia route in isolation, we:
+// 1. Mock the route's external deps (`getAuth`, `createDb`, `getEnv`) at
+// module scope. vi.mock is hoisted so subsequent imports see the mocks.
+// 2. Lazy-import `consentRoute` AFTER the mocks register, and mount it on a
+// throwaway Elysia instance for `.fetch(...)` calls.
+//
+// Each route test reshapes the mocks via mockImplementationOnce so behaviour
+// is per-test (different session, different DB row).
+
+const mockGetSession = vi.fn();
+const mockSelectChain = vi.fn();
+
+vi.mock('@packrat/api/auth', () => ({
+ getAuth: vi.fn(async () => ({
+ api: { getSession: mockGetSession },
+ })),
+}));
+
+vi.mock('@packrat/api/db', () => ({
+ createDb: vi.fn(() => ({ select: mockSelectChain })),
+}));
+
+vi.mock('@packrat/api/utils/env-validation', () => ({
+ getEnv: vi.fn(() => ({ NEON_DATABASE_URL: 'postgres://stub' })),
+}));
+
+async function buildTestApp() {
+ const { consentRoute } = await import('../consent-route');
+ return new Elysia().use(consentRoute);
+}
+
+// Cached after first import to avoid re-mounting the route per test. Typed as
+// the precise mounted-app type (Elysia's generics are invariant, so the bare
+// `Elysia` type can't hold it).
+let testApp: Awaited> | undefined;
+
+async function getTestApp(): Promise>> {
+ if (!testApp) {
+ testApp = await buildTestApp();
+ }
+ return testApp;
+}
+
+beforeEach(() => {
+ mockGetSession.mockReset();
+ mockSelectChain.mockReset();
+});
+
+function mockSession(user: { id: string; name?: string; email: string; role?: string } | null) {
+ mockGetSession.mockResolvedValueOnce(user ? { user } : null);
+}
+
+function mockOauthClientRow(row: Record | null) {
+ const limit = vi.fn().mockResolvedValue(row ? [row] : []);
+ const where = vi.fn().mockReturnValue({ limit });
+ const from = vi.fn().mockReturnValue({ where });
+ mockSelectChain.mockReturnValueOnce({ from });
+}
+
+const baseUser = { name: 'Test User', email: 'user@example.com' };
+
+const baseClient = {
+ clientId: 'packrat-claude-mcp',
+ name: 'Claude',
+ icon: 'https://packratai.com/mcp-logo-256.png',
+ tos: 'https://www.anthropic.com/legal/consumer-terms',
+ policy: 'https://www.anthropic.com/legal/privacy',
+ uri: 'https://claude.ai',
+};
+
+function makeData(overrides: Partial = {}): ConsentPageData {
+ return {
+ user: baseUser,
+ isAdmin: false,
+ client: baseClient,
+ requestedScopes: ['mcp:read', 'mcp:write', 'mcp:admin'],
+ approvableScopes: ['mcp:read', 'mcp:write'],
+ oauthQuery: 'client_id=packrat-claude-mcp&scope=mcp%3Aread+mcp%3Awrite+mcp%3Aadmin&sig=abc',
+ ...overrides,
+ };
+}
+
+describe('renderConsentPage()', () => {
+ it('renders the client name in the header', () => {
+ const html = renderConsentPage(makeData());
+ expect(html).toContain('Claude wants to access your PackRat account');
+ });
+
+ it("renders the user's name and email as the signed-in identity", () => {
+ const html = renderConsentPage(makeData());
+ expect(html).toContain('Test User');
+ expect(html).toContain('user@example.com');
+ });
+
+ it('renders only the approvable scopes as form inputs (non-admin path)', () => {
+ const html = renderConsentPage(
+ makeData({
+ isAdmin: false,
+ requestedScopes: ['mcp:read', 'mcp:write', 'mcp:admin'],
+ approvableScopes: ['mcp:read', 'mcp:write'],
+ }),
+ );
+ expect(html).toContain('value="mcp:read"');
+ expect(html).toContain('value="mcp:write"');
+ expect(html).not.toContain('value="mcp:admin"');
+ });
+
+ // ── scope serialization contract ─────────────────────────────────────────
+ //
+ // Better Auth's /oauth2/consent endpoint reads `scope` as a SINGLE
+ // space-joined string (`ctx.body.scope?.split(" ")`, body schema
+ // `scope: z.string().optional()`). Submitting one form field per scope all
+ // named `scope` would collapse to a single value and silently grant only
+ // one scope, breaking consent-time scope reduction. These tests pin the
+ // contract: exactly one hidden `name="scope"` field carrying the
+ // space-joined approvable set, and the per-scope checkboxes use a different
+ // name so they never POST a `scope` field.
+
+ it('submits a SINGLE space-joined hidden `scope` field (no-JS default = approvable set)', () => {
+ const html = renderConsentPage(
+ makeData({
+ approvableScopes: ['mcp:read', 'mcp:write'],
+ }),
+ );
+ // Exactly one hidden input named `scope`, value = space-joined set.
+ expect(html).toContain('name="scope" value="mcp:read mcp:write"');
+ // It is the only `name="scope"` field in the document (checkboxes use a
+ // different name) — so the endpoint receives one space-joined string.
+ expect(html.match(/name="scope"/g)).toHaveLength(1);
+ });
+
+ it('does NOT render any checkbox named `scope` (would break the single-string contract)', () => {
+ const html = renderConsentPage(makeData());
+ // Checkboxes drive UX only; they must not post a `scope` field.
+ expect(html).not.toContain('type="checkbox" name="scope"');
+ expect(html).toContain('type="checkbox" name="scope_option"');
+ });
+
+ it('includes the inline submit handler that joins checked scopes into the hidden field', () => {
+ const html = renderConsentPage(makeData());
+ expect(html).toContain('id="consent-form"');
+ expect(html).toContain('id="consent-scope"');
+ expect(html).toContain('input[name="scope_option"]:checked');
+ });
+
+ it('joins all approvable scopes (incl. mcp:admin) for the admin no-JS default', () => {
+ const html = renderConsentPage(
+ makeData({
+ isAdmin: true,
+ approvableScopes: ['mcp:read', 'mcp:write', 'mcp:admin'],
+ }),
+ );
+ expect(html).toContain('name="scope" value="mcp:read mcp:write mcp:admin"');
+ expect(html.match(/name="scope"/g)).toHaveLength(1);
+ });
+
+ it('renders mcp:admin as an approvable scope for admins', () => {
+ const html = renderConsentPage(
+ makeData({
+ isAdmin: true,
+ requestedScopes: ['mcp:read', 'mcp:write', 'mcp:admin'],
+ approvableScopes: ['mcp:read', 'mcp:write', 'mcp:admin'],
+ }),
+ );
+ expect(html).toContain('value="mcp:admin"');
+ });
+
+ it('renders the form posting to /api/auth/oauth2/consent', () => {
+ const html = renderConsentPage(makeData());
+ expect(html).toContain('action="/api/auth/oauth2/consent"');
+ });
+
+ it('echoes the oauth_query as a hidden input verbatim', () => {
+ const html = renderConsentPage(makeData());
+ expect(html).toContain(
+ 'name="oauth_query" value="client_id=packrat-claude-mcp&scope=mcp%3Aread+mcp%3Awrite+mcp%3Aadmin&sig=abc"',
+ );
+ });
+
+ it('escapes HTML in the client name to prevent injection', () => {
+ const html = renderConsentPage(
+ makeData({
+ client: { ...baseClient, name: '' },
+ }),
+ );
+ // The actual XSS protection: the `<` is encoded to `<` so the
+ // injected `');
+ expect(html).toContain('<script');
+ });
+
+ it('renders client policy + tos links when present', () => {
+ const html = renderConsentPage(makeData());
+ expect(html).toContain('https://www.anthropic.com/legal/privacy');
+ expect(html).toContain('https://www.anthropic.com/legal/consumer-terms');
+ });
+
+ it('falls back to a generic client name when name is missing', () => {
+ const html = renderConsentPage(
+ makeData({
+ client: { ...baseClient, name: null },
+ }),
+ );
+ expect(html).toContain('An MCP client wants to access your PackRat account');
+ });
+
+ it('renders accept and deny buttons with the correct submit values', () => {
+ const html = renderConsentPage(makeData());
+ // The form POSTs `accept=true` or `accept=false` per the plugin's
+ // /oauth2/consent endpoint schema.
+ expect(html).toContain('name="accept" value="true"');
+ expect(html).toContain('name="accept" value="false"');
+ });
+});
+
+describe('GET /oauth/consent (Elysia route)', () => {
+ it('returns 400 when client_id is missing', async () => {
+ const res = await (await getTestApp()).fetch(
+ new Request('http://localhost/oauth/consent?scope=mcp%3Aread'),
+ );
+ expect(res.status).toBe(400);
+ });
+
+ it('redirects to /api/auth/sign-in when the user is not signed in', async () => {
+ mockSession(null);
+ const res = await (await getTestApp()).fetch(
+ new Request('http://localhost/oauth/consent?client_id=packrat-claude-mcp&scope=mcp%3Aread'),
+ );
+ expect(res.status).toBe(302);
+ expect(res.headers.get('location')).toContain('/api/auth/sign-in');
+ expect(res.headers.get('location')).toContain('callbackURL=');
+ });
+
+ it('returns 404 when the client_id does not exist in oauthClient', async () => {
+ mockSession({ id: 'u1', email: 'u@e.com', role: 'USER' });
+ mockOauthClientRow(null);
+ const res = await (await getTestApp()).fetch(
+ new Request('http://localhost/oauth/consent?client_id=unknown&scope=mcp%3Aread'),
+ );
+ expect(res.status).toBe(404);
+ });
+
+ it('renders the consent page (200, text/html) with mcp:admin stripped for non-admin', async () => {
+ mockSession({ id: 'u1', name: 'Test User', email: 'u@e.com', role: 'USER' });
+ mockOauthClientRow({
+ clientId: 'packrat-claude-mcp',
+ name: 'Claude',
+ icon: null,
+ tos: null,
+ policy: null,
+ uri: null,
+ });
+ const res = await (await getTestApp()).fetch(
+ new Request(
+ 'http://localhost/oauth/consent?client_id=packrat-claude-mcp&scope=mcp%3Aread+mcp%3Awrite+mcp%3Aadmin&sig=abc',
+ ),
+ );
+ expect(res.status).toBe(200);
+ expect(res.headers.get('content-type')).toContain('text/html');
+ expect(res.headers.get('x-frame-options')).toBe('DENY');
+ expect(res.headers.get('x-content-type-options')).toBe('nosniff');
+
+ const html = await res.text();
+ expect(html).toContain('Claude wants to access your PackRat account');
+ expect(html).toContain('value="mcp:read"');
+ expect(html).toContain('value="mcp:write"');
+ expect(html).not.toContain('value="mcp:admin"');
+ });
+
+ it('renders mcp:admin for an admin user', async () => {
+ mockSession({ id: 'u1', email: 'admin@e.com', role: 'ADMIN' });
+ mockOauthClientRow({
+ clientId: 'packrat-claude-mcp',
+ name: 'Claude',
+ icon: null,
+ tos: null,
+ policy: null,
+ uri: null,
+ });
+ const res = await (await getTestApp()).fetch(
+ new Request('http://localhost/oauth/consent?client_id=packrat-claude-mcp&scope=mcp%3Aadmin'),
+ );
+ expect(res.status).toBe(200);
+ const html = await res.text();
+ expect(html).toContain('value="mcp:admin"');
+ });
+
+ it('treats a session user with no role as non-admin (mcp:admin stripped)', async () => {
+ // session.user.role is undefined → `?? 'USER'` fallback → isAdmin=false.
+ mockSession({ id: 'u1', name: 'No Role', email: 'norole@e.com' });
+ mockOauthClientRow({
+ clientId: 'packrat-claude-mcp',
+ name: 'Claude',
+ icon: null,
+ tos: null,
+ policy: null,
+ uri: null,
+ });
+ const res = await (await getTestApp()).fetch(
+ new Request(
+ 'http://localhost/oauth/consent?client_id=packrat-claude-mcp&scope=mcp%3Aread+mcp%3Aadmin',
+ ),
+ );
+ expect(res.status).toBe(200);
+ const html = await res.text();
+ expect(html).toContain('value="mcp:read"');
+ expect(html).not.toContain('value="mcp:admin"');
+ });
+
+ it('renders with an empty scope set when the scope param is absent', async () => {
+ // query.scope missing → `isString(...) ? : ''` takes the '' branch →
+ // no approvable scopes, but the page still renders 200.
+ mockSession({ id: 'u1', name: 'Test User', email: 'u@e.com', role: 'USER' });
+ mockOauthClientRow({
+ clientId: 'packrat-claude-mcp',
+ name: 'Claude',
+ icon: null,
+ tos: null,
+ policy: null,
+ uri: null,
+ });
+ const res = await (await getTestApp()).fetch(
+ new Request('http://localhost/oauth/consent?client_id=packrat-claude-mcp'),
+ );
+ expect(res.status).toBe(200);
+ expect(res.headers.get('content-type')).toContain('text/html');
+ const html = await res.text();
+ expect(html).toContain('Claude wants to access your PackRat account');
+ expect(html).not.toContain('value="mcp:admin"');
+ });
+});
diff --git a/packages/api/src/auth/__tests__/oauth-provider.test.ts b/packages/api/src/auth/__tests__/oauth-provider.test.ts
new file mode 100644
index 0000000000..b6e0bffc37
--- /dev/null
+++ b/packages/api/src/auth/__tests__/oauth-provider.test.ts
@@ -0,0 +1,96 @@
+/**
+ * Unit tests for the @better-auth/oauth-provider plugin wiring.
+ *
+ * Coverage targets:
+ * - schema export: all four OAuth tables exist on @packrat/db with the
+ * expected shape (column names + nullability matching the plugin's
+ * declared schema, so the drizzle adapter's auto-registration finds them)
+ * - plugin export shape: imported as a function from
+ * '@better-auth/oauth-provider', exports authServer/openidConfig helpers
+ *
+ * Discovery + flow assertions (issuer match, PKCE S256, JWT-only-with-resource
+ * regression guard) live in the integration test suite in test/auth.test.ts;
+ * they need a live Better Auth instance against the docker-test database
+ * which the unit-test pool can't provide.
+ */
+
+import { oauthAccessToken, oauthClient, oauthConsent, oauthRefreshToken } from '@packrat/db';
+import { describe, expect, it } from 'vitest';
+
+describe('OAuth provider schema (@packrat/db)', () => {
+ it('exports oauthClient table with snake_case columns', () => {
+ expect(oauthClient).toBeDefined();
+ const cols = Object.keys(oauthClient);
+ expect(cols).toContain('clientId');
+ expect(cols).toContain('redirectUris');
+ expect(cols).toContain('tokenEndpointAuthMethod');
+ expect(cols).toContain('requirePKCE');
+ expect(cols).toContain('scopes');
+ expect(cols).toContain('name');
+ expect(cols).toContain('icon');
+ expect(cols).toContain('tos');
+ expect(cols).toContain('policy');
+ expect(cols).toContain('uri');
+ });
+
+ it('exports oauthAccessToken table with refresh_id FK column', () => {
+ expect(oauthAccessToken).toBeDefined();
+ const cols = Object.keys(oauthAccessToken);
+ expect(cols).toContain('clientId');
+ expect(cols).toContain('userId');
+ expect(cols).toContain('sessionId');
+ expect(cols).toContain('refreshId');
+ expect(cols).toContain('scopes');
+ expect(cols).toContain('expiresAt');
+ });
+
+ it('exports oauthRefreshToken table with all RFC-required fields', () => {
+ // oauthRefreshToken was MISSING from the original plan — spike caught
+ // it. Verify its presence so refresh-token rotation works at first
+ // attempt (R2: refresh tokens rotate with proper invalidation).
+ expect(oauthRefreshToken).toBeDefined();
+ const cols = Object.keys(oauthRefreshToken);
+ expect(cols).toContain('clientId');
+ expect(cols).toContain('userId');
+ expect(cols).toContain('sessionId');
+ expect(cols).toContain('token');
+ expect(cols).toContain('expiresAt');
+ expect(cols).toContain('revoked');
+ expect(cols).toContain('authTime');
+ expect(cols).toContain('scopes');
+ });
+
+ it('exports oauthConsent table', () => {
+ expect(oauthConsent).toBeDefined();
+ const cols = Object.keys(oauthConsent);
+ expect(cols).toContain('clientId');
+ expect(cols).toContain('userId');
+ expect(cols).toContain('scopes');
+ });
+});
+
+describe('OAuth provider plugin export', () => {
+ it('exports oauthProvider as a callable plugin factory', async () => {
+ const mod = await import('@better-auth/oauth-provider');
+ expect(typeof mod.oauthProvider).toBe('function');
+ });
+
+ it('exports the AS metadata helper (oauthProviderAuthServerMetadata)', async () => {
+ const mod = await import('@better-auth/oauth-provider');
+ expect(typeof mod.oauthProviderAuthServerMetadata).toBe('function');
+ });
+
+ it('exports the OIDC config helper (oauthProviderOpenIdConfigMetadata)', async () => {
+ const mod = await import('@better-auth/oauth-provider');
+ expect(typeof mod.oauthProviderOpenIdConfigMetadata).toBe('function');
+ });
+
+ it('does NOT export oAuthDiscoveryMetadata (the spike-flagged wrong name)', async () => {
+ // The plan originally referenced `oAuthDiscoveryMetadata` — spike
+ // confirmed no such export exists in @better-auth/oauth-provider@1.6.11.
+ // This test fails fast if a future upgrade introduces a different export
+ // shape and the wrong helper name sneaks back into the plan.
+ const mod = (await import('@better-auth/oauth-provider')) as Record;
+ expect(mod.oAuthDiscoveryMetadata).toBeUndefined();
+ });
+});
diff --git a/packages/api/src/auth/auth.config.ts b/packages/api/src/auth/auth.config.ts
index dba1f58e03..5972cbef57 100644
--- a/packages/api/src/auth/auth.config.ts
+++ b/packages/api/src/auth/auth.config.ts
@@ -11,6 +11,7 @@
*/
import { drizzleAdapter } from '@better-auth/drizzle-adapter';
+import { oauthProvider } from '@better-auth/oauth-provider';
import { neon } from '@neondatabase/serverless';
import * as schema from '@packrat/db';
import { betterAuth } from 'better-auth';
@@ -38,6 +39,11 @@ export const auth = betterAuth({
session: schema.session,
account: schema.account,
verification: schema.verification,
+ jwks: schema.jwks,
+ oauthClient: schema.oauthClient,
+ oauthAccessToken: schema.oauthAccessToken,
+ oauthRefreshToken: schema.oauthRefreshToken,
+ oauthConsent: schema.oauthConsent,
},
}),
@@ -69,7 +75,36 @@ export const auth = betterAuth({
},
},
- plugins: [bearer(), jwt({ jwks: { disablePrivateKeyEncryption: true } }), admin()],
+ plugins: [
+ bearer(),
+ jwt({ jwks: { disablePrivateKeyEncryption: true } }),
+ admin(),
+ // OAuth 2.1 provider — schema-affecting; mirrors index.ts. See the
+ // runtime config in src/auth/index.ts for the option rationale.
+ oauthProvider({
+ scopes: [
+ 'openid',
+ 'profile',
+ 'email',
+ 'offline_access',
+ 'mcp:read',
+ 'mcp:write',
+ 'mcp:admin',
+ ],
+ validAudiences: ['https://mcp.packratai.com/mcp'],
+ allowDynamicClientRegistration: false,
+ allowUnauthenticatedClientRegistration: false,
+ consentPage: '/oauth/consent',
+ loginPage: '/api/auth/sign-in',
+ }),
+ ],
+ // NOTE: keep in lockstep with `index.ts` (the runtime config). The two
+ // lists drift independently — see
+ // `docs/solutions/developer-experience/better-auth-cli-cloudflare-worker-factory-2026-05-02.md`
+ // and `docs/mcp/runbook.md` § "Better Auth trustedOrigins" for the
+ // schema-regen reminder.
+ // `https://mcp.packratai.com` removed in U1 of the OAuth provider
+ // consolidation refactor — MCP no longer calls Better Auth directly.
trustedOrigins: ['http://localhost:8787', 'packrat://'],
});
diff --git a/packages/api/src/auth/consent-route.ts b/packages/api/src/auth/consent-route.ts
new file mode 100644
index 0000000000..b7b50d3c21
--- /dev/null
+++ b/packages/api/src/auth/consent-route.ts
@@ -0,0 +1,119 @@
+/**
+ * Elysia route for the OAuth consent page (`GET /oauth/consent`).
+ *
+ * Mounted on the top-level `app` in `src/index.ts`. The `@better-auth/oauth-provider`
+ * plugin redirects the user-agent here mid-OAuth-flow when the user needs to
+ * approve scopes for a client; the route reads the user's Better Auth
+ * session, optionally filters `mcp:admin` from the rendered scope list for
+ * non-admins, and renders the branded consent page.
+ *
+ * The HTML renderer lives in `@packrat/consent-ui` — a BUILT package whose
+ * public surface is plain (`renderConsentPage(data): string`), so its
+ * @kitajs/html global JSX namespace never enters the API's type program. This
+ * file is plain TS (no JSX) and owns only the routing + dependency glue; it
+ * sets `Content-Type: text/html` itself rather than via @elysiajs/html.
+ *
+ * Behaviour:
+ * - 400 if `client_id` is missing from the query
+ * - 302 to `/api/auth/sign-in?callbackURL=...` when there's no session
+ * - 404 if `client_id` doesn't match any `oauthClient` row
+ * - 200 text/html with the consent form otherwise (security headers set
+ * via `set.headers`: Cache-Control: no-store, X-Content-Type-Options,
+ * X-Frame-Options: DENY)
+ */
+
+import { getAuth } from '@packrat/api/auth';
+import { createDb } from '@packrat/api/db';
+import { getEnv } from '@packrat/api/utils/env-validation';
+import { type OAuthClientRecord, renderConsentPage } from '@packrat/consent-ui';
+import * as dbSchema from '@packrat/db';
+import { isString, toRecord, toString as toStr } from '@packrat/guards';
+import { eq } from 'drizzle-orm';
+import { Elysia } from 'elysia';
+import { createRegExp, oneOrMore, whitespace } from 'magic-regexp';
+
+// Matches RFC 6749 §3.3 (space-separated scopes).
+const SCOPE_SEPARATOR_RE = createRegExp(oneOrMore(whitespace));
+
+export const consentRoute = new Elysia().get('/oauth/consent', async ({ request, query, set }) => {
+ const clientId = isString(query.client_id) ? query.client_id : '';
+ if (!clientId) {
+ set.status = 400;
+ return 'Missing client_id parameter';
+ }
+
+ const env = getEnv();
+ const auth = await getAuth(env);
+
+ // Resolve the current Better Auth session from cookies/bearer. The plugin
+ // would normally redirect to loginPage when no session, but the page
+ // route is hit directly — re-check here to fail closed.
+ const session = await auth.api.getSession({ headers: request.headers });
+ if (!session?.user) {
+ const url = new URL(request.url);
+ const signInUrl = new URL('/api/auth/sign-in', url.origin);
+ signInUrl.searchParams.set('callbackURL', url.toString());
+ set.status = 302;
+ set.headers.location = signInUrl.toString();
+ return null;
+ }
+
+ // Load the OAuth client row for branding (name, logo, tos, policy, uri).
+ const db = createDb();
+ const clientRows = await db
+ .select()
+ .from(dbSchema.oauthClient)
+ .where(eq(dbSchema.oauthClient.clientId, clientId))
+ .limit(1);
+ const clientRow = clientRows[0] as (OAuthClientRecord & { clientId: string }) | undefined;
+
+ if (!clientRow) {
+ set.status = 404;
+ // Plain-text response (no HTML), so the validated clientId can't be an
+ // XSS vector and we avoid any @kitajs/html dependency here.
+ set.headers['content-type'] = 'text/plain; charset=utf-8';
+ return `Unknown OAuth client: ${clientId}`;
+ }
+
+ const requestedScopeStr = isString(query.scope) ? query.scope : '';
+ const requestedScopes = requestedScopeStr.split(SCOPE_SEPARATOR_RE).filter(Boolean);
+
+ // Admin-scope filter: non-admin users can NOT approve mcp:admin even if
+ // the client requested it. Spike-verified: POSTing a reduced `scope` to
+ // /oauth2/consent results in a JWT carrying ONLY the reduced set.
+ //
+ // `session.user.role` is added by Better Auth's admin plugin but isn't
+ // surfaced on the base getSession() return type; @packrat/guards' toRecord
+ // + toString narrow it without a hand-written cast.
+ const userRole = toStr(toRecord(session.user).role) ?? 'USER';
+ const isAdmin = userRole === 'ADMIN';
+ const approvableScopes = requestedScopes.filter((s) => isAdmin || s !== 'mcp:admin');
+
+ const url = new URL(request.url);
+ const oauthQuery = url.search.startsWith('?') ? url.search.slice(1) : url.search;
+
+ // renderConsentPage returns a complete HTML document string; set the
+ // content-type ourselves (no @elysiajs/html plugin — importing it would
+ // re-pull @kitajs/html's global JSX into the API's type surface). The rest
+ // are OAuth-flow security defaults.
+ set.headers['content-type'] = 'text/html; charset=utf-8';
+ set.headers['cache-control'] = 'no-store';
+ set.headers['x-content-type-options'] = 'nosniff';
+ set.headers['x-frame-options'] = 'DENY';
+
+ return renderConsentPage({
+ user: { name: session.user.name, email: session.user.email },
+ isAdmin,
+ client: {
+ clientId: clientRow.clientId,
+ name: clientRow.name,
+ icon: clientRow.icon,
+ tos: clientRow.tos,
+ policy: clientRow.policy,
+ uri: clientRow.uri,
+ },
+ requestedScopes,
+ approvableScopes,
+ oauthQuery,
+ });
+});
diff --git a/packages/api/src/auth/index.ts b/packages/api/src/auth/index.ts
index 4958db7aab..b98b965e48 100644
--- a/packages/api/src/auth/index.ts
+++ b/packages/api/src/auth/index.ts
@@ -9,6 +9,7 @@
import { drizzleAdapter } from '@better-auth/drizzle-adapter';
import { expo } from '@better-auth/expo';
+import { oauthProvider } from '@better-auth/oauth-provider';
import { generateAppleClientSecret, verifyPasswordCompat } from '@packrat/api/auth/auth.helpers';
import { createConnection } from '@packrat/api/db';
import type { ValidatedEnv } from '@packrat/api/utils/env-validation';
@@ -17,11 +18,32 @@ import { isObject } from '@packrat/guards';
import { betterAuth } from 'better-auth';
import { admin, bearer, jwt } from 'better-auth/plugins';
+// ─── MCP OAuth scope catalog (advertised in scopes_supported) ───────────────
+// `openid`, `profile`, `email`, `offline_access` are the OIDC standard scopes
+// the plugin advertises by default; we include them explicitly so this list
+// is the single source of truth for `scopes_supported` in discovery metadata.
+// MCP scopes are mapped to tool visibility in packages/mcp/src/scopes.ts.
+const MCP_OAUTH_SCOPES = [
+ 'openid',
+ 'profile',
+ 'email',
+ 'offline_access',
+ 'mcp:read',
+ 'mcp:write',
+ 'mcp:admin',
+] as const;
+
+// RFC 8707 audience — JWT access tokens are bound to this `aud` claim.
+// The MCP worker verifies tokens carry exactly this audience; any other
+// `resource` parameter results in `invalid_request` (400) from the plugin's
+// `checkResource` (validAudiences enforcement).
+const MCP_AUDIENCE = 'https://mcp.packratai.com/mcp';
+
// ─── Per-isolate auth instance cache ─────────────────────────────────────────
// Stores the in-flight Promise so concurrent requests that arrive before the
// first initialization completes all await the same Promise rather than each
// kicking off a redundant build. Evicted on rejection so the next call retries.
-// Keyed by NEON_DATABASE_URL|BETTER_AUTH_URL — miniflare creates a new env
+// Keyed by NEON_DATABASE_URL|PACKRAT_API_URL — miniflare creates a new env
// object per request, so a WeakMap never hits; the URL composite key is stable
// within an isolate lifetime and distinguishes different env configurations.
// biome-ignore lint/suspicious/noExplicitAny: Better Auth's generic type parameter is too specific to the exact plugin set — can't use ReturnType here
@@ -32,12 +54,17 @@ function getTrustedOrigins(env: ValidatedEnv): string[] {
.map((origin) => origin.trim())
.filter(Boolean);
- return [env.BETTER_AUTH_URL, ...(configured ?? []), 'packrat://'];
+ return [
+ env.PACKRAT_API_URL,
+ ...(configured ?? []),
+ 'packrat://',
+ ...(env.ENVIRONMENT === 'development' ? ['http://localhost:*'] : []),
+ ];
}
// biome-ignore lint/suspicious/noExplicitAny: Better Auth instance type is plugin-specific and can't be expressed at declaration time without duplicating the full config signature
export async function getAuth(env: ValidatedEnv): Promise {
- const cacheKey = `${env.NEON_DATABASE_URL}|${env.BETTER_AUTH_URL}|${env.BETTER_AUTH_TRUSTED_ORIGINS ?? ''}`;
+ const cacheKey = `${env.NEON_DATABASE_URL}|${env.PACKRAT_API_URL}|${env.BETTER_AUTH_TRUSTED_ORIGINS ?? ''}|${env.ENVIRONMENT}`;
const cached = authCache.get(cacheKey);
if (cached) return cached;
@@ -56,8 +83,8 @@ async function buildAuth(env: ValidatedEnv): Promise {
const db = createConnection({ url: env.NEON_DATABASE_URL, useNeonHttp: true });
const auth = betterAuth({
- baseURL: env.BETTER_AUTH_URL,
- secret: env.BETTER_AUTH_SECRET,
+ baseURL: env.PACKRAT_API_URL,
+ secret: env.PACKRAT_AUTH_SECRET,
advanced: {
// All IDs are UUID-formatted text (matching the DB migration).
@@ -96,6 +123,13 @@ async function buildAuth(env: ValidatedEnv): Promise {
account: schema.account,
verification: schema.verification,
jwks: schema.jwks,
+ // OAuth provider (@better-auth/oauth-provider@1.6.x) tables.
+ // The plugin auto-registers these models when present, gating its
+ // discovery + token + consent endpoints on their availability.
+ oauthClient: schema.oauthClient,
+ oauthAccessToken: schema.oauthAccessToken,
+ oauthRefreshToken: schema.oauthRefreshToken,
+ oauthConsent: schema.oauthConsent,
},
}),
@@ -161,9 +195,12 @@ async function buildAuth(env: ValidatedEnv): Promise {
bearer(),
// JWT: issues asymmetric JWTs and exposes a JWKS endpoint at
- // /api/auth/jwks for downstream service verification.
+ // /api/auth/jwks for downstream service verification. The OAuth provider
+ // plugin reads this plugin's signer to mint JWT access tokens when a
+ // client sends `resource` (RFC 8707) — so this config also gates MCP.
+ //
// Private key encryption is disabled — it causes decrypt failures when
- // BETTER_AUTH_SECRET rotates or differs across environments.
+ // PACKRAT_AUTH_SECRET rotates or differs across environments.
//
// The adapter.getJwks filter skips any rows that were stored in the old
// encrypted format (where JSON.parse(privateKey) returns a string rather
@@ -196,6 +233,43 @@ async function buildAuth(env: ValidatedEnv): Promise {
// passes for requests from the native app (which can't send a browser
// Origin header).
expo(),
+
+ // OAuth 2.1 Authorization Server for the MCP worker.
+ //
+ // Configuration rationale (cross-reference: spike findings in
+ // docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md):
+ // - `scopes`: declares the MCP scope catalog; advertised under
+ // `scopes_supported` in the AS metadata.
+ // - `validAudiences`: RFC 8707 — `/oauth2/authorize` rejects any
+ // `resource` parameter not in this list with 400 invalid_request.
+ // - `allowDynamicClientRegistration: false` + Claude pre-registered
+ // via packages/api/src/db/seed-claude-oauth-client.ts — DCR is
+ // closed because we know our connector clients ahead of time.
+ // - `consentPage`: points at `/oauth/consent` (mounted in the worker
+ // fetch handler in src/index.ts). The consent page server-side
+ // filters `mcp:admin` from non-admin grants and POSTs the reduced
+ // scope to `/oauth2/consent` — the plugin's native scope-reduction
+ // mechanism (customAccessTokenClaims CANNOT reduce scope; see
+ // spike §Q1-Q2).
+ // - `loginPage`: '/api/auth/sign-in' is a static placeholder URL the
+ // plugin redirects to for `prompt=login`. PackRat clients (Claude)
+ // rely on the user being already signed in via Better Auth's web
+ // auth flow before initiating OAuth; this URL is set so the plugin
+ // doesn't throw on missing config — the actual sign-in surface is
+ // the existing Better Auth endpoints, not a custom page.
+ // - `disableJwtPlugin` is intentionally unset: JWT access tokens are
+ // the default — but ONLY issued when the client sends a `resource`
+ // parameter (`isJwtAccessToken = audience && !opts.disableJwtPlugin`,
+ // spike §Q4). Claude.ai sends `resource` per the MCP 2025-11-25
+ // spec. Verified in U9 dev verification.
+ oauthProvider({
+ scopes: [...MCP_OAUTH_SCOPES],
+ validAudiences: [MCP_AUDIENCE],
+ allowDynamicClientRegistration: false,
+ allowUnauthenticatedClientRegistration: false,
+ consentPage: '/oauth/consent',
+ loginPage: '/api/auth/sign-in',
+ }),
],
rateLimit: {
@@ -205,6 +279,10 @@ async function buildAuth(env: ValidatedEnv): Promise {
storage: 'secondary-storage',
},
+ // NOTE: keep in lockstep with `auth.config.ts` (the CLI-facing static
+ // config). `https://mcp.packratai.com` is intentionally not trusted here:
+ // OAuth lives on api.packrat.world and the MCP worker does not call Better
+ // Auth sign-in endpoints directly.
trustedOrigins: getTrustedOrigins(env),
});
diff --git a/packages/api/src/db/seed-claude-oauth-client.ts b/packages/api/src/db/seed-claude-oauth-client.ts
new file mode 100644
index 0000000000..ce42b300e5
--- /dev/null
+++ b/packages/api/src/db/seed-claude-oauth-client.ts
@@ -0,0 +1,169 @@
+/**
+ * Seed: pre-register Claude as an OAuth client in the
+ * @better-auth/oauth-provider `oauthClient` table.
+ *
+ * Background: the plugin doesn't have a `trustedClients` config option
+ * (spike-verified — see docs/mcp/better-auth-oauth-provider-spike-2026-05-25.md
+ * §Q7). Pre-registration is via DB seed. Dynamic client registration is
+ * intentionally disabled (`allowDynamicClientRegistration: false` in
+ * src/auth/index.ts), so this script is the only way Claude can be registered.
+ *
+ * Implementation note: uses `drizzle-seed` for the insert path so all four
+ * PackRat seeders share one tool surface. drizzle-seed has no native upsert,
+ * so an explicit existence check before `seed()` keeps re-runs idempotent
+ * (drizzle-seed's `reset()` truncates and would break user packs that
+ * reference Featured Pack templates — never the right option for prod
+ * config rows). Every column gets an explicit `f.default()` because
+ * drizzle-seed generates random values for any column not specified in
+ * `.refine()` — for fixed config rows you want determinism, not generation.
+ *
+ * Usage:
+ * NEON_DATABASE_URL= bun run packages/api/src/db/seed-claude-oauth-client.ts
+ *
+ * Or via the package script (also wired into CI's post-deploy step):
+ * cd packages/api && bun run db:seed:oauth-clients
+ *
+ * Operator runs this ONCE per environment (prod, dev) after deploying the API
+ * with the oauthProvider plugin enabled. Re-runs are safe (no-op).
+ */
+
+import { neon, neonConfig } from '@neondatabase/serverless';
+import * as schema from '@packrat/db/schema';
+import { nodeEnv } from '@packrat/env/node';
+import { eq } from 'drizzle-orm';
+import { drizzle, type NeonHttpDatabase } from 'drizzle-orm/neon-http';
+import { drizzle as drizzlePg, type NodePgDatabase } from 'drizzle-orm/node-postgres';
+import { seed } from 'drizzle-seed';
+import { Client } from 'pg';
+import WebSocket from 'ws';
+
+neonConfig.webSocketConstructor = WebSocket;
+
+const isStandardPostgresUrl = (url: string) => {
+ try {
+ const u = new URL(url);
+ const host = u.hostname.toLowerCase();
+ const isNeonTech = host === 'neon.tech' || host.endsWith('.neon.tech');
+ const isNeonCom = host === 'neon.com' || host.endsWith('.neon.com');
+ return u.protocol === 'postgres:' && !isNeonTech && !isNeonCom;
+ } catch {
+ return false;
+ }
+};
+
+// ── Configuration ───────────────────────────────────────────────────────────
+//
+// The Claude connector callback URLs. Both `claude.ai` and `claude.com`
+// origins are supported — `claude.com` is the new canonical domain, `claude.ai`
+// is the legacy origin still in use. Allowlisting both is intentional and
+// matches what Anthropic's connector troubleshooting docs recommend.
+const CLAUDE_REDIRECT_URIS = [
+ 'https://claude.ai/api/mcp/auth_callback',
+ 'https://claude.com/api/mcp/auth_callback',
+];
+
+// Deterministic client_id so re-runs are idempotent. Standard OAuth practice
+// would be `generateRandomString(32, "a-z", "A-Z")`; we override to keep this
+// script repeatable. The id is opaque to Claude — it's sent in
+// /oauth2/authorize and validated against this row's `clientId`.
+const CLAUDE_CLIENT_ID = 'packrat-claude-mcp';
+
+// Public client — Claude is a native/browser client that can't safely hold a
+// shared secret. token_endpoint_auth_method=none requires PKCE on every
+// /oauth2/token exchange (RFC 7636 + OAuth 2.1).
+const CLAUDE_CLIENT_NAME = 'Claude';
+
+// Client metadata URIs — surfaced on the consent screen
+// (packages/api/src/auth/consent-page.tsx reads `name`, `icon`, `tos`,
+// `policy`, `uri` from the row). Users see these mid-OAuth-flow.
+const CLAUDE_LOGO_URI = 'https://packratai.com/mcp-logo-256.png';
+const CLAUDE_POLICY_URI = 'https://www.anthropic.com/legal/privacy';
+const CLAUDE_TOS_URI = 'https://www.anthropic.com/legal/consumer-terms';
+const CLAUDE_CLIENT_URI = 'https://claude.ai';
+
+const CLAUDE_SCOPES = ['openid', 'profile', 'email', 'offline_access', 'mcp:read', 'mcp:write'];
+
+// ── Script body ─────────────────────────────────────────────────────────────
+
+async function seedClaudeOAuthClient(): Promise {
+ const dbUrl = nodeEnv.NEON_DATABASE_URL;
+ if (!dbUrl) throw new Error('NEON_DATABASE_URL is required');
+
+ type SeedDatabase = NodePgDatabase | NeonHttpDatabase;
+ let db: SeedDatabase;
+ let pgClient: Client | undefined;
+
+ if (isStandardPostgresUrl(dbUrl)) {
+ pgClient = new Client({ connectionString: dbUrl });
+ await pgClient.connect();
+ db = drizzlePg(pgClient, { schema });
+ } else {
+ db = drizzle(neon(dbUrl), { schema });
+ }
+
+ try {
+ // Idempotency check: drizzle-seed has no native upsert, so we gate the
+ // seed() call on an explicit existence query keyed on the deterministic
+ // `clientId`. Re-runs short-circuit cleanly without touching the DB.
+ const existing = await db
+ .select({ clientId: schema.oauthClient.clientId, name: schema.oauthClient.name })
+ .from(schema.oauthClient)
+ .where(eq(schema.oauthClient.clientId, CLAUDE_CLIENT_ID))
+ .limit(1);
+
+ if (existing.length > 0) {
+ console.log(
+ `[seed] OAuth client "${CLAUDE_CLIENT_ID}" already exists (name="${existing[0]?.name ?? ''}"). Skipping.`,
+ );
+ return;
+ }
+
+ const id = crypto.randomUUID();
+ const now = new Date();
+
+ // Every column is fixed via f.default() so drizzle-seed's per-column
+ // random generator doesn't fire (the default behaviour for columns not
+ // listed in .refine() is to generate a random value — wrong for a
+ // deterministic config row).
+ await seed(db, { oauthClient: schema.oauthClient }).refine((f) => ({
+ oauthClient: {
+ count: 1,
+ columns: {
+ id: f.default({ defaultValue: id }),
+ clientId: f.default({ defaultValue: CLAUDE_CLIENT_ID }),
+ clientSecret: f.default({ defaultValue: null }),
+ name: f.default({ defaultValue: CLAUDE_CLIENT_NAME }),
+ icon: f.default({ defaultValue: CLAUDE_LOGO_URI }),
+ policy: f.default({ defaultValue: CLAUDE_POLICY_URI }),
+ tos: f.default({ defaultValue: CLAUDE_TOS_URI }),
+ uri: f.default({ defaultValue: CLAUDE_CLIENT_URI }),
+ redirectUris: f.default({ defaultValue: CLAUDE_REDIRECT_URIS }),
+ grantTypes: f.default({ defaultValue: ['authorization_code', 'refresh_token'] }),
+ responseTypes: f.default({ defaultValue: ['code'] }),
+ tokenEndpointAuthMethod: f.default({ defaultValue: 'none' }),
+ scopes: f.default({ defaultValue: CLAUDE_SCOPES }),
+ type: f.default({ defaultValue: 'web' }),
+ public: f.default({ defaultValue: true }),
+ requirePKCE: f.default({ defaultValue: true }),
+ disabled: f.default({ defaultValue: false }),
+ skipConsent: f.default({ defaultValue: false }),
+ createdAt: f.default({ defaultValue: now }),
+ updatedAt: f.default({ defaultValue: now }),
+ },
+ },
+ }));
+
+ console.log(`[seed] Registered OAuth client "${CLAUDE_CLIENT_ID}":`);
+ console.log(` name = ${CLAUDE_CLIENT_NAME}`);
+ console.log(` redirect_uris = ${JSON.stringify(CLAUDE_REDIRECT_URIS)}`);
+ console.log(` token_endpoint_auth_method = none (public client, PKCE required)`);
+ console.log(` scopes = ${CLAUDE_SCOPES.join(' ')}`);
+ } finally {
+ await pgClient?.end();
+ }
+}
+
+seedClaudeOAuthClient().catch((err) => {
+ console.error('[seed] Failed:', err);
+ process.exit(1);
+});
diff --git a/packages/api/src/db/seed-dev.ts b/packages/api/src/db/seed-dev.ts
new file mode 100644
index 0000000000..2921cafe9a
--- /dev/null
+++ b/packages/api/src/db/seed-dev.ts
@@ -0,0 +1,403 @@
+/**
+ * Dev DB seeder — realistic fake data for local development + QA.
+ *
+ * Run:
+ * cd packages/api
+ * NEON_DATABASE_URL=postgres://test_user:test_password@localhost:5432/packrat_test \
+ * bun run db:seed:dev
+ *
+ * Use case: new devs hitting a fresh DB, QA wanting realistic pagination /
+ * empty-vs-populated state, perf-at-scale smoke. Uses `drizzle-seed`'s
+ * reproducible-randomness via a fixed numeric seed so re-runs produce the
+ * same data; pair with `reset()` if you want a clean re-seed.
+ *
+ * NOT for production. The script HARD-refuses to run against a Neon-hosted
+ * URL (no override flag) — drizzle-seed expects to TRUNCATE tables and a
+ * stray prod run would wipe real user data. The 3 prod-config
+ * seeds (`seed.ts`, `seed-e2e-user.ts`, `seed-claude-oauth-client.ts`) are
+ * the correct path for production-row management — they use plain
+ * `db.insert()` with idempotency checks, not drizzle-seed.
+ *
+ * Tables seeded:
+ * - users (50)
+ * - packs (each user gets 2-5)
+ * - packItems (each pack gets 8-20)
+ * - catalogItems (100, independent)
+ * - posts (each user gets 0-3)
+ * - postComments (each post gets 0-5)
+ *
+ * Tables explicitly NOT seeded:
+ * - session/account/verification/jwks — Better Auth manages these; faking
+ * them would create unusable sessions (no real auth credentials)
+ * - oauth* — handled by `seed-claude-oauth-client.ts` (deterministic config)
+ * - packTemplates/packTemplateItems — handled by `seed.ts` (Featured Packs)
+ * - postLikes/commentLikes — unique (postId,userId) constraint is hard to
+ * satisfy with random nested generation; revisit if needed
+ * - trips/trailConditionReports — depend on OSM data not present locally
+ * - reportedContent/invalidItemLogs/etlJobs — rare admin paths
+ */
+
+import { neon, neonConfig } from '@neondatabase/serverless';
+import * as schema from '@packrat/db/schema';
+import { nodeEnv } from '@packrat/env/node';
+import { drizzle, type NeonHttpDatabase } from 'drizzle-orm/neon-http';
+import { drizzle as drizzlePg, type NodePgDatabase } from 'drizzle-orm/node-postgres';
+import { seed } from 'drizzle-seed';
+import { Client } from 'pg';
+import WebSocket from 'ws';
+
+neonConfig.webSocketConstructor = WebSocket;
+
+// Fixed numeric seed → reproducible randomness across runs.
+const SEED = 42;
+
+// ── Outdoor-domain word lists for realistic content ──────────────────────
+
+const PACK_NAME_REGIONS = [
+ 'Yosemite',
+ 'Patagonia',
+ 'PCT Section',
+ 'Alps Traverse',
+ 'Glacier NP',
+ 'Zion Narrows',
+ 'Joshua Tree',
+ 'Acadia Loop',
+ 'Olympic Coast',
+ 'Big Sur',
+ 'Sawtooth',
+ 'Wind River',
+ 'High Sierra',
+ 'White Mountains',
+ 'Cascades',
+];
+const PACK_NAME_FORMS = [
+ '3-day',
+ 'Weekend',
+ 'Thru-Hike',
+ 'Day Trip',
+ 'Overnight',
+ 'Winter Edition',
+ 'Summer Loop',
+ 'Spring Trek',
+ 'Solo',
+ 'With Kids',
+ 'Ultralight',
+ 'Fastpack',
+];
+
+const ITEM_NAMES = [
+ 'Backpack',
+ 'Tent',
+ 'Sleeping Bag',
+ 'Sleeping Pad',
+ 'Headlamp',
+ 'Stove',
+ 'Water Filter',
+ 'Trekking Poles',
+ 'Rain Jacket',
+ 'Down Jacket',
+ 'Base Layer Top',
+ 'Base Layer Bottom',
+ 'Hiking Boots',
+ 'Trail Runners',
+ 'Camp Shoes',
+ 'First Aid Kit',
+ 'Map',
+ 'Compass',
+ 'Whistle',
+ 'Multi-tool',
+ 'Pocket Knife',
+ 'Cooking Pot',
+ 'Spork',
+ 'Insulated Mug',
+ 'Water Bottle',
+ 'Hydration Bladder',
+ 'Sunscreen',
+ 'Bug Spray',
+ 'Toilet Paper',
+ 'Trowel',
+ 'Bear Canister',
+ 'Camera',
+ 'Power Bank',
+ 'Trail Mix',
+ 'Energy Bars',
+ 'Dehydrated Meal',
+ 'Beanie',
+ 'Sun Hat',
+ 'Gloves',
+ 'Buff',
+];
+
+const BRANDS = [
+ 'REI Co-op',
+ 'Patagonia',
+ 'The North Face',
+ "Arc'teryx",
+ 'Black Diamond',
+ 'MSR',
+ 'Big Agnes',
+ 'Therm-a-Rest',
+ 'Osprey',
+ 'Gregory',
+ 'Salomon',
+ 'Merrell',
+ 'Smartwool',
+ 'Darn Tough',
+ 'Sea to Summit',
+ 'Petzl',
+ 'Garmin',
+ 'Hyperlite',
+ 'Zpacks',
+ 'Six Moon Designs',
+];
+
+const ITEM_CATEGORIES = [
+ 'clothing',
+ 'shelter',
+ 'sleep',
+ 'kitchen',
+ 'water',
+ 'electronics',
+ 'first-aid',
+ 'navigation',
+ 'tools',
+ 'consumables',
+ 'miscellaneous',
+] as const;
+
+const PACK_CATEGORIES = [
+ 'hiking',
+ 'backpacking',
+ 'camping',
+ 'climbing',
+ 'winter',
+ 'desert',
+ 'water sports',
+ 'skiing',
+] as const;
+
+const POST_CAPTIONS = [
+ 'Day 3 of the loop — weather was perfect.',
+ 'Switched to a smaller pack and dropped 8 lbs. Worth it.',
+ 'First night out with the new tent — held up in 30mph gusts.',
+ 'Anyone got beta on the upper traverse?',
+ 'Trip recap: 47 miles, 11k feet, no blisters.',
+ 'New ultralight setup ready for next weekend.',
+ 'Gear shakedown done — about to leave for the trailhead.',
+ 'Wildflowers are out, get up here.',
+ 'Lessons from a Type 2 weekend.',
+ 'My loadout for the upcoming thru-hike.',
+];
+
+// ── Safety guard ────────────────────────────────────────────────────────
+
+// Hosts considered safe for destructive seeding: loopback + common docker
+// service hostnames used in local compose setups. Anything else (including a
+// non-neon managed Postgres URL) is rejected unless explicitly overridden.
+const LOCAL_SEED_HOSTS = new Set([
+ 'localhost',
+ '127.0.0.1',
+ '::1',
+ '[::1]',
+ '0.0.0.0',
+ 'postgres',
+ 'db',
+ 'database',
+ 'pg',
+ 'host.docker.internal',
+]);
+
+function assertNotProduction(dbUrl: string): void {
+ // Explicit operator override for non-local targets (e.g. an ephemeral CI
+ // database). Conservative opt-in only — never on by default.
+ if (nodeEnv.ALLOW_DESTRUCTIVE_SEED === '1') {
+ return;
+ }
+
+ const host = (() => {
+ try {
+ return new URL(dbUrl).hostname.toLowerCase();
+ } catch {
+ return '';
+ }
+ })();
+
+ // Allowlist: only permit known-local hosts. drizzle-seed TRUNCATEs tables
+ // before inserting, so any non-local host could destroy real data — reject
+ // by default rather than blocklisting specific managed providers.
+ if (LOCAL_SEED_HOSTS.has(host)) {
+ return;
+ }
+
+ throw new Error(
+ `Refusing to seed-dev against a non-local database host (${host || 'unparseable URL'}). ` +
+ 'drizzle-seed TRUNCATEs tables before inserting, which would destroy data on a ' +
+ 'production or shared instance. Point at a local/docker Postgres (localhost, 127.0.0.1, ' +
+ 'or a docker service hostname), or set ALLOW_DESTRUCTIVE_SEED=1 to override deliberately.',
+ );
+}
+
+const isStandardPostgresUrl = (url: string) => {
+ try {
+ const u = new URL(url);
+ const host = u.hostname.toLowerCase();
+ const isNeonTech = host === 'neon.tech' || host.endsWith('.neon.tech');
+ const isNeonCom = host === 'neon.com' || host.endsWith('.neon.com');
+ return u.protocol === 'postgres:' && !isNeonTech && !isNeonCom;
+ } catch {
+ return false;
+ }
+};
+
+// ── Script body ─────────────────────────────────────────────────────────
+
+async function seedDev(): Promise {
+ const dbUrl = nodeEnv.NEON_DATABASE_URL;
+ if (!dbUrl) throw new Error('NEON_DATABASE_URL is required');
+
+ assertNotProduction(dbUrl);
+
+ type SeedDatabase = NodePgDatabase | NeonHttpDatabase;
+ let db: SeedDatabase;
+ let pgClient: Client | undefined;
+
+ if (isStandardPostgresUrl(dbUrl)) {
+ pgClient = new Client({ connectionString: dbUrl });
+ await pgClient.connect();
+ db = drizzlePg(pgClient, { schema });
+ } else {
+ db = drizzle(neon(dbUrl), { schema });
+ }
+
+ try {
+ console.log('[seed-dev] Seeding with drizzle-seed (seed=42)...');
+
+ // Scope: just the 6 core tables. We pass a SCHEMA SUBSET to seed() so
+ // drizzle-seed doesn't try to TRUNCATE+populate Better Auth tables,
+ // pgvector index columns, etc.
+ const scoped = {
+ users: schema.users,
+ packs: schema.packs,
+ packItems: schema.packItems,
+ catalogItems: schema.catalogItems,
+ posts: schema.posts,
+ postComments: schema.postComments,
+ };
+
+ await seed(db, scoped, { seed: SEED }).refine((f) => ({
+ users: {
+ count: 50,
+ columns: {
+ id: f.uuid(),
+ email: f.email(),
+ name: f.fullName(),
+ firstName: f.firstName(),
+ lastName: f.lastName(),
+ role: f.valuesFromArray({
+ values: [
+ { weight: 0.95, values: ['USER'] },
+ { weight: 0.05, values: ['ADMIN'] },
+ ],
+ }),
+ emailVerified: f.boolean(),
+ // Avatar/image left as default (text nullable).
+ },
+ },
+
+ packs: {
+ count: 150, // ≈ 3 per user × 50 users
+ columns: {
+ id: f.uuid(),
+ name: f.valuesFromArray({
+ values: PACK_NAME_REGIONS.flatMap((r) => PACK_NAME_FORMS.map((s) => `${r} ${s}`)),
+ }),
+ description: f.loremIpsum({ sentencesCount: 2 }),
+ category: f.valuesFromArray({ values: [...PACK_CATEGORIES] }),
+ isPublic: f.valuesFromArray({
+ values: [
+ { weight: 0.7, values: [true] },
+ { weight: 0.3, values: [false] },
+ ],
+ }),
+ tags: f.default({ defaultValue: [] }),
+ localCreatedAt: f.date({ minDate: '2024-01-01', maxDate: '2026-05-25' }),
+ localUpdatedAt: f.date({ minDate: '2024-01-01', maxDate: '2026-05-25' }),
+ },
+ },
+
+ packItems: {
+ count: 1500, // ≈ 10 per pack × 150 packs
+ columns: {
+ id: f.uuid(),
+ name: f.valuesFromArray({ values: ITEM_NAMES }),
+ description: f.loremIpsum({ sentencesCount: 1 }),
+ weight: f.number({ minValue: 10, maxValue: 2000, precision: 1 }),
+ weightUnit: f.valuesFromArray({ values: ['g', 'oz'] }),
+ quantity: f.int({ minValue: 1, maxValue: 4 }),
+ category: f.valuesFromArray({ values: [...ITEM_CATEGORIES] }),
+ consumable: f.valuesFromArray({
+ values: [
+ { weight: 0.85, values: [false] },
+ { weight: 0.15, values: [true] },
+ ],
+ }),
+ worn: f.valuesFromArray({
+ values: [
+ { weight: 0.8, values: [false] },
+ { weight: 0.2, values: [true] },
+ ],
+ }),
+ // embedding (pgvector) left as default null — drizzle-seed doesn't
+ // know about vector columns and we don't need real embeddings for dev.
+ },
+ },
+
+ catalogItems: {
+ count: 100,
+ columns: {
+ name: f.valuesFromArray({ values: ITEM_NAMES }),
+ productUrl: f.default({ defaultValue: 'https://example.com/product' }),
+ sku: f.uuid(),
+ weight: f.number({ minValue: 10, maxValue: 2000, precision: 1 }),
+ weightUnit: f.valuesFromArray({ values: ['g', 'oz'] }),
+ description: f.loremIpsum({ sentencesCount: 2 }),
+ brand: f.valuesFromArray({ values: BRANDS }),
+ price: f.number({ minValue: 10, maxValue: 800, precision: 2 }),
+ categories: f.default({ defaultValue: ['gear'] }),
+ images: f.default({ defaultValue: [] }),
+ },
+ },
+
+ posts: {
+ count: 80, // ≈ 1.6 per user
+ columns: {
+ caption: f.valuesFromArray({ values: POST_CAPTIONS }),
+ images: f.default({ defaultValue: [] }),
+ },
+ },
+
+ postComments: {
+ count: 200, // ≈ 2.5 per post
+ columns: {
+ content: f.loremIpsum({ sentencesCount: 1 }),
+ // parentCommentId left as default null — no nested-thread modeling here.
+ },
+ },
+ }));
+
+ console.log('[seed-dev] Done. Approximate counts:');
+ console.log(' users: 50');
+ console.log(' packs: 150');
+ console.log(' packItems: 1500');
+ console.log(' catalogItems: 100');
+ console.log(' posts: 80');
+ console.log(' postComments: 200');
+ } finally {
+ await pgClient?.end();
+ }
+}
+
+seedDev().catch((err) => {
+ console.error('[seed-dev] Failed:', err);
+ process.exit(1);
+});
diff --git a/packages/api/src/db/seed-e2e-user.ts b/packages/api/src/db/seed-e2e-user.ts
index 64852c294c..4b288b35ba 100644
--- a/packages/api/src/db/seed-e2e-user.ts
+++ b/packages/api/src/db/seed-e2e-user.ts
@@ -6,7 +6,12 @@
* bun run packages/api/src/db/seed-e2e-user.ts
*
* Re-running is safe: if the user exists, the password hash and
- * `emailVerified=true` flag are refreshed; otherwise the user is created.
+ * `emailVerified=true` flag are refreshed via `db.update` (drizzle-seed
+ * has no UPDATE primitive); otherwise the user is created via the
+ * `drizzle-seed` `.refine()` API so this seeder shares the same tool
+ * surface as the other prod-config seeders. Every column is fixed via
+ * `f.default()` because drizzle-seed generates a random value for any
+ * column not listed in `.refine()`.
*/
import { neon, neonConfig } from '@neondatabase/serverless';
@@ -15,6 +20,7 @@ import { nodeEnv } from '@packrat/env/node';
import { eq } from 'drizzle-orm';
import { drizzle, type NeonHttpDatabase } from 'drizzle-orm/neon-http';
import { drizzle as drizzlePg, type NodePgDatabase } from 'drizzle-orm/node-postgres';
+import { seed } from 'drizzle-seed';
import { Client } from 'pg';
import WebSocket from 'ws';
import { hashPassword } from '../utils/auth';
@@ -33,7 +39,7 @@ const isStandardPostgresUrl = (url: string) => {
}
};
-async function seedE2EUser() {
+async function seedE2EUser(): Promise {
const dbUrl = nodeEnv.NEON_DATABASE_URL;
const email = nodeEnv.E2E_TEST_EMAIL;
const password = nodeEnv.E2E_TEST_PASSWORD;
@@ -68,33 +74,47 @@ async function seedE2EUser() {
let userId = existingUser?.id;
if (existingUser) {
+ // drizzle-seed has no UPDATE primitive; use db.update for the
+ // password-refresh path. Insert path below uses drizzle-seed.
await db
.update(schema.users)
.set({ passwordHash, emailVerified: true, updatedAt: new Date() })
.where(eq(schema.users.id, existingUser.id));
console.log(`E2E user refreshed: ${normalizedEmail} (id=${existingUser.id})`);
} else {
- const [inserted] = await db
- .insert(schema.users)
- .values({
- id: crypto.randomUUID(),
- name: 'E2E Automation',
- email: normalizedEmail,
- passwordHash,
- emailVerified: true,
- firstName: 'E2E',
- lastName: 'Automation',
- role: 'USER',
- })
- .returning();
- userId = inserted?.id;
- console.log(`E2E user created: ${normalizedEmail} (id=${inserted?.id})`);
+ userId = crypto.randomUUID();
+ const now = new Date();
+ await seed(db, { users: schema.users }).refine((f) => ({
+ users: {
+ count: 1,
+ columns: {
+ id: f.default({ defaultValue: userId }),
+ name: f.default({ defaultValue: 'E2E Automation' }),
+ email: f.default({ defaultValue: normalizedEmail }),
+ emailVerified: f.default({ defaultValue: true }),
+ image: f.default({ defaultValue: null }),
+ role: f.default({ defaultValue: 'USER' }),
+ banned: f.default({ defaultValue: false }),
+ banReason: f.default({ defaultValue: null }),
+ banExpires: f.default({ defaultValue: null }),
+ firstName: f.default({ defaultValue: 'E2E' }),
+ lastName: f.default({ defaultValue: 'Automation' }),
+ avatarUrl: f.default({ defaultValue: null }),
+ passwordHash: f.default({ defaultValue: passwordHash }),
+ createdAt: f.default({ defaultValue: now }),
+ updatedAt: f.default({ defaultValue: now }),
+ },
+ },
+ }));
+ console.log(`E2E user created: ${normalizedEmail} (id=${userId})`);
}
if (!userId) throw new Error(`Failed to resolve E2E user id for ${normalizedEmail}`);
// Upsert the credential account row that better-auth looks up during sign-in.
// better-auth sets accountId = user.id for the 'credential' provider.
+ // (drizzle-seed has no upsert; this requires onConflictDoUpdate so we use
+ // db.insert directly here rather than drizzle-seed's refine path.)
await db
.insert(schema.account)
.values({
diff --git a/packages/api/src/db/seed.ts b/packages/api/src/db/seed.ts
index feed0a1b45..5ccb81fafc 100644
--- a/packages/api/src/db/seed.ts
+++ b/packages/api/src/db/seed.ts
@@ -22,6 +22,7 @@ import { nodeEnv } from '@packrat/env/node';
import { and, eq } from 'drizzle-orm';
import { drizzle, type NeonHttpDatabase } from 'drizzle-orm/neon-http';
import { drizzle as drizzlePg, type NodePgDatabase } from 'drizzle-orm/node-postgres';
+import { seed as drizzleSeed } from 'drizzle-seed';
import { Client } from 'pg';
import WebSocket from 'ws';
@@ -1879,59 +1880,108 @@ async function seed() {
let skippedTemplates = 0;
let insertedItems = 0;
+ // Featured Packs use drizzle-seed for the insert mechanism — matching
+ // the seed-claude-oauth-client + seed-e2e-user pattern so all four
+ // PackRat seeders share one tool surface.
+ //
+ // drizzle-seed has no native upsert, so each template is gated on an
+ // explicit existence check (`packTemplates.id`). The whole-table
+ // `reset()` mode is destructive — it would TRUNCATE pack_templates +
+ // cascade-break user packs referencing these templates via FK. The
+ // per-template existence check preserves the original script's
+ // partial-resume behaviour (3-of-6 already populated → only inserts
+ // the missing 3).
+ //
+ // Every column is fixed via f.default() / f.valuesFromArray() so
+ // drizzle-seed doesn't fire its random per-column generators for
+ // anything we left unspecified.
for (const templateDef of FEATURED_TEMPLATES) {
- // Check if this featured template already exists (idempotent seed)
- const existing = await seedDb.query.packTemplates.findFirst({
- where: and(
- eq(schema.packTemplates.id, templateDef.id),
- eq(schema.packTemplates.deleted, false),
- ),
- });
+ const items = templateDef.items;
- if (existing) {
- console.log(` ↳ Skipping "${templateDef.name}" (already exists)`);
- skippedTemplates++;
- continue;
- }
+ // Wrap the existence check + both inserts in a single transaction so a
+ // crash between the template insert and its items insert rolls the
+ // template row back. Without this, a half-written template would be
+ // skipped by the existence check on rerun, breaking idempotent resume.
+ const skipped = await seedDb.transaction(async (tx) => {
+ const existing = await tx.query.packTemplates.findFirst({
+ where: and(
+ eq(schema.packTemplates.id, templateDef.id),
+ eq(schema.packTemplates.deleted, false),
+ ),
+ });
- // Insert template
- await seedDb.insert(schema.packTemplates).values({
- id: templateDef.id,
- name: templateDef.name,
- description: templateDef.description,
- category: templateDef.category,
- userId: adminUserId,
- tags: templateDef.tags,
- isAppTemplate: true,
- deleted: false,
- localCreatedAt: now,
- localUpdatedAt: now,
- });
+ if (existing) {
+ console.log(` ↳ Skipping "${templateDef.name}" (already exists)`);
+ return true;
+ }
- console.log(` ✓ Inserted template: "${templateDef.name}"`);
+ // Template — one row with every column fixed to literal values.
+ await drizzleSeed(tx, { packTemplates: schema.packTemplates }).refine((f) => ({
+ packTemplates: {
+ count: 1,
+ columns: {
+ id: f.default({ defaultValue: templateDef.id }),
+ name: f.default({ defaultValue: templateDef.name }),
+ description: f.default({ defaultValue: templateDef.description }),
+ category: f.default({ defaultValue: templateDef.category }),
+ userId: f.default({ defaultValue: adminUserId }),
+ image: f.default({ defaultValue: null }),
+ tags: f.default({ defaultValue: templateDef.tags }),
+ isAppTemplate: f.default({ defaultValue: true }),
+ deleted: f.default({ defaultValue: false }),
+ contentSource: f.default({ defaultValue: null }),
+ contentId: f.default({ defaultValue: null }),
+ localCreatedAt: f.default({ defaultValue: now }),
+ localUpdatedAt: f.default({ defaultValue: now }),
+ createdAt: f.default({ defaultValue: now }),
+ updatedAt: f.default({ defaultValue: now }),
+ },
+ },
+ }));
- // Insert items
- for (const item of templateDef.items) {
- await seedDb.insert(schema.packTemplateItems).values({
- id: item.id,
- name: item.name,
- description: item.description,
- weight: item.weight,
- weightUnit: item.weightUnit,
- quantity: item.quantity,
- category: item.category,
- consumable: item.consumable,
- worn: item.worn,
- notes: item.notes,
- packTemplateId: templateDef.id,
- userId: adminUserId,
- deleted: false,
- });
- insertedItems++;
- }
+ console.log(` ✓ Inserted template: "${templateDef.name}"`);
+
+ // Items — N rows, each column cycled via valuesFromArray over the
+ // template's items[]. drizzle-seed iterates row-by-row, taking the
+ // i-th value from each column's values array, so the columns stay
+ // aligned per item.
+ await drizzleSeed(tx, { packTemplateItems: schema.packTemplateItems }).refine((f) => ({
+ packTemplateItems: {
+ count: items.length,
+ columns: {
+ id: f.valuesFromArray({ values: items.map((i) => i.id) }),
+ name: f.valuesFromArray({ values: items.map((i) => i.name) }),
+ description: f.valuesFromArray({
+ values: items.map((i) => i.description ?? undefined),
+ }),
+ weight: f.valuesFromArray({ values: items.map((i) => i.weight) }),
+ weightUnit: f.valuesFromArray({ values: items.map((i) => i.weightUnit) }),
+ quantity: f.valuesFromArray({ values: items.map((i) => i.quantity) }),
+ category: f.valuesFromArray({ values: items.map((i) => i.category ?? null) }),
+ consumable: f.valuesFromArray({ values: items.map((i) => i.consumable) }),
+ worn: f.valuesFromArray({ values: items.map((i) => i.worn) }),
+ image: f.default({ defaultValue: null }),
+ notes: f.valuesFromArray({ values: items.map((i) => i.notes ?? undefined) }),
+ packTemplateId: f.default({ defaultValue: templateDef.id }),
+ catalogItemId: f.default({ defaultValue: null }),
+ userId: f.default({ defaultValue: adminUserId }),
+ deleted: f.default({ defaultValue: false }),
+ createdAt: f.default({ defaultValue: now }),
+ updatedAt: f.default({ defaultValue: now }),
+ },
+ },
+ }));
+
+ console.log(` ↳ Inserted ${items.length} items`);
+ return false;
+ });
- console.log(` ↳ Inserted ${templateDef.items.length} items`);
- insertedTemplates++;
+ if (skipped) {
+ skippedTemplates++;
+ } else {
+ insertedItems += items.length;
+ insertedTemplates++;
+ }
}
console.log('\n✅ Seed complete!');
diff --git a/packages/api/src/e2e-worker.ts b/packages/api/src/e2e-worker.ts
index 6a37c03db0..73259dae73 100644
--- a/packages/api/src/e2e-worker.ts
+++ b/packages/api/src/e2e-worker.ts
@@ -1,5 +1,5 @@
import type { MessageBatch } from '@cloudflare/workers-types';
-import { addCorsHeaders, app, corsPreflightResponse } from '@packrat/api/app';
+import { addCorsHeaders, appBase, corsPreflightResponse } from '@packrat/api/app';
import { getAuth } from '@packrat/api/auth';
import type { Env } from '@packrat/api/utils/env-validation';
import { setWorkerEnv } from '@packrat/api/utils/env-validation';
@@ -26,7 +26,7 @@ export default {
return addCorsHeaders({ request, response: await auth.handler(request) });
}
- return Reflect.apply(app.fetch, app, [request, e, ctx]);
+ return Reflect.apply(appBase.fetch, appBase, [request, e, ctx]);
},
async queue(_batch: MessageBatch): Promise {
diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts
index d0254d4418..18231a6bc3 100644
--- a/packages/api/src/index.ts
+++ b/packages/api/src/index.ts
@@ -6,49 +6,34 @@
* Elysia-native so Eden Treaty gets full end-to-end type safety.
*/
+import {
+ oauthProviderAuthServerMetadata,
+ oauthProviderOpenIdConfigMetadata,
+} from '@better-auth/oauth-provider';
import type { MessageBatch, ScheduledController } from '@cloudflare/workers-types';
-import { cors } from '@elysiajs/cors';
import { neonConfig } from '@neondatabase/serverless';
+import { type App, appBase } from '@packrat/api/app';
import { getAuth } from '@packrat/api/auth';
+import { consentRoute } from '@packrat/api/auth/consent-route';
import { AppContainer } from '@packrat/api/containers';
-import { routes } from '@packrat/api/routes';
import { CatalogService } from '@packrat/api/services';
import { processQueueBatch } from '@packrat/api/services/etl/queue';
import { sweepInvalidItemLogs } from '@packrat/api/services/retention/invalidLogRetention';
import type { Env } from '@packrat/api/utils/env-validation';
import { getEnv, setWorkerEnv } from '@packrat/api/utils/env-validation';
-import { packratOpenApi } from '@packrat/api/utils/openapi';
import {
createQueryMetricsStore,
flushQueryMetrics,
initQueryMetricsStore,
queryMetricsAls,
} from '@packrat/api/utils/queryMetrics';
-import { captureApiException } from '@packrat/api/utils/sentry';
+import { captureApiException, record } from '@packrat/api/utils/sentry';
import { CatalogEtlWorkflow as RawCatalogEtlWorkflow } from '@packrat/api/workflows/catalog-etl-workflow';
import { instrumentWorkflowWithSentry, withSentry } from '@sentry/cloudflare';
-import { Elysia } from 'elysia';
-import { CloudflareAdapter } from 'elysia/adapter/cloudflare-worker';
import type { CatalogETLMessage } from './services/etl/types';
-// Origins allowed to make cross-origin (credentialed) requests to the API.
-const ALLOWED_ORIGIN_PATTERNS = [
- /^https:\/\/(www\.)?packrat\.world$/,
- /^https:\/\/[\w-]+\.packrat\.world$/,
- /^https:\/\/[\w-]+\.packratai\.com$/,
- /^https?:\/\/[\w-]+\.workers\.dev$/,
- /^http:\/\/localhost:\d+$/,
- /^exp:\/\//,
-];
-
-function isAllowedOrigin(origin: string | null): origin is string {
- return !!origin && ALLOWED_ORIGIN_PATTERNS.some((re) => re.test(origin));
-}
+export type { App };
-// Sentry options for both the Worker handlers and the workflow class.
-// Reads SENTRY_DSN + ENVIRONMENT from the validated env. tracesSampleRate
-// defaults to 10% — observable enough for prod debugging without
-// overwhelming the Sentry quota.
function sentryOptions(env: Env) {
return {
dsn: env.SENTRY_DSN,
@@ -58,79 +43,11 @@ function sentryOptions(env: Env) {
};
}
-export const app = new Elysia({ adapter: CloudflareAdapter })
- .use(
- cors({
- // Better Auth uses cookies — credentials must be true and origins must
- // be explicit (not wildcard) so the browser sends cookies cross-origin.
- credentials: true,
- origin: (request) => isAllowedOrigin(request.headers.get('Origin')),
- allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key'],
- methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
- }),
- )
- .use(packratOpenApi)
- .onError(({ error, code, request }) => {
- // Only report unexpected server errors — not user-input or routing errors.
- if (code !== 'VALIDATION' && code !== 'PARSE' && code !== 'NOT_FOUND') {
- captureApiException({
- error: error,
- operation: 'elysia.onError',
- tags: {
- error_code: String(code),
- method: request?.method ?? 'UNKNOWN',
- path: request ? new URL(request.url).pathname : 'UNKNOWN',
- },
- extra: { errorCode: String(code), httpStatus: 500 },
- });
- }
-
- if (code === 'VALIDATION' || code === 'PARSE') {
- return new Response(JSON.stringify({ error: 'Validation failed' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' },
- });
- }
- if (code === 'NOT_FOUND') {
- return new Response(JSON.stringify({ error: 'Not found' }), {
- status: 404,
- headers: { 'Content-Type': 'application/json' },
- });
- }
- return new Response(JSON.stringify({ error: 'Internal server error' }), {
- status: 500,
- headers: { 'Content-Type': 'application/json' },
- });
- })
- .get('/', () => 'PackRat API is running!', {
- detail: { summary: 'Health check', tags: ['Meta'] },
- })
- .get('/health', () => ({ status: 'ok' as const }), {
- detail: { summary: 'Health status', tags: ['Meta'] },
- })
- // Better Auth handles all /api/auth/** requests. Routing it through Elysia
- // (rather than dispatching before Elysia) means the `cors` plugin above
- // applies its credentialed-CORS policy and OPTIONS preflight to auth routes
- // too. `auth` is resolved per-request because it depends on the Cloudflare
- // env bindings, which are only available at request time.
- .all(
- '/api/auth/*',
- async ({ request }) => {
- const auth = await getAuth(getEnv());
- return auth.handler(request);
- },
- { parse: 'none', detail: { hide: true } },
- )
- .use(routes)
- .compile();
-
-export type App = typeof app;
+// Runtime instance: same routes as `App` plus the branded OAuth consent page.
+export const app = appBase.use(consentRoute).compile();
export { AppContainer };
-// Wrap the workflow class with Sentry instrumentation so each step.do span
-// + any uncaught throw inside a step lands in Sentry with workflow/instance
-// context attached automatically.
export const CatalogEtlWorkflow = instrumentWorkflowWithSentry(
sentryOptions,
RawCatalogEtlWorkflow,
@@ -149,13 +66,6 @@ function enrichEnv(env: Env): Env {
return env;
}
-// Local-dev hook: route `@neondatabase/serverless` through Neon's official local
-// proxy (`ghcr.io/timowilhelm/local-neon-http-proxy`, see docker-compose.test.yml
-// and https://neon.com/guides/local-development-with-neon) when NEON_DATABASE_URL
-// points at `db.localtest.me`. The proxy serves the HTTP /sql API (neon-http,
-// used by auth) and the WebSocket /v2 endpoint (neon-serverless Pool), so local
-// and prod share the exact same driver path — no node-postgres TCP sockets
-// (which workerd silently drops between requests).
let neonLocalConfigured = false;
function maybeConfigureLocalNeon(databaseUrl: string | undefined): void {
if (neonLocalConfigured || !databaseUrl) return;
@@ -168,13 +78,40 @@ function maybeConfigureLocalNeon(databaseUrl: string | undefined): void {
neonConfig.wsProxy = (h) => (h === 'db.localtest.me' ? `${h}:${proxyPort}/v2` : `${h}/v2`);
neonConfig.useSecureWebSocket = false;
} catch {
- // not a valid URL — leave neon defaults in place
+ // not a valid URL - leave neon defaults in place
} finally {
neonLocalConfigured = true;
}
}
-const handler: ExportedHandler = {
+function flushFetchMetrics({ ctx, response }: { ctx: ExecutionContext; response: Response }): void {
+ const metricsStore = queryMetricsAls.getStore();
+ if (!metricsStore) return;
+
+ metricsStore.totalDurationMs = Date.now() - metricsStore.startTimeMs;
+ const contentLength = response.headers.get('content-length');
+ if (contentLength !== null) {
+ metricsStore.estimatedEgressBytes = Number(contentLength);
+ ctx.waitUntil(flushQueryMetrics({ store: metricsStore, statusCode: response.status }));
+ return;
+ }
+
+ const ct = response.headers.get('content-type') ?? '';
+ if (ct.startsWith('application/json') || ct.startsWith('text/')) {
+ const clone = response.clone();
+ ctx.waitUntil(
+ clone.arrayBuffer().then((buf) => {
+ metricsStore.estimatedEgressBytes = buf.byteLength;
+ return flushQueryMetrics({ store: metricsStore, statusCode: response.status });
+ }),
+ );
+ return;
+ }
+
+ ctx.waitUntil(flushQueryMetrics({ store: metricsStore, statusCode: response.status }));
+}
+
+const workerHandler = {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise {
const e = enrichEnv(env);
maybeConfigureLocalNeon(e.NEON_DATABASE_URL);
@@ -182,29 +119,35 @@ const handler: ExportedHandler = {
const metricsStore = initQueryMetricsStore(request);
return queryMetricsAls.run(metricsStore, async () => {
- const response = await (app.fetch as unknown as CfFetchFn)(request, e, ctx); // safe-cast: Elysia's fetch has Cloudflare-specific env/ctx params not in the standard type
- metricsStore.totalDurationMs = Date.now() - metricsStore.startTimeMs;
- // Use Content-Length when available; fall back to cloning only for JSON/text
- // responses. Skip body buffering for streaming or binary responses to avoid
- // doubling memory usage.
- const contentLength = response.headers.get('content-length');
- if (contentLength !== null) {
- metricsStore.estimatedEgressBytes = Number(contentLength);
- ctx.waitUntil(flushQueryMetrics({ store: metricsStore, statusCode: response.status }));
- } else {
- const ct = response.headers.get('content-type') ?? '';
- if (ct.startsWith('application/json') || ct.startsWith('text/')) {
- const clone = response.clone();
- ctx.waitUntil(
- clone.arrayBuffer().then((buf) => {
- metricsStore.estimatedEgressBytes = buf.byteLength;
- return flushQueryMetrics({ store: metricsStore, statusCode: response.status });
- }),
- );
- } else {
- ctx.waitUntil(flushQueryMetrics({ store: metricsStore, statusCode: response.status }));
+ const url = new URL(request.url);
+
+ if (request.method === 'GET') {
+ if (
+ url.pathname === '/.well-known/oauth-authorization-server' ||
+ url.pathname === '/.well-known/openid-configuration'
+ ) {
+ const validatedEnv = getEnv();
+ const auth = await getAuth(validatedEnv);
+ const handler =
+ url.pathname === '/.well-known/openid-configuration'
+ ? oauthProviderOpenIdConfigMetadata(auth)
+ : oauthProviderAuthServerMetadata(auth);
+ const response = await handler(request);
+ flushFetchMetrics({ ctx, response });
+ return response;
}
}
+
+ if (url.pathname.startsWith('/api/auth')) {
+ const validatedEnv = getEnv();
+ const auth = await getAuth(validatedEnv);
+ const response = await auth.handler(request);
+ flushFetchMetrics({ ctx, response });
+ return response;
+ }
+
+ const response = await (app.fetch as unknown as CfFetchFn)(request, e, ctx); // safe-cast: Elysia's fetch has Cloudflare-specific env/ctx params not in the standard type
+ flushFetchMetrics({ ctx, response });
return response;
});
},
@@ -231,7 +174,7 @@ const handler: ExportedHandler = {
}
} catch (error) {
captureApiException({
- error: error,
+ error,
operation: 'queue.handler',
tags: { queue_name: batch.queue },
extra: { messageCount: batch.messages.length },
@@ -254,7 +197,12 @@ const handler: ExportedHandler = {
await queryMetricsAls.run(store, async () => {
try {
if (controller.cron === '0 9 * * *') {
- const result = await sweepInvalidItemLogs({ env });
+ const result = await record({
+ operation: 'sweepInvalidItemLogs',
+ tags: { trigger: 'cron' },
+ extra: { cron: controller.cron },
+ fn: async () => sweepInvalidItemLogs({ env }),
+ });
console.log(
`[retention] invalid_item_logs sweep: deleted=${result.deleted} ` +
`iterations=${result.iterations} capped=${result.capped} ` +
@@ -275,9 +223,15 @@ const handler: ExportedHandler = {
}
});
},
-};
+} satisfies ExportedHandler;
-// withSentry wraps the fetch/queue/scheduled handlers to initialize Sentry
-// on first invocation and forward uncaught exceptions to Sentry. The
-// instrumented workflow class is exported separately above.
-export default withSentry(sentryOptions, handler);
+export default withSentry(
+ (env) => ({
+ dsn: env.SENTRY_DSN,
+ environment: env.ENVIRONMENT ?? 'production',
+ tracesSampleRate: env.ENVIRONMENT === 'production' ? 0.1 : 1.0,
+ sendDefaultPii: false,
+ release: env.SENTRY_RELEASE,
+ }),
+ workerHandler,
+);
diff --git a/packages/api/src/middleware/__tests__/cfAccess.test.ts b/packages/api/src/middleware/__tests__/cfAccess.test.ts
index bd74d00402..361003330a 100644
--- a/packages/api/src/middleware/__tests__/cfAccess.test.ts
+++ b/packages/api/src/middleware/__tests__/cfAccess.test.ts
@@ -10,16 +10,13 @@
* trusted keypair, exports the public JWK, and stores a createLocalJWKSet
* keyset in that global. Tests then call verifyCFAccessRequest directly.
*/
-import {
- createLocalJWKSet,
- exportJWK,
- generateKeyPair,
- type JWTPayload,
- type KeyLike,
- SignJWT,
-} from 'jose';
+import { createLocalJWKSet, exportJWK, generateKeyPair, type JWTPayload, SignJWT } from 'jose';
import { beforeAll, describe, expect, it, vi } from 'vitest';
+// jose 6 dropped the `KeyLike` export; derive the key type from what
+// `generateKeyPair` actually returns (a `CryptoKey | KeyObject` union).
+type KeyLike = Awaited>['privateKey'];
+
// ---------------------------------------------------------------------------
// Mock jose before cfAccess.ts is loaded so createRemoteJWKSet is intercepted.
// ---------------------------------------------------------------------------
diff --git a/packages/api/src/routes/admin/analytics/catalog.ts b/packages/api/src/routes/admin/analytics/catalog.ts
index ce0adf4268..ec5d241618 100644
--- a/packages/api/src/routes/admin/analytics/catalog.ts
+++ b/packages/api/src/routes/admin/analytics/catalog.ts
@@ -1,6 +1,7 @@
import { createDb } from '@packrat/api/db';
import { R2BucketService } from '@packrat/api/services/r2-bucket';
import { getEnv } from '@packrat/api/utils/env-validation';
+import { captureApiException } from '@packrat/api/utils/sentry';
import type { CatalogEtlWorkflowParams } from '@packrat/api/workflows/catalog-etl-workflow';
import { type ChunkSpec, chunkCsvForR2 } from '@packrat/api/workflows/shared/chunkCsvForR2';
import { catalogItems, etlJobs, invalidItemLogs } from '@packrat/db';
@@ -167,7 +168,18 @@ async function reingestJob(args: {
return { success: true, newJobId, objectKey, workflowInstanceId };
} catch (error) {
- console.error(`ETL ${mode} error:`, error);
+ captureApiException({
+ error,
+ operation: `admin.analytics.catalog.reingest.${mode}`,
+ tags: { feature: 'catalogAnalytics' },
+ extra: {
+ httpStatus: 500,
+ errorCode: mode === 'retry' ? 'ETL_RETRY_ERROR' : 'ETL_REPAIR_ERROR',
+ originalJobId,
+ mode,
+ force,
+ },
+ });
return {
_statusCode: 500,
error: `Failed to ${mode === 'retry' ? 'retry' : 'repair'} ETL job`,
@@ -748,7 +760,12 @@ export const catalogAnalyticsRoutes = new Elysia({ prefix: '/catalog' })
delta,
};
} catch (error) {
- console.error('ETL reconcile error:', error);
+ captureApiException({
+ error,
+ operation: 'admin.analytics.catalog.reconcile',
+ tags: { feature: 'catalogAnalytics' },
+ extra: { httpStatus: 500, errorCode: 'ETL_RECONCILE_ERROR', jobId: params.jobId },
+ });
return status(500, {
error: 'Failed to reconcile ETL job',
code: 'ETL_RECONCILE_ERROR',
@@ -792,7 +809,7 @@ export const catalogAnalyticsRoutes = new Elysia({ prefix: '/catalog' })
// Single GROUP BY query. catalog_item_etl_jobs is the per-item-per-job
// join; we attribute each catalog item to its most recent ingest source
// via DISTINCT ON. Then aggregate per source.
- const rows = (await db.tag('adminAnalytics.catalogAudit').execute(sql`
+ const auditResult = await db.tag('adminAnalytics.catalogAudit').execute(sql`
WITH latest_per_item AS (
SELECT DISTINCT ON (cie.catalog_item_id)
cie.catalog_item_id,
@@ -843,7 +860,8 @@ export const catalogAnalyticsRoutes = new Elysia({ prefix: '/catalog' })
${sourceFilter ? sql`WHERE lpi.source = ${sourceFilter}` : sql``}
GROUP BY lpi.source, lj.last_id, lj.last_at
ORDER BY lpi.source
- `)) as unknown as Array<{
+ `);
+ const rows = (auditResult.rows ?? auditResult) as Array<{
source: string;
total_items: number;
last_id: string | null;
@@ -937,7 +955,12 @@ export const catalogAnalyticsRoutes = new Elysia({ prefix: '/catalog' })
sources,
};
} catch (error) {
- console.error('Catalog audit error:', error);
+ captureApiException({
+ error,
+ operation: 'admin.analytics.catalog.audit',
+ tags: { feature: 'catalogAnalytics' },
+ extra: { httpStatus: 500, errorCode: 'AUDIT_ERROR', source: query.source ?? null },
+ });
return status(500, { error: 'Failed to generate catalog audit', code: 'AUDIT_ERROR' });
}
},
diff --git a/packages/api/src/routes/admin/index.ts b/packages/api/src/routes/admin/index.ts
index 6a16e48aed..fdbf23bb6b 100644
--- a/packages/api/src/routes/admin/index.ts
+++ b/packages/api/src/routes/admin/index.ts
@@ -1,8 +1,10 @@
import { cors } from '@elysiajs/cors';
+import { getAuth } from '@packrat/api/auth';
import { createDb } from '@packrat/api/db';
import { verifyCFAccessRequest } from '@packrat/api/middleware/cfAccess';
import { timingSafeEqual } from '@packrat/api/utils/auth';
import { getEnv } from '@packrat/api/utils/env-validation';
+import { captureApiException } from '@packrat/api/utils/sentry';
import { catalogItems, packs, users } from '@packrat/db';
import { assertAllDefined, queryBoolean } from '@packrat/guards';
import {
@@ -22,6 +24,13 @@ import { z } from 'zod';
import { analyticsRoutes } from './analytics';
import { adminTrailsRoutes } from './trails';
+/**
+ * Timeout for the Better Auth `getSession` fallback in `adminAuthGuard`.
+ * Keeps degraded Better Auth behaviour bounded: a slow session lookup fails
+ * closed in 5s rather than holding the request open.
+ */
+const BETTER_AUTH_GUARD_TIMEOUT_MS = 5000;
+
const ADMIN_TOKEN_TTL_SECONDS = 3600; // 1 hour
const ADMIN_JWT_ISSUER = 'packrat-api';
const ADMIN_JWT_AUDIENCE = 'packrat-admin';
@@ -58,7 +67,7 @@ function basicAuthGuard(request: Request): { authorized: true } | { authorized:
async function issueAdminJwt(username: string): Promise {
const env = getEnv();
- const secret = new TextEncoder().encode(env.BETTER_AUTH_SECRET);
+ const secret = new TextEncoder().encode(env.PACKRAT_AUTH_SECRET);
return new SignJWT({ role: 'admin' })
.setProtectedHeader({ alg: 'HS256' })
.setSubject(username)
@@ -72,7 +81,7 @@ async function issueAdminJwt(username: string): Promise {
async function verifyAdminJwt(token: string): Promise {
try {
const env = getEnv();
- const secret = new TextEncoder().encode(env.BETTER_AUTH_SECRET);
+ const secret = new TextEncoder().encode(env.PACKRAT_AUTH_SECRET);
const { payload } = await jwtVerify(token, secret, {
issuer: ADMIN_JWT_ISSUER,
audience: ADMIN_JWT_AUDIENCE,
@@ -83,16 +92,101 @@ async function verifyAdminJwt(token: string): Promise {
}
}
-// Protected routes: Bearer JWT is always accepted.
-// When CF Access is configured, CF JWT is also accepted directly (the CF edge
-// injects Cf-Access-Jwt-Assertion on every request, so the user has already
-// passed the CF Access gate). Basic auth is accepted only in local dev.
+/**
+ * Verify a bearer as a Better Auth session whose `user.role === 'ADMIN'`.
+ *
+ * Wraps `auth.api.getSession({ headers })` in a 5s timeout so a degraded
+ * Better Auth fails closed (returns false) rather than hanging the
+ * request indefinitely. Any thrown error or timeout is treated as
+ * "not authorized" — the API can't safely escalate scope on a
+ * partial response.
+ *
+ * The Better Auth `bearer()` plugin extracts the token from the
+ * `Authorization: Bearer ...` header; we pass `request.headers` through
+ * unmodified rather than reconstructing them so the same code path
+ * works for any future cookie-bearing variant Better Auth adds.
+ */
+async function verifyBetterAuthAdmin(request: Request): Promise {
+ const env = getEnv();
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), BETTER_AUTH_GUARD_TIMEOUT_MS);
+ try {
+ const auth = await getAuth(env);
+ // Run the session lookup in a Promise.race against the timeout so a
+ // slow/hanging Neon-backed Better Auth doesn't block the guard.
+ // The AbortController is best-effort; Better Auth's internal HTTP
+ // client may or may not propagate the abort signal.
+ const session = await Promise.race([
+ auth.api.getSession({ headers: request.headers }),
+ new Promise((resolve) => {
+ controller.signal.addEventListener('abort', () => resolve(null), { once: true });
+ }),
+ ]);
+ if (!session || !session.user) return false;
+ const role = (session.user as { role?: string }).role;
+ return role === 'ADMIN';
+ } catch (err) {
+ // Fail closed on any error path — DB outages, transport failures,
+ // malformed bearer, etc. The 401 from `adminAuthGuard` is the
+ // operationally correct response: the caller's bearer didn't
+ // resolve into an authorized session. Capture first so a real
+ // Better Auth/DB outage leaves a Sentry trail instead of looking
+ // identical to a bad bearer.
+ captureApiException({ error: err, operation: 'verifyBetterAuthAdmin' });
+ return false;
+ } finally {
+ clearTimeout(timeoutId);
+ }
+}
+
+/**
+ * Protected-route auth guard.
+ *
+ * Per the U5 resolved D1 decision (per
+ * docs/plans/2026-05-22-001-feat-mcp-connector-store-readiness-plan.md U5),
+ * this guard accepts TWO bearer formats, tried in order:
+ *
+ * 1. The legacy HS256 `packrat-admin` JWT (issued by `/admin/token` or
+ * `/admin/login`). Kept for back-compat with `apps/admin`, which
+ * uses the JWT path.
+ *
+ * 2. A Better Auth session bearer whose `user.role === 'ADMIN'`. This
+ * is the path the MCP Worker uses — admin tools send the same
+ * Better Auth bearer as user tools, and the API gates them by
+ * role rather than a parallel token type.
+ *
+ * If both bearer paths fail, falls through to:
+ *
+ * 3. CF Access JWT (when CF Access is configured).
+ * 4. Basic auth (local dev only).
+ *
+ * All four paths returning false yields a 401 from the caller.
+ *
+ * SECURITY NOTE (U5):
+ * Accepting Better Auth session bearers means a stolen Better Auth
+ * session of an admin user is now ALSO a path to `/admin/*`. This is
+ * intentional: Better Auth session theft of an admin has always been
+ * catastrophic (it grants full PackRat-app admin access via the normal
+ * user surface), and removing the parallel admin JWT mechanism — which
+ * had its own minting + revocation surface to keep in sync — is the
+ * simplification this trade-off buys. Revocation is now a single
+ * problem: invalidate the Better Auth session. There is no second
+ * token type to remember to rotate.
+ */
async function adminAuthGuard(request: Request): Promise {
const env = getEnv();
const { CF_ACCESS_TEAM_DOMAIN, CF_ACCESS_AUD } = env;
const header = request.headers.get('authorization') ?? '';
- if (header.startsWith('Bearer ')) return verifyAdminJwt(header.slice(7));
+ if (header.startsWith('Bearer ')) {
+ // Try the HS256 admin JWT first — fast (in-memory verify) and the
+ // legacy `apps/admin` path. Falling back to Better Auth on failure
+ // means any other Bearer (Better Auth session token) gets the
+ // role check.
+ if (await verifyAdminJwt(header.slice(7))) return true;
+ // U5: bearer wasn't a valid admin JWT — try as Better Auth session.
+ if (await verifyBetterAuthAdmin(request)) return true;
+ }
// When CF Access is configured, verify the CF JWT injected by the CF edge.
if (CF_ACCESS_TEAM_DOMAIN && CF_ACCESS_AUD) {
diff --git a/packages/api/src/routes/catalog/__tests__/instanceId.test.ts b/packages/api/src/routes/catalog/__tests__/instanceId.test.ts
index b4f876f2d8..ed46991bdd 100644
--- a/packages/api/src/routes/catalog/__tests__/instanceId.test.ts
+++ b/packages/api/src/routes/catalog/__tests__/instanceId.test.ts
@@ -1,29 +1,24 @@
/**
* Regression tests for CF Workflows instanceId construction.
*
- * CF Workflows only allows [a-zA-Z0-9_-] in instance IDs (max 64 chars).
- * A prior bug let the raw filename (including its ".csv" extension) flow
- * directly into the instanceId, producing dots that CF rejected with a 500.
+ * CF Workflows constrains instance IDs to `^[a-zA-Z0-9_][a-zA-Z0-9-_]*$`
+ * (max 64 chars enforced by CF; we cap at 100). A prior bug let the raw
+ * filename (including its ".csv" extension, spaces, and punctuation) flow
+ * directly into the instanceId, producing chars that CF rejected with a 500.
*
- * The fix (packages/api/src/routes/catalog/index.ts):
- * const FILE_EXT_RE = /\.[^.]*$/;
- * const instanceId = `${source}-${filename.replace(FILE_EXT_RE, '')}`.slice(0, 64);
+ * The fix (packages/api/src/utils/buildInstanceId.ts): the exported
+ * `buildInstanceId` helper strips the extension, replaces disallowed chars
+ * with `-`, collapses/trims `-`, and guarantees a valid leading char.
*/
+import { buildInstanceId } from '@packrat/api/utils/buildInstanceId';
import { describe, expect, it } from 'vitest';
-// Mirror the exact logic from the route so this test breaks if the
-// implementation drifts.
-const FILE_EXT_RE = /\.[^.]*$/;
-
-function buildInstanceId(source: string, filename: string): string {
- return `${source}-${filename.replace(FILE_EXT_RE, '')}`.slice(0, 64);
-}
-
-const CF_INSTANCE_ID_RE = /^[a-zA-Z0-9_-]{1,64}$/;
+// CF Workflows instance-id constraint.
+const CF_INSTANCE_ID_RE = /^[a-zA-Z0-9_][a-zA-Z0-9-_]*$/;
describe('catalog ETL instanceId', () => {
it('basic: strips .csv extension and produces a valid CF instance ID', () => {
- const id = buildInstanceId('cotopaxi', 'cotopaxi_2026-05-14T16-54-05.csv');
+ const id = buildInstanceId('cotopaxi-cotopaxi_2026-05-14T16-54-05.csv');
expect(id).toMatch(CF_INSTANCE_ID_RE);
expect(id).not.toContain('.');
@@ -31,32 +26,66 @@ describe('catalog ETL instanceId', () => {
});
it('no extension in input: still produces a valid CF instance ID', () => {
- const id = buildInstanceId('foo', 'foo_2026-01-01T00-00-00');
+ const id = buildInstanceId('foo-foo_2026-01-01T00-00-00');
expect(id).toMatch(CF_INSTANCE_ID_RE);
expect(id).not.toContain('.');
expect(id).toBe('foo-foo_2026-01-01T00-00-00');
});
- it('long name truncation: result is capped at 64 chars', () => {
- // 20-char source + '-' + 60-char filename (no ext) = 81 chars before slice
- const source = 'a'.repeat(20);
- const filename = `${'b'.repeat(60)}.csv`;
-
- const id = buildInstanceId(source, filename);
+ it('long name truncation: result is capped at 100 chars', () => {
+ const id = buildInstanceId(`${'b'.repeat(150)}.csv`);
- expect(id.length).toBe(64);
+ expect(id.length).toBe(100);
expect(id).toMatch(CF_INSTANCE_ID_RE);
});
it('timestamp format: underscores and hyphens pass through as valid chars', () => {
- // Typical scraper filename pattern uses underscores and ISO-8601 hyphens
- const id = buildInstanceId('rei', 'rei_catalog_2026-05-14T16-54-05.csv');
+ const id = buildInstanceId('rei-rei_catalog_2026-05-14T16-54-05.csv');
expect(id).toMatch(CF_INSTANCE_ID_RE);
expect(id).not.toContain('.');
- // Both _ and - must survive the strip
expect(id).toContain('_');
expect(id).toContain('-');
});
+
+ it('spaces and punctuation: replaced with hyphens and collapsed', () => {
+ const id = buildInstanceId('rei - cool catalog (final).csv');
+
+ expect(id).toMatch(CF_INSTANCE_ID_RE);
+ expect(id).not.toContain(' ');
+ expect(id).not.toContain('(');
+ expect(id).not.toContain(')');
+ // No doubled hyphens from collapsing runs of disallowed chars.
+ expect(id).not.toContain('--');
+ expect(id).toBe('rei-cool-catalog-final');
+ });
+
+ it('leading dot / hidden file: result starts with a valid char', () => {
+ const id = buildInstanceId('.hidden.csv');
+
+ expect(id).toMatch(CF_INSTANCE_ID_RE);
+ expect(id[0]).toMatch(/[A-Za-z0-9_]/);
+ });
+
+ it('leading non-alphanumeric: prefixed so first char is valid', () => {
+ const id = buildInstanceId('-_-weird-name.csv');
+
+ expect(id).toMatch(CF_INSTANCE_ID_RE);
+ expect(id[0]).toMatch(/[A-Za-z0-9_]/);
+ });
+
+ it('all-punctuation input: still yields a non-empty valid ID', () => {
+ const id = buildInstanceId('!!!.csv');
+
+ expect(id.length).toBeGreaterThan(0);
+ expect(id).toMatch(CF_INSTANCE_ID_RE);
+ });
+
+ it('over-long with punctuation: sanitized then capped at 100 chars', () => {
+ const id = buildInstanceId(`${'a b!'.repeat(60)}.csv`);
+
+ expect(id.length).toBeLessThanOrEqual(100);
+ expect(id).toMatch(CF_INSTANCE_ID_RE);
+ });
});
diff --git a/packages/api/src/routes/catalog/index.ts b/packages/api/src/routes/catalog/index.ts
index 42297077c4..f6c164fdc5 100644
--- a/packages/api/src/routes/catalog/index.ts
+++ b/packages/api/src/routes/catalog/index.ts
@@ -4,6 +4,7 @@ import { CatalogService } from '@packrat/api/services';
import { generateEmbedding } from '@packrat/api/services/embeddingService';
import { queueCatalogETL } from '@packrat/api/services/etl/queue';
import { R2BucketService } from '@packrat/api/services/r2-bucket';
+import { buildInstanceId } from '@packrat/api/utils/buildInstanceId';
import { getEmbeddingText } from '@packrat/api/utils/embeddingHelper';
import { getEnv } from '@packrat/api/utils/env-validation';
import type { CatalogEtlWorkflowParams } from '@packrat/api/workflows/catalog-etl-workflow';
@@ -37,8 +38,6 @@ import {
import { Elysia, NotFoundError, status } from 'elysia';
import { z } from 'zod';
-const FILE_EXT_RE = /\.[^.]*$/;
-
export const catalogRoutes = new Elysia({ prefix: '/catalog' })
.use(authPlugin)
.use(apiKeyAuthPlugin)
@@ -346,8 +345,10 @@ export const catalogRoutes = new Elysia({ prefix: '/catalog' })
chunksTotal: totalChunks,
}));
- // CF Workflows instance IDs only allow [a-zA-Z0-9_-] — strip the file extension.
- const instanceId = `${source}-${filename.replace(FILE_EXT_RE, '')}`.slice(0, 64);
+ // CF Workflows instance IDs must match ^[a-zA-Z0-9_][a-zA-Z0-9-_]*$ — the
+ // freeform filename is sanitized (extension stripped, disallowed chars
+ // replaced, leading char guaranteed valid) before it's combined with source.
+ const instanceId = buildInstanceId(`${source}-${filename}`);
await db.tag('catalog.etlCreateJob').insert(etlJobs).values({
id: jobId,
diff --git a/packages/api/src/services/etl/CatalogItemValidator.ts b/packages/api/src/services/etl/CatalogItemValidator.ts
index 11af59f9d1..b3b178063d 100644
--- a/packages/api/src/services/etl/CatalogItemValidator.ts
+++ b/packages/api/src/services/etl/CatalogItemValidator.ts
@@ -25,6 +25,58 @@ const SKU_MAX_LENGTH = 200;
const SKU_PATTERN = /^[A-Za-z0-9_./-]+$/;
const IPV6_BRACKET_PATTERN = /^\[(.+)\]$/;
+// IPv4-mapped IPv6 prefix, e.g. `::ffff:127.0.0.1` or its normalized hex form
+// `::ffff:7f00:1`, and the `::ffff:0:…` variant. `URL.hostname` collapses the
+// dotted tail into two hex groups, so we must accept both textual and hex tails.
+// Matches the prefix and captures whatever follows it (one or two hex groups, or
+// a dotted-quad), case-insensitively.
+const IPV4_MAPPED_IPV6_PATTERN = /^::ffff:(?:0:)?([0-9a-f.:]+)$/i;
+// Hoisted to top level (lint/performance/useTopLevelRegex) — used per-octet/group
+// inside extractMappedIpv4's hot path.
+const IPV4_OCTET_PATTERN = /^\d{1,3}$/;
+const IPV6_HEX_GROUP_PATTERN = /^[0-9a-f]{1,4}$/i;
+
+/**
+ * If `hostname` is an IPv4-mapped IPv6 address (`::ffff:…` / `::ffff:0:…`, in
+ * either dotted `::ffff:127.0.0.1` or hex `::ffff:7f00:1` form), returns the
+ * embedded dotted-quad IPv4 string (e.g. `127.0.0.1`). Otherwise returns null.
+ *
+ * This lets the existing IPv4 private/loopback/link-local/CGNAT ranges be
+ * re-applied to addresses that would otherwise slip through as opaque IPv6 hex.
+ */
+function extractMappedIpv4(hostname: string): string | null {
+ const match = IPV4_MAPPED_IPV6_PATTERN.exec(hostname);
+ const tail = match?.[1];
+ if (tail === undefined) return null;
+
+ // Already a dotted quad (e.g. `::ffff:127.0.0.1`).
+ if (tail.includes('.')) {
+ const octets = tail.split('.');
+ if (octets.length !== 4) return null;
+ if (octets.some((o) => o === '' || !IPV4_OCTET_PATTERN.test(o) || Number(o) > 255)) return null;
+ return octets.join('.');
+ }
+
+ // Hex form: one or two 16-bit groups (e.g. `7f00:1` → 127.0.0.1, or `1` → 0.0.0.1).
+ const groups = tail.split(':');
+ if (groups.length > 2 || groups.some((g) => g === '' || !IPV6_HEX_GROUP_PATTERN.test(g))) {
+ return null;
+ }
+ // Combine into a single 32-bit value: high group is the upper 16 bits. The
+ // guard above guarantees every group is a non-empty hex string; the explicit
+ // undefined checks satisfy noUncheckedIndexedAccess without a non-null assert.
+ const highStr = groups.length === 2 ? groups[0] : '0';
+ const lowStr = groups[groups.length - 1];
+ if (highStr === undefined || lowStr === undefined) return null;
+ const high = Number.parseInt(highStr, 16);
+ const low = Number.parseInt(lowStr, 16);
+ if (Number.isNaN(high) || Number.isNaN(low) || high > 0xffff || low > 0xffff) return null;
+ const value = (high << 16) | low;
+ return [(value >>> 24) & 0xff, (value >>> 16) & 0xff, (value >>> 8) & 0xff, value & 0xff].join(
+ '.',
+ );
+}
+
export class CatalogItemValidator {
validateItem(item: Partial): ValidatedCatalogItem {
const errors: ValidationError[] = [];
@@ -164,6 +216,15 @@ export class CatalogItemValidator {
return 'Product URL hostname must not be a private/loopback/link-local address';
}
+ // IPv4-mapped IPv6 (`::ffff:127.0.0.1`) normalizes to hex (`::ffff:7f00:1`)
+ // in URL.hostname, matching neither the IPv4 nor the IPv6 branches above.
+ // Extract the embedded IPv4 and re-test it so mapped forms can't bypass the
+ // private/loopback/link-local/CGNAT ranges.
+ const mappedIpv4 = extractMappedIpv4(hostname);
+ if (mappedIpv4 !== null && PRIVATE_HOSTNAME_PATTERN.test(mappedIpv4)) {
+ return 'Product URL hostname must not be a private/loopback/link-local address';
+ }
+
// Hostnames with non-ASCII characters are IDN homograph candidates.
// Native URL parsing already encodes them to punycode in parsed.hostname,
// so non-ASCII presence here means the hostname survived encoding (rare)
diff --git a/packages/api/src/services/etl/__tests__/CatalogItemValidator.test.ts b/packages/api/src/services/etl/__tests__/CatalogItemValidator.test.ts
index df79a5e776..7b6a18a3f0 100644
--- a/packages/api/src/services/etl/__tests__/CatalogItemValidator.test.ts
+++ b/packages/api/src/services/etl/__tests__/CatalogItemValidator.test.ts
@@ -88,6 +88,36 @@ describe('CatalogItemValidator', () => {
const ok2 = v.validateItem({ ...baseItem, productUrl: 'http://172.32.0.1/x' });
expect(ok2.isValid).toBe(true);
});
+
+ it('rejects IPv4-mapped IPv6 pointing at private/loopback IPv4', () => {
+ // URL.hostname normalizes the dotted tail to hex (e.g. ::ffff:7f00:1),
+ // so the guard must re-derive the embedded IPv4 and re-test it.
+ for (const url of [
+ 'http://[::ffff:127.0.0.1]/x', // dotted loopback
+ 'http://[::ffff:7f00:1]/x', // hex loopback (the normalized form)
+ 'http://[::ffff:10.0.0.1]/x', // dotted RFC-1918
+ 'http://[::ffff:a00:1]/x', // hex RFC-1918
+ 'http://[::ffff:192.168.1.1]/x', // dotted RFC-1918
+ 'http://[::ffff:169.254.169.254]/x', // dotted link-local (cloud metadata)
+ 'http://[::ffff:0:127.0.0.1]/x', // ::ffff:0: variant
+ ]) {
+ const result = v.validateItem({ ...baseItem, productUrl: url });
+ expect(result.isValid, url).toBe(false);
+ expect(reasonsFor('productUrl', result.errors).join(' '), url).toMatch(
+ /private|loopback|link-local/i,
+ );
+ }
+ });
+
+ it('allows IPv4-mapped IPv6 pointing at a public IPv4', () => {
+ const ok = v.validateItem({ ...baseItem, productUrl: 'http://[::ffff:8.8.8.8]/x' });
+ expect(ok.isValid).toBe(true);
+ });
+
+ it('allows a normal public URL', () => {
+ const ok = v.validateItem({ ...baseItem, productUrl: 'https://example.com/product/1' });
+ expect(ok.isValid).toBe(true);
+ });
});
describe('URL length cap', () => {
diff --git a/packages/api/src/services/etl/processLogsBatch.ts b/packages/api/src/services/etl/processLogsBatch.ts
index 9f2f3422d8..ceace7db89 100644
--- a/packages/api/src/services/etl/processLogsBatch.ts
+++ b/packages/api/src/services/etl/processLogsBatch.ts
@@ -1,6 +1,7 @@
import { createDbClient } from '@packrat/api/db';
import type { Env } from '@packrat/api/utils/env-validation';
import { logger } from '@packrat/api/utils/logger';
+import { record } from '@packrat/api/utils/sentry';
import { invalidItemLogs, type NewInvalidItemLog } from '@packrat/db';
import { updateEtlJobProgress } from './updateEtlJobProgress';
@@ -15,27 +16,29 @@ export async function processLogsBatch({
}): Promise {
const db = createDbClient(env);
- try {
- await db.tag('etl.insertInvalidLogs').insert(invalidItemLogs).values(logs);
- await updateEtlJobProgress({
- env,
- params: {
- jobId,
- invalid: logs.length,
- processed: logs.length,
- },
- });
+ await record({
+ operation: 'etl.processLogsBatch',
+ extra: { jobId, count: logs.length },
+ fn: async () => {
+ try {
+ await db.tag('etl.insertInvalidLogs').insert(invalidItemLogs).values(logs);
+ await updateEtlJobProgress({
+ env,
+ params: {
+ jobId,
+ invalid: logs.length,
+ processed: logs.length,
+ },
+ });
- logger.info({ event: 'etl.invalid_logs.persisted', ctx: { jobId, count: logs.length } });
- } catch (error) {
- // Rethrow — invalid_item_logs is the forensic record of what failed
- // validation. Silently swallowing a DB write loss here means an
- // operator chasing a data-quality complaint has no trail. Closes
- // audit P2 #2.
- logger.error({
- event: 'etl.invalid_logs.persist_failed',
- ctx: { jobId, count: logs.length, err: error },
- });
- throw error;
- }
+ logger.info({ event: 'etl.invalid_logs.persisted', ctx: { jobId, count: logs.length } });
+ } catch (error) {
+ logger.error({
+ event: 'etl.invalid_logs.persist_failed',
+ ctx: { jobId, count: logs.length, err: error },
+ });
+ throw error;
+ }
+ },
+ });
}
diff --git a/packages/api/src/services/imageDetectionService.ts b/packages/api/src/services/imageDetectionService.ts
index eb94498f44..7d63cee306 100644
--- a/packages/api/src/services/imageDetectionService.ts
+++ b/packages/api/src/services/imageDetectionService.ts
@@ -17,6 +17,12 @@ When analyzing images of items laid out for packing, identify each visible item
- Provide a brief description that includes key characteristics (material, type, color if relevant)
- Estimate quantity if multiple identical items are visible
+For every item you MUST also emit these fields:
+- quantity: a positive integer count of how many identical units are visible (default to 1 when a single unit is shown)
+- consumable: a boolean — true if the item is used up over a trip (e.g. food, fuel, batteries), otherwise false
+- worn: a boolean — true if the item is typically worn on the body rather than packed (e.g. boots, jacket), otherwise false
+- notes: a short string with any extra context worth recording, or null if there is nothing to add
+
Be thorough but focused on packable outdoor gear and equipment.`;
const detectedItemSchema = z.object({
diff --git a/packages/api/src/services/retention/invalidLogRetention.ts b/packages/api/src/services/retention/invalidLogRetention.ts
index 0a5eca0cd7..50295d4806 100644
--- a/packages/api/src/services/retention/invalidLogRetention.ts
+++ b/packages/api/src/services/retention/invalidLogRetention.ts
@@ -1,18 +1,11 @@
// Bounded-batch DELETE of expired invalid_item_logs.
//
// Each ETL run can produce thousands of invalid_item_logs rows. Left alone
-// the table grows without bound — a single bad scraper upload can be
-// hundreds of MB of jsonb. This sweep is the periodic cleanup.
-//
-// Why batched: a naive `DELETE FROM invalid_item_logs WHERE created_at < ...`
-// on a table that has been accumulating for months would acquire row-level
-// locks on millions of rows in a single statement, hit Neon's statement
-// timeout, and roll back having pruned nothing. The batched loop deletes
-// in 10k-row chunks and bails after a configurable max iteration count so
-// a runaway first-run can't monopolize the daily window.
+// the table grows without bound. This sweep is the periodic cleanup.
import { createDbClient } from '@packrat/api/db';
import type { Env } from '@packrat/api/utils/env-validation';
+import { record } from '@packrat/api/utils/sentry';
import { invalidItemLogs } from '@packrat/db';
import { inArray, lt, sql } from 'drizzle-orm';
@@ -40,7 +33,7 @@ export type RetentionOptions = {
/**
* Delete invalid_item_logs older than the retention window in bounded batches.
*
- * Default retention is 90 days. The default 100-iteration cap × 10k batch
+ * Default retention is 90 days. The default 100-iteration cap x 10k batch
* size = up to 1M rows per run. If the table has more expired rows than
* that on first execution, the function returns `capped: true` and the
* remainder is swept on subsequent runs.
@@ -59,40 +52,44 @@ export async function sweepInvalidItemLogs({
const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;
const maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS;
- const db = createDbClient(env);
+ return record({
+ operation: 'retention.sweepInvalidItemLogs',
+ extra: { retentionDays, batchSize, maxIterations },
+ fn: async () => {
+ const db = createDbClient(env);
- let deleted = 0;
- let iterations = 0;
- let rowCount = 0;
- const cutoff = sql`now() - (${retentionDays}::int * interval '1 day')`;
+ let deleted = 0;
+ let iterations = 0;
+ let rowCount = 0;
+ const cutoff = sql`now() - (${retentionDays}::int * interval '1 day')`;
- for (let i = 0; i < maxIterations; i++) {
- iterations++;
+ for (let i = 0; i < maxIterations; i++) {
+ iterations++;
- const selectExpired = db
- .tag('retention.selectExpiredLogs')
- .select({ id: invalidItemLogs.id })
- .from(invalidItemLogs)
- .where(lt(invalidItemLogs.createdAt, cutoff))
- .limit(batchSize);
+ const selectExpired = db
+ .tag('retention.selectExpiredLogs')
+ .select({ id: invalidItemLogs.id })
+ .from(invalidItemLogs)
+ .where(lt(invalidItemLogs.createdAt, cutoff))
+ .limit(batchSize);
- const removed = await db
- .tag('retention.deleteInvalidLogs')
- .delete(invalidItemLogs)
- .where(inArray(invalidItemLogs.id, selectExpired))
- .returning();
+ const removed = await db
+ .tag('retention.deleteInvalidLogs')
+ .delete(invalidItemLogs)
+ .where(inArray(invalidItemLogs.id, selectExpired))
+ .returning();
- rowCount = removed.length;
- deleted += rowCount;
- if (rowCount === 0) break;
- }
+ rowCount = removed.length;
+ deleted += rowCount;
+ if (rowCount === 0) break;
+ }
- return {
- deleted,
- iterations,
- // capped only when we hit the iteration ceiling with rows still remaining;
- // if the last batch returned 0 rows we exhausted the table (not capped).
- capped: rowCount > 0,
- retentionDays,
- };
+ return {
+ deleted,
+ iterations,
+ capped: rowCount > 0,
+ retentionDays,
+ };
+ },
+ });
}
diff --git a/packages/api/src/services/userService.ts b/packages/api/src/services/userService.ts
index 4783bf609c..626f1feb5c 100644
--- a/packages/api/src/services/userService.ts
+++ b/packages/api/src/services/userService.ts
@@ -6,6 +6,9 @@ import { eq } from 'drizzle-orm';
export type CreateUserInput = {
email: string;
password?: string;
+ /** Better Auth display name. Derived from first/last name (or the email
+ * local-part) when not supplied — the `users.name` column is NOT NULL. */
+ name?: string;
firstName?: string | null;
lastName?: string | null;
role?: 'USER' | 'ADMIN';
@@ -31,19 +34,20 @@ export class UserService {
async create(input: CreateUserInput): Promise {
const passwordHash = input.password ? await hashPassword(input.password) : null;
+ // `users.name` is NOT NULL (Better Auth display name). Prefer an explicit
+ // name, else build one from first/last, else fall back to the email local-part.
+ const name =
+ input.name?.trim() ||
+ [input.firstName, input.lastName].filter(Boolean).join(' ').trim() ||
+ (input.email.split('@')[0] ?? input.email);
- // Better Auth's users schema requires a non-null `name`; derive from first/
- // last, fall back to email. Per-package tsc surfaces this as a missing-field
- // error against the Drizzle insert type — root tsc misses it but Postgres
- // would reject the insert at runtime.
- const fullName = [input.firstName, input.lastName].filter(Boolean).join(' ').trim();
const [user] = await this.db
.tag('user.create')
.insert(users)
.values({
id: crypto.randomUUID(),
email: input.email.toLowerCase(),
- name: fullName || input.email.toLowerCase(),
+ name,
passwordHash,
firstName: input.firstName ?? null,
lastName: input.lastName ?? null,
diff --git a/packages/api/src/utils/__tests__/env-validation.test.ts b/packages/api/src/utils/__tests__/env-validation.test.ts
index 54d2c79f84..0903f11b32 100644
--- a/packages/api/src/utils/__tests__/env-validation.test.ts
+++ b/packages/api/src/utils/__tests__/env-validation.test.ts
@@ -14,8 +14,11 @@ function makeRawEnv(overrides: Record = {}): Record {
(process.env as Record).NODE_ENV = 'production';
const rawEnv = makeRawEnv();
const result = getEnv(rawEnv);
- expect(result.BETTER_AUTH_SECRET).toBe('a-secret-that-is-at-least-32-characters-long!!');
+ expect(result.PACKRAT_AUTH_SECRET).toBe('a-secret-that-is-at-least-32-characters-long!!');
expect(result.ENVIRONMENT).toBe('production');
});
it('uses relaxed validation in test environment', () => {
(process.env as Record).NODE_ENV = 'test';
- const result = getEnv({ BETTER_AUTH_SECRET: 'test-better-auth-secret-32-chars-long!!' });
- expect(result.BETTER_AUTH_SECRET).toBe('test-better-auth-secret-32-chars-long!!');
+ const result = getEnv({ PACKRAT_AUTH_SECRET: 'test-better-auth-secret-32-chars-long!!' });
+ expect(result.PACKRAT_AUTH_SECRET).toBe('test-better-auth-secret-32-chars-long!!');
expect(result.ENVIRONMENT).toBe('development');
expect(result.SENTRY_DSN).toBe('https://test@test.ingest.sentry.io/test');
});
@@ -227,8 +230,73 @@ describe('env-validation', () => {
});
it('throws on missing required variable', () => {
- const invalid = makeRawEnv({ BETTER_AUTH_SECRET: undefined });
+ const invalid = makeRawEnv({ PACKRAT_AUTH_SECRET: undefined });
+ // No BETTER_AUTH_SECRET fallback either → schema rejects.
expect(() => validateCloudflareApiEnv(invalid)).toThrow();
});
});
+
+ // Transitional rename (2026-05-25): the schema accepts BETTER_AUTH_SECRET /
+ // BETTER_AUTH_URL as legacy fallbacks when the canonical PACKRAT_AUTH_SECRET /
+ // PACKRAT_API_URL names are missing, and resolves the canonical fields from
+ // whichever name was provided. A follow-up PR will drop the BETTER_AUTH_*
+ // fallback once all CF Worker secrets are renamed.
+ describe('transitional BETTER_AUTH_* → PACKRAT_* migration', () => {
+ it('falls back to BETTER_AUTH_SECRET when PACKRAT_AUTH_SECRET is missing', () => {
+ (process.env as Record).NODE_ENV = 'production';
+ const result = getEnv(
+ makeRawEnv({
+ PACKRAT_AUTH_SECRET: undefined,
+ BETTER_AUTH_SECRET: 'legacy-secret-that-is-at-least-32-chars-long!!',
+ }),
+ );
+ expect(result.PACKRAT_AUTH_SECRET).toBe('legacy-secret-that-is-at-least-32-chars-long!!');
+ });
+
+ it('falls back to BETTER_AUTH_URL when PACKRAT_API_URL is missing', () => {
+ (process.env as Record).NODE_ENV = 'production';
+ const result = getEnv(
+ makeRawEnv({
+ PACKRAT_API_URL: undefined,
+ BETTER_AUTH_URL: 'https://legacy.packrat.world',
+ }),
+ );
+ expect(result.PACKRAT_API_URL).toBe('https://legacy.packrat.world');
+ });
+
+ it('prefers PACKRAT_AUTH_SECRET when both names are set', () => {
+ (process.env as Record).NODE_ENV = 'production';
+ const result = getEnv(
+ makeRawEnv({
+ PACKRAT_AUTH_SECRET: 'new-name-secret-that-is-at-least-32-chars!!',
+ BETTER_AUTH_SECRET: 'legacy-secret-that-is-at-least-32-chars-long!!',
+ }),
+ );
+ expect(result.PACKRAT_AUTH_SECRET).toBe('new-name-secret-that-is-at-least-32-chars!!');
+ });
+
+ it('rejects when neither PACKRAT_AUTH_SECRET nor BETTER_AUTH_SECRET is set', () => {
+ (process.env as Record).NODE_ENV = 'production';
+ expect(() =>
+ getEnv(
+ makeRawEnv({
+ PACKRAT_AUTH_SECRET: undefined,
+ BETTER_AUTH_SECRET: undefined,
+ }),
+ ),
+ ).toThrow(/PACKRAT_AUTH_SECRET/);
+ });
+
+ it('rejects when neither PACKRAT_API_URL nor BETTER_AUTH_URL is set', () => {
+ (process.env as Record).NODE_ENV = 'production';
+ expect(() =>
+ getEnv(
+ makeRawEnv({
+ PACKRAT_API_URL: undefined,
+ BETTER_AUTH_URL: undefined,
+ }),
+ ),
+ ).toThrow(/PACKRAT_API_URL/);
+ });
+ });
});
diff --git a/packages/api/src/utils/__tests__/json-utils.catch-branches.test.ts b/packages/api/src/utils/__tests__/json-utils.catch-branches.test.ts
new file mode 100644
index 0000000000..4de428ffd9
--- /dev/null
+++ b/packages/api/src/utils/__tests__/json-utils.catch-branches.test.ts
@@ -0,0 +1,61 @@
+// Covers the defensive fallback branches in mapJsonRowToItem that real
+// csv-utils helpers cannot trigger:
+// - parseFaqs / safeJsonParse never throw, so the faqs `[]` / techs `{}`
+// catch branches need the helpers forced to throw.
+// - parseWeight always yields a non-null weight + a schema-valid unit for a
+// positive weightStr, so the `weight ?? undefined` (null) and
+// `parsedUnit.success ? : undefined` (false) branches across all three
+// weight paths need parseWeight forced to return a null/invalid result.
+// The happy-path behaviour lives in json-utils.test.ts.
+
+import { describe, expect, it, vi } from 'vitest';
+
+vi.mock('@packrat/api/utils/csv-utils', async (importActual) => {
+ const actual = await importActual();
+ return {
+ ...actual,
+ parseFaqs: vi.fn(() => {
+ throw new Error('boom: parseFaqs');
+ }),
+ safeJsonParse: vi.fn(() => {
+ throw new Error('boom: safeJsonParse');
+ }),
+ // Null weight + a unit the WeightUnitSchema rejects, so both the nullish
+ // and the safeParse-failure branches run.
+ parseWeight: vi.fn(() => ({ weight: null, unit: 'INVALID_UNIT' })),
+ };
+});
+
+const { mapJsonRowToItem } = await import('../json-utils');
+
+describe('mapJsonRowToItem — catch fallbacks', () => {
+ it('falls back to an empty faqs array when parseFaqs throws', () => {
+ const result = mapJsonRowToItem({ name: 'X', faqs: '[{"question":"Q","answer":"A"}]' });
+ expect(result?.faqs).toEqual([]);
+ });
+
+ it('falls back to an empty techs record when safeJsonParse throws', () => {
+ const result = mapJsonRowToItem({ name: 'X', techs: '{"Material":"Nylon"}' });
+ expect(result?.techs).toEqual({});
+ });
+});
+
+describe('mapJsonRowToItem — weight fallback branches (null weight / invalid unit)', () => {
+ it('leaves weight/weightUnit unset for a numeric weight when parseWeight yields null/invalid', () => {
+ const result = mapJsonRowToItem({ weight: 280, weightUnit: 'g' });
+ expect(result?.weight).toBeUndefined();
+ expect(result?.weightUnit).toBeUndefined();
+ });
+
+ it('leaves weight/weightUnit unset for a string weight when parseWeight yields null/invalid', () => {
+ const result = mapJsonRowToItem({ weight: '1.5 lbs' });
+ expect(result?.weight).toBeUndefined();
+ expect(result?.weightUnit).toBeUndefined();
+ });
+
+ it('leaves weight/weightUnit unset for techs-derived weight when parseWeight yields null/invalid', () => {
+ const result = mapJsonRowToItem({ techs: { 'Claimed Weight': '280g' } });
+ expect(result?.weight).toBeUndefined();
+ expect(result?.weightUnit).toBeUndefined();
+ });
+});
diff --git a/packages/api/src/utils/__tests__/json-utils.test.ts b/packages/api/src/utils/__tests__/json-utils.test.ts
index b5b593dc51..c0c297ce6f 100644
--- a/packages/api/src/utils/__tests__/json-utils.test.ts
+++ b/packages/api/src/utils/__tests__/json-utils.test.ts
@@ -70,6 +70,51 @@ describe('json-utils', () => {
expect(result?.reviewCount).toBe(42);
});
+ it('maps a sub-1 reviewCount number to 0 (|| 0 fallback)', () => {
+ // Math.trunc(0.4) === 0, so the `|| 0` fallback branch must run.
+ const result = mapJsonRowToItem({ reviewCount: 0.4 });
+ expect(result?.reviewCount).toBe(0);
+ });
+
+ it('parses faqs and techs supplied as JSON strings', () => {
+ const result = mapJsonRowToItem({
+ name: 'X',
+ faqs: '[{"question":"Q1","answer":"A1"}]',
+ techs: '{"Material":"Nylon","Capacity":"40L"}',
+ });
+ expect(result?.faqs).toBeDefined();
+ expect(result?.techs).toMatchObject({ Material: 'Nylon', Capacity: '40L' });
+ });
+
+ it('falls back to an empty faqs array when the faqs string is malformed', () => {
+ const result = mapJsonRowToItem({ name: 'Y', faqs: '{not valid json' });
+ expect(result?.faqs).toEqual([]);
+ });
+
+ it('maps techs to {} when the techs string parses to a JSON array', () => {
+ // A JSON-array string is structurally valid JSON but not a key/value
+ // record, so it must collapse to {} rather than index into the array.
+ const result = mapJsonRowToItem({ name: 'Z', techs: '[1,2,3]' });
+ expect(result?.techs).toEqual({});
+ });
+
+ it('maps techs to {} when the techs string is malformed', () => {
+ // safeJsonParse returns [] on malformed input, which Array.isArray
+ // collapses to {} — techs must never be left as an array.
+ const result = mapJsonRowToItem({ name: 'Z', techs: '{not valid json' });
+ expect(result?.techs).toEqual({});
+ });
+
+ it('does not derive weight from techs when no claimed/weight key is present', () => {
+ // techs is a valid record but lacks 'Claimed Weight'/'weight', so the
+ // claimedWeight-falsy branch of the weight fallback must run and leave
+ // weight unset.
+ const result = mapJsonRowToItem({ name: 'Z', techs: '{"Material":"Nylon"}' });
+ expect(result?.techs).toEqual({ Material: 'Nylon' });
+ expect(result?.weight).toBeUndefined();
+ expect(result?.weightUnit).toBeUndefined();
+ });
+
it('maps reviewCount from string', () => {
const result = mapJsonRowToItem({ reviewCount: '128' });
expect(result?.reviewCount).toBe(128);
@@ -162,8 +207,8 @@ describe('json-utils', () => {
it('maps weight from number with unit string', () => {
const result = mapJsonRowToItem({ weight: 280, weightUnit: 'g' });
- expect(result?.weight).toBeGreaterThan(0);
- expect(result?.weightUnit).toBeDefined();
+ expect(result?.weight).toBe(280);
+ expect(result?.weightUnit).toBe('g');
});
it('maps weight from string', () => {
@@ -228,6 +273,12 @@ describe('json-utils', () => {
expect(result?.weight).toBeGreaterThan(0);
});
+ it('ignores zero weight from techs Claimed Weight field', () => {
+ const result = mapJsonRowToItem({ techs: { 'Claimed Weight': '0 g' } });
+ expect(result?.weight).toBeUndefined();
+ expect(result?.weightUnit).toBeUndefined();
+ });
+
it('maps availability from valid string', () => {
const result = mapJsonRowToItem({ availability: 'in_stock' });
expect(result?.availability).toBe('in_stock');
diff --git a/packages/api/src/utils/__tests__/sentry.test.ts b/packages/api/src/utils/__tests__/sentry.test.ts
index 82ec7ba40f..22dfd519c0 100644
--- a/packages/api/src/utils/__tests__/sentry.test.ts
+++ b/packages/api/src/utils/__tests__/sentry.test.ts
@@ -1,101 +1,148 @@
-// Unit tests for the Sentry API helpers.
+// Unit tests for the Sentry helpers (@packrat/api/utils/sentry).
-import { beforeEach, describe, expect, it, vi } from 'vitest';
+import {
+ apiAddBreadcrumb,
+ captureApiException,
+ clearApiUser,
+ isCaptured,
+ record,
+ setApiUser,
+ setRequestId,
+} from '@packrat/api/utils/sentry';
+import * as Sentry from '@sentry/cloudflare';
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
-const scope = vi.hoisted(() => ({
- setTag: vi.fn(),
- setExtra: vi.fn(),
-}));
+// Shared scope stub returned by both withScope and getCurrentScope.
+const scope = { setTag: vi.fn(), setExtra: vi.fn() };
-const sentry = vi.hoisted(() => ({
+vi.mock('@sentry/cloudflare', () => ({
addBreadcrumb: vi.fn(),
captureException: vi.fn(),
captureMessage: vi.fn(),
+ getCurrentScope: vi.fn(() => scope),
setUser: vi.fn(),
+ // startSpan runs the callback and returns its promise (matches the real
+ // contract closely enough: the callback owns the try/catch in `record`).
+ startSpan: vi.fn((_opts: unknown, cb: () => unknown) => cb()),
withScope: vi.fn((cb: (s: typeof scope) => void) => cb(scope)),
}));
-vi.mock('@sentry/cloudflare', () => sentry);
-
-import {
- apiAddBreadcrumb,
- captureApiException,
- clearApiUser,
- setApiUser,
-} from '@packrat/api/utils/sentry';
-
describe('sentry helpers', () => {
beforeEach(() => {
vi.clearAllMocks();
+ vi.spyOn(console, 'error').mockImplementation(() => undefined);
});
+ afterEach(() => vi.restoreAllMocks());
describe('captureApiException', () => {
- it('tags operation + user_id, applies tags/extra, and captures the error', () => {
- const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
- const error = new Error('boom');
-
+ it('reports with operation + userId + tags + extra and logs to console', () => {
+ const err = new Error('boom');
captureApiException({
- error,
- operation: 'pack.create',
+ error: err,
+ operation: 'op.test',
userId: 'u1',
- tags: { feature: 'packs' },
- extra: { packId: 'p1' },
+ tags: { feature: 'x' },
+ extra: { relevantId: 7 },
});
-
- expect(sentry.withScope).toHaveBeenCalledOnce();
- expect(scope.setTag).toHaveBeenCalledWith('operation', 'pack.create');
+ expect(Sentry.withScope).toHaveBeenCalledOnce();
+ expect(scope.setTag).toHaveBeenCalledWith('operation', 'op.test');
expect(scope.setTag).toHaveBeenCalledWith('user_id', 'u1');
- expect(scope.setTag).toHaveBeenCalledWith('feature', 'packs');
- expect(scope.setExtra).toHaveBeenCalledWith('packId', 'p1');
- expect(sentry.captureException).toHaveBeenCalledWith(error);
- expect(errorSpy).toHaveBeenCalledWith('[sentry][pack.create]', error);
-
- errorSpy.mockRestore();
+ expect(scope.setTag).toHaveBeenCalledWith('feature', 'x');
+ expect(scope.setExtra).toHaveBeenCalledWith('relevantId', 7);
+ expect(Sentry.captureException).toHaveBeenCalledWith(err);
+ expect(console.error).toHaveBeenCalled();
});
- it('omits user_id / tags / extra when they are not provided', () => {
- vi.spyOn(console, 'error').mockImplementation(() => undefined);
+ it('is idempotent — the same error is reported only once (dedup marker)', () => {
+ const err = new Error('dup');
+ captureApiException({ error: err, operation: 'first' });
+ captureApiException({ error: err, operation: 'second' });
+ expect(Sentry.captureException).toHaveBeenCalledTimes(1);
+ expect(isCaptured(err)).toBe(true);
+ });
- captureApiException({ error: new Error('x'), operation: 'op' });
+ it('captures non-object errors without marking them', () => {
+ captureApiException({ error: 'string-error', operation: 'op' });
+ expect(Sentry.captureException).toHaveBeenCalledWith('string-error');
+ expect(isCaptured('string-error')).toBe(false);
+ });
+ });
- expect(scope.setTag).toHaveBeenCalledWith('operation', 'op');
- expect(scope.setTag).not.toHaveBeenCalledWith('user_id', expect.anything());
- expect(scope.setExtra).not.toHaveBeenCalled();
+ describe('isCaptured', () => {
+ it('is false for a fresh error, undefined, and non-objects', () => {
+ expect(isCaptured(new Error('fresh'))).toBe(false);
+ expect(isCaptured(undefined)).toBe(false);
+ expect(isCaptured('x')).toBe(false);
});
});
- describe('apiAddBreadcrumb', () => {
- it('adds a default-type breadcrumb with the provided fields', () => {
- apiAddBreadcrumb({
- category: 'etl',
- message: 'started',
- level: 'info',
- data: { jobId: 'j1' },
+ describe('record', () => {
+ it('runs fn inside a span and returns its result, no capture on success', async () => {
+ const result = await record({
+ operation: 'span.ok',
+ extra: { jobId: '1' },
+ fn: async () => 42,
});
+ expect(result).toBe(42);
+ expect(Sentry.startSpan).toHaveBeenCalledOnce();
+ const [opts] = vi.mocked(Sentry.startSpan).mock.calls[0] ?? [];
+ expect(opts).toMatchObject({ name: 'span.ok' });
+ expect(Sentry.captureException).not.toHaveBeenCalled();
+ });
- expect(sentry.addBreadcrumb).toHaveBeenCalledWith({
- type: 'default',
- category: 'etl',
- message: 'started',
- level: 'info',
- data: { jobId: 'j1' },
+ it('captures with operation context and rethrows on failure', async () => {
+ const err = new Error('span boom');
+ await expect(
+ record({
+ operation: 'span.fail',
+ extra: { jobId: '2' },
+ fn: async () => {
+ throw err;
+ },
+ }),
+ ).rejects.toBe(err);
+ expect(Sentry.captureException).toHaveBeenCalledWith(err);
+ expect(scope.setTag).toHaveBeenCalledWith('operation', 'span.fail');
+ expect(isCaptured(err)).toBe(true);
+ });
+
+ it('forwards attributes to the span', async () => {
+ await record({
+ operation: 'span.attr',
+ attributes: { jobId: 'abc', count: 3 },
+ fn: async () => undefined,
});
+ const [opts] = vi.mocked(Sentry.startSpan).mock.calls.at(-1) ?? [];
+ expect(opts).toMatchObject({ attributes: { jobId: 'abc', count: 3 } });
});
});
- describe('setApiUser / clearApiUser', () => {
- it('maps role to username when setting the user', () => {
- setApiUser({ id: 'u1', email: 'a@b.co', role: 'ADMIN' });
- expect(sentry.setUser).toHaveBeenCalledWith({
- id: 'u1',
- email: 'a@b.co',
- username: 'ADMIN',
- });
+ describe('request/user/breadcrumb helpers', () => {
+ it('setRequestId tags the current scope with request_id', () => {
+ setRequestId('cf-ray-123');
+ expect(Sentry.getCurrentScope).toHaveBeenCalled();
+ expect(scope.setTag).toHaveBeenCalledWith('request_id', 'cf-ray-123');
+ });
+
+ it('setApiUser maps role to username', () => {
+ setApiUser({ id: 'u', email: 'e@x.com', role: 'ADMIN' });
+ expect(Sentry.setUser).toHaveBeenCalledWith({ id: 'u', email: 'e@x.com', username: 'ADMIN' });
});
- it('clears the user context', () => {
+ it('clearApiUser clears the user', () => {
clearApiUser();
- expect(sentry.setUser).toHaveBeenCalledWith(null);
+ expect(Sentry.setUser).toHaveBeenCalledWith(null);
+ });
+
+ it('apiAddBreadcrumb forwards with a default type', () => {
+ apiAddBreadcrumb({ category: 'feature', message: 'm', level: 'info', data: { a: 1 } });
+ expect(Sentry.addBreadcrumb).toHaveBeenCalledWith({
+ type: 'default',
+ category: 'feature',
+ message: 'm',
+ level: 'info',
+ data: { a: 1 },
+ });
});
});
});
diff --git a/packages/api/src/utils/buildInstanceId.ts b/packages/api/src/utils/buildInstanceId.ts
new file mode 100644
index 0000000000..3bf344e492
--- /dev/null
+++ b/packages/api/src/utils/buildInstanceId.ts
@@ -0,0 +1,40 @@
+/**
+ * CF Workflows instance-id construction.
+ *
+ * CF Workflows constrains instance IDs to `^[a-zA-Z0-9_][a-zA-Z0-9-_]*$`
+ * (max 64 chars enforced by CF). The catalog ETL trigger builds the id from a
+ * freeform request-body filename, which can contain a file extension, spaces,
+ * punctuation, and leading non-alphanumerics — all of which violate that
+ * pattern and get rejected with a 500.
+ *
+ * Lives in its own module (rather than inline in the route) so it can be unit
+ * tested without importing the whole Elysia route graph.
+ */
+
+// Hoisted so the literals aren't re-allocated per call (lint/performance and
+// the repo's no-raw-regex rule, which forbids inline regex literals).
+const FILE_EXT_RE = /\.[^.]*$/;
+const DISALLOWED_CHAR_RE = /[^A-Za-z0-9_-]/g;
+const REPEATED_DASH_RE = /-+/g;
+const EDGE_DASH_RE = /^-+|-+$/g;
+const VALID_FIRST_CHAR_RE = /^[A-Za-z0-9_]/;
+
+/**
+ * Sanitize a filename into a valid CF Workflows instance ID.
+ *
+ * Strips the file extension, replaces any disallowed char with `-`, collapses
+ * repeated `-`, trims leading/trailing `-`, guarantees the first char is
+ * `[A-Za-z0-9_]` (prefixing `f-` otherwise), and caps the length at 100.
+ */
+export function buildInstanceId(filename: string): string {
+ const withoutExt = filename.replace(FILE_EXT_RE, '');
+ let id = withoutExt
+ .replace(DISALLOWED_CHAR_RE, '-')
+ .replace(REPEATED_DASH_RE, '-')
+ .replace(EDGE_DASH_RE, '');
+ // First char must be [A-Za-z0-9_]; an empty result also needs a valid prefix.
+ if (id === '' || !VALID_FIRST_CHAR_RE.test(id)) {
+ id = `f-${id}`;
+ }
+ return id.slice(0, 100);
+}
diff --git a/packages/api/src/utils/env-validation.ts b/packages/api/src/utils/env-validation.ts
index c4b33f89a9..c47485b125 100644
--- a/packages/api/src/utils/env-validation.ts
+++ b/packages/api/src/utils/env-validation.ts
@@ -2,7 +2,10 @@ import type { Container } from '@cloudflare/containers';
import { isObject } from '@packrat/guards';
import { z } from 'zod';
-// Define the Zod schema for all environment variables
+// Base Zod schema for all environment variables. Stays a ZodObject so tests can
+// introspect via `.shape.X` (re-exported as `apiEnvSchema` below). The runtime
+// validation path uses `validatedApiEnvSchema`, which adds the
+// BETTER_AUTH_* → PACKRAT_* migration superRefine + transform.
export const apiEnvObjectSchema = z.object({
// Environment & Deployment
ENVIRONMENT: z.enum(['development', 'production']).default('production'),
@@ -17,9 +20,23 @@ export const apiEnvObjectSchema = z.object({
// set to env.OSM_HYPERDRIVE.connectionString (Hyperdrive binding).
OSM_DATABASE_URL: z.string().url().optional(),
- // Better Auth
- BETTER_AUTH_SECRET: z.string().min(32),
- BETTER_AUTH_URL: z.string().url(), // API base URL e.g. https://api.packrat.world
+ // Auth — TRANSITIONAL (2026-05-25 rename).
+ //
+ // Canonical names: PACKRAT_AUTH_SECRET, PACKRAT_API_URL. These unify with
+ // PACKRAT_API_URL already used by the MCP worker + CLI package, and drop
+ // the framework-specific BETTER_AUTH_* prefix.
+ //
+ // Legacy fallbacks: BETTER_AUTH_SECRET, BETTER_AUTH_URL — accepted during
+ // the rolling migration. Operator must set the new-name CF secrets, then a
+ // follow-up PR removes the BETTER_AUTH_* schema entries entirely.
+ //
+ // Either set in each pair satisfies the schema. The .superRefine() below
+ // enforces "at least one of each pair"; the .transform() resolves the new
+ // name to the legacy fallback so consumer code only reads the new name.
+ PACKRAT_AUTH_SECRET: z.string().min(32).optional(),
+ PACKRAT_API_URL: z.string().url().optional(),
+ BETTER_AUTH_SECRET: z.string().min(32).optional(),
+ BETTER_AUTH_URL: z.string().url().optional(),
BETTER_AUTH_TRUSTED_ORIGINS: z.string().optional(),
// Google OAuth (Better Auth social provider)
GOOGLE_CLIENT_ID: z.string(),
@@ -94,33 +111,106 @@ export const apiEnvObjectSchema = z.object({
METRICS_DB: z.unknown(),
});
+// Re-export the object schema under its historical name for tests/consumers
+// that introspect `.shape`.
export const apiEnvSchema = apiEnvObjectSchema;
-// Relaxed schema for test environments
-const testEnvSchema = apiEnvObjectSchema.partial().extend({
- ENVIRONMENT: z.enum(['development', 'production']).default('development'),
- SENTRY_DSN: z.string().url().optional().default('https://test@test.ingest.sentry.io/test'),
- NEON_DATABASE_URL: z.string().optional().default('postgres://user:pass@localhost/db'),
- NEON_DATABASE_URL_READONLY: z.string().optional().default('postgres://user:pass@localhost/db'),
- OSM_DATABASE_URL: z.string().url().optional().default('postgres://user:pass@localhost/db'),
- BETTER_AUTH_SECRET: z.string().optional().default('test-better-auth-secret-32-chars-long!!'),
- BETTER_AUTH_URL: z.string().url().optional().default('http://localhost:8787'),
- BETTER_AUTH_TRUSTED_ORIGINS: z.string().optional(),
- CF_VERSION_METADATA: z.unknown().optional().default({ id: 'test-version' }),
- AI: z.unknown().optional(),
- PACKRAT_SCRAPY_BUCKET: z.unknown().optional(),
- PACKRAT_BUCKET: z.unknown().optional(),
- PACKRAT_GUIDES_BUCKET: z.unknown().optional(),
- ETL_QUEUE: z.unknown().optional(),
- LOGS_QUEUE: z.unknown().optional(),
- EMBEDDINGS_QUEUE: z.unknown().optional(),
- ETL_WORKFLOW: z.unknown().optional(),
- APP_CONTAINER: z.unknown().optional(),
- AUTH_KV: z.unknown().optional(),
- METRICS_DB: z.unknown().optional(),
-});
+// Shared BETTER_AUTH_* → PACKRAT_* migration logic. Applied to both the
+// runtime schema and the relaxed test schema so a lone BETTER_AUTH_SECRET /
+// BETTER_AUTH_URL maps to the canonical name in either context.
+type AuthMigrationEnv = {
+ PACKRAT_AUTH_SECRET?: string;
+ PACKRAT_API_URL?: string;
+ BETTER_AUTH_SECRET?: string;
+ BETTER_AUTH_URL?: string;
+};
+
+function resolveAuthPair(
+ env: T,
+): T & {
+ PACKRAT_AUTH_SECRET: string;
+ PACKRAT_API_URL: string;
+} {
+ return {
+ ...env,
+ // safe-assertion: refineAuthPair guarantees one side of each pair is set.
+ PACKRAT_AUTH_SECRET: (env.PACKRAT_AUTH_SECRET ?? env.BETTER_AUTH_SECRET) as string,
+ PACKRAT_API_URL: (env.PACKRAT_API_URL ?? env.BETTER_AUTH_URL) as string,
+ };
+}
+
+// Runtime validation schema: enforces "at least one of each transitional
+// pair" (BETTER_AUTH_* OR PACKRAT_*) and resolves the canonical PACKRAT_*
+// fields from whichever name was provided. Consumer code reads
+// env.PACKRAT_AUTH_SECRET / env.PACKRAT_API_URL only.
+const validatedApiEnvSchema = apiEnvObjectSchema
+ // Inline superRefine callback (matches the codebase convention in
+ // packages/env/src/analytics.ts): the (value, ctx) signature is Zod's, not
+ // an owned API, so it's exempt from the one-object-param lint.
+ .superRefine((env, ctx) => {
+ if (!env.PACKRAT_AUTH_SECRET && !env.BETTER_AUTH_SECRET) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ path: ['PACKRAT_AUTH_SECRET'],
+ message:
+ 'PACKRAT_AUTH_SECRET (preferred) or legacy BETTER_AUTH_SECRET must be set (min 32 chars)',
+ });
+ }
+ if (!env.PACKRAT_API_URL && !env.BETTER_AUTH_URL) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ path: ['PACKRAT_API_URL'],
+ message: 'PACKRAT_API_URL (preferred) or legacy BETTER_AUTH_URL must be set (URL)',
+ });
+ }
+ })
+ .transform(resolveAuthPair);
+
+// Stable test defaults for the auth pair. Applied inside the transform so a
+// lone BETTER_AUTH_SECRET / BETTER_AUTH_URL still maps to the canonical name
+// (an inline `.default()` on the PACKRAT_* fields would always win over the
+// BETTER_AUTH_* fallback, defeating the migration in tests).
+const TEST_AUTH_SECRET_DEFAULT = 'test-better-auth-secret-32-chars-long!!';
+const TEST_API_URL_DEFAULT = 'http://localhost:8787';
+
+// Relaxed schema for test environments. Mirrors the runtime schema's
+// BETTER_AUTH_* → PACKRAT_* fallback so a lone BETTER_AUTH_SECRET /
+// BETTER_AUTH_URL resolves to the canonical name. Falls back to stable test
+// defaults only when neither name in a pair is provided.
+const testEnvSchema = apiEnvObjectSchema
+ .partial()
+ .extend({
+ ENVIRONMENT: z.enum(['development', 'production']).default('development'),
+ SENTRY_DSN: z.string().url().optional().default('https://test@test.ingest.sentry.io/test'),
+ NEON_DATABASE_URL: z.string().optional().default('postgres://user:pass@localhost/db'),
+ NEON_DATABASE_URL_READONLY: z.string().optional().default('postgres://user:pass@localhost/db'),
+ OSM_DATABASE_URL: z.string().url().optional().default('postgres://user:pass@localhost/db'),
+ PACKRAT_AUTH_SECRET: z.string().optional(),
+ PACKRAT_API_URL: z.string().url().optional(),
+ BETTER_AUTH_SECRET: z.string().optional(),
+ BETTER_AUTH_URL: z.string().url().optional(),
+ BETTER_AUTH_TRUSTED_ORIGINS: z.string().optional(),
+ CF_VERSION_METADATA: z.unknown().optional().default({ id: 'test-version' }),
+ AI: z.unknown().optional(),
+ PACKRAT_SCRAPY_BUCKET: z.unknown().optional(),
+ PACKRAT_BUCKET: z.unknown().optional(),
+ PACKRAT_GUIDES_BUCKET: z.unknown().optional(),
+ ETL_QUEUE: z.unknown().optional(),
+ LOGS_QUEUE: z.unknown().optional(),
+ EMBEDDINGS_QUEUE: z.unknown().optional(),
+ ETL_WORKFLOW: z.unknown().optional(),
+ APP_CONTAINER: z.unknown().optional(),
+ AUTH_KV: z.unknown().optional(),
+ METRICS_DB: z.unknown().optional(),
+ })
+ .transform((env) => ({
+ ...env,
+ PACKRAT_AUTH_SECRET:
+ env.PACKRAT_AUTH_SECRET ?? env.BETTER_AUTH_SECRET ?? TEST_AUTH_SECRET_DEFAULT,
+ PACKRAT_API_URL: env.PACKRAT_API_URL ?? env.BETTER_AUTH_URL ?? TEST_API_URL_DEFAULT,
+ }));
-type ValidatedAppEnv = z.infer;
+type ValidatedAppEnv = z.infer;
// Override Cloudflare binding types with proper TypeScript types
export type ValidatedEnv = Omit<
@@ -172,7 +262,10 @@ function isTestEnvironment(rawEnv?: Record): boolean {
}
function validate(rawEnv: Record): ValidatedEnv {
- const schema = isTestEnvironment(rawEnv) ? testEnvSchema : apiEnvSchema;
+ // Production runs through the post-transform schema so the canonical
+ // PACKRAT_* fields are always populated; tests use the relaxed schema
+ // with explicit defaults for those fields.
+ const schema = isTestEnvironment(rawEnv) ? testEnvSchema : validatedApiEnvSchema;
const validated = schema.safeParse(rawEnv);
if (!validated.success) {
throw new Error(`Invalid environment variables: ${validated.error.message}`);
@@ -251,7 +344,9 @@ export function getEnv(explicitEnv?: Record): ValidatedEnv {
/**
* Validate Cloudflare API environment variables at build/deploy time.
+ * Uses the post-transform schema so the BETTER_AUTH_* → PACKRAT_* migration
+ * fallback is enforced (at least one of each pair must be present).
*/
export function validateCloudflareApiEnv(env: Record): void {
- apiEnvSchema.parse(env);
+ validatedApiEnvSchema.parse(env);
}
diff --git a/packages/api/src/utils/json-utils.ts b/packages/api/src/utils/json-utils.ts
index f9b338eae8..2c15e411f5 100644
--- a/packages/api/src/utils/json-utils.ts
+++ b/packages/api/src/utils/json-utils.ts
@@ -185,7 +185,9 @@ export function mapJsonRowToItem(obj: Record): Partial 0` guard so a techs value like
+ // '0 g' is not persisted as weight: 0.
+ if (claimedWeight && parseFloat(claimedWeight) > 0) {
const { weight, unit } = parseWeight({ weightStr: claimedWeight });
item.weight = weight ?? undefined;
const parsedUnit = WeightUnitSchema.safeParse(unit);
diff --git a/packages/api/src/utils/logger.ts b/packages/api/src/utils/logger.ts
index af11a140db..abb126f2ad 100644
--- a/packages/api/src/utils/logger.ts
+++ b/packages/api/src/utils/logger.ts
@@ -45,7 +45,15 @@ function forwardToSentry({ level, event, ctx }: EmitArgs): void {
err = v;
continue;
}
- if (isString(v) || isNumber(v) || v === true || v === false) {
+ // Per CLAUDE.md, httpStatus and errorCode must always be searchable in
+ // Sentry `extra`. Keep them in tags too (for pivoting) but always copy
+ // them into extras regardless of their scalar type.
+ if (k === 'httpStatus' || k === 'errorCode') {
+ sentryExtras[k] = v;
+ if (isString(v) || isNumber(v) || v === true || v === false) {
+ sentryTags[k] = String(v);
+ }
+ } else if (isString(v) || isNumber(v) || v === true || v === false) {
sentryTags[k] = String(v);
} else {
sentryExtras[k] = v;
diff --git a/packages/api/src/utils/sentry.ts b/packages/api/src/utils/sentry.ts
index 04bb5114c1..ffddf3a967 100644
--- a/packages/api/src/utils/sentry.ts
+++ b/packages/api/src/utils/sentry.ts
@@ -9,11 +9,21 @@ import {
addBreadcrumb,
captureException,
captureMessage,
+ getCurrentScope,
setUser,
+ startSpan,
withScope,
} from '@sentry/cloudflare';
-export { addBreadcrumb, captureException, captureMessage, setUser, withScope };
+export {
+ addBreadcrumb,
+ captureException,
+ captureMessage,
+ getCurrentScope,
+ setUser,
+ startSpan,
+ withScope,
+};
export type SentryOperationContext = {
operation: string;
@@ -22,13 +32,54 @@ export type SentryOperationContext = {
extra?: Record;
};
+/**
+ * Dedup set. PackRat has three overlapping Sentry boundaries on Workers:
+ * 1. `withSentry` (index.ts) — outer net over fetch/queue/scheduled.
+ * 2. `instrumentWorkflowWithSentry` (index.ts) — workflow entrypoints.
+ * 3. Elysia `.onError` (app.ts) — route handlers.
+ *
+ * When inner code enriches an error with `captureApiException`/`record` and
+ * then rethrows, the boundary it propagates into would report it a second
+ * time. We track reported errors here and skip repeats, so enrich-and-rethrow
+ * is safe to use anywhere.
+ *
+ * A `WeakSet` (rather than a stamped symbol) avoids mutating — possibly
+ * frozen — error objects and is GC-friendly. The api worker is a single
+ * bundle, so all three boundaries share this instance.
+ */
+const capturedErrors = new WeakSet