diff --git a/.cursor/rules/bff-typescript-cdk-best-practices.mdc b/.cursor/rules/bff-typescript-cdk-best-practices.mdc new file mode 100644 index 0000000..64dce65 --- /dev/null +++ b/.cursor/rules/bff-typescript-cdk-best-practices.mdc @@ -0,0 +1,301 @@ +--- +description: Best practices for this pnpm + turbo TypeScript monorepo — a NestJS BFF on a single Lambda, shared packages, and AWS CDK infrastructure. Covers repo layout, naming, module organization, config and secrets, testing, tooling, CI/CD, and CDK conventions. +globs: apps/bff/**/*.ts,infra/cdk/**/*.ts,packages/**/*.ts,data/**/*.ts,.github/workflows/*.yml,*.json +alwaysApply: false +--- + +# TypeScript BFF + AWS CDK Best Practices and Coding Standards + +Conventions for building and shipping the BFF (`apps/bff`) and its AWS infrastructure (`infra/cdk`). Items marked **(recommended)** are not adopted in the repo yet; everything else describes what the repo already does and should keep doing. + +## 1. Code Organization and Structure + +### Directory Structure + +Top-level folders are split by deployable role, not by technical layer. + +* **`apps/`**: Deployable applications. Each is its own pnpm workspace package. + * **`bff/`**: NestJS + Fastify API. One Lambda in production, a plain Node server locally. + * **`web/`**: Vite/React frontend. Never talks to AWS directly; only calls `/api/*`. + * **`scraper/`**: Scheduled data-ingestion job. + * **`e2e/`**: Playwright tests that run against a deployed stage. +* **`packages/`**: Libraries shared by apps and infra. + * **`shared-types/`**: Contracts and pure logic used by both `web` and `bff`. No decorators, no Node-only APIs, no AWS SDK. + * **`config/`**: Shared `tsconfig-*.json` presets. +* **`infra/cdk/`**: The CDK app. `bin/` instantiates, `lib/` holds stacks and helpers, `lambda/` holds small non-BFF function code, `scripts/` holds operational scripts. +* **`data/`**: Seed and data-prep tooling. +* **`docs/`**: Architecture, data model, CI/CD, infra and cost notes. Update the relevant doc in the same PR as the change. +* **`scripts/`**: Repo-level helper scripts. +* **`assets/`**: Static assets not owned by an app. +* **`.github/`**: `workflows/` (CI and deploy) and `CODEOWNERS`. +* **`.claude/skills/`** and **`.cursor/rules/`**: Agent instructions. Keep them short and task-specific. + +Example: + +```plain text +root-project/ +├── .claude/ +│ └── skills/ +├── .cursor/ +│ └── rules/ +├── .github/ +│ ├── workflows/ +│ │ ├── ci.yml +│ │ └── deploy.yml +│ └── CODEOWNERS +├── apps/ +│ ├── bff/ +│ │ ├── scripts/build-lambda.mjs +│ │ └── src/ +│ │ ├── app.ts # createApp(): shared by lambda.ts and main.ts +│ │ ├── app.module.ts +│ │ ├── lambda.ts # Lambda entrypoint +│ │ ├── main.ts # local dev entrypoint +│ │ ├── mycota-config.ts # the one place env vars become typed config +│ │ ├── dynamo/ +│ │ ├── filters/ +│ │ ├── types/ # ambient .d.ts +│ │ └── / # things/, contributions/, search/, ... +│ ├── e2e/ +│ ├── scraper/ +│ └── web/ +├── assets/ +├── data/ +├── docs/ +├── infra/ +│ └── cdk/ +│ ├── bin/app.ts +│ ├── lambda/ +│ ├── lib/ +│ └── scripts/ +├── packages/ +│ ├── config/ +│ └── shared-types/ +├── scripts/ +├── .npmrc +├── .nvmrc +├── .oxfmtrc.json +├── .oxlintrc.json +├── AGENTS.md / CLAUDE.md # pointers only; the rules live in .cursor/rules/ +├── lefthook.yml +├── package.json +├── pnpm-lock.yaml +├── pnpm-workspace.yaml +├── README.md +├── tsconfig.base.json +└── turbo.json +``` + +### Root Configuration Files + +Each file owns one concern. Put a setting in the most specific place that owns it. + +| File | Owns | +| --- | --- | +| `package.json` | `engines`, pinned `packageManager`, root scripts that fan out through turbo | +| `pnpm-workspace.yaml` | Workspace globs, install/supply-chain policy (`minimumReleaseAge*`), native build allowlist, `saveExact`, `supportedArchitectures`, dependency `overrides` | +| `.npmrc` | `save-exact=true` for npm and older pnpm. pnpm 11 ignores it for this setting, so `saveExact: true` in `pnpm-workspace.yaml` is the one that takes effect (tested) | +| `tsconfig.base.json` | Strict compiler baseline for every package | +| `packages/config/tsconfig-*.json` | Per-runtime presets (Node, React) that extend the base | +| `turbo.json` | Task graph and cache outputs | +| `.oxlintrc.json` / `.oxfmtrc.json` | Lint and format rules (oxlint + oxfmt, not ESLint/Prettier) | +| `lefthook.yml` | Pre-commit lint and format on staged files | +| `.nvmrc` | Node version, read locally and by every GitHub Actions job via `node-version-file: .nvmrc` | +| `docker-compose.yml` | Local dependencies (DynamoDB Local) | + +### File Naming Conventions + +* Files are `kebab-case` with a role suffix that says what the file is: `things.controller.ts`, `things.service.ts`, `things.module.ts`, `create-thing.dto.ts`, `stage-error.filter.ts`, `dynamo.constants.ts`. +* Classes and types are `PascalCase`. Injection tokens and env-derived constants are `UPPER_SNAKE_CASE` (`DYNAMO_DOC_CLIENT`, `CONTENT_TABLE_NAME`). +* Specs sit next to the code they test as `.spec.ts`. Ambient declarations live in `types/*.d.ts`. +* CDK files are `-stack.ts` exporting `Stack`. Helpers that are not stacks use a plain descriptive name (`lambda-canary.ts`). +* Relative imports use the `.js` extension (NodeNext ESM). Node built-ins use the `node:` prefix. +* Type-only imports use `import type` (required by `isolatedModules`). + +### Module Organization + +* **A BFF feature is one folder** containing `.module.ts`, `.controller.ts`, `.service.ts`, and a `dto/` folder if it accepts a body. Register the module once in `app.module.ts`. +* **Dependency direction is one-way:** `apps/*` and `infra` may depend on `packages/*`; `packages/*` never depends on an app. `shared-types` depends on nothing runtime-heavy. +* **Controllers are thin.** They handle HTTP concerns only: routing, guards, DTO binding, status codes. Logic lives in services. +* **Cross-feature use goes through the module.** Export the service from its module and import the module. Do not deep-import another feature's internals. +* **Wrap external systems behind a port.** A small interface, a real adapter over an *injected* client (no SDK construction inside domain code), and a fake for tests and local runs. This is the same shape the mycota packages use. +* **Response shapes the frontend needs live in `packages/shared-types`,** not in the controller. +* **Prefer the first-party `@bubltec/mycota-*` packages** (auth, dynamo, config, cdk constructs) before writing a new equivalent. + +## 2. TypeScript Standards + +* `strict` and `noUncheckedIndexedAccess` are on. Handle `undefined` from indexed access instead of asserting it away. +* No `any`. Use `unknown` and narrow. A justified exception gets a one-line comment (see `test-utils.ts`). +* Decorators (`experimentalDecorators`, `emitDecoratorMetadata`) are enabled only in `apps/bff`. Do not let them leak into `shared-types` or the web build. +* Model states with discriminated unions and literal types (`'dev' | 'prod'`), not booleans and strings that can drift. +* Validate at boundaries only: incoming HTTP bodies, external API responses, and legacy stored data. Trust internal types. +* Runtime is Node per `engines` in the root `package.json`. Use ES2023 features freely; do not add polyfills. +* **TypeScript 7 no longer auto-includes every `@types/*` package.** The Node preset sets `"types": ["node"]`, so every workspace that extends it must declare `@types/node` as its own `devDependency`. Relying on a hoisted copy compiles by accident and fails after a clean install. + +## 3. BFF Practices (NestJS + Fastify on Lambda) + +### Requests and validation + +* The global `ValidationPipe` is built from the one exported `VALIDATION_PIPE_OPTIONS` (`apps/bff/src/validation.ts`): `whitelist`, `forbidNonWhitelisted`, `transform`. `app.ts` and the DTO specs both import it, so tests exercise the real config. Consequences you must design for: + * **An undeclared field is a 400** (`forbidNonWhitelisted`), not silently dropped. Silent dropping hid a `thingId` sent in the wrong place, so edits lost their target. When you add a field on the client, add it to the DTO in the same change. + * **Every DTO property needs at least one validator decorator,** otherwise it counts as undeclared. + * **A required nested object needs `@IsDefined()` + `@ValidateNested()` + `@Type(() => Dto)`.** `@ValidateNested()` alone only validates the value *if present*; a body missing the property passes and later crashes as a 500 instead of returning a 400. + * Arrays of nested DTOs use `@IsArray()` + `@ValidateNested({ each: true })` + `@Type(...)`. +* Add a pipe-level regression test whenever a DTO shape changes (see `create-contribution.dto.spec.ts`): it must use the same pipe options as `app.ts`. +* Client mistakes are `4xx`. Throw the matching `HttpException` subclass (`BadRequestException`, `NotFoundException`, ...). A `500` means a bug, and a `500` from bad input is itself a bug. + +### Auth and errors + +* Gate routes with `JwtAuthGuard` / `VerifiedGuard` from the auth package. Do not hand-roll auth checks in controllers. +* Prod returns a generic 500 body. Non-prod stages return the underlying message via `StageErrorFilter`. Never leak internals in prod. + +### Configuration + +* Environment variables are read in **one** place (`mycota-config.ts` and the Dynamo constants) and passed down as typed config. Do not scatter `process.env` through services. +* Local defaults must be obviously fake (`change-me-in-local-env`) and must never work in a deployed stage. This is enforced, not just advised: `requireInProduction()` and `corsOrigin()` (`apps/bff/src/env.ts`) throw at startup when `NODE_ENV=production` and `JWT_SECRET` or `WEB_ORIGIN` is missing or still a `REPLACE_*`/`change-me*` placeholder. Use them for any new secret or origin instead of `?? 'default'`. + +### Data access + +* DynamoDB is single-table (`PK`/`SK` plus `GSI1`/`GSI2`); see `docs/data-model.md` before adding an access pattern. +* Use the injected `DYNAMO_DOC_CLIENT`. Never construct an SDK client inside a service. +* Prefer `Query` on a key or GSI. A `Scan` is acceptable only for the small, cached catalog read; paginate on `LastEvaluatedKey` and never issue one per request. +* After writing a `Thing`, call `SearchService.invalidate()`. It clears the cache in **this container only**; other warm containers can serve the old rows for up to 60s. That is acceptable for this data, but do not rely on the cache for correctness. +* Data already in the table can predate a schema change. Sanitize at the read boundary rather than assuming current types. + +### Lambda and cold starts + +* `lambda.ts` and `main.ts` both call the same `createApp()`, so anything wired into `AppModule` works locally and deployed with no extra step. +* Bootstrap once per container (`proxy ??= await bootstrap()`). Resolve secrets during bootstrap, before providers that read them are constructed. +* Reuse SDK clients across invocations (module scope or DI singletons). Do no heavy work at import time. +* Size timeouts for a cold container, not a warm one (email sign-in does DNS + fetch + Bedrock + SES in one request). + +### Logging and alerts + +* In production the BFF logs **one JSON object per line** (`JsonLogger`, `apps/bff/src/logging/`) with `level`, `requestId`, `context`, `message`, `stack`. A stack stays inside one CloudWatch event. Use Nest's `Logger`; do not `console.log` in services. +* `lambda.ts` runs each invocation inside an `AsyncLocalStorage` context carrying `awsRequestId`, so every line, including cold-start logs, is tagged with its request. Filter CloudWatch on `requestId` to follow one request. +* The bundle keeps class names (`keepNames`) and ships its `.map`; `NODE_OPTIONS=--enable-source-maps` turns minified frames into `src/*.ts:line`. Do not remove either, or stack traces go back to `lambda.js:687:76249`. +* Log groups are explicit with retention (14 days dev, 30 prod). Prod has an alarm on API 5xx that emails via SNS. The SNS email subscription must be confirmed once by the recipient. + +## 4. Security + +* **No secrets in the repo, in `config.ts`, or in plaintext Lambda environment variables.** Store secrets as SSM `SecureString` (or Secrets Manager) and fetch them at cold start, as the GitHub client secret already does. Non-secret identifiers (client IDs, table names, region) may be plain env vars. +* Placeholders like `REPLACE_BEFORE_DEPLOYING_*` must fail loudly if they reach a deployed stage, never fall through to a working default. Enforced for `JWT_SECRET` and `WEB_ORIGIN` by `requireInProduction()`; use it for every new secret. +* CI authenticates to AWS with GitHub OIDC. No long-lived access keys anywhere. +* IAM is least privilege (see CDK section). Any wildcard resource needs a comment that explains why a narrower scope fails. +* Dev stages are locked behind WAF Basic Auth. Cookies are `httpOnly` and secure in deployed stages. +* Keep dependency policy in `pnpm-workspace.yaml` (`minimumReleaseAge`, with the first-party `@bubltec/*` scope explicitly exempted). + +## 5. AWS CDK Best Practices + +### Structure + +* `bin/app.ts` only instantiates. It creates the account-level stacks once (`BtfpDns`, `BtfpEmail`, `BtfpCi`) and one `AppStage` per environment (`BtfpDev`, `BtfpProd`). +* `AppStage` composes the per-environment stacks (`Data`, `Scraper`, `Api`, `Web`). Dev and prod are the **same composition** parameterized by `EnvConfig`. +* One stack per concern: storage in `data-stack.ts`, compute/routing in `api-stack.ts`, edge and DNS in `web-stack.ts`. A genuinely new concern (queue, scheduled job) is a new stack wired in `app-stage.ts`. +* Constants and `EnvConfig` live in `lib/config.ts`. Environment-specific behavior branches only on `envConfig.envName`, and only for real differences (removal policy, PITR, deployment preference). +* Pass resources between stacks as **typed props** (`contentTable`, `httpApi`), not string exports or `Fn.importValue`. + +### Synthesis must be deterministic and credential-free + +* `npx cdk synth "**"` must succeed with no AWS credentials. No `fromLookup`, no `valueFromLookup`. Import by attributes (`fromHostedZoneAttributes`, `fromSecureStringParameterAttributes`) with values from `config.ts`. +* No I/O, clock, or randomness at synth time. +* Pin the Docker platform (`Platform.LINUX_AMD64`) so a local Apple Silicon build and CI hash to the same image and are not deployed twice. + +### Resources + +* Prefer L2 constructs. Drop to L1 or `addPropertyOverride` only when no L2 covers it, and isolate it in a documented helper. The lesson from the Lambda alias: an SAM `AutoPublishAlias` transform plus L1 overrides was tried, needed a manual one-time `delete-alias` and five follow-up fixes (#41, #42, #44, #45, #46), and was replaced by plain `lambda.Alias` + `LambdaDeploymentGroup`. If an escape hatch needs a manual migration step, treat that as a sign to look for the native construct first. +* **Stateful vs stateless:** stateful resources use `RemovalPolicy.RETAIN` and point-in-time recovery in prod, `DESTROY` in dev. DynamoDB is `PAY_PER_REQUEST`. +* **Physical names:** do not pin explicit names on resources that may need replacement (Lambda functions, roles) because it blocks create-before-delete. Pin a name only where something external depends on it and replacement is not expected (stateful tables, the CI role), and say why. +* **IAM:** use `grant*` methods (`table.grantReadWriteData(fn)`) first. Hand-written `PolicyStatement`s scope actions and resources as tightly as the service allows, with a comment on any wildcard. +* **Lambda traffic** goes to the published `current` alias, never `$LATEST` (`publishCurrentAlias`, `infra/cdk/lib/lambda-canary.ts`). Prod passes a `canary` config, which creates a CodeDeploy deployment group with two rollback alarms. Dev passes none, so the alias flips immediately with no CodeDeploy wait. The alias is not named `live` because CloudFormation creates before it deletes, so reusing an existing alias name 409s. +* **Secrets** are referenced (SSM/Secrets Manager + `grantRead`), never inlined into the template. +* **Cost:** check `docs/infra.md` before adding anything with a fixed monthly cost (ALB, NAT, OpenSearch, always-on compute). The budget assumes everything scales to zero. + +### Verification + +* CDK tests exist under `infra/cdk` (vitest + `aws-cdk-lib/assertions`, run by the turbo `test` task). `lambda-canary.spec.ts` asserts the alias, the canary group and both alarms, and the absence of a SAM `Transform`. Add a spec for any construct helper you write. `vitest.config.ts` restricts collection to `lib/**` because `cdk.out/` holds copies of other packages' specs. +* **Before merging an `aws-cdk-lib` bump, synth every stack before and after and diff the templates** (ignore `CDKMetadata` and content hashes). A library upgrade can change generated resources silently. +* **(recommended)** Extend the specs to the other properties that matter: prod tables `RETAIN` + PITR on, Lambda role has no `*` actions. +* **(recommended)** Add `cdk-nag` (AwsSolutions pack) as an `Aspect` in `bin/app.ts`, with each suppression carrying a written reason. +* **(recommended)** Apply `Tags.of(app)` for `env`, `service`, and `owner` so cost reports can be split by stage. + +## 6. Testing + +* Runner is `vitest`. Specs live beside source as `*.spec.ts`. Each package owns its own `test` script; turbo runs them all. +* Unit-test services against fakes/mocks. Mock AWS with `aws-sdk-client-mock` through the shared `mockAws` helper. Unit tests never touch real AWS. +* Test through the real `ValidationPipe` configuration when a DTO is involved, not by constructing DTO instances by hand. +* Reproduce a bug in a failing test first, then fix it. If the failure only appears deployed, pull the actual server logs (CloudWatch) instead of inferring from a generic 500. +* `apps/e2e` (Playwright) runs against a **deployed stage**. Assert on the response body, not only the status, so a failure explains itself. +* Do not add retries to an e2e test to paper over a failure until you know whether it is infrastructure flake or a real defect. +* **Unit tests and typecheck cannot catch load-time failures.** After any dependency upgrade that touches the runtime (Nest, Fastify, swagger, a mycota release), build the Lambda bundle and drive real requests through it with `NODE_ENV=production`: a route, an unauthenticated guarded route, and an invalid body. An ESM-first dependency using `import.meta.url` compiled and passed every test, then crashed the bundle at startup. +* After changing dependencies, prove it from scratch: delete every `node_modules`, `pnpm install --frozen-lockfile`, then typecheck, build and test. A green run on an existing `node_modules` can pass only because of a stale hoisted copy. + +## 7. Tooling and Automation + +* Package manager is the pinned pnpm in `packageManager`; Node follows `engines`. Do not use npm or yarn. +* Lint and format with oxlint and oxfmt. `lefthook` runs them on staged files at commit. Do not add ESLint or Prettier alongside. +* Before opening a PR run: `pnpm turbo run typecheck lint build test`. +* `turbo.json` expresses task order (`dependsOn: ["^build"]`); do not hand-order builds in scripts. +* Use conventional-commit style PR titles (`fix:`, `feat:`). + +### Dependencies + +* **Every dependency is pinned to an exact version** (`saveExact`), so `pnpm add` records `1.2.3`. When converting existing ranges, pin to the version that is **installed** (`pnpm ls -r --depth 0 --json`), never by stripping the `^`: that silently downgrades anything installed above its range's floor. +* Check for updates against the registry (`pnpm outdated -r`). Test major bumps rather than assuming. +* **Framework and validation packages come from one copy.** `@bubltec/mycota-*` declare Nest, `class-validator`, `class-transformer`, `passport`, `reflect-metadata` and `rxjs` as **peer dependencies**, so this app owns the single copy. Verify with `pnpm why @nestjs/common`: exactly one version. Two copies break DI, and make `class-validator` decorators register into a store the `ValidationPipe` never reads. +* **Upgrade order is mycota first.** Upgrade and release `../mycota`, then bump the `@bubltec/mycota-*` pins here to the released version and run `pnpm install` to regenerate the lockfile. A branch prepared before the release cannot have a valid lockfile, and pnpm's pre-run install check will fail every `pnpm exec` in it; set `pnpm_config_verify_deps_before_run=false` for that window (the pnpm 11 prefix is `pnpm_config_`; `npm_config_` is ignored). +* `@nestjs/platform-fastify` pins `fastify` exactly as a regular dependency. The workspace `overrides` entry keeps one Fastify copy; keep it equal to `apps/bff`'s `fastify` version, or the plugin types (`@fastify/cookie`) stop lining up. +* Node comes from `.nvmrc`. Change it there only; CI reads it with `node-version-file`. + +### Build and bundling + +* The BFF builds with **`tsc` first, then `esbuild`** (`scripts/build-lambda.mjs`). `tsc` produces the decorator metadata NestJS DI needs; esbuild's own TS transform does not reproduce it reliably, and DI then silently injects `undefined`. +* Bundle to a single minified file with sourcemaps. Externalize optional Nest/Fastify peers you do not use rather than installing them. + +## 8. CI/CD + +* **Build once, deploy many.** `build` produces `bff-dist` and `web-dist` artifacts; dev and prod deploy those exact artifacts. Never rebuild per environment. +* Pipeline order: build, deploy dev, e2e against dev, `cdk diff` for prod, then prod behind a protected GitHub Environment approval. +* Jobs that touch AWS declare `permissions: { id-token: write, contents: read }` and assume the OIDC deploy role. PR-triggered runs get no AWS credentials by design. +* The OIDC `sub` claim uses immutable IDs (`owner@id/repo@id`) and changes shape when a job sets `environment:`. Keep both patterns in the trust policy and confirm against a real token. +* Deploy workflows use a non-cancelling `concurrency` group so an in-flight deploy is never aborted. +* Actions are currently pinned to a major tag (see Known deviations). +* The Node version is read from `.nvmrc` (`node-version-file`), never hard-coded in a workflow. + +## 9. Performance + +* Cold start is the dominant latency. Keep the bundle small, avoid import-time work, and reuse clients. +* Cache read-mostly data in memory with a short TTL and explicit invalidation on write, rather than adding a managed search or cache service before the dataset needs it. +* Right-size Lambda memory and timeout deliberately, and record the reason in a comment beside the value. + +## 10. Common Pitfalls + +* **Missing required nested body → 500.** `@ValidateNested()` without `@IsDefined()` lets an absent property through; the service then dereferences `undefined`. +* **Undecorated DTO property is silently stripped** by `whitelist: true`, so the field never reaches the service. +* **esbuild-only builds break Nest DI** with no error at build time. Always compile with `tsc` first. +* **`fromLookup` breaks credential-free `cdk synth`.** Import by attributes instead. +* **Pinned physical names block replacement** of the resource. +* **Routing to `$LATEST` instead of the `current` alias** bypasses canary and rollback. +* **Duplicate framework copies.** Two `@nestjs/common` or two `fastify` installs compile with confusing type errors or fail at runtime. Check `pnpm why`, and use a workspace `override` when a dependency pins an exact version. +* **A green build on an old `node_modules` proves little.** A missing `@types/node` declaration passed because a hoisted copy happened to exist. Prove dependency changes from a clean install. +* **ESM-first packages in the CJS bundle.** `import.meta.url` is an empty object after esbuild's CJS output, so a package that calls `createRequire(import.meta.url)` at load time crashes the Lambda at startup. Define `import.meta.url` in the build, and smoke-test the bundle. +* **`.npmrc` `save-exact` is ignored by pnpm 11.** Set `saveExact` in `pnpm-workspace.yaml`. +* **Passport under Fastify** needs `reply.setHeader`/`reply.end` bound to the raw response before OAuth redirects work. +* **DTO instances written to DynamoDB** need `convertClassInstanceToMap` on the document client. +* **A wrong OIDC `sub` pattern** fails `AssumeRole` only at deploy time. Check the real claim. +* **A first request after deploy is a cold start.** Timeouts and e2e waits must allow for it, but do not assume every post-deploy failure is a cold start. +* **Plaintext secrets in Lambda env vars** are visible in the console and in CloudFormation. Use SSM or Secrets Manager. + +## 11. Known Deviations + +Things this rule asks for that the repo does not do yet. Do not copy these as patterns, and do not assume they are settled. + +* **Plaintext secrets in Lambda env vars.** `JWT_SECRET` and `BRAVE_SEARCH_API_KEY` are set from CI secrets into the function's environment (visible in the console and the template). Only the GitHub client secret uses SSM. Moving them to SSM `SecureString` fetched at cold start needs the parameters created first, so it must be sequenced with a deploy. +* **Actions are pinned to a major tag, not a commit SHA**, and `actions/cache` is on a different major than the rest. There is no Dependabot config to keep pins fresh. +* **`.oxlintrc.json` sets only ignore patterns**, so oxlint runs its default rules. No extra categories or type-aware rules. +* **Full-table `Scan` on a cache miss** reads every item in the content table, including contribution rows. Fine at ~1k rows; revisit with a GSI or a dedicated partition if it grows. +* **Dev and prod share one AWS account** and one deploy role (prod is gated only by the GitHub Environment approval). +* **DTO classes duplicate `shared-types`.** A schema-first approach (for example Zod, shared between web and BFF) would end drift between the two, at the cost of a migration. Not adopted. +* **Log retention, the source-map env var and the prod 5xx alarm are written but not committed** (they live in uncommitted changes to `api-stack.ts` and `email-stack.ts`, held while an unrelated uncommitted hunk in that file is resolved). Until they land, the "Logging and alerts" bullets about retention and the alarm describe intent. + +By following these practices, you keep the BFF, shared packages, and infrastructure consistent, secure, cheap to run, and easy to change. diff --git a/.cursor/rules/recover-from-merged-branch.mdc b/.cursor/rules/recover-from-merged-branch.mdc new file mode 100644 index 0000000..2caf5d1 --- /dev/null +++ b/.cursor/rules/recover-from-merged-branch.mdc @@ -0,0 +1,28 @@ +--- +description: Stash-and-restart sequence to use when the current branch's PR already merged into main +alwaysApply: false +--- + +# Recover from a merged branch + +Use this when `sync-before-code-changes` found that the current branch's own work +already shipped (its PR merged), so follow-up work needs a fresh branch off the +latest `main`. + +**Precondition:** no merge or rebase in progress (`git rev-parse --verify MERGE_HEAD` +fails and `.git/rebase-merge` is absent). If one exists, stop and ask the user. + +1. **Confirm it merged:** + `gh pr list --state merged --head --json number,mergedAt,mergeCommit`. + A hit means the content is in `main` under a (possibly squashed) different commit. +2. **Save uncommitted work:** `git stash -u` (includes untracked files). +3. **Fast-forward `main` without checking it out:** `git fetch . origin/main:main` + from the current (non-main) branch. + - Git refuses to fetch into the *checked-out* branch, so do this **before** + switching to `main`. If you are already on `main`, use + `git merge --ff-only origin/main` instead. +4. **Branch fresh:** `git checkout -b main`. +5. **Reapply with `git stash apply`, not `pop`.** Keep the stash entry until you + have confirmed the reapplied changes are still needed and correct. Some of what + was stashed may now be redundant with what already merged. +6. Once verified, drop the stash entry (`git stash drop`). diff --git a/.cursor/rules/sync-before-code-changes.mdc b/.cursor/rules/sync-before-code-changes.mdc index 0ae3b5f..9ec76e2 100644 --- a/.cursor/rules/sync-before-code-changes.mdc +++ b/.cursor/rules/sync-before-code-changes.mdc @@ -5,17 +5,33 @@ alwaysApply: true # Sync before code changes +Work sometimes gets committed, pushed, and merged to `main` outside the current +session — a previous session, a teammate, a direct push — so local state can be +stale in ways that aren't obvious from `git status` alone. + Before **any** file edit, commit, or new branch work: 1. `git fetch origin` -2. Compare the **current branch** to its upstream and to `origin/main`: +2. Compare local `main` with `origin/main`: `git log main..origin/main --oneline` +3. Compare the **current branch**: - `git status -sb` - `git log HEAD..origin/main --oneline` (are you behind main?) - - `git log origin/main..HEAD --oneline` (unpushed / unmerged work?) -3. If this branch has (or had) an open PR, check merge state **before** stacking more commits: - - `gh pr list --head $(git branch --show-current) --state all --json number,state,mergedAt` - - If `MERGED`: do **not** keep committing on this branch. Follow `CLAUDE.md` — stash if needed, fast-forward `main`, start a **new** branch for follow-up work. - - If it is **not** merged and `git log origin/main..HEAD` is non-empty: **keep this branch**. Rebase onto `origin/main` if behind; do not open a second branch for the same line of work. -4. If `git rev-parse --verify MERGE_HEAD` or `.git/rebase-merge` exists, finish or abort that operation first; do not stash over an in-progress merge/rebase without asking the user. + - `git log origin/main..HEAD --oneline` (unpushed or unmerged work?) +4. Check whether the branch's PR already merged: + `gh pr list --head --state all --json number,state,mergedAt,mergeCommit` +5. Decide: + - **PR merged** → stop committing on this branch. Its content is already in + `main` under a (possibly squashed) different commit. Follow the + `recover-from-merged-branch` rule. + - **PR not merged, and the branch has commits not in `origin/main`** → keep + working on this branch, and rebase if it is behind. Do not start a second + branch for the same work. + - **`origin/main` moved, but this branch's PR was not merged** (genuinely + unrelated upstream work) → surface that to the user. Do not act on it + unilaterally. +6. **Merge/rebase guard.** If `git rev-parse --verify MERGE_HEAD` succeeds or + `.git/rebase-merge` exists, work to reconcile this exact situation is already + underway. Finish or abort it first, and ask the user how they want to proceed + rather than stashing over it. -Only after the branch is aligned with intent (rebased on current `main` or confirmed still the right feature branch) should you edit files. +Only edit files once the branch is aligned with intent. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03c0231..62807d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/setup-node@v7 with: - node-version: 26 + node-version-file: .nvmrc cache: pnpm - run: pnpm install --frozen-lockfile diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 48aa64c..fd08539 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -19,7 +19,7 @@ jobs: - uses: pnpm/action-setup@v6 - uses: actions/setup-node@v7 with: - node-version: 26 + node-version-file: .nvmrc cache: pnpm - run: pnpm install --frozen-lockfile @@ -58,7 +58,7 @@ jobs: - uses: pnpm/action-setup@v6 - uses: actions/setup-node@v7 with: - node-version: 26 + node-version-file: .nvmrc cache: pnpm - run: pnpm install --frozen-lockfile @@ -104,7 +104,7 @@ jobs: - uses: pnpm/action-setup@v6 - uses: actions/setup-node@v7 with: - node-version: 26 + node-version-file: .nvmrc cache: pnpm - run: pnpm install --frozen-lockfile @@ -185,7 +185,7 @@ jobs: - uses: pnpm/action-setup@v6 - uses: actions/setup-node@v7 with: - node-version: 26 + node-version-file: .nvmrc cache: pnpm - run: pnpm install --frozen-lockfile @@ -245,7 +245,7 @@ jobs: - uses: pnpm/action-setup@v6 - uses: actions/setup-node@v7 with: - node-version: 26 + node-version-file: .nvmrc cache: pnpm - run: pnpm install --frozen-lockfile @@ -327,7 +327,7 @@ jobs: - uses: pnpm/action-setup@v6 - uses: actions/setup-node@v7 with: - node-version: 26 + node-version-file: .nvmrc cache: pnpm - run: pnpm install --frozen-lockfile diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..d763315 --- /dev/null +++ b/.npmrc @@ -0,0 +1,4 @@ +# Record exact versions when adding dependencies (`add x` writes "1.2.3", not "^1.2.3"). +# pnpm 11 ignores this file for save-exact and reads `saveExact` from +# pnpm-workspace.yaml instead (both are set). npm and older pnpm read this one. +save-exact=true diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..b2d464d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,23 @@ +# Agent instructions + +**The source of truth for agent instructions in this repo is [`.cursor/rules/`](.cursor/rules/).** +Read the rules there before making changes. Rules with `alwaysApply: true` always +apply; the others apply when their `globs` match the files you are touching, or when +their `description` fits the task. + +This file and `CLAUDE.md` are pointers only. Do not add rules here. Add or change +them in `.cursor/rules/`, so there is exactly one place to keep current. + +| Rule | Applies | Covers | +| --- | --- | --- | +| [`sync-before-code-changes`](.cursor/rules/sync-before-code-changes.mdc) | always | Fetch origin, compare `main` and the current branch, check whether the branch's PR merged, and the merge/rebase guard | +| [`recover-from-merged-branch`](.cursor/rules/recover-from-merged-branch.mdc) | on request | The stash-and-restart sequence when a branch's PR already merged | +| [`bff-typescript-cdk-best-practices`](.cursor/rules/bff-typescript-cdk-best-practices.mdc) | globs | Repo layout, NestJS BFF on Lambda, validation, config and secrets, AWS CDK conventions, testing, CI/CD | + +Also in this repo: + +- [`.claude/skills/`](.claude/skills/) holds Claude Code task playbooks (adding an API + endpoint, an infra resource, or a thing type). They follow the conventions in the rules above. +- [`docs/`](docs/) holds human-facing architecture, data model, CI/CD and infra notes. +- The sibling library repo `../mycota` publishes the `@bubltec/mycota-*` packages this app + consumes, and has its own `.cursor/rules/`. diff --git a/CLAUDE.md b/CLAUDE.md index 81dc08f..98f2931 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,39 +1,12 @@ # Working in this repo -## Check for upstream changes before starting work +Agent instructions live in [`.cursor/rules/`](.cursor/rules/), the single source of +truth (see [AGENTS.md](AGENTS.md) for the index). Do not add rules to this file. -Before making any changes, run `git fetch origin` and compare local `main` -against `origin/main` (`git log main..origin/main --oneline`). Work -sometimes gets committed, pushed, and merged to `main` outside the current -session — a previous session, a teammate, a direct push — so local state -can be stale in ways that aren't obvious from `git status` alone. +The always-apply rules are imported here so Claude Code loads them every session: -Also check the **current branch** before editing: `git log HEAD..origin/main ---oneline` and whether its PR is already merged (`gh pr list --head - --state all`). If the PR merged, stop committing on that branch — -rebase or branch fresh from `origin/main` for follow-ups (see step 2 below). -If the PR is **not** merged and the branch already has commits not in -`origin/main`, keep working on that branch (rebase if behind); do not start -a second branch for the same work. +@.cursor/rules/sync-before-code-changes.mdc +@.cursor/rules/recover-from-merged-branch.mdc -If `origin/main` has commits not in local `main`: - -1. Check whether the **current branch's own work** already shipped — - `gh pr list --state merged --head --json number,mergedAt,mergeCommit`. - If a merged PR shows up for this exact branch, its content is already in - `main` under a (possibly squashed) different commit. -2. If so: `git stash -u` (uncommitted work, including untracked files), - `git checkout main`, `git fetch . origin/main:main` to fast-forward, - `git checkout -b ` for whatever comes next, then - `git stash apply` (not `pop` — keep the stash entry until you've - confirmed the reapplied changes are actually still needed/correct, since - some of what was stashed may now be redundant with what already merged). -3. If `origin/main` moved but the *current* branch's PR was **not** merged - (i.e., it's genuinely unrelated upstream work), just surface that to the - user — don't act on it unilaterally. - -Only do the stash-and-restart sequence when there's no merge/rebase already -in progress (`git rev-parse --verify MERGE_HEAD` / `.git/rebase-merge` both -absent) — if one exists, that means work to reconcile this exact situation -is already underway; ask the user how they want to proceed instead of -stashing over it. +Read `.cursor/rules/bff-typescript-cdk-best-practices.mdc` before changing the BFF, +shared packages, infrastructure, tests or CI. diff --git a/apps/bff/Dockerfile b/apps/bff/Dockerfile index 0e17873..b0097b7 100644 --- a/apps/bff/Dockerfile +++ b/apps/bff/Dockerfile @@ -7,6 +7,8 @@ # until AWS GA (~Nov 2026); it's still Node 26. FROM public.ecr.aws/lambda/nodejs:26-preview -COPY dist/lambda.js ${LAMBDA_TASK_ROOT}/ +# The .map is what lets NODE_OPTIONS=--enable-source-maps (set in api-stack.ts) +# turn minified stack traces back into real file:line. +COPY dist/lambda.js dist/lambda.js.map ${LAMBDA_TASK_ROOT}/ CMD ["lambda.handler"] diff --git a/apps/bff/package.json b/apps/bff/package.json index 0f83963..c319c4d 100644 --- a/apps/bff/package.json +++ b/apps/bff/package.json @@ -10,42 +10,42 @@ "test": "vitest run" }, "dependencies": { - "@aws-sdk/client-bedrock-runtime": "^3.716.0", - "@aws-sdk/client-dynamodb": "^3.716.0", - "@aws-sdk/client-ses": "^3.716.0", - "@aws-sdk/client-ssm": "^3.716.0", - "@aws-sdk/lib-dynamodb": "^3.716.0", + "@aws-sdk/client-bedrock-runtime": "3.1136.0", + "@aws-sdk/client-dynamodb": "3.1136.0", + "@aws-sdk/client-ses": "3.1136.0", + "@aws-sdk/client-ssm": "3.1136.0", + "@aws-sdk/lib-dynamodb": "3.1136.0", "@btfp/shared-types": "workspace:*", - "@bubltec/mycota-auth": "0.6.0", - "@bubltec/mycota-dynamo": "0.6.0", - "@bubltec/mycota-professional-verification": "0.6.0", - "@fastify/aws-lambda": "^4.1.0", - "@fastify/cookie": "^9.4.0", - "@nestjs/common": "^10.4.0", - "@nestjs/config": "^3.3.0", - "@nestjs/core": "^10.4.0", - "@nestjs/jwt": "^10.2.0", - "@nestjs/passport": "^10.0.3", - "@nestjs/platform-fastify": "^10.4.0", - "@nestjs/swagger": "^8.1.1", - "class-transformer": "^0.5.1", - "class-validator": "^0.14.1", - "fastify": "^4.28.1", - "fuse.js": "^7.0.0", - "passport": "^0.7.0", - "passport-github2": "^0.1.12", - "passport-google-oauth20": "^2.0.0", - "reflect-metadata": "^0.2.2", - "rxjs": "^7.8.1" + "@bubltec/mycota-auth": "1.0.0", + "@bubltec/mycota-dynamo": "1.0.0", + "@bubltec/mycota-professional-verification": "1.0.0", + "@fastify/aws-lambda": "6.4.1", + "@fastify/cookie": "11.1.2", + "@nestjs/common": "12.0.3", + "@nestjs/config": "12.0.0", + "@nestjs/core": "12.0.3", + "@nestjs/jwt": "12.0.2", + "@nestjs/passport": "12.0.0", + "@nestjs/platform-fastify": "12.0.3", + "@nestjs/swagger": "12.0.1", + "class-transformer": "0.5.1", + "class-validator": "0.15.1", + "fastify": "5.12.5", + "fuse.js": "7.5.0", + "passport": "0.7.0", + "passport-github2": "0.1.12", + "passport-google-oauth20": "2.0.0", + "reflect-metadata": "0.2.2", + "rxjs": "7.8.2" }, "devDependencies": { - "aws-sdk-client-mock": "^4.1.0", - "@types/node": "^26.6.1", - "@types/passport-github2": "^1.2.9", - "@types/passport-google-oauth20": "^2.0.16", - "esbuild": "^0.24.2", - "tsc-watch": "^7.2.1", - "typescript": "^5.8.0", - "vitest": "^2.1.0" + "@types/node": "26.6.2", + "@types/passport-github2": "1.2.9", + "@types/passport-google-oauth20": "2.0.17", + "aws-sdk-client-mock": "4.1.0", + "esbuild": "0.28.2", + "tsc-watch": "7.2.1", + "typescript": "7.0.2", + "vitest": "5.0.1" } } diff --git a/apps/bff/scripts/build-lambda.mjs b/apps/bff/scripts/build-lambda.mjs index cb6c21e..a187545 100644 --- a/apps/bff/scripts/build-lambda.mjs +++ b/apps/bff/scripts/build-lambda.mjs @@ -34,8 +34,16 @@ await build({ // fallback is unreachable at runtime. 'class-transformer/storage', ], + // @nestjs/swagger 12 is ESM-first and runs `createRequire(import.meta.url)` at + // load time. esbuild turns import.meta into an empty object in CJS output, so + // that call throws and the whole Lambda fails to start. Give it a real value. + banner: { js: "const __importMetaUrl = require('node:url').pathToFileURL(__filename).href;" }, + define: { 'import.meta.url': '__importMetaUrl' }, sourcemap: true, minify: true, + // Minification mangles class names, which are what Nest prints as its log + // context ("[e]" instead of "[SearchService]"). Keep them; the size cost is small. + keepNames: true, logLevel: 'info', }); diff --git a/apps/bff/src/app.module.ts b/apps/bff/src/app.module.ts index a56ecb9..983a9e5 100644 --- a/apps/bff/src/app.module.ts +++ b/apps/bff/src/app.module.ts @@ -2,7 +2,7 @@ import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { BffDynamoModule } from './dynamo/bff-dynamo.module.js'; import { MycotaAuthModule } from '@bubltec/mycota-auth'; -import { ProfessionalVerificationModule } from '@bubltec/mycota-professional-verification'; +import { ProfessionalVerificationModule } from './professional-verification/professional-verification.module.js'; import { PetTypesModule } from './pet-types/pet-types.module.js'; import { BreedsModule } from './breeds/breeds.module.js'; import { ThingTypesModule } from './thing-types/thing-types.module.js'; diff --git a/apps/bff/src/app.ts b/apps/bff/src/app.ts index 89cc51c..65fc510 100644 --- a/apps/bff/src/app.ts +++ b/apps/bff/src/app.ts @@ -5,11 +5,14 @@ import { ValidationPipe } from '@nestjs/common'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import fastifyCookie from '@fastify/cookie'; import { AppModule } from './app.module.js'; +import { corsOrigin, isProduction } from './env.js'; +import { JsonLogger } from './logging/json-logger.js'; import { StageErrorFilter } from './filters/stage-error.filter.js'; +import { VALIDATION_PIPE_OPTIONS } from './validation.js'; export async function createApp(adapter: FastifyAdapter): Promise { const app = await NestFactory.create(AppModule, adapter, { - logger: ['error', 'warn', 'log'], + logger: isProduction() ? new JsonLogger() : ['error', 'warn', 'log'], }); await app.register(fastifyCookie); @@ -34,10 +37,10 @@ export async function createApp(adapter: FastifyAdapter): Promise { const db = mockAws(DynamoDBDocumentClient); db.on(PutCommand).resolves({}); + db.on(QueryCommand).resolves({ Items: [] }); const dto = (await pipe.transform(e2eSubmitBody, { type: 'body', @@ -40,9 +42,11 @@ describe('Contributions POST pipeline (ValidationPipe → propose → PutCommand })) as CreateContributionDto; const service = new ContributionsService( - DynamoDBDocumentClient.from(new DynamoDBClient({}), { - marshallOptions: { removeUndefinedValues: true, convertClassInstanceToMap: false }, - }), + new DynamoPendingContributionStore( + DynamoDBDocumentClient.from(new DynamoDBClient({}), { + marshallOptions: { removeUndefinedValues: true, convertClassInstanceToMap: false }, + }), + ), {} as never, {} as never, { findDuplicate: vi.fn().mockResolvedValue(undefined) } as unknown as SearchService, diff --git a/apps/bff/src/contributions/contributions.service.spec.ts b/apps/bff/src/contributions/contributions.service.spec.ts index c924898..f5a7680 100644 --- a/apps/bff/src/contributions/contributions.service.spec.ts +++ b/apps/bff/src/contributions/contributions.service.spec.ts @@ -3,11 +3,29 @@ import { describe, expect, it, vi } from 'vitest'; import { BadRequestException, ValidationPipe } from '@nestjs/common'; import { CreateContributionDto } from './dto/create-contribution.dto.js'; import { mockAws } from '../test-utils.js'; -import { DynamoDBDocumentClient, PutCommand, QueryCommand } from '@aws-sdk/lib-dynamodb'; +import { + DynamoDBDocumentClient, + PutCommand, + QueryCommand, + UpdateCommand, +} from '@aws-sdk/lib-dynamodb'; import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; import { ContributionsService } from './contributions.service.js'; +import { DynamoPendingContributionStore } from './dynamo-pending-contribution.store.js'; import type { SearchService } from '../search/search.service.js'; +function contributionsService( + db: DynamoDBDocumentClient, + search: SearchService, +): ContributionsService { + return new ContributionsService( + new DynamoPendingContributionStore(db), + {} as never, + {} as never, + search, + ); +} + const e2ePayload: CreateContributionDto = { payload: { name: 'Chocolate', @@ -24,18 +42,16 @@ describe('ContributionsService.propose', () => { it('plainifies ValidationPipe class instances before PutCommand', async () => { const db = mockAws(DynamoDBDocumentClient); db.on(PutCommand).resolves({}); + db.on(QueryCommand).resolves({ Items: [] }); const dto = (await pipe.transform(e2ePayload, { type: 'body', metatype: CreateContributionDto, })) as CreateContributionDto; - const service = new ContributionsService( - DynamoDBDocumentClient.from(new DynamoDBClient({})), - {} as never, - {} as never, - { findDuplicate: vi.fn().mockResolvedValue(undefined) } as unknown as SearchService, - ); + const service = contributionsService(DynamoDBDocumentClient.from(new DynamoDBClient({})), { + findDuplicate: vi.fn().mockResolvedValue(undefined), + } as unknown as SearchService); await service.propose(dto, 'e2e-user'); const item = db.commandCalls(PutCommand)[0]?.args[0].input.Item as Record; @@ -48,15 +64,14 @@ describe('ContributionsService.propose', () => { it('writes the same DynamoDB item shape as the scraper (new thing, no duplicate)', async () => { const db = mockAws(DynamoDBDocumentClient); db.on(PutCommand).resolves({}); + db.on(QueryCommand).resolves({ Items: [] }); const search = { findDuplicate: vi.fn().mockResolvedValue(undefined), } as unknown as SearchService; - const service = new ContributionsService( + const service = contributionsService( DynamoDBDocumentClient.from(new DynamoDBClient({})), - {} as never, - {} as never, search, ); @@ -74,18 +89,16 @@ describe('ContributionsService.propose', () => { }); it('rejects a session with no contributor id', async () => { - const service = new ContributionsService( - DynamoDBDocumentClient.from(new DynamoDBClient({})), - {} as never, - {} as never, - { findDuplicate: vi.fn() } as unknown as SearchService, - ); + const service = contributionsService(DynamoDBDocumentClient.from(new DynamoDBClient({})), { + findDuplicate: vi.fn(), + } as unknown as SearchService); await expect(service.propose(e2ePayload, ' ')).rejects.toBeInstanceOf(BadRequestException); }); it('ignores a blank duplicate id and creates a new Thing partition', async () => { const db = mockAws(DynamoDBDocumentClient); db.on(PutCommand).resolves({}); + db.on(QueryCommand).resolves({ Items: [] }); const search = { findDuplicate: vi @@ -93,10 +106,8 @@ describe('ContributionsService.propose', () => { .mockResolvedValue({ id: ' ', name: 'Chocolate', thingTypeId: 'food' }), } as unknown as SearchService; - const service = new ContributionsService( + const service = contributionsService( DynamoDBDocumentClient.from(new DynamoDBClient({})), - {} as never, - {} as never, search, ); @@ -109,6 +120,7 @@ describe('ContributionsService.propose', () => { it('attaches to an existing Thing id when findDuplicate matches', async () => { const db = mockAws(DynamoDBDocumentClient); db.on(PutCommand).resolves({}); + db.on(QueryCommand).resolves({ Items: [] }); const search = { findDuplicate: vi.fn().mockResolvedValue({ @@ -118,10 +130,8 @@ describe('ContributionsService.propose', () => { }), } as unknown as SearchService; - const service = new ContributionsService( + const service = contributionsService( DynamoDBDocumentClient.from(new DynamoDBClient({})), - {} as never, - {} as never, search, ); @@ -131,6 +141,58 @@ describe('ContributionsService.propose', () => { const item = db.commandCalls(PutCommand)[0]?.args[0].input.Item as Record; expect(item.PK).toBe('THING#existing-chocolate'); }); + + it('merges a later Chocolate submit into the existing pending row', async () => { + const db = mockAws(DynamoDBDocumentClient); + db.on(QueryCommand).resolves({ + Items: [ + { + id: 'queued', + PK: 'THING#existing-chocolate', + SK: 'CONTRIB#2026-01-01T00:00:00.000Z#e2e-user', + thingId: 'existing-chocolate', + contributorId: 'e2e-user', + status: 'pending', + createdAt: '2026-01-01T00:00:00.000Z', + payload: { name: 'Chocolate', thingTypeId: 'food', details: { notes: 'theobromine' } }, + }, + ], + }); + db.on(UpdateCommand).resolves({}); + + const service = contributionsService(DynamoDBDocumentClient.from(new DynamoDBClient({})), { + findDuplicate: vi.fn().mockResolvedValue({ + id: 'existing-chocolate', + name: 'Chocolate', + thingTypeId: 'food', + }), + } as unknown as SearchService); + + const contribution = await service.propose( + { + payload: { + name: 'Chocolate', + thingTypeId: 'food', + petTypes: [{ petTypeId: 'dog', severity: 'unknown' }], + details: { notes: 'theobromine', clinicalSigns: 'vomiting' }, + source: 'e2e', + }, + }, + 'e2e-user', + ); + + expect(db.commandCalls(PutCommand)).toHaveLength(0); + expect(contribution.thingId).toBe('existing-chocolate'); + expect(contribution.payload.details).toEqual({ + notes: 'theobromine', + clinicalSigns: 'vomiting', + }); + const update = db.commandCalls(UpdateCommand)[0]?.args[0].input; + expect(update.Key).toEqual({ + PK: 'THING#existing-chocolate', + SK: 'CONTRIB#2026-01-01T00:00:00.000Z#e2e-user', + }); + }); }); describe('ContributionsService.listPending', () => { @@ -149,16 +211,42 @@ describe('ContributionsService.listPending', () => { ], }); - const service = new ContributionsService( - DynamoDBDocumentClient.from(new DynamoDBClient({})), - {} as never, - {} as never, - { findDuplicate: vi.fn() } as unknown as SearchService, - ); + const service = contributionsService(DynamoDBDocumentClient.from(new DynamoDBClient({})), { + findDuplicate: vi.fn(), + } as unknown as SearchService); const pending = await service.listPending(); expect(pending).toHaveLength(1); expect(pending[0]?.payload).toMatchObject({ name: 'Xylitol' }); expect(db.commandCalls(QueryCommand)[0]?.args[0].input.ScanIndexForward).toBe(false); }); + + it('shows one queue card for several pending Chocolate edits', async () => { + const db = mockAws(DynamoDBDocumentClient); + db.on(QueryCommand).resolves({ + Items: [ + { + id: '1', + createdAt: '2026-01-02T00:00:00.000Z', + thingId: 'choc', + payload: { name: 'Chocolate', thingTypeId: 'food' }, + }, + { + id: '2', + createdAt: '2026-01-01T00:00:00.000Z', + thingId: 'choc', + payload: { name: 'Chocolate', thingTypeId: 'food', details: { notes: 'toxic' } }, + }, + ], + }); + + const service = contributionsService(DynamoDBDocumentClient.from(new DynamoDBClient({})), { + findDuplicate: vi.fn(), + } as unknown as SearchService); + + const pending = await service.listPending(); + expect(pending).toHaveLength(1); + expect(pending[0]?.id).toBe('1'); + expect(pending[0]?.payload.details).toEqual({ notes: 'toxic' }); + }); }); diff --git a/apps/bff/src/contributions/contributions.service.ts b/apps/bff/src/contributions/contributions.service.ts index c7a1ad8..531c813 100644 --- a/apps/bff/src/contributions/contributions.service.ts +++ b/apps/bff/src/contributions/contributions.service.ts @@ -1,25 +1,26 @@ -import { BadRequestException, Inject, Injectable, NotFoundException } from '@nestjs/common'; +import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; import { instanceToPlain } from 'class-transformer'; import { randomUUID } from 'node:crypto'; import { - GetCommand, - PutCommand, - QueryCommand, - UpdateCommand, - DynamoDBDocumentClient, -} from '@aws-sdk/lib-dynamodb'; -import { mergeThings, type Contribution, type Thing, type ThingIdentity } from '@btfp/shared-types'; -import { DYNAMO_DOC_CLIENT } from '@bubltec/mycota-dynamo'; + clusterPendingContributions, + contributionsMatch, + mergeThingPayload, + mergeThings, + planContributionAttach, + type Contribution, + type Thing, + type ThingIdentity, +} from '@btfp/shared-types'; import { UsersService } from '@bubltec/mycota-auth'; -import { CONTENT_TABLE_NAME } from '../dynamo/dynamo.constants.js'; import { ThingsService } from '../things/things.service.js'; import { SearchService } from '../search/search.service.js'; import type { CreateContributionDto } from './dto/create-contribution.dto.js'; +import { PendingContributionStore, type PendingRow } from './pending-contribution.store.js'; @Injectable() export class ContributionsService { constructor( - @Inject(DYNAMO_DOC_CLIENT) private readonly db: DynamoDBDocumentClient, + private readonly queue: PendingContributionStore, private readonly things: ThingsService, private readonly users: UsersService, private readonly search: SearchService, @@ -34,81 +35,60 @@ export class ContributionsService { throw new BadRequestException('payload.name and payload.thingTypeId are required'); } - const id = randomUUID(); - const now = new Date().toISOString(); - const linkedThingId = normalizeLinkedThingId(dto.thingId); - const duplicateId = - !linkedThingId && dto.payload.name && dto.payload.thingTypeId - ? normalizeLinkedThingId((await this.search.findDuplicate(dto.payload))?.id) - : undefined; - const existingId = linkedThingId ?? duplicateId; - // ValidationPipe leaves nested DTOs as class instances; Dynamo's - // marshaller rejects those unless convertClassInstanceToMap is enabled. const payload = JSON.parse( JSON.stringify(instanceToPlain(dto.payload)), ) as Contribution['payload']; - const contribution: Contribution = { - id, - thingId: existingId, - contributorId: contributor, - status: 'pending', - payload, - createdAt: now, - }; - - const targetThingId = existingId ?? id; - // Document client on Lambda does not strip undefined attributes — a missing - // thingId on new submissions must be omitted, not set to undefined. - const item: Record = { - ...contribution, - PK: `THING#${targetThingId}`, - SK: `CONTRIB#${now}#${contributor}`, - GSI2PK: 'STATUS#pending', - GSI2SK: `CONTRIB#${now}`, - }; - if (existingId === undefined) delete item.thingId; - - await this.db.send( - new PutCommand({ - TableName: CONTENT_TABLE_NAME, - Item: item, - }), - ); + const identity = payload as ThingIdentity; + const linkedThingId = normalizeLinkedThingId(dto.thingId); + const catalogMatchId = !linkedThingId + ? normalizeLinkedThingId((await this.search.findDuplicate(identity))?.id) + : undefined; + // Full pending set (not Limit) so attach can see older cards of the same + // identity. The queue is small; this is a GSI Query, not a table Scan. + const pending = await this.queue.listAll(); + const { pendingMatch, thingId } = planContributionAttach({ + payload: identity, + explicitThingId: linkedThingId, + catalogMatchId, + pending, + }); + + if (pendingMatch) { + const existing = pendingMatch as PendingRow; + const merged = mergeThingPayload(existing.payload, payload); + const linked = thingId ?? existing.thingId; + if (!existing.SK) { + return this.insertPending(payload, linked, contributor); + } + await this.queue.accumulate(existing, payload, linked); + return { ...existing, payload: merged, thingId: linked }; + } - return contribution; + return this.insertPending(payload, thingId, contributor); } async listPending(limit = 50): Promise { - const result = await this.db.send( - new QueryCommand({ - TableName: CONTENT_TABLE_NAME, - IndexName: 'GSI2', - KeyConditionExpression: 'GSI2PK = :pk', - ExpressionAttributeValues: { ':pk': 'STATUS#pending' }, - // Newest first so recent scraper/user rows aren't buried under - // pre-payload legacy contribs (which we drop below). - ScanIndexForward: false, - Limit: limit, - }), - ); - return ((result.Items ?? []) as Contribution[]).filter(hasPayload); + return clusterPendingContributions(await this.queue.listAll()).slice(0, limit); } async approve(thingId: string, sk: string, reviewerId: string): Promise { - const existing = await this.db.send( - new GetCommand({ TableName: CONTENT_TABLE_NAME, Key: { PK: `THING#${thingId}`, SK: sk } }), - ); - const contribution = existing.Item as (Contribution & { PK: string; SK: string }) | undefined; + const contribution = await this.queue.get(thingId, sk); if (!contribution) throw new NotFoundException('Contribution not found'); if (!hasPayload(contribution)) { throw new BadRequestException('Contribution is missing payload and cannot be approved'); } + const siblings = (await this.queue.listAll()).filter( + (row) => + row.SK !== contribution.SK && hasPayload(row) && contributionsMatch(contribution, row), + ); + let payload = contribution.payload; + for (const sibling of siblings) { + payload = mergeThingPayload(payload, sibling.payload); + } + const now = new Date().toISOString(); const contributor = await this.users.getById(contribution.contributorId); - const payload = contribution.payload; - // Explicit edits target contribution.thingId. A "new" thing that matches - // an existing row is folded into that row instead of inserting a duplicate. const duplicate = !contribution.thingId && payload.name && payload.thingTypeId ? await this.search.findDuplicate(payload as ThingIdentity) @@ -117,18 +97,13 @@ export class ContributionsService { ? await this.things.getById(contribution.thingId) : (duplicate ?? null); - const details = { ...existingThing?.details, ...payload.details }; - if (contributor?.professional?.status === 'verified') { - details.verifiedOrgDomain = contributor.professional.domain; - } - const incoming: Thing = { id: existingThing?.id ?? contribution.thingId ?? thingId, name: payload.name ?? existingThing?.name ?? 'Unnamed', otherNames: payload.otherNames ?? existingThing?.otherNames ?? [], thingTypeId: payload.thingTypeId ?? existingThing?.thingTypeId ?? 'unknown', petTypes: payload.petTypes ?? existingThing?.petTypes ?? [], - details, + details: payload.details ?? {}, source: payload.source ?? existingThing?.source ?? `contributor:${contribution.contributorId}`, sourceUrl: payload.sourceUrl ?? existingThing?.sourceUrl, @@ -140,40 +115,41 @@ export class ContributionsService { const thing: Thing = !existingThing ? incoming - : contribution.thingId - ? { - ...existingThing, - ...incoming, - id: existingThing.id, - details, - createdAt: existingThing.createdAt, - } - : { - ...mergeThings(existingThing, incoming), - verified: true, - contributorId: contribution.contributorId, - updatedAt: now, - details, - }; + : { + ...mergeThings(existingThing, incoming), + verified: true, + contributorId: contribution.contributorId, + updatedAt: now, + }; + if (contributor?.professional?.status === 'verified') { + thing.details = { + ...thing.details, + verifiedOrgDomain: contributor.professional.domain, + }; + } await this.things.putThing(thing); - - await this.db.send( - new UpdateCommand({ - TableName: CONTENT_TABLE_NAME, - Key: { PK: `THING#${thingId}`, SK: sk }, - UpdateExpression: - 'SET #status = :approved, reviewedAt = :now, reviewerId = :reviewer REMOVE GSI2PK, GSI2SK', - ExpressionAttributeNames: { '#status': 'status' }, - ExpressionAttributeValues: { - ':approved': 'approved', - ':now': now, - ':reviewer': reviewerId, - }, - }), - ); - + await this.queue.markApproved([contribution, ...siblings], reviewerId, now); return thing; } + + private async insertPending( + payload: Contribution['payload'], + thingId: string | undefined, + contributorId: string, + ): Promise { + const id = randomUUID(); + const now = new Date().toISOString(); + const contribution: Contribution = { + id, + thingId, + contributorId, + status: 'pending', + payload, + createdAt: now, + }; + await this.queue.insert(contribution, thingId); + return contribution; + } } function hasPayload(item: Contribution | undefined): item is Contribution { diff --git a/apps/bff/src/contributions/create-contribution.dto.spec.ts b/apps/bff/src/contributions/create-contribution.dto.spec.ts index c5cb697..29a3849 100644 --- a/apps/bff/src/contributions/create-contribution.dto.spec.ts +++ b/apps/bff/src/contributions/create-contribution.dto.spec.ts @@ -1,10 +1,13 @@ import 'reflect-metadata'; -import { ValidationPipe } from '@nestjs/common'; +import { BadRequestException, ValidationPipe } from '@nestjs/common'; import { describe, expect, it } from 'vitest'; +import { VALIDATION_PIPE_OPTIONS } from '../validation.js'; import { CreateContributionDto } from './dto/create-contribution.dto.js'; -/** Same pipe as apps/bff/src/app.ts — regressions here broke deploy e2e twice. */ -const pipe = new ValidationPipe({ whitelist: true, transform: true }); +/** The real pipe config — regressions here broke deploy e2e repeatedly. */ +const pipe = new ValidationPipe(VALIDATION_PIPE_OPTIONS); +const run = (body: unknown) => + pipe.transform(body, { type: 'body', metatype: CreateContributionDto }); const e2eSubmitBody = { payload: { @@ -21,11 +24,8 @@ const e2eSubmitBody = { }; describe('CreateContributionDto (ValidationPipe)', () => { - it('keeps nested payload through whitelist: true', async () => { - const dto = (await pipe.transform(e2eSubmitBody, { - type: 'body', - metatype: CreateContributionDto, - })) as CreateContributionDto; + it('keeps nested payload through the real pipe config', async () => { + const dto = (await run(e2eSubmitBody)) as CreateContributionDto; expect(dto.payload.name).toBe('Chocolate'); expect(dto.payload.thingTypeId).toBe('food'); @@ -34,11 +34,26 @@ describe('CreateContributionDto (ValidationPipe)', () => { expect(dto.payload.source).toContain('aspca.org'); }); + it('accepts an edit: thingId is a top-level field', async () => { + const dto = (await run({ ...e2eSubmitBody, thingId: 'thing-1' })) as CreateContributionDto; + expect(dto.thingId).toBe('thing-1'); + }); + it('leaves payload as class instances (must be plainified before Dynamo writes)', async () => { - const dto = (await pipe.transform(e2eSubmitBody, { - type: 'body', - metatype: CreateContributionDto, - })) as CreateContributionDto; + const dto = (await run(e2eSubmitBody)) as CreateContributionDto; expect(dto.payload.constructor.name).not.toBe('Object'); }); + + it('rejects a body with no payload (400, not a 500 later in the service)', async () => { + await expect(run({})).rejects.toThrow(BadRequestException); + }); + + it('rejects a thingId buried inside payload instead of silently dropping it', async () => { + const body = { payload: { ...e2eSubmitBody.payload, thingId: 'thing-1' } }; + await expect(run(body)).rejects.toThrow(BadRequestException); + }); + + it('rejects unknown top-level fields', async () => { + await expect(run({ ...e2eSubmitBody, extra: true })).rejects.toThrow(BadRequestException); + }); }); diff --git a/apps/bff/src/contributions/dynamo-pending-contribution.store.ts b/apps/bff/src/contributions/dynamo-pending-contribution.store.ts new file mode 100644 index 0000000..d8e38ca --- /dev/null +++ b/apps/bff/src/contributions/dynamo-pending-contribution.store.ts @@ -0,0 +1,126 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { + GetCommand, + PutCommand, + QueryCommand, + UpdateCommand, + DynamoDBDocumentClient, +} from '@aws-sdk/lib-dynamodb'; +import { mergeThingPayload, type Contribution } from '@btfp/shared-types'; +import { DYNAMO_DOC_CLIENT } from '@bubltec/mycota-dynamo'; +import { CONTENT_TABLE_NAME } from '../dynamo/dynamo.constants.js'; +import { PendingContributionStore, type PendingRow } from './pending-contribution.store.js'; + +@Injectable() +export class DynamoPendingContributionStore extends PendingContributionStore { + constructor(@Inject(DYNAMO_DOC_CLIENT) private readonly db: DynamoDBDocumentClient) { + super(); + } + + async listAll(): Promise { + const items: PendingRow[] = []; + let lastKey: Record | undefined; + do { + const result = await this.db.send( + new QueryCommand({ + TableName: CONTENT_TABLE_NAME, + IndexName: 'GSI2', + KeyConditionExpression: 'GSI2PK = :pk', + ExpressionAttributeValues: { ':pk': 'STATUS#pending' }, + ScanIndexForward: false, + ExclusiveStartKey: lastKey, + }), + ); + items.push( + ...((result.Items ?? []) as PendingRow[]).filter(hasPayload).map(sanitizePendingRow), + ); + lastKey = result.LastEvaluatedKey as Record | undefined; + } while (lastKey); + return items; + } + + async get(thingId: string, sk: string): Promise { + const result = await this.db.send( + new GetCommand({ + TableName: CONTENT_TABLE_NAME, + Key: { PK: `THING#${thingId}`, SK: sk }, + }), + ); + return result.Item ? sanitizePendingRow(result.Item as PendingRow) : undefined; + } + + async insert(contribution: Contribution, thingId: string | undefined): Promise { + const targetThingId = thingId ?? contribution.id; + const item: Record = { + ...contribution, + PK: `THING#${targetThingId}`, + SK: `CONTRIB#${contribution.createdAt}#${contribution.contributorId}`, + GSI2PK: 'STATUS#pending', + GSI2SK: `CONTRIB#${contribution.createdAt}`, + }; + if (thingId === undefined) delete item.thingId; + await this.db.send(new PutCommand({ TableName: CONTENT_TABLE_NAME, Item: item })); + } + + async accumulate( + existing: PendingRow, + incoming: Contribution['payload'], + thingId: string | undefined, + ): Promise { + const pk = existing.PK ?? `THING#${existing.thingId ?? existing.id}`; + const sk = existing.SK; + if (!sk) { + throw new Error('Pending contribution is missing SK'); + } + const payload = mergeThingPayload(existing.payload, incoming); + const linked = thingId ?? existing.thingId; + await this.db.send( + new UpdateCommand({ + TableName: CONTENT_TABLE_NAME, + Key: { PK: pk, SK: sk }, + UpdateExpression: linked + ? 'SET payload = :payload, thingId = :thingId' + : 'SET payload = :payload', + ExpressionAttributeValues: { + ':payload': payload, + ...(linked ? { ':thingId': linked } : {}), + }, + }), + ); + } + + async markApproved(rows: PendingRow[], reviewerId: string, now: string): Promise { + for (const row of rows) { + if (!row.PK || !row.SK) continue; + await this.db.send( + new UpdateCommand({ + TableName: CONTENT_TABLE_NAME, + Key: { PK: row.PK, SK: row.SK }, + UpdateExpression: + 'SET #status = :approved, reviewedAt = :now, reviewerId = :reviewer REMOVE GSI2PK, GSI2SK', + ExpressionAttributeNames: { '#status': 'status' }, + ExpressionAttributeValues: { + ':approved': 'approved', + ':now': now, + ':reviewer': reviewerId, + }, + }), + ); + } + } +} + +function hasPayload(item: Contribution | undefined): item is Contribution { + return Boolean(item?.payload && typeof item.payload === 'object'); +} + +function sanitizePendingRow(row: PendingRow): PendingRow { + return { + ...row, + id: typeof row.id === 'string' ? row.id : '', + contributorId: typeof row.contributorId === 'string' ? row.contributorId : '', + status: row.status === 'approved' || row.status === 'rejected' ? row.status : 'pending', + createdAt: typeof row.createdAt === 'string' ? row.createdAt : '', + payload: row.payload, + }; +} diff --git a/apps/bff/src/contributions/pending-contribution.store.ts b/apps/bff/src/contributions/pending-contribution.store.ts new file mode 100644 index 0000000..83e5161 --- /dev/null +++ b/apps/bff/src/contributions/pending-contribution.store.ts @@ -0,0 +1,19 @@ +import type { Contribution } from '@btfp/shared-types'; + +export type PendingRow = Contribution & { PK?: string; SK?: string }; + +/** + * Port for the pending-contribution queue. Dynamo adapter in + * `dynamo-pending-contribution.store.ts`; tests pass a fake. + */ +export abstract class PendingContributionStore { + abstract listAll(): Promise; + abstract get(thingId: string, sk: string): Promise; + abstract insert(contribution: Contribution, thingId: string | undefined): Promise; + abstract accumulate( + existing: PendingRow, + payload: Contribution['payload'], + thingId: string | undefined, + ): Promise; + abstract markApproved(rows: PendingRow[], reviewerId: string, now: string): Promise; +} diff --git a/apps/bff/src/env.spec.ts b/apps/bff/src/env.spec.ts new file mode 100644 index 0000000..607f3d2 --- /dev/null +++ b/apps/bff/src/env.spec.ts @@ -0,0 +1,45 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { corsOrigin, requireInProduction } from './env.js'; + +afterEach(() => vi.unstubAllEnvs()); + +describe('requireInProduction', () => { + it('outside production: uses the value, else the local default', () => { + vi.stubEnv('NODE_ENV', 'development'); + expect(requireInProduction('JWT_SECRET', 'real', 'local')).toBe('real'); + expect(requireInProduction('JWT_SECRET', undefined, 'local')).toBe('local'); + }); + + it('in production: returns a real value', () => { + vi.stubEnv('NODE_ENV', 'production'); + expect(requireInProduction('JWT_SECRET', 'a-real-secret', 'local')).toBe('a-real-secret'); + }); + + it.each([undefined, '', 'REPLACE_BEFORE_DEPLOYING_DEV', 'change-me-in-local-env'])( + 'in production: throws for %j instead of falling back', + (value) => { + vi.stubEnv('NODE_ENV', 'production'); + expect(() => requireInProduction('JWT_SECRET', value, 'local')).toThrow(/JWT_SECRET/); + }, + ); +}); + +describe('corsOrigin', () => { + it('uses WEB_ORIGIN when set', () => { + vi.stubEnv('NODE_ENV', 'production'); + vi.stubEnv('WEB_ORIGIN', 'https://example.com'); + expect(corsOrigin()).toBe('https://example.com'); + }); + + it('reflects any origin only outside production', () => { + vi.stubEnv('NODE_ENV', 'development'); + vi.stubEnv('WEB_ORIGIN', ''); + expect(corsOrigin()).toBe(true); + }); + + it('throws in production when WEB_ORIGIN is unset', () => { + vi.stubEnv('NODE_ENV', 'production'); + vi.stubEnv('WEB_ORIGIN', ''); + expect(() => corsOrigin()).toThrow(/WEB_ORIGIN/); + }); +}); diff --git a/apps/bff/src/env.ts b/apps/bff/src/env.ts new file mode 100644 index 0000000..14d4f78 --- /dev/null +++ b/apps/bff/src/env.ts @@ -0,0 +1,32 @@ +const PLACEHOLDER = /^(REPLACE_|change-me)/i; + +export function isProduction(): boolean { + return process.env.NODE_ENV === 'production'; +} + +/** + * Returns `value`, or `localDefault` outside production. In production a + * missing or placeholder value throws: a silent fallback there means running + * with a publicly known secret. + */ +export function requireInProduction( + name: string, + value: string | undefined, + localDefault: string, +): string { + if (!isProduction()) return value ?? localDefault; + if (!value || PLACEHOLDER.test(value)) { + throw new Error(`${name} is missing or still a placeholder; refusing to start in production`); + } + return value; +} + +/** CORS origin. Reflecting any origin is only allowed locally — credentials are enabled. */ +export function corsOrigin(): string | true { + const configured = process.env.WEB_ORIGIN; + if (configured) return configured; + if (isProduction()) { + throw new Error('WEB_ORIGIN must be set in production; refusing to reflect any origin'); + } + return true; +} diff --git a/apps/bff/src/lambda.ts b/apps/bff/src/lambda.ts index 6b71581..f680c32 100644 --- a/apps/bff/src/lambda.ts +++ b/apps/bff/src/lambda.ts @@ -2,6 +2,7 @@ import { FastifyAdapter } from '@nestjs/platform-fastify'; import awsLambdaFastify from '@fastify/aws-lambda'; import { SSMClient, GetParameterCommand } from '@aws-sdk/client-ssm'; import { createApp } from './app.js'; +import { requestContext } from './logging/request-context.js'; type Proxy = (event: unknown, context: unknown) => Promise; let proxy: Proxy | undefined; @@ -29,7 +30,8 @@ async function bootstrap(): Promise { return awsLambdaFastify(adapter.getInstance()) as Proxy; } -export const handler = async (event: unknown, context: unknown) => { - proxy ??= await bootstrap(); - return proxy(event, context); -}; +export const handler = async (event: unknown, context: { awsRequestId?: string }) => + requestContext.run({ requestId: context.awsRequestId ?? 'unknown' }, async () => { + proxy ??= await bootstrap(); + return proxy(event, context); + }); diff --git a/apps/bff/src/logging/json-logger.spec.ts b/apps/bff/src/logging/json-logger.spec.ts new file mode 100644 index 0000000..65c4b21 --- /dev/null +++ b/apps/bff/src/logging/json-logger.spec.ts @@ -0,0 +1,74 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { JsonLogger } from './json-logger.js'; +import { requestContext } from './request-context.js'; + +function capture(fn: () => void): Record[] { + const lines: string[] = []; + const spy = vi.spyOn(process.stdout, 'write').mockImplementation((chunk) => { + lines.push(String(chunk)); + return true; + }); + try { + fn(); + } finally { + spy.mockRestore(); + } + return lines.map((line) => JSON.parse(line)); +} + +afterEach(() => vi.restoreAllMocks()); + +describe('JsonLogger', () => { + it('writes exactly one single-line JSON object per call', () => { + const [entry, ...more] = capture(() => new JsonLogger().log('hello', 'AppService')); + expect(more).toHaveLength(0); + expect(entry).toMatchObject({ level: 'info', message: 'hello', context: 'AppService' }); + }); + + it('keeps a multi-line stack inside one event (message, stack, context)', () => { + const stack = 'TypeError: boom\n at foo (/var/task/lambda.js:1:1)\n at bar (x.js:2:2)'; + const entries = capture(() => new JsonLogger().error('boom', stack, 'ExceptionsHandler')); + expect(entries).toHaveLength(1); + expect(entries[0]).toMatchObject({ + level: 'error', + message: 'boom', + stack, + context: 'ExceptionsHandler', + }); + }); + + it('treats a lone string after an error message as context, not a stack', () => { + const [entry] = capture(() => new JsonLogger().error('nope', 'SomeContext')); + expect(entry?.context).toBe('SomeContext'); + expect(entry?.stack).toBeUndefined(); + }); + + it('serializes an Error argument with its stack', () => { + const err = new Error('kaboom'); + const [entry] = capture(() => new JsonLogger().error(err)); + expect(entry).toMatchObject({ message: 'kaboom', stack: err.stack }); + }); + + it('tags lines with the Lambda request id from the request context', () => { + const [entry] = capture(() => + requestContext.run({ requestId: 'req-123' }, () => new JsonLogger().warn('careful')), + ); + expect(entry).toMatchObject({ level: 'warn', requestId: 'req-123' }); + }); + + it('omits requestId outside a request', () => { + const [entry] = capture(() => new JsonLogger().log('startup')); + expect(entry).not.toHaveProperty('requestId'); + }); + + it('suppresses debug/verbose unless enabled', () => { + expect(capture(() => new JsonLogger(false).debug('d'))).toHaveLength(0); + expect(capture(() => new JsonLogger(true).debug('d'))).toHaveLength(1); + }); + + it('does not throw on a circular object message', () => { + const circular: Record = {}; + circular.self = circular; + expect(() => capture(() => new JsonLogger().log(circular))).not.toThrow(); + }); +}); diff --git a/apps/bff/src/logging/json-logger.ts b/apps/bff/src/logging/json-logger.ts new file mode 100644 index 0000000..e6c1d3b --- /dev/null +++ b/apps/bff/src/logging/json-logger.ts @@ -0,0 +1,68 @@ +import type { LoggerService } from '@nestjs/common'; +import { requestContext } from './request-context.js'; + +type Level = 'debug' | 'info' | 'warn' | 'error' | 'fatal'; + +const STACK_FRAME = /\n\s+at .+/; + +function printable(message: unknown): unknown { + if (message instanceof Error) return message.message; + if (typeof message === 'string') return message; + try { + JSON.stringify(message); + return message; + } catch { + return String(message); + } +} + +/** + * One JSON object per line on stdout. A multi-line stack trace stays inside a + * single `stack` field, so CloudWatch stores one event per log call instead of + * splitting the trace across events. Used in production; local dev keeps Nest's + * readable console logger. + */ +export class JsonLogger implements LoggerService { + constructor(private readonly debugEnabled = process.env.LOG_LEVEL === 'debug') {} + + log(message: unknown, ...params: unknown[]): void { + this.emit('info', message, params); + } + warn(message: unknown, ...params: unknown[]): void { + this.emit('warn', message, params); + } + error(message: unknown, ...params: unknown[]): void { + this.emit('error', message, params); + } + fatal(message: unknown, ...params: unknown[]): void { + this.emit('fatal', message, params); + } + debug(message: unknown, ...params: unknown[]): void { + if (this.debugEnabled) this.emit('debug', message, params); + } + verbose(message: unknown, ...params: unknown[]): void { + if (this.debugEnabled) this.emit('debug', message, params); + } + + private emit(level: Level, message: unknown, params: unknown[]): void { + // Nest passes (message, stack?, context?) for errors and (message, context?) otherwise. + let rest = params; + let context: string | undefined; + const last = rest.at(-1); + if (typeof last === 'string' && !STACK_FRAME.test(last)) { + context = last; + rest = rest.slice(0, -1); + } + const stackParam = rest.find((p): p is string => typeof p === 'string' && STACK_FRAME.test(p)); + + const entry = { + level, + time: new Date().toISOString(), + requestId: requestContext.getStore()?.requestId, + context, + message: printable(message), + stack: message instanceof Error ? message.stack : stackParam, + }; + process.stdout.write(`${JSON.stringify(entry)}\n`); + } +} diff --git a/apps/bff/src/logging/request-context.ts b/apps/bff/src/logging/request-context.ts new file mode 100644 index 0000000..f9ff38f --- /dev/null +++ b/apps/bff/src/logging/request-context.ts @@ -0,0 +1,4 @@ +import { AsyncLocalStorage } from 'node:async_hooks'; + +/** Set by the Lambda handler so every log line in a request carries its request id. */ +export const requestContext = new AsyncLocalStorage<{ requestId: string }>(); diff --git a/apps/bff/src/mycota-config.ts b/apps/bff/src/mycota-config.ts index 4d5446e..5346df6 100644 --- a/apps/bff/src/mycota-config.ts +++ b/apps/bff/src/mycota-config.ts @@ -1,5 +1,6 @@ import type { MycotaAuthConfig } from '@bubltec/mycota-auth'; import { USERS_TABLE_NAME } from './dynamo/dynamo.constants.js'; +import { requireInProduction } from './env.js'; /** * The one place in apps/bff that still reads these process.env names — @@ -11,8 +12,8 @@ import { USERS_TABLE_NAME } from './dynamo/dynamo.constants.js'; */ export function buildMycotaAuthConfig(): MycotaAuthConfig { return { - jwtSecret: process.env.JWT_SECRET ?? 'change-me-in-local-env', - webOrigin: process.env.WEB_ORIGIN ?? 'http://localhost:5173', + jwtSecret: requireInProduction('JWT_SECRET', process.env.JWT_SECRET, 'change-me-in-local-env'), + webOrigin: requireInProduction('WEB_ORIGIN', process.env.WEB_ORIGIN, 'http://localhost:5173'), usersTableName: USERS_TABLE_NAME, emailFromAddress: process.env.SES_FROM_ADDRESS ?? 'noreply@badthingsforpets.com', sessionCookieName: process.env.SESSION_COOKIE_NAME ?? 'btfp_session', diff --git a/apps/bff/src/professional-verification/professional-verification.controller.ts b/apps/bff/src/professional-verification/professional-verification.controller.ts new file mode 100644 index 0000000..3139ef5 --- /dev/null +++ b/apps/bff/src/professional-verification/professional-verification.controller.ts @@ -0,0 +1,58 @@ +import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common'; +import { + ConfirmProfessionalVerificationDto, + RequestProfessionalVerificationDto, + ReviewProfessionalVerificationDto, +} from '@bubltec/mycota-professional-verification'; +import { + CurrentUser, + EmailCodeService, + JwtAuthGuard, + VerifiedGuard, + type AuthenticatedUser, +} from '@bubltec/mycota-auth'; +import { HydratingUsersService } from '../users/hydrating-users.service.js'; + +/** + * HTTP adapter over mycota EmailCodeService + HydratingUsersService. + * mycota's own controller is not registered — its pending list strips PK + * and cannot review legacy rows that never stored `id`. + */ +@Controller('verification/professional') +export class ProfessionalVerificationController { + constructor( + private readonly emailCode: EmailCodeService, + private readonly users: HydratingUsersService, + ) {} + + @Post('request') + @UseGuards(JwtAuthGuard) + request(@Body() dto: RequestProfessionalVerificationDto, @CurrentUser() user: AuthenticatedUser) { + return this.emailCode.request(user, dto.email); + } + + @Post('confirm') + @UseGuards(JwtAuthGuard) + async confirm( + @Body() dto: ConfirmProfessionalVerificationDto, + @CurrentUser() user: AuthenticatedUser, + ) { + return { confirmed: await this.emailCode.confirm(user, dto.code) }; + } + + @Get('pending') + @UseGuards(VerifiedGuard) + pending() { + return this.users.listAwaitingReview(); + } + + @Post(':userId/review') + @UseGuards(VerifiedGuard) + review( + @Param('userId') userId: string, + @Body() dto: ReviewProfessionalVerificationDto, + @CurrentUser() user: AuthenticatedUser, + ) { + return this.users.reviewProfessional(userId, dto.approve, user.id, dto.reason); + } +} diff --git a/apps/bff/src/professional-verification/professional-verification.module.ts b/apps/bff/src/professional-verification/professional-verification.module.ts new file mode 100644 index 0000000..823cf78 --- /dev/null +++ b/apps/bff/src/professional-verification/professional-verification.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { ProfessionalVerificationController } from './professional-verification.controller.js'; +import { UsersModule } from '../users/users.module.js'; + +@Module({ + imports: [UsersModule], + controllers: [ProfessionalVerificationController], +}) +export class ProfessionalVerificationModule {} diff --git a/apps/bff/src/users/hydrating-users.service.spec.ts b/apps/bff/src/users/hydrating-users.service.spec.ts new file mode 100644 index 0000000..d902757 --- /dev/null +++ b/apps/bff/src/users/hydrating-users.service.spec.ts @@ -0,0 +1,56 @@ +import { describe, expect, it } from 'vitest'; +import { BadRequestException } from '@nestjs/common'; +import { mockAws } from '../test-utils.js'; +import { DynamoDBDocumentClient, ScanCommand, UpdateCommand } from '@aws-sdk/lib-dynamodb'; +import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; +import { HydratingUsersService } from './hydrating-users.service.js'; + +const config = { usersTableName: 'btfp-dev-users', stage: 'dev' }; + +describe('HydratingUsersService.listAwaitingReview', () => { + it('backfills id from PK so review is not called with undefined', async () => { + const db = mockAws(DynamoDBDocumentClient); + db.on(ScanCommand).resolves({ + Items: [ + { + PK: 'USER#email#someone@g-p.com', + professional: { + status: 'awaiting_review', + domain: 'g-p.com', + requestedAt: '2026-01-01T00:00:00.000Z', + }, + }, + ], + }); + db.on(UpdateCommand).resolves({}); + + const users = new HydratingUsersService( + DynamoDBDocumentClient.from(new DynamoDBClient({})), + config as never, + ); + const pending = await users.listAwaitingReview(); + + expect(pending).toHaveLength(1); + expect(pending[0]?.id).toMatch( + /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, + ); + expect(pending[0]?.provider).toBe('email'); + expect(pending[0]?.providerAccountId).toBe('someone@g-p.com'); + expect(pending[0]?.displayName).toBe('g-p.com'); + expect(db.commandCalls(UpdateCommand)[0]?.args[0].input.ExpressionAttributeValues[':gsi']).toBe( + `USERID#${pending[0]?.id}`, + ); + }); +}); + +describe('HydratingUsersService.reviewProfessional', () => { + it('rejects a missing user id as 400, not a Dynamo lookup of "undefined"', async () => { + const users = new HydratingUsersService( + DynamoDBDocumentClient.from(new DynamoDBClient({})), + config as never, + ); + await expect(users.reviewProfessional('undefined', true, 'reviewer')).rejects.toBeInstanceOf( + BadRequestException, + ); + }); +}); diff --git a/apps/bff/src/users/hydrating-users.service.ts b/apps/bff/src/users/hydrating-users.service.ts new file mode 100644 index 0000000..a95f7a0 --- /dev/null +++ b/apps/bff/src/users/hydrating-users.service.ts @@ -0,0 +1,126 @@ +import { BadRequestException, Inject, Injectable, NotFoundException } from '@nestjs/common'; +import { randomUUID } from 'node:crypto'; +import { ScanCommand, UpdateCommand, DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; +import { DYNAMO_DOC_CLIENT } from '@bubltec/mycota-dynamo'; +import { + MYCOTA_AUTH_CONFIG, + UsersService, + type MycotaAuthConfig, + type User, +} from '@bubltec/mycota-auth'; + +/** + * mycota's listAwaitingReview strips PK/GSI1PK. Legacy / UpdateCommand-created + * rows can lack `id`, so review then looks up USERID#undefined. Sanitize at + * the read boundary (same Scan mycota already uses for this small table) and + * backfill identity so the mycota review path can resolve the user. + */ +@Injectable() +export class HydratingUsersService extends UsersService { + constructor( + @Inject(DYNAMO_DOC_CLIENT) private readonly doc: DynamoDBDocumentClient, + @Inject(MYCOTA_AUTH_CONFIG) private readonly authConfig: MycotaAuthConfig, + ) { + super(doc, authConfig); + } + + override async listAwaitingReview(): Promise { + const items = await this.scanAwaiting(); + return Promise.all(items.map((item) => this.hydrate(item))); + } + + override async reviewProfessional( + id: string, + approve: boolean, + reviewerId: string, + reason?: string, + ): Promise { + if (!id?.trim() || id === 'undefined') { + throw new BadRequestException('User id is required'); + } + const existing = await this.getById(id); + if (existing) { + return super.reviewProfessional(id, approve, reviewerId, reason); + } + const match = (await this.scanAwaiting()).find( + (item) => item.id === id || item.GSI1PK === `USERID#${id}`, + ); + if (!match) throw new NotFoundException(`No user with id ${id}`); + const user = await this.hydrate(match); + return super.reviewProfessional(user.id, approve, reviewerId, reason); + } + + private async scanAwaiting(): Promise[]> { + const result = await this.doc.send( + new ScanCommand({ + TableName: this.authConfig.usersTableName, + FilterExpression: 'professional.#status = :status', + ExpressionAttributeNames: { '#status': 'status' }, + ExpressionAttributeValues: { ':status': 'awaiting_review' }, + }), + ); + return (result.Items ?? []) as Record[]; + } + + private async hydrate(item: Record): Promise { + const parsed = parseUserPk(typeof item.PK === 'string' ? item.PK : ''); + const fromGsi = + typeof item.GSI1PK === 'string' && item.GSI1PK.startsWith('USERID#') + ? item.GSI1PK.slice('USERID#'.length) + : undefined; + const id = (typeof item.id === 'string' && item.id.trim()) || fromGsi || randomUUID(); + const provider = + (typeof item.provider === 'string' && item.provider) || parsed?.provider || 'email'; + const providerAccountId = + (typeof item.providerAccountId === 'string' && item.providerAccountId) || + parsed?.providerAccountId || + id; + const professional = isProfessional(item.professional) ? item.professional : undefined; + const displayName = + (typeof item.displayName === 'string' && item.displayName) || + professional?.domain || + providerAccountId; + + if (item.PK && (!item.id || !item.GSI1PK || !item.provider || !item.displayName)) { + await this.doc.send( + new UpdateCommand({ + TableName: this.authConfig.usersTableName, + Key: { PK: item.PK }, + UpdateExpression: + 'SET id = :id, GSI1PK = :gsi, #provider = :provider, providerAccountId = :paid, displayName = :name', + ExpressionAttributeNames: { '#provider': 'provider' }, + ExpressionAttributeValues: { + ':id': id, + ':gsi': `USERID#${id}`, + ':provider': provider, + ':paid': providerAccountId, + ':name': displayName, + }, + }), + ); + } + + return { + id, + provider: provider as User['provider'], + providerAccountId, + displayName, + verifiedContributor: item.verifiedContributor === true, + createdAt: typeof item.createdAt === 'string' ? item.createdAt : '', + email: typeof item.email === 'string' ? item.email : undefined, + avatarUrl: typeof item.avatarUrl === 'string' ? item.avatarUrl : undefined, + verifiedAt: typeof item.verifiedAt === 'string' ? item.verifiedAt : undefined, + professional, + }; + } +} + +function isProfessional(value: unknown): value is NonNullable { + return Boolean(value && typeof value === 'object' && 'status' in value && 'domain' in value); +} + +function parseUserPk(pk: string): { provider: string; providerAccountId: string } | undefined { + const match = /^USER#([^#]+)#(.+)$/.exec(pk); + if (!match) return undefined; + return { provider: match[1]!, providerAccountId: match[2]! }; +} diff --git a/apps/bff/src/users/users.module.ts b/apps/bff/src/users/users.module.ts new file mode 100644 index 0000000..54ee3de --- /dev/null +++ b/apps/bff/src/users/users.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { HydratingUsersService } from './hydrating-users.service.js'; + +@Module({ + providers: [HydratingUsersService], + exports: [HydratingUsersService], +}) +export class UsersModule {} diff --git a/apps/bff/src/validation.ts b/apps/bff/src/validation.ts new file mode 100644 index 0000000..29987c3 --- /dev/null +++ b/apps/bff/src/validation.ts @@ -0,0 +1,15 @@ +import type { ValidationPipeOptions } from '@nestjs/common'; + +/** + * The one ValidationPipe configuration. app.ts and the DTO specs both import + * it, so tests exercise the real pipe rather than a hand-copied one. + * + * `forbidNonWhitelisted` makes an undeclared field a 400. With `whitelist` + * alone it is silently stripped, which hid a dropped `payload` and a `thingId` + * sent in the wrong place. + */ +export const VALIDATION_PIPE_OPTIONS: ValidationPipeOptions = { + whitelist: true, + forbidNonWhitelisted: true, + transform: true, +}; diff --git a/apps/bff/vitest.config.ts b/apps/bff/vitest.config.ts new file mode 100644 index 0000000..07589eb --- /dev/null +++ b/apps/bff/vitest.config.ts @@ -0,0 +1,8 @@ +import { configDefaults, defineConfig } from 'vitest/config'; + +// Vitest 3+ no longer excludes build output. The Lambda bundle build compiles into +// .tsc-out while turbo runs the tests in parallel, so half-written *.spec.js copies +// get collected and fail with "Cannot find module". +export default defineConfig({ + test: { exclude: [...configDefaults.exclude, '**/.tsc-out/**', '**/dist*/**'] }, +}); diff --git a/apps/e2e/package.json b/apps/e2e/package.json index 985cf1c..235d07b 100644 --- a/apps/e2e/package.json +++ b/apps/e2e/package.json @@ -11,12 +11,12 @@ "typecheck": "tsc -b --noEmit" }, "dependencies": { - "@aws-sdk/client-bedrock-runtime": "^3.716.0" + "@aws-sdk/client-bedrock-runtime": "3.1136.0" }, "devDependencies": { - "@playwright/test": "^1.56.0", - "@types/node": "^26.6.1", - "tsx": "^4.19.0", - "typescript": "^5.8.0" + "@playwright/test": "1.63.0", + "@types/node": "26.6.2", + "tsx": "4.23.13", + "typescript": "7.0.2" } } diff --git a/apps/scraper/package.json b/apps/scraper/package.json index ae5d0d5..4ea8e57 100644 --- a/apps/scraper/package.json +++ b/apps/scraper/package.json @@ -10,22 +10,22 @@ "test": "vitest run" }, "dependencies": { - "@aws-crypto/sha256-js": "^5.2.0", - "@aws-sdk/client-bedrock-agentcore": "^3.716.0", - "@aws-sdk/client-bedrock-runtime": "^3.716.0", - "@aws-sdk/client-dynamodb": "^3.716.0", - "@aws-sdk/credential-provider-node": "^3.716.0", - "@aws-sdk/lib-dynamodb": "^3.716.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-bedrock-agentcore": "3.1136.0", + "@aws-sdk/client-bedrock-runtime": "3.1136.0", + "@aws-sdk/client-dynamodb": "3.1136.0", + "@aws-sdk/credential-provider-node": "3.972.83", + "@aws-sdk/lib-dynamodb": "3.1136.0", "@btfp/shared-types": "workspace:*", - "@smithy/protocol-http": "^5.3.10", - "@smithy/signature-v4": "^5.3.10", - "playwright-core": "^1.55.0" + "@smithy/protocol-http": "5.6.2", + "@smithy/signature-v4": "5.7.3", + "playwright-core": "1.63.0" }, "devDependencies": { - "@types/node": "^26.6.1", - "aws-sdk-client-mock": "^4.1.0", - "esbuild": "^0.24.2", - "typescript": "^5.8.0", - "vitest": "^2.1.0" + "@types/node": "26.6.2", + "aws-sdk-client-mock": "4.1.0", + "esbuild": "0.28.2", + "typescript": "7.0.2", + "vitest": "5.0.1" } } diff --git a/apps/scraper/src/contribution.spec.ts b/apps/scraper/src/contribution.spec.ts index 4306436..e379530 100644 --- a/apps/scraper/src/contribution.spec.ts +++ b/apps/scraper/src/contribution.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; import { mockAws } from './test-utils.js'; -import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb'; +import { DynamoDBDocumentClient, PutCommand, QueryCommand } from '@aws-sdk/lib-dynamodb'; import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; import { SCRAPER_CONTRIBUTOR_ID, writeContribution } from './contribution.js'; import type { CandidateDocument } from './search/types.js'; @@ -28,6 +28,7 @@ describe('writeContribution', () => { it("writes an item matching contributions.service.ts propose()'s exact key shape", async () => { const db = mockAws(DynamoDBDocumentClient); db.on(PutCommand).resolves({}); + db.on(QueryCommand).resolves({ Items: [] }); const contribution = await writeContribution( DynamoDBDocumentClient.from(new DynamoDBClient({})), @@ -50,6 +51,7 @@ describe('writeContribution', () => { it('preserves the search source URL, severity, and trend term', async () => { const db = mockAws(DynamoDBDocumentClient); db.on(PutCommand).resolves({}); + db.on(QueryCommand).resolves({ Items: [] }); const contribution = await writeContribution( DynamoDBDocumentClient.from(new DynamoDBClient({})), @@ -66,6 +68,7 @@ describe('writeContribution', () => { it('defaults to an empty petTypes array when the extraction has no petTypeId', async () => { const db = mockAws(DynamoDBDocumentClient); db.on(PutCommand).resolves({}); + db.on(QueryCommand).resolves({ Items: [] }); const contribution = await writeContribution( DynamoDBDocumentClient.from(new DynamoDBClient({})), @@ -79,6 +82,7 @@ describe('writeContribution', () => { it('attaches to an existing Thing when the extracted name matches the catalog', async () => { const db = mockAws(DynamoDBDocumentClient); db.on(PutCommand).resolves({}); + db.on(QueryCommand).resolves({ Items: [] }); const contribution = await writeContribution( DynamoDBDocumentClient.from(new DynamoDBClient({})), diff --git a/apps/scraper/src/contribution.ts b/apps/scraper/src/contribution.ts index b91046a..7d0d0a8 100644 --- a/apps/scraper/src/contribution.ts +++ b/apps/scraper/src/contribution.ts @@ -1,6 +1,16 @@ import { randomUUID } from 'node:crypto'; -import { PutCommand, type DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; -import { findDuplicateThing, type Contribution } from '@btfp/shared-types'; +import { + PutCommand, + QueryCommand, + UpdateCommand, + type DynamoDBDocumentClient, +} from '@aws-sdk/lib-dynamodb'; +import { + findDuplicateThing, + mergeThingPayload, + planContributionAttach, + type Contribution, +} from '@btfp/shared-types'; import { CONTENT_TABLE_NAME } from './dynamo.js'; import type { CandidateDocument } from './search/types.js'; import type { ExtractionResult } from './extract/types.js'; @@ -11,12 +21,29 @@ import type { CatalogThing } from './taxonomy.js'; * optional chain, which degrades gracefully for an unresolvable id. */ export const SCRAPER_CONTRIBUTOR_ID = 'system:agentcore-scraper'; +async function listPending(db: DynamoDBDocumentClient): Promise { + const items: Contribution[] = []; + let lastKey: Record | undefined; + do { + const result = await db.send( + new QueryCommand({ + TableName: CONTENT_TABLE_NAME, + IndexName: 'GSI2', + KeyConditionExpression: 'GSI2PK = :pk', + ExpressionAttributeValues: { ':pk': 'STATUS#pending' }, + ExclusiveStartKey: lastKey, + }), + ); + items.push(...((result?.Items ?? []) as Contribution[])); + lastKey = result?.LastEvaluatedKey as Record | undefined; + } while (lastKey); + return items.filter((item) => item.payload && typeof item.payload === 'object'); +} + /** - * Exact replica of contributions.service.ts propose()'s item shape. If the - * extracted name matches an existing Thing, `thingId` is set so approval - * becomes an edit of that row instead of a duplicate. Reusing this shape - * means ModerationPage.tsx and the approve() flow need zero changes to - * handle scraper-sourced candidates. + * Same attach/accumulate rules as ContributionsService.propose: catalog + * match becomes an edit; an already-queued identity folds new facts into + * that pending row instead of another moderation card. */ export async function writeContribution( db: DynamoDBDocumentClient, @@ -24,32 +51,64 @@ export async function writeContribution( extraction: ExtractionResult, catalog: CatalogThing[] = [], ): Promise { - const id = randomUUID(); - const now = new Date().toISOString(); - const duplicate = + const payload: Contribution['payload'] = { + name: extraction.thingName, + thingTypeId: extraction.thingTypeId, + petTypes: extraction.petTypeId + ? [{ petTypeId: extraction.petTypeId, severity: extraction.severity ?? 'unknown' }] + : [], + details: { summary: extraction.summary, trendTerm: document.topic }, + source: document.source, + sourceUrl: document.sourceUrl, + }; + + const identity = extraction.thingName && extraction.thingTypeId - ? findDuplicateThing(catalog, { - name: extraction.thingName, - thingTypeId: extraction.thingTypeId, - }) + ? { name: extraction.thingName, thingTypeId: extraction.thingTypeId } : undefined; - const targetThingId = duplicate?.id ?? id; + const catalogMatch = identity ? findDuplicateThing(catalog, identity) : undefined; + const pending = await listPending(db); + const { pendingMatch, thingId } = identity + ? planContributionAttach({ + payload: identity, + catalogMatchId: catalogMatch?.id, + pending, + }) + : { pendingMatch: undefined, thingId: catalogMatch?.id }; + + if (pendingMatch) { + const merged = mergeThingPayload(pendingMatch.payload, payload); + const row = pendingMatch as Contribution & { PK?: string; SK?: string }; + const pk = row.PK ?? `THING#${pendingMatch.thingId ?? pendingMatch.id}`; + const sk = row.SK; + if (sk) { + const linked = thingId ?? pendingMatch.thingId; + await db.send( + new UpdateCommand({ + TableName: CONTENT_TABLE_NAME, + Key: { PK: pk, SK: sk }, + UpdateExpression: linked + ? 'SET payload = :payload, thingId = :thingId' + : 'SET payload = :payload', + ExpressionAttributeValues: { + ':payload': merged, + ...(linked ? { ':thingId': linked } : {}), + }, + }), + ); + return { ...pendingMatch, payload: merged, thingId: linked }; + } + } + const id = randomUUID(); + const now = new Date().toISOString(); + const targetThingId = thingId ?? id; const contribution: Contribution = { id, - thingId: duplicate?.id, + thingId, contributorId: SCRAPER_CONTRIBUTOR_ID, status: 'pending', - payload: { - name: extraction.thingName, - thingTypeId: extraction.thingTypeId, - petTypes: extraction.petTypeId - ? [{ petTypeId: extraction.petTypeId, severity: extraction.severity ?? 'unknown' }] - : [], - details: { summary: extraction.summary, trendTerm: document.topic }, - source: document.source, - sourceUrl: document.sourceUrl, - }, + payload, createdAt: now, }; diff --git a/apps/scraper/src/run.spec.ts b/apps/scraper/src/run.spec.ts index e1d1599..e403d77 100644 --- a/apps/scraper/src/run.spec.ts +++ b/apps/scraper/src/run.spec.ts @@ -1,6 +1,12 @@ import { describe, expect, it, vi } from 'vitest'; import { mockAws } from './test-utils.js'; -import { DynamoDBDocumentClient, GetCommand, PutCommand, ScanCommand } from '@aws-sdk/lib-dynamodb'; +import { + DynamoDBDocumentClient, + GetCommand, + PutCommand, + QueryCommand, + ScanCommand, +} from '@aws-sdk/lib-dynamodb'; import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; import { run, type ScraperDeps } from './run.js'; import type { ScraperConfig } from './config.js'; @@ -67,6 +73,7 @@ describe('run', () => { const db = mockAws(DynamoDBDocumentClient); db.on(GetCommand).resolves({}); db.on(ScanCommand).resolves({ Items: [] }); + db.on(QueryCommand).resolves({ Items: [] }); db.on(PutCommand).resolves({}); await run(config, client(), deps()); diff --git a/apps/web/package.json b/apps/web/package.json index d7bcc02..5ae2432 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -10,21 +10,21 @@ "prerender": "node scripts/prerender.mjs" }, "dependencies": { - "@base-ui-components/react": "^1.0.0-rc.0", + "@base-ui/react": "1.8.0", "@btfp/shared-types": "workspace:*", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "react-router-dom": "^7.1.0" + "react": "19.3.0", + "react-dom": "19.3.0", + "react-router-dom": "7.18.4" }, "devDependencies": { - "@playwright/test": "^1.56.0", - "@tailwindcss/vite": "^4.0.0", - "@types/node": "^26.6.1", - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.0", - "typescript": "^5.8.0", - "vite": "^6.0.0" + "@playwright/test": "1.63.0", + "@tailwindcss/vite": "4.3.3", + "@types/node": "26.6.2", + "@types/react": "19.3.0", + "@types/react-dom": "19.3.0", + "@vitejs/plugin-react": "6.1.1", + "tailwindcss": "4.3.3", + "typescript": "7.0.2", + "vite": "8.3.0" } } diff --git a/apps/web/src/components/BreedSelect.tsx b/apps/web/src/components/BreedSelect.tsx index 8aec6a1..ebb94fa 100644 --- a/apps/web/src/components/BreedSelect.tsx +++ b/apps/web/src/components/BreedSelect.tsx @@ -1,4 +1,4 @@ -import { Combobox } from '@base-ui-components/react/combobox'; +import { Combobox } from '@base-ui/react/combobox'; import type { Breed } from '@btfp/shared-types'; export function BreedSelect({ diff --git a/apps/web/src/components/EmailSignInDialog.tsx b/apps/web/src/components/EmailSignInDialog.tsx index 6507aee..6664064 100644 --- a/apps/web/src/components/EmailSignInDialog.tsx +++ b/apps/web/src/components/EmailSignInDialog.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Dialog } from '@base-ui-components/react/dialog'; +import { Dialog } from '@base-ui/react/dialog'; import { api } from '../lib/api.js'; type Step = 'email' | 'code'; diff --git a/apps/web/src/components/PetTypeSelect.tsx b/apps/web/src/components/PetTypeSelect.tsx index 69b01f2..4b8fa81 100644 --- a/apps/web/src/components/PetTypeSelect.tsx +++ b/apps/web/src/components/PetTypeSelect.tsx @@ -1,4 +1,4 @@ -import { Select } from '@base-ui-components/react/select'; +import { Select } from '@base-ui/react/select'; import type { PetType } from '@btfp/shared-types'; export function PetTypeSelect({ diff --git a/apps/web/src/components/ProfessionalVerificationDialog.tsx b/apps/web/src/components/ProfessionalVerificationDialog.tsx index 5657648..e6daf38 100644 --- a/apps/web/src/components/ProfessionalVerificationDialog.tsx +++ b/apps/web/src/components/ProfessionalVerificationDialog.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Dialog } from '@base-ui-components/react/dialog'; +import { Dialog } from '@base-ui/react/dialog'; import { api } from '../lib/api.js'; type Step = 'email' | 'code' | 'submitted'; diff --git a/apps/web/src/components/QuizDialog.tsx b/apps/web/src/components/QuizDialog.tsx index 891d03d..1d2fab5 100644 --- a/apps/web/src/components/QuizDialog.tsx +++ b/apps/web/src/components/QuizDialog.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { Dialog } from '@base-ui-components/react/dialog'; +import { Dialog } from '@base-ui/react/dialog'; import type { QuizQuestion } from '@btfp/shared-types'; import { api } from '../lib/api.js'; diff --git a/apps/web/src/pages/ModerationPage.tsx b/apps/web/src/pages/ModerationPage.tsx index 381e02c..057f1f5 100644 --- a/apps/web/src/pages/ModerationPage.tsx +++ b/apps/web/src/pages/ModerationPage.tsx @@ -141,6 +141,10 @@ function ProfessionalVerificationsSection() { }, []); async function review(user: User, approve: boolean) { + if (!user.id) { + setError('This verification is missing a user id and cannot be reviewed.'); + return; + } try { const reason = approve ? undefined : (prompt('Rejection reason (optional):') ?? undefined); await api.reviewProfessionalVerification(user.id, approve, reason); @@ -161,9 +165,16 @@ function ProfessionalVerificationsSection() { ) : (
    {items.map((user) => ( -
  • -

    {user.displayName}

    -

    {user.professional?.domain}

    +
  • +

    + {user.displayName || user.professional?.domain || 'Unknown organization'} +

    + {user.professional?.domain && user.professional.domain !== user.displayName && ( +

    {user.professional.domain}

    + )} {user.professional?.orgClassification && (

    Bedrock guess: {user.professional.orgClassification.replaceAll('_', ' ')} —{' '} diff --git a/apps/web/src/pages/SubmitPage.tsx b/apps/web/src/pages/SubmitPage.tsx index 8579335..eab04bf 100644 --- a/apps/web/src/pages/SubmitPage.tsx +++ b/apps/web/src/pages/SubmitPage.tsx @@ -136,17 +136,19 @@ export function SubmitPage() { setSubmitting(true); setError(null); try { - await api.submitContribution({ - ...(editingId ? { thingId: editingId } : {}), - name, - thingTypeId, - petTypes: Object.entries(petSeverities).map(([petTypeId, severity]) => ({ - petTypeId, - severity, - })), - details: { notes }, - source: source || `contributor:${user?.displayName}`, - }); + await api.submitContribution( + { + name, + thingTypeId, + petTypes: Object.entries(petSeverities).map(([petTypeId, severity]) => ({ + petTypeId, + severity, + })), + details: { notes }, + source: source || `contributor:${user?.displayName}`, + }, + editingId, + ); setDone(true); } catch (err) { setError(err instanceof Error ? err.message : 'Something went wrong'); diff --git a/data/seed/package.json b/data/seed/package.json index 4440a12..5e8f613 100644 --- a/data/seed/package.json +++ b/data/seed/package.json @@ -11,17 +11,17 @@ "test": "vitest run" }, "dependencies": { - "@aws-sdk/client-bedrock-runtime": "^3.716.0", - "@aws-sdk/client-dynamodb": "^3.716.0", - "@aws-sdk/lib-dynamodb": "^3.716.0", + "@aws-sdk/client-bedrock-runtime": "3.1136.0", + "@aws-sdk/client-dynamodb": "3.1136.0", + "@aws-sdk/lib-dynamodb": "3.1136.0", "@btfp/shared-types": "workspace:*", - "cheerio": "^1.0.0" + "cheerio": "1.2.0" }, "devDependencies": { - "@types/node": "^26.6.1", - "aws-sdk-client-mock": "^4.1.0", - "tsx": "^4.19.0", - "typescript": "^5.8.0", - "vitest": "^2.1.0" + "@types/node": "26.6.2", + "aws-sdk-client-mock": "4.1.0", + "tsx": "4.23.13", + "typescript": "7.0.2", + "vitest": "5.0.1" } } diff --git a/data/seed/src/scrape-vetmeds.ts b/data/seed/src/scrape-vetmeds.ts index 697c614..902f48b 100644 --- a/data/seed/src/scrape-vetmeds.ts +++ b/data/seed/src/scrape-vetmeds.ts @@ -130,7 +130,9 @@ async function main(): Promise { await writeFile(OUTPUT_PATH, JSON.stringify(staging, null, 2) + '\n', 'utf-8'); console.log(`Wrote ${staging.length} entries to ${OUTPUT_PATH}`); - console.log('Review and correct category/thingTypeId/severity before promoting to vetmeds-toxins.json.'); + console.log( + 'Review and correct category/thingTypeId/severity before promoting to vetmeds-toxins.json.', + ); } main().catch((err) => { diff --git a/docs/architecture.md b/docs/architecture.md index ed45696..35638e0 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -11,7 +11,7 @@ apps/web (Vite/React) --/api/*--> CloudFront --> apps/bff (NestJS, one Lambda One CloudFront distribution serves both: the default behavior serves the built React app from S3, and `/api/*` is routed to an API Gateway HTTP API in front of the BFF Lambda's -`live` alias (SAM `AutoPublishAlias`; prod canaries, see [ci-cd.md](ci-cd.md)). This means the +`current` alias (prod canaries, see [infra.md](infra.md#lambda-alias-and-canary)). This means the frontend and API share an origin in every environment (no CORS to think about in prod), and WAF at the CloudFront layer covers both. @@ -40,9 +40,17 @@ WAF at the CloudFront layer covers both. 1. User signs in via GitHub OAuth (`AuthModule`) — see [verification-flow.md](verification-flow.md) for why GitHub specifically and how the quiz gate works. -2. Verified users `POST /api/contributions`, which writes a pending item under the target - Thing's partition (or a fresh id for a new Thing) — never directly to the live item. -3. A verified contributor can review the queue at `GET /api/contributions/pending` and - `POST /api/contributions/:thingId/:sk/approve`, which promotes the payload into a real - `Thing` item. There's no admin-role check yet — see the note in +2. Verified users `POST /api/contributions`. Identity matching + (`planContributionAttach` in `packages/shared-types`) is shared by the BFF and the + scraper: an explicit `thingId`, else a catalog match (`SearchService.findDuplicate`), + else an already-pending queue row. A match **accumulates** new payload fields onto + that pending row (`mergeThingPayload`) instead of inserting another card. A miss + writes a pending item under the target Thing's partition (or a fresh id) — never + directly to the live item. +3. `GET /api/contributions/pending` clusters leftover duplicates of the same identity + into one card. `POST /api/contributions/:thingId/:sk/approve` folds sibling pending + payloads into the live `Thing` (`mergeThings`) and marks those rows approved. + Dynamo access for the queue goes through `PendingContributionStore` (Dynamo adapter + in the BFF; the scraper talks to the table directly but uses the same shared-types + plan). There's no admin-role check yet — see the note in `contributions.controller.ts`. diff --git a/docs/ci-cd.md b/docs/ci-cd.md index 86f3eaa..7207d1b 100644 --- a/docs/ci-cd.md +++ b/docs/ci-cd.md @@ -23,9 +23,9 @@ is the fallback for hotfixes or debugging a broken pipeline). 4. **`deploy-dev`** — assumes the deploy role via OIDC, runs `cdk deploy BtfpDev/*`. The BFF Lambda is a container image (`apps/bff/Dockerfile`, `DockerImageCode.fromImageAsset` in `infra/cdk/lib/api-stack.ts`) — the Docker build and push to ECR happen automatically inside - this one `cdk deploy` call. API Gateway invokes the function's `live` alias, not `$LATEST` (SAM - `AutoPublishAlias` + `DeploymentPreference: AllAtOnce` on dev — no 5-minute - canary wait). Dev is never prerendered + this one `cdk deploy` call. API Gateway invokes the function's `current` alias, not + `$LATEST`; dev cuts over immediately with no CodeDeploy deployment (so no 5-minute canary + wait — see [docs/infra.md](./infra.md#lambda-alias-and-canary)). Dev is never prerendered (Basic-Auth-walled, `noindex` — see [docs/seo.md](./seo.md)), so that's the whole job. 5. **`e2e`** — warms dev's BFF with a cheap `GET /api/pet-types` (Nest container cold start after deploy), then runs `apps/e2e`'s Playwright suite against diff --git a/docs/infra.md b/docs/infra.md index 6cfb081..c457309 100644 --- a/docs/infra.md +++ b/docs/infra.md @@ -32,31 +32,41 @@ deploy gets done, just no longer the routine way changes ship. AgentCore Browser and writes unverified `Contribution`s — see [docs/scraper.md](./scraper.md). - **Api** — one Lambda (container image — see [docs/ci-cd.md](./ci-cd.md)) running the - NestJS BFF, behind an API Gateway HTTP API. Traffic hits a `live` alias - (`AutoPublishAlias`). Prod canaries 10% / 5 minutes; dev is `AllAtOnce`. + NestJS BFF, behind an API Gateway HTTP API. Traffic hits a `current` alias + (see [Lambda alias and canary](#lambda-alias-and-canary)). - **Web** — S3 (private, OAC) + CloudFront + WAFv2 + ACM cert + Route53 alias record(s). `BtfpDev` serves `dev.badthingsforpets.com`; `BtfpProd` serves `badthingsforpets.com` and `www.badthingsforpets.com`. -### One-time: migrating a function onto SAM's `AutoPublishAlias` - -If a Lambda function previously got its `live` alias from a CDK-managed `fn.addAlias('live')` -(pre-SAM canary setup), SAM's `AutoPublishAlias` cannot create its own `live` alias while -that one still exists — CloudFormation has no built-in way to order "delete the old alias" -before "create the new one" without an ordering dependency that cycles back on itself (the -migration needs the function's name via `Ref`, so it always depends on the function; adding -the reverse dependency propagates through SAM to the function's generated `Version` and -`Alias` too, forming a direct cycle). Delete the stale alias by hand, once, before deploying: - -```bash -aws lambda delete-alias --function-name --name live -``` - -Safe to run even if the alias doesn't exist (returns `ResourceNotFoundException`). Do this -right before the deploy that introduces `publishLiveAlias` for that function — the alias is -briefly gone until SAM recreates it during that same deploy. Fine for dev (Basic-Auth-walled); -for prod, do it immediately before approving `deploy-prod` to minimize the gap. +### Lambda alias and canary + +`publishCurrentAlias` (`infra/cdk/lib/lambda-canary.ts`) publishes a `current` alias pointing +at each deploy's version. Callers must route traffic to the alias, never `$LATEST`, or a +canary never sees user traffic. + +- **Dev** (and the SES forwarder): no `canary` option, so the alias flips to the new version + immediately and CloudFormation doesn't wait on a CodeDeploy deployment. +- **Prod**: a CodeDeploy `LambdaDeploymentGroup` shifts 10% of traffic for 5 minutes, then + the rest. It rolls back automatically if either alarm fires — `Errors >= 1` on the alias, + or on the new version only (an error on the old version must not fail a good deploy). + +This is plain CDK constructs (`lambda.Alias` + `codedeploy.LambdaDeploymentGroup`) — no SAM +transform. The behavior is covered by `infra/cdk/lib/lambda-canary.spec.ts`. + +### Logging and alerts + +- **Format:** in production the BFF logs one JSON object per line (`JsonLogger`, + `apps/bff/src/logging/`) with `level`, `requestId`, `context`, `message`, and `stack`. A stack + trace stays inside one event instead of being split across CloudWatch events. Local dev keeps + Nest's readable console logger. Set `LOG_LEVEL=debug` to include debug lines. +- **Readable stacks:** the bundle keeps class names (`keepNames`) and ships its `.map`; + `NODE_OPTIONS=--enable-source-maps` turns minified frames back into `src/*.ts:line`. +- **Retention:** the BFF and the SES forwarder use explicit log groups, 14 days on dev and 30 + on prod (prod logs are retained if the stack is deleted). Lambda's auto-created group never expires. +- **Alerts:** prod has an alarm on 3+ API 5xx responses in 5 minutes that publishes to an SNS + topic emailing `FORWARD_TO_ADDRESS`. SNS emails a confirmation link the first time; alerts are + not delivered until it's clicked. ## Budget (rough, at low/unknown traffic) diff --git a/docs/verification-flow.md b/docs/verification-flow.md index a853caf..6c470d5 100644 --- a/docs/verification-flow.md +++ b/docs/verification-flow.md @@ -90,7 +90,10 @@ Either way, the mechanism itself: not the full email — keeps the local-part private from reviewers) at `GET /verification/professional/pending` and approve/reject it. Same "any verified contributor can moderate" pattern as contribution review — see the gap - noted below. + noted below. `HydratingUsersService` sanitizes this list: mycota strips PK, and some + older rows never stored `id`, which produced + `POST /verification/professional/undefined/review`. Missing identity is backfilled + from `USER#provider#accountId` before the mycota review path runs. Approving sets `verifiedContributor: true` (same unlock as the quiz) and, on any contribution later approved from that user, stamps `details.verifiedOrgDomain` on the diff --git a/infra/cdk/lib/api-stack.ts b/infra/cdk/lib/api-stack.ts index fd8e07b..554816e 100644 --- a/infra/cdk/lib/api-stack.ts +++ b/infra/cdk/lib/api-stack.ts @@ -14,13 +14,20 @@ import { BEDROCK_INFERENCE_PROFILE_ID, BRAVE_SEARCH_API_KEY, DEV_JWT_SECRET, + FORWARD_TO_ADDRESS, GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET_PARAM_NAME, PROD_JWT_SECRET, ROOT_DOMAIN, SES_FROM_ADDRESS, } from './config.js'; -import { publishLiveAlias } from './lambda-canary.js'; +import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch'; +import * as cloudwatchActions from 'aws-cdk-lib/aws-cloudwatch-actions'; +import * as codedeploy from 'aws-cdk-lib/aws-codedeploy'; +import * as logs from 'aws-cdk-lib/aws-logs'; +import * as sns from 'aws-cdk-lib/aws-sns'; +import * as subscriptions from 'aws-cdk-lib/aws-sns-subscriptions'; +import { publishCurrentAlias } from './lambda-canary.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -77,8 +84,16 @@ export class ApiStack extends cdk.Stack { // Email sign-in does DNS + homepage fetch + Bedrock + SES in one request; // on a cold container (right after deploy) that can exceed 15s. timeout: cdk.Duration.seconds(30), + // Explicit group so logs expire. Lambda's auto-created group never does. + logGroup: new logs.LogGroup(this, 'BffLogGroup', { + retention: isProd ? logs.RetentionDays.ONE_MONTH : logs.RetentionDays.TWO_WEEKS, + removalPolicy: isProd ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY, + }), environment: { NODE_ENV: 'production', + // Maps minified stack frames back to src/*.ts using the bundled .map + // (see apps/bff/Dockerfile). + NODE_OPTIONS: '--enable-source-maps', STAGE: props.envConfig.envName, CONTENT_TABLE_NAME: props.contentTable.tableName, USERS_TABLE_NAME: props.usersTable.tableName, @@ -94,8 +109,8 @@ export class ApiStack extends cdk.Stack { }, }); - const live = publishLiveAlias(handler, { - type: isProd ? 'Canary10Percent5Minutes' : 'AllAtOnce', + const current = publishCurrentAlias(handler, { + canary: isProd ? codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_5MINUTES : undefined, }); props.contentTable.grantReadWriteData(handler); @@ -134,10 +149,29 @@ export class ApiStack extends cdk.Stack { this.httpApi = new apigwv2.HttpApi(this, 'HttpApi', { apiName: `btfp-${props.envConfig.envName}-api`, - // Alias, not `$LATEST` — SAM AutoPublishAlias owns `live`. - defaultIntegration: new HttpLambdaIntegration('BffIntegration', live), + // Alias, not `$LATEST` — otherwise a prod canary never sees user traffic. + defaultIntegration: new HttpLambdaIntegration('BffIntegration', current), }); + if (isProd) { + // The canary alarms only guard a deploy. This one notifies on 5xx in + // steady state. The email subscription must be confirmed once by the + // recipient (SNS sends a confirmation link) before alerts are delivered. + const alerts = new sns.Topic(this, 'AlertsTopic'); + alerts.addSubscription(new subscriptions.EmailSubscription(FORWARD_TO_ADDRESS)); + new cloudwatch.Alarm(this, 'ApiServerErrors', { + alarmDescription: 'BFF API returned 3+ 5xx responses in 5 minutes', + metric: this.httpApi.metricServerError({ + period: cdk.Duration.minutes(5), + statistic: 'sum', + }), + threshold: 3, + evaluationPeriods: 1, + comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING, + }).addAlarmAction(new cloudwatchActions.SnsAction(alerts)); + } + new cdk.CfnOutput(this, 'HttpApiUrl', { value: this.httpApi.apiEndpoint }); } } diff --git a/infra/cdk/lib/email-stack.ts b/infra/cdk/lib/email-stack.ts index 26a32cd..2ccdc94 100644 --- a/infra/cdk/lib/email-stack.ts +++ b/infra/cdk/lib/email-stack.ts @@ -5,6 +5,7 @@ import * as ses from 'aws-cdk-lib/aws-ses'; import * as sesActions from 'aws-cdk-lib/aws-ses-actions'; import * as s3 from 'aws-cdk-lib/aws-s3'; import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as logs from 'aws-cdk-lib/aws-logs'; import { Platform } from 'aws-cdk-lib/aws-ecr-assets'; import * as iam from 'aws-cdk-lib/aws-iam'; import { @@ -15,7 +16,7 @@ import { import * as path from 'node:path'; import { fileURLToPath } from 'node:url'; import { HOSTED_ZONE_ID, ROOT_DOMAIN, FORWARD_TO_ADDRESS } from './config.js'; -import { publishLiveAlias } from './lambda-canary.js'; +import { publishCurrentAlias } from './lambda-canary.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -92,6 +93,10 @@ export class EmailStack extends cdk.Stack { }, ), timeout: cdk.Duration.seconds(30), + logGroup: new logs.LogGroup(this, 'ForwarderLogGroup', { + retention: logs.RetentionDays.ONE_MONTH, + removalPolicy: cdk.RemovalPolicy.DESTROY, + }), environment: { MAIL_BUCKET_NAME: mailBucket.bucketName, FORWARD_FROM_ADDRESS: `forwarder@${ROOT_DOMAIN}`, @@ -99,7 +104,7 @@ export class EmailStack extends cdk.Stack { }, }); - const live = publishLiveAlias(forwarderFn, { type: 'AllAtOnce' }); + const current = publishCurrentAlias(forwarderFn); mailBucket.grantRead(forwarderFn); forwarderFn.addToRolePolicy( @@ -109,7 +114,7 @@ export class EmailStack extends cdk.Stack { }), ); // sesActions.Lambda's bind() below auto-grants SES invoke permission on - // the live alias, so no explicit addPermission call needed here. + // the current alias, so no explicit addPermission call needed here. const ruleSet = new ses.ReceiptRuleSet(this, 'ReceiptRuleSet', { receiptRuleSetName: 'btfp-inbound', @@ -128,7 +133,7 @@ export class EmailStack extends cdk.Stack { scanEnabled: true, actions: [ new sesActions.S3({ bucket: mailBucket }), - new sesActions.Lambda({ function: live }), + new sesActions.Lambda({ function: current }), ], }); diff --git a/infra/cdk/lib/lambda-canary.spec.ts b/infra/cdk/lib/lambda-canary.spec.ts new file mode 100644 index 0000000..27dc8eb --- /dev/null +++ b/infra/cdk/lib/lambda-canary.spec.ts @@ -0,0 +1,57 @@ +import * as cdk from 'aws-cdk-lib'; +import { Match, Template } from 'aws-cdk-lib/assertions'; +import * as codedeploy from 'aws-cdk-lib/aws-codedeploy'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; +import { describe, expect, it } from 'vitest'; +import { publishCurrentAlias } from './lambda-canary.js'; + +function synth(options?: Parameters[1]): Template { + const stack = new cdk.Stack(new cdk.App(), 'Test'); + const fn = new lambda.Function(stack, 'Fn', { + runtime: lambda.Runtime.NODEJS_22_X, + handler: 'index.handler', + code: lambda.Code.fromInline('exports.handler = async () => ({})'), + }); + publishCurrentAlias(fn, options); + return Template.fromStack(stack); +} + +describe('publishCurrentAlias', () => { + it('without a canary: publishes the alias, no CodeDeploy, no SAM transform', () => { + const template = synth(); + + template.hasResourceProperties('AWS::Lambda::Alias', { Name: 'current' }); + template.resourceCountIs('AWS::CodeDeploy::DeploymentGroup', 0); + template.resourceCountIs('AWS::CloudWatch::Alarm', 0); + expect(template.toJSON().Transform).toBeUndefined(); + }); + + it('with a canary: shifts traffic via CodeDeploy and rolls back on either alarm', () => { + const template = synth({ + canary: codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_5MINUTES, + }); + + template.hasResourceProperties('AWS::CodeDeploy::DeploymentGroup', { + DeploymentConfigName: 'CodeDeployDefault.LambdaCanary10Percent5Minutes', + AlarmConfiguration: Match.objectLike({ Enabled: true }), + AutoRollbackConfiguration: Match.objectLike({ Enabled: true }), + }); + const [group] = Object.values(template.findResources('AWS::CodeDeploy::DeploymentGroup')); + expect(group?.Properties.AlarmConfiguration.Alarms).toHaveLength(2); + template.hasResource('AWS::Lambda::Alias', { + UpdatePolicy: { CodeDeployLambdaAliasUpdate: Match.objectLike({}) }, + }); + template.resourceCountIs('AWS::CloudWatch::Alarm', 2); + expect(template.toJSON().Transform).toBeUndefined(); + }); + + it('scopes the new-version alarm to the executed version, not the whole alias', () => { + const template = synth({ + canary: codedeploy.LambdaDeploymentConfig.CANARY_10PERCENT_5MINUTES, + }); + + template.hasResourceProperties('AWS::CloudWatch::Alarm', { + Dimensions: Match.arrayWith([Match.objectLike({ Name: 'ExecutedVersion' })]), + }); + }); +}); diff --git a/infra/cdk/lib/lambda-canary.ts b/infra/cdk/lib/lambda-canary.ts index aba79c4..938576c 100644 --- a/infra/cdk/lib/lambda-canary.ts +++ b/infra/cdk/lib/lambda-canary.ts @@ -1,99 +1,86 @@ import * as cdk from 'aws-cdk-lib'; import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch'; +import * as codedeploy from 'aws-cdk-lib/aws-codedeploy'; import * as lambda from 'aws-cdk-lib/aws-lambda'; -import * as sam from 'aws-cdk-lib/aws-sam'; +const ALIAS_NAME = 'current'; const CANARY_PERIOD = cdk.Duration.minutes(1); +export interface CurrentAliasOptions { + /** + * Traffic-shifting strategy for new versions. Omit for an immediate cutover: + * the alias simply points at the new version and CloudFormation does not wait + * on a CodeDeploy deployment. + */ + canary?: codedeploy.ILambdaDeploymentConfig; +} + +function errorAlarm( + scope: lambda.Function, + id: string, + description: string, + metric: cloudwatch.IMetric, +): cloudwatch.Alarm { + return new cloudwatch.Alarm(scope, id, { + alarmDescription: description, + metric, + threshold: 1, + evaluationPeriods: 1, + comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING, + }); +} + /** - * Turns a CDK `Function` into an `AWS::Serverless::Function` so we get SAM's - * AutoPublishAlias / AutoPublishAliasAllProperties / DeploymentPreference - * instead of a hand-rolled CodeDeploy `LambdaDeploymentGroup`. - * - * `deploymentPreference` is SAM's `CfnFunction.DeploymentPreferenceProperty`. - * `type` starts the traffic shift; `alarms` (if any) only roll it back. + * Publishes a `current` alias pointing at this deploy's version, and returns + * it. Callers must send invoke traffic at the returned alias, not `$LATEST`, + * or a canary never sees user traffic. Do not set `additionalVersions` on the + * alias; CodeDeploy owns the weights during a shift. * - * Traffic must go to the returned `:live` alias, not `$LATEST`. - * - * One-time migration note: a function that previously used a CDK-managed - * `fn.addAlias('live')` (pre-SAM) has an existing `live` alias outside this - * stack's control. SAM's `AutoPublishAlias` cannot create it while it - * exists — CloudFormation has no reliable way to order that deletion - * before this creation without a Ref-based custom resource depending on - * the function, which cycles back through SAM's DependsOn propagation to - * every resource generated from it (Version, Alias). Delete it manually, - * once, before deploying this change: - * aws lambda delete-alias --function-name --name live - * Safe to run against a function with no alias (returns ResourceNotFoundException). - * See docs/infra.md. + * With `canary`, CodeDeploy shifts traffic per that config and rolls the alias + * back if either alarm fires: Errors on the alias, or on the new version only + * (an error on the old version must not fail a good deploy). */ -export function publishLiveAlias( +export function publishCurrentAlias( fn: lambda.Function, - deploymentPreference: sam.CfnFunction.DeploymentPreferenceProperty, -): lambda.IFunction { - // PublishVersion fails with "A version for this Lambda function exists (N)" - // when code+config match an already-published version. That is the usual - // first-deploy of AutoPublishAlias onto a function that already has versions - // from an earlier CDK `currentVersion` — the SAM Version resource is new to - // the stack, but Lambda sees no change. This env var is the configuration - // change that lets CreateVersion succeed; later deploys keep it. - fn.addEnvironment('BTFP_INVOKE_ALIAS', 'live'); - - fn.stack.addTransform('AWS::Serverless-2016-10-31'); - - const cfn = fn.node.defaultChild as lambda.CfnFunction; - cfn.addOverride('Type', 'AWS::Serverless::Function'); + options: CurrentAliasOptions = {}, +): lambda.Alias { + const alias = new lambda.Alias(fn, 'CurrentAlias', { + aliasName: ALIAS_NAME, + version: fn.currentVersion, + }); - const imageUri = (cfn.code as lambda.CfnFunction.CodeProperty | undefined)?.imageUri; - if (imageUri) { - cfn.addPropertyOverride('ImageUri', imageUri); - cfn.addPropertyDeletionOverride('Code'); - } + if (!options.canary) return alias; - cfn.addPropertyOverride('AutoPublishAlias', 'live'); - cfn.addPropertyOverride('AutoPublishAliasAllProperties', true); + const aliasErrors = errorAlarm( + fn, + 'CurrentAliasErrors', + `${fn.node.path} ${ALIAS_NAME} alias Errors >= 1 — CodeDeploy rolls the canary back`, + alias.metricErrors({ period: CANARY_PERIOD, statistic: 'sum' }), + ); - const shifting = deploymentPreference.type && deploymentPreference.type !== 'AllAtOnce'; - let alarms = deploymentPreference.alarms; - if (shifting && !alarms) { - const aliasErrors = new cloudwatch.Alarm(fn, 'LiveAliasErrors', { - alarmDescription: `${fn.node.path} live alias Errors >= 1 — SAM rolls the canary back`, - metric: new cloudwatch.Metric({ - namespace: 'AWS/Lambda', - metricName: 'Errors', - statistic: 'sum', - period: CANARY_PERIOD, - dimensionsMap: { - FunctionName: fn.functionName, - Resource: `${fn.functionName}:live`, - }, - }), - threshold: 1, - evaluationPeriods: 1, - comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, - treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING, - }); - alarms = [aliasErrors.alarmName]; - } + const newVersionErrors = errorAlarm( + fn, + 'CurrentVersionErrors', + `${fn.node.path} new version Errors >= 1 — CodeDeploy rolls the canary back`, + new cloudwatch.Metric({ + namespace: 'AWS/Lambda', + metricName: 'Errors', + statistic: 'sum', + period: CANARY_PERIOD, + dimensionsMap: { + FunctionName: fn.functionName, + Resource: `${fn.functionName}:${ALIAS_NAME}`, + ExecutedVersion: fn.currentVersion.version, + }, + }), + ); - cfn.addPropertyOverride('DeploymentPreference', { - Type: deploymentPreference.type, - ...(alarms ? { Alarms: alarms } : {}), - ...(deploymentPreference.enabled !== undefined - ? { Enabled: deploymentPreference.enabled } - : {}), - ...(deploymentPreference.hooks ? { Hooks: deploymentPreference.hooks } : {}), - ...(deploymentPreference.role ? { Role: deploymentPreference.role } : {}), + new codedeploy.LambdaDeploymentGroup(fn, 'Canary', { + alias, + deploymentConfig: options.canary, + alarms: [aliasErrors, newVersionErrors], }); - return lambda.Function.fromFunctionAttributes(fn, 'LiveAlias', { - functionArn: `${fn.functionArn}:live`, - role: fn.role, - // Without this, CDK treats the imported alias as possibly - // cross-account/region (fn.functionArn is a token) and silently no-ops - // addPermission() — grantInvoke() from HttpLambdaIntegration then adds - // no resource policy at all, so API Gateway gets 500s invoking it. - // It's always the same stack's own function, just via an alias ARN. - sameEnvironment: true, - }); + return alias; } diff --git a/infra/cdk/package.json b/infra/cdk/package.json index 862840d..6644ae2 100644 --- a/infra/cdk/package.json +++ b/infra/cdk/package.json @@ -6,6 +6,7 @@ "scripts": { "build": "tsc -b", "typecheck": "tsc -b --noEmit", + "test": "vitest run", "cdk": "cdk", "secrets:push": "tsx scripts/secrets.ts push", "secrets:sync": "tsx scripts/secrets.ts sync" @@ -13,17 +14,18 @@ "devDependencies": { "@btfp/bff": "workspace:*", "@btfp/scraper": "workspace:*", - "@types/node": "^26.6.1", - "aws-cdk": "^2.1131.0", - "tsx": "^4.19.0", - "typescript": "^5.8.0" + "@types/node": "26.6.2", + "aws-cdk": "2.1142.0", + "tsx": "4.23.13", + "typescript": "7.0.2", + "vitest": "5.0.1" }, "dependencies": { - "@aws-sdk/client-ssm": "^3.716.0", - "@aws-sdk/client-sts": "^3.716.0", - "@bubltec/mycota-cdk": "0.6.0", - "aws-cdk-lib": "^2.261.0", - "constructs": "^10.4.0", - "source-map-support": "^0.5.21" + "@aws-sdk/client-ssm": "3.1136.0", + "@aws-sdk/client-sts": "3.1136.0", + "@bubltec/mycota-cdk": "1.0.0", + "aws-cdk-lib": "2.270.0", + "constructs": "10.8.1", + "source-map-support": "0.5.21" } } diff --git a/infra/cdk/vitest.config.ts b/infra/cdk/vitest.config.ts new file mode 100644 index 0000000..f64c68c --- /dev/null +++ b/infra/cdk/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vitest/config'; + +// cdk.out/ holds staged copies of other packages' sources (including their +// specs) as deploy assets — never collect those. +export default defineConfig({ + test: { include: ['lib/**/*.spec.ts'] }, +}); diff --git a/package.json b/package.json index b069763..9c1494f 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "engines": { - "node": ">=24" + "node": ">=26" }, "packageManager": "pnpm@11.20.0", "scripts": { @@ -23,10 +23,10 @@ "mycota:pull": "bash scripts/mycota-pull.sh" }, "devDependencies": { - "lefthook": "^1.13.6", - "oxfmt": "^0.59.0", - "oxlint": "^1.74.0", - "turbo": "^2.3.0", - "typescript": "^5.8.0" + "lefthook": "2.1.14", + "oxfmt": "0.68.0", + "oxlint": "1.83.0", + "turbo": "2.11.2", + "typescript": "7.0.2" } } diff --git a/packages/config/tsconfig-node.json b/packages/config/tsconfig-node.json index 82833a4..9a67ab9 100644 --- a/packages/config/tsconfig-node.json +++ b/packages/config/tsconfig-node.json @@ -3,6 +3,7 @@ "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext", - "target": "ES2023" + "target": "ES2023", + "types": ["node"] } } diff --git a/packages/shared-types/package.json b/packages/shared-types/package.json index cd192fb..fd0c207 100644 --- a/packages/shared-types/package.json +++ b/packages/shared-types/package.json @@ -17,7 +17,8 @@ "test": "vitest run" }, "devDependencies": { - "typescript": "^5.8.0", - "vitest": "^2.1.0" + "@types/node": "26.6.2", + "typescript": "7.0.2", + "vitest": "5.0.1" } } diff --git a/packages/shared-types/src/contribution-queue.spec.ts b/packages/shared-types/src/contribution-queue.spec.ts new file mode 100644 index 0000000..2049505 --- /dev/null +++ b/packages/shared-types/src/contribution-queue.spec.ts @@ -0,0 +1,86 @@ +import { describe, expect, it } from 'vitest'; +import type { Contribution } from './contribution.js'; +import { + clusterPendingContributions, + findMatchingContribution, + planContributionAttach, +} from './contribution-queue.js'; +import { mergeThingPayload } from './thing-identity.js'; + +function pending( + overrides: Partial & Pick, +): Contribution { + return { + contributorId: 'user', + status: 'pending', + payload: { name: 'Chocolate', thingTypeId: 'food' }, + ...overrides, + }; +} + +describe('clusterPendingContributions', () => { + it('folds duplicate Chocolate queue rows into the newest card', () => { + const clustered = clusterPendingContributions([ + pending({ + id: 'a', + createdAt: '2026-01-01T00:00:00.000Z', + thingId: 'choc', + payload: { name: 'Chocolate', thingTypeId: 'food', details: { notes: 'theobromine' } }, + }), + pending({ + id: 'b', + createdAt: '2026-01-02T00:00:00.000Z', + thingId: 'choc', + payload: { name: 'Chocolate', thingTypeId: 'food', details: { notes: 'theobromine' } }, + }), + pending({ + id: 'c', + createdAt: '2026-01-03T00:00:00.000Z', + payload: { name: 'Xylitol', thingTypeId: 'food' }, + }), + ]); + + expect(clustered).toHaveLength(2); + expect(clustered[0]?.id).toBe('c'); + expect(clustered[1]?.id).toBe('b'); + expect(clustered[1]?.payload.details).toEqual({ notes: 'theobromine' }); + }); + + it('accumulates new details instead of repeating the same text', () => { + const merged = mergeThingPayload( + { name: 'Chocolate', thingTypeId: 'food', details: { notes: 'theobromine' } }, + { + name: 'Chocolate', + thingTypeId: 'food', + details: { notes: 'theobromine', clinicalSigns: 'vomiting' }, + }, + ); + expect(merged.details).toEqual({ notes: 'theobromine', clinicalSigns: 'vomiting' }); + }); +}); + +describe('planContributionAttach', () => { + it('updates an existing pending row for the same live Thing', () => { + const existing = pending({ + id: 'queued', + createdAt: '2026-01-01T00:00:00.000Z', + thingId: 'choc', + }); + const plan = planContributionAttach({ + payload: { name: 'Chocolate', thingTypeId: 'food' }, + catalogMatchId: 'choc', + pending: [existing], + }); + expect(plan.pendingMatch?.id).toBe('queued'); + expect(plan.thingId).toBe('choc'); + }); + + it('matches by identity when thingId is not set yet', () => { + const existing = pending({ id: 'queued', createdAt: '2026-01-01T00:00:00.000Z' }); + expect( + findMatchingContribution([existing], { + payload: { name: 'chocolate', thingTypeId: 'food' }, + })?.id, + ).toBe('queued'); + }); +}); diff --git a/packages/shared-types/src/contribution-queue.ts b/packages/shared-types/src/contribution-queue.ts new file mode 100644 index 0000000..72054b0 --- /dev/null +++ b/packages/shared-types/src/contribution-queue.ts @@ -0,0 +1,79 @@ +import type { Contribution } from './contribution.js'; +import { mergeThingPayload, thingsMatch, type ThingIdentity } from './thing-identity.js'; + +export function contributionIdentity( + contribution: Pick, +): ThingIdentity | undefined { + const name = contribution.payload?.name; + const thingTypeId = contribution.payload?.thingTypeId; + if (typeof name !== 'string' || !name.trim()) return undefined; + if (typeof thingTypeId !== 'string' || !thingTypeId.trim()) return undefined; + return { + name, + thingTypeId, + otherNames: contribution.payload.otherNames, + details: contribution.payload.details, + }; +} + +export function contributionsMatch( + a: Pick, + b: Pick, +): boolean { + if (a.thingId && b.thingId && a.thingId === b.thingId) return true; + const left = contributionIdentity(a); + const right = contributionIdentity(b); + if (!left || !right) return false; + try { + return thingsMatch(left, right); + } catch { + return false; + } +} + +export function findMatchingContribution>( + pending: T[], + candidate: Pick, +): T | undefined { + return pending.find((item) => contributionsMatch(item, candidate)); +} + +/** One queue row per identity: newest SK kept, older payloads folded in. */ +export function clusterPendingContributions(items: T[]): T[] { + const ordered = [...items].sort((a, b) => b.createdAt.localeCompare(a.createdAt)); + const used = new Set(); + const clustered: T[] = []; + + for (let i = 0; i < ordered.length; i++) { + if (used.has(i)) continue; + const newest = ordered[i]!; + used.add(i); + let payload = newest.payload; + let thingId = newest.thingId; + for (let j = i + 1; j < ordered.length; j++) { + if (used.has(j)) continue; + const other = ordered[j]!; + if (!contributionsMatch(newest, other)) continue; + used.add(j); + payload = mergeThingPayload(payload, other.payload); + thingId ??= other.thingId; + } + clustered.push({ ...newest, payload, thingId }); + } + + return clustered; +} + +export function planContributionAttach(input: { + payload: ThingIdentity; + explicitThingId?: string; + catalogMatchId?: string; + pending: Contribution[]; +}): { pendingMatch?: Contribution; thingId?: string } { + const thingId = input.explicitThingId ?? input.catalogMatchId; + const pendingMatch = findMatchingContribution(input.pending, { + payload: input.payload, + thingId, + }); + return { pendingMatch, thingId: thingId ?? pendingMatch?.thingId }; +} diff --git a/packages/shared-types/src/index.ts b/packages/shared-types/src/index.ts index 6da0e2c..4a73fc5 100644 --- a/packages/shared-types/src/index.ts +++ b/packages/shared-types/src/index.ts @@ -4,6 +4,7 @@ export * from './thing-type.js'; export * from './thing.js'; export * from './user.js'; export * from './contribution.js'; +export * from './contribution-queue.js'; export * from './quiz.js'; export * from './slugify.js'; export * from './thing-identity.js'; diff --git a/packages/shared-types/src/thing-identity.ts b/packages/shared-types/src/thing-identity.ts index 6ea7893..ea499a4 100644 --- a/packages/shared-types/src/thing-identity.ts +++ b/packages/shared-types/src/thing-identity.ts @@ -255,3 +255,50 @@ export function mergeThings(canonical: Thing, extra: Thing): Thing { contributorId: canonical.contributorId ?? extra.contributorId, }; } + +function mergeDetailsAccumulating( + canonical: Record, + extra: Record, +): Record { + const details = { ...canonical }; + for (const [key, value] of Object.entries(extra)) { + if (isEmptyDetail(details[key])) { + details[key] = value; + continue; + } + if ( + typeof details[key] === 'string' && + typeof value === 'string' && + value.trim() && + !String(details[key]).includes(value.trim()) + ) { + details[key] = `${details[key]}\n\n${value}`; + } + } + return details; +} + +/** + * Fold a later contribution/edit into an earlier payload. New pet types, + * aliases, and empty details are added; identical text is not repeated. + */ +export function mergeThingPayload( + canonical: Partial, + extra: Partial, +): Partial { + const name = canonical.name?.trim() || extra.name; + return { + ...canonical, + name, + thingTypeId: canonical.thingTypeId ?? extra.thingTypeId, + otherNames: uniqueNames(name ?? '', [ + ...(canonical.otherNames ?? []), + ...(extra.name && extra.name !== name ? [extra.name] : []), + ...(extra.otherNames ?? []), + ]), + petTypes: mergePetTypes(canonical.petTypes ?? [], extra.petTypes ?? []), + details: mergeDetailsAccumulating(canonical.details ?? {}, extra.details ?? {}), + source: canonical.source ?? extra.source, + sourceUrl: canonical.sourceUrl ?? extra.sourceUrl, + }; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a1a3619..3981b44 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,302 +4,305 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + fastify: 5.12.5 + importers: .: devDependencies: lefthook: - specifier: ^1.13.6 - version: 1.13.6 + specifier: 2.1.14 + version: 2.1.14 oxfmt: - specifier: ^0.59.0 - version: 0.59.0 + specifier: 0.68.0 + version: 0.68.0 oxlint: - specifier: ^1.74.0 - version: 1.74.0 + specifier: 1.83.0 + version: 1.83.0 turbo: - specifier: ^2.3.0 - version: 2.10.5 + specifier: 2.11.2 + version: 2.11.2 typescript: - specifier: ^5.8.0 - version: 5.9.3 + specifier: 7.0.2 + version: 7.0.2 apps/bff: dependencies: '@aws-sdk/client-bedrock-runtime': - specifier: ^3.716.0 - version: 3.1087.0 + specifier: 3.1136.0 + version: 3.1136.0 '@aws-sdk/client-dynamodb': - specifier: ^3.716.0 - version: 3.1087.0 + specifier: 3.1136.0 + version: 3.1136.0 '@aws-sdk/client-ses': - specifier: ^3.716.0 - version: 3.1087.0 + specifier: 3.1136.0 + version: 3.1136.0 '@aws-sdk/client-ssm': - specifier: ^3.716.0 - version: 3.1088.0 + specifier: 3.1136.0 + version: 3.1136.0 '@aws-sdk/lib-dynamodb': - specifier: ^3.716.0 - version: 3.1087.0(@aws-sdk/client-dynamodb@3.1087.0) + specifier: 3.1136.0 + version: 3.1136.0(@aws-sdk/client-dynamodb@3.1136.0) '@btfp/shared-types': specifier: workspace:* version: link:../../packages/shared-types '@bubltec/mycota-auth': - specifier: 0.6.0 - version: 0.6.0(@aws-sdk/client-dynamodb@3.1087.0)(supports-color@7.2.0) + specifier: 1.0.0 + version: 1.0.0(@aws-sdk/client-dynamodb@3.1136.0)(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/jwt@12.0.2(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)))(@nestjs/passport@12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0))(class-transformer@0.5.1)(class-validator@0.15.1)(passport@0.7.0)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@bubltec/mycota-dynamo': - specifier: 0.6.0 - version: 0.6.0(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + specifier: 1.0.0 + version: 1.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)) '@bubltec/mycota-professional-verification': - specifier: 0.6.0 - version: 0.6.0(@aws-sdk/client-dynamodb@3.1087.0)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + specifier: 1.0.0 + version: 1.0.0(@aws-sdk/client-dynamodb@3.1136.0)(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/jwt@12.0.2(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)))(@nestjs/passport@12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0))(class-transformer@0.5.1)(class-validator@0.15.1)(passport@0.7.0)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@fastify/aws-lambda': - specifier: ^4.1.0 - version: 4.1.0 + specifier: 6.4.1 + version: 6.4.1 '@fastify/cookie': - specifier: ^9.4.0 - version: 9.4.0 + specifier: 11.1.2 + version: 11.1.2 '@nestjs/common': - specifier: ^10.4.0 - version: 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + specifier: 12.0.3 + version: 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) '@nestjs/config': - specifier: ^3.3.0 - version: 3.3.0(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(rxjs@7.8.2) + specifier: 12.0.0 + version: 12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(rxjs@7.8.2) '@nestjs/core': - specifier: ^10.4.0 - version: 10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2) + specifier: 12.0.3 + version: 12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/jwt': - specifier: ^10.2.0 - version: 10.2.0(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)) + specifier: 12.0.2 + version: 12.0.2(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)) '@nestjs/passport': - specifier: ^10.0.3 - version: 10.0.3(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0) + specifier: 12.0.0 + version: 12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0) '@nestjs/platform-fastify': - specifier: ^10.4.0 - version: 10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2)) + specifier: 12.0.3 + version: 12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2)) '@nestjs/swagger': - specifier: ^8.1.1 - version: 8.1.1(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2) + specifier: 12.0.1 + version: 12.0.1(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2) class-transformer: - specifier: ^0.5.1 + specifier: 0.5.1 version: 0.5.1 class-validator: - specifier: ^0.14.1 - version: 0.14.4 + specifier: 0.15.1 + version: 0.15.1 fastify: - specifier: ^4.28.1 - version: 4.28.1 + specifier: 5.12.5 + version: 5.12.5 fuse.js: - specifier: ^7.0.0 + specifier: 7.5.0 version: 7.5.0 passport: - specifier: ^0.7.0 + specifier: 0.7.0 version: 0.7.0 passport-github2: - specifier: ^0.1.12 + specifier: 0.1.12 version: 0.1.12 passport-google-oauth20: - specifier: ^2.0.0 + specifier: 2.0.0 version: 2.0.0 reflect-metadata: - specifier: ^0.2.2 + specifier: 0.2.2 version: 0.2.2 rxjs: - specifier: ^7.8.1 + specifier: 7.8.2 version: 7.8.2 devDependencies: '@types/node': - specifier: ^26.6.1 - version: 26.6.1 + specifier: 26.6.2 + version: 26.6.2 '@types/passport-github2': - specifier: ^1.2.9 + specifier: 1.2.9 version: 1.2.9 '@types/passport-google-oauth20': - specifier: ^2.0.16 + specifier: 2.0.17 version: 2.0.17 aws-sdk-client-mock: - specifier: ^4.1.0 + specifier: 4.1.0 version: 4.1.0 esbuild: - specifier: ^0.24.2 - version: 0.24.2 + specifier: 0.28.2 + version: 0.28.2 tsc-watch: - specifier: ^7.2.1 - version: 7.2.1(typescript@5.9.3) + specifier: 7.2.1 + version: 7.2.1(typescript@7.0.2) typescript: - specifier: ^5.8.0 - version: 5.9.3 + specifier: 7.0.2 + version: 7.0.2 vitest: - specifier: ^2.1.0 - version: 2.1.9(@types/node@26.6.1)(lightningcss@1.32.0)(supports-color@7.2.0) + specifier: 5.0.1 + version: 5.0.1(@types/node@26.6.2)(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)) apps/e2e: dependencies: '@aws-sdk/client-bedrock-runtime': - specifier: ^3.716.0 - version: 3.1087.0 + specifier: 3.1136.0 + version: 3.1136.0 devDependencies: '@playwright/test': - specifier: ^1.56.0 - version: 1.61.1 + specifier: 1.63.0 + version: 1.63.0 '@types/node': - specifier: ^26.6.1 - version: 26.6.1 + specifier: 26.6.2 + version: 26.6.2 tsx: - specifier: ^4.19.0 - version: 4.23.1 + specifier: 4.23.13 + version: 4.23.13 typescript: - specifier: ^5.8.0 - version: 5.9.3 + specifier: 7.0.2 + version: 7.0.2 apps/scraper: dependencies: '@aws-crypto/sha256-js': - specifier: ^5.2.0 + specifier: 5.2.0 version: 5.2.0 '@aws-sdk/client-bedrock-agentcore': - specifier: ^3.716.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/client-bedrock-runtime': - specifier: ^3.716.0 - version: 3.1087.0 + specifier: 3.1136.0 + version: 3.1136.0 '@aws-sdk/client-dynamodb': - specifier: ^3.716.0 - version: 3.1087.0 + specifier: 3.1136.0 + version: 3.1136.0 '@aws-sdk/credential-provider-node': - specifier: ^3.716.0 - version: 3.972.70 + specifier: 3.972.83 + version: 3.972.83 '@aws-sdk/lib-dynamodb': - specifier: ^3.716.0 - version: 3.1087.0(@aws-sdk/client-dynamodb@3.1087.0) + specifier: 3.1136.0 + version: 3.1136.0(@aws-sdk/client-dynamodb@3.1136.0) '@btfp/shared-types': specifier: workspace:* version: link:../../packages/shared-types '@smithy/protocol-http': - specifier: ^5.3.10 + specifier: 5.6.2 version: 5.6.2 '@smithy/signature-v4': - specifier: ^5.3.10 - version: 5.6.5 + specifier: 5.7.3 + version: 5.7.3 playwright-core: - specifier: ^1.55.0 - version: 1.61.1 + specifier: 1.63.0 + version: 1.63.0 devDependencies: '@types/node': - specifier: ^26.6.1 - version: 26.6.1 + specifier: 26.6.2 + version: 26.6.2 aws-sdk-client-mock: - specifier: ^4.1.0 + specifier: 4.1.0 version: 4.1.0 esbuild: - specifier: ^0.24.2 - version: 0.24.2 + specifier: 0.28.2 + version: 0.28.2 typescript: - specifier: ^5.8.0 - version: 5.9.3 + specifier: 7.0.2 + version: 7.0.2 vitest: - specifier: ^2.1.0 - version: 2.1.9(@types/node@26.6.1)(lightningcss@1.32.0)(supports-color@7.2.0) + specifier: 5.0.1 + version: 5.0.1(@types/node@26.6.2)(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)) apps/web: dependencies: - '@base-ui-components/react': - specifier: ^1.0.0-rc.0 - version: 1.0.0-rc.0(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@base-ui/react': + specifier: 1.8.0 + version: 1.8.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@btfp/shared-types': specifier: workspace:* version: link:../../packages/shared-types react: - specifier: ^19.0.0 - version: 19.2.7 + specifier: 19.3.0 + version: 19.3.0 react-dom: - specifier: ^19.0.0 - version: 19.2.7(react@19.2.7) + specifier: 19.3.0 + version: 19.3.0(react@19.3.0) react-router-dom: - specifier: ^7.1.0 - version: 7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: 7.18.4 + version: 7.18.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0) devDependencies: '@playwright/test': - specifier: ^1.56.0 - version: 1.61.1 + specifier: 1.63.0 + version: 1.63.0 '@tailwindcss/vite': - specifier: ^4.0.0 - version: 4.3.2(vite@6.4.3(@types/node@26.6.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)) + specifier: 4.3.3 + version: 4.3.3(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)) '@types/node': - specifier: ^26.6.1 - version: 26.6.1 + specifier: 26.6.2 + version: 26.6.2 '@types/react': - specifier: ^19.0.0 - version: 19.2.17 + specifier: 19.3.0 + version: 19.3.0 '@types/react-dom': - specifier: ^19.0.0 - version: 19.2.3(@types/react@19.2.17) + specifier: 19.3.0 + version: 19.3.0(@types/react@19.3.0) '@vitejs/plugin-react': - specifier: ^4.3.4 - version: 4.7.0(supports-color@7.2.0)(vite@6.4.3(@types/node@26.6.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)) + specifier: 6.1.1 + version: 6.1.1(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)) tailwindcss: - specifier: ^4.0.0 - version: 4.3.2 + specifier: 4.3.3 + version: 4.3.3 typescript: - specifier: ^5.8.0 - version: 5.9.3 + specifier: 7.0.2 + version: 7.0.2 vite: - specifier: ^6.0.0 - version: 6.4.3(@types/node@26.6.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1) + specifier: 8.3.0 + version: 8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13) data/seed: dependencies: '@aws-sdk/client-bedrock-runtime': - specifier: ^3.716.0 - version: 3.1087.0 + specifier: 3.1136.0 + version: 3.1136.0 '@aws-sdk/client-dynamodb': - specifier: ^3.716.0 - version: 3.1087.0 + specifier: 3.1136.0 + version: 3.1136.0 '@aws-sdk/lib-dynamodb': - specifier: ^3.716.0 - version: 3.1087.0(@aws-sdk/client-dynamodb@3.1087.0) + specifier: 3.1136.0 + version: 3.1136.0(@aws-sdk/client-dynamodb@3.1136.0) '@btfp/shared-types': specifier: workspace:* version: link:../../packages/shared-types cheerio: - specifier: ^1.0.0 + specifier: 1.2.0 version: 1.2.0 devDependencies: '@types/node': - specifier: ^26.6.1 - version: 26.6.1 + specifier: 26.6.2 + version: 26.6.2 aws-sdk-client-mock: - specifier: ^4.1.0 + specifier: 4.1.0 version: 4.1.0 tsx: - specifier: ^4.19.0 - version: 4.23.1 + specifier: 4.23.13 + version: 4.23.13 typescript: - specifier: ^5.8.0 - version: 5.9.3 + specifier: 7.0.2 + version: 7.0.2 vitest: - specifier: ^2.1.0 - version: 2.1.9(@types/node@26.6.1)(lightningcss@1.32.0)(supports-color@7.2.0) + specifier: 5.0.1 + version: 5.0.1(@types/node@26.6.2)(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)) infra/cdk: dependencies: '@aws-sdk/client-ssm': - specifier: ^3.716.0 - version: 3.1088.0 + specifier: 3.1136.0 + version: 3.1136.0 '@aws-sdk/client-sts': - specifier: ^3.716.0 - version: 3.1089.0 + specifier: 3.1136.0 + version: 3.1136.0 '@bubltec/mycota-cdk': - specifier: 0.6.0 - version: 0.6.0(aws-cdk-lib@2.261.0(constructs@10.6.0))(constructs@10.6.0) + specifier: 1.0.0 + version: 1.0.0(aws-cdk-lib@2.270.0(constructs@10.8.1))(constructs@10.8.1) aws-cdk-lib: - specifier: ^2.261.0 - version: 2.261.0(constructs@10.6.0) + specifier: 2.270.0 + version: 2.270.0(constructs@10.8.1) constructs: - specifier: ^10.4.0 - version: 10.6.0 + specifier: 10.8.1 + version: 10.8.1 source-map-support: - specifier: ^0.5.21 + specifier: 0.5.21 version: 0.5.21 devDependencies: '@btfp/bff': @@ -309,39 +312,45 @@ importers: specifier: workspace:* version: link:../../apps/scraper '@types/node': - specifier: ^26.6.1 - version: 26.6.1 + specifier: 26.6.2 + version: 26.6.2 aws-cdk: - specifier: ^2.1131.0 - version: 2.1131.0 + specifier: 2.1142.0 + version: 2.1142.0 tsx: - specifier: ^4.19.0 - version: 4.23.1 + specifier: 4.23.13 + version: 4.23.13 typescript: - specifier: ^5.8.0 - version: 5.9.3 + specifier: 7.0.2 + version: 7.0.2 + vitest: + specifier: 5.0.1 + version: 5.0.1(@types/node@26.6.2)(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)) packages/config: {} packages/shared-types: devDependencies: + '@types/node': + specifier: 26.6.2 + version: 26.6.2 typescript: - specifier: ^5.8.0 - version: 5.9.3 + specifier: 7.0.2 + version: 7.0.2 vitest: - specifier: ^2.1.0 - version: 2.1.9(@types/node@26.6.1)(lightningcss@1.32.0)(supports-color@7.2.0) + specifier: 5.0.1 + version: 5.0.1(@types/node@26.6.2)(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)) packages: - '@aws-cdk/asset-awscli-v1@2.2.282': - resolution: {integrity: sha512-7hKMi5tTxDcKGIMIOq14PnY0GBcugW33Uh/2YHDZiEwSxLeFOCYBwhR+BFXONb/EJeVI3RETFgailNZbkcKF6g==} + '@aws-cdk/asset-awscli-v1@2.2.292': + resolution: {integrity: sha512-d4aMFsAFj19FtxVyw8IzlUKv5Zu4sIvgnEjI2IU6IWBJgVbJ4aFnadANqYa+6MwB1CQbGOg0jh8WE77M+Nb/9A==} - '@aws-cdk/asset-node-proxy-agent-v6@2.1.2': - resolution: {integrity: sha512-pDiuqH+qY3zM9lhhLjbKJ1tnKOHzQ2V4Wr/3qsxyKeKAkuPMI/BVGvZG1PbrikUw949cGVTfVEt4ETKKYnrj0Q==} + '@aws-cdk/asset-node-proxy-agent-v6@2.1.3': + resolution: {integrity: sha512-98We1QWfin9vtuuQtNFhIIAEWb8CreyYTAP0Vn8HqSBoNiFJM9nZgifJeQawT9Wq0NX1HCNFlxCyTccIrK1PSA==} - '@aws-cdk/cloud-assembly-schema@54.11.0': - resolution: {integrity: sha512-qpkGINVp8CIaXXkEX5sPmARPk8bbvCFXhMHm/Nmae3K3V+OzDVthntuFVwGxl/jzfdrKPIhbkE9Mrxk+f1mK3A==} + '@aws-cdk/cloud-assembly-schema@54.24.0': + resolution: {integrity: sha512-9sH1pBpWuqZR/9rYAveNi62B/jDrc9BNOL83alD/wtIUSbRkg1aj6JX2r1cSugQwLBjCizQscQZgAb5wWnTTMg==} engines: {node: '>= 18.0.0'} bundledDependencies: - jsonschema @@ -358,58 +367,34 @@ packages: resolution: {integrity: sha512-fpyMhUO8FMqtsJv4+2b6iE/vkSI2arraWdqo8FOYGnkeLfwtikao3QOwqiNj1ihZ0wk7xr+Sscg5M1wigQEMFw==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-bedrock-runtime@3.1087.0': - resolution: {integrity: sha512-Nyv5gbmraL+Q8yrT7bFgcH7lxBcUnSQdOc1jbiisi7kk/dg26PAnqbwEDpFtbh4HGnLaTWudhCwVUAyVKhtiWQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/client-dynamodb@3.1087.0': - resolution: {integrity: sha512-3Rsk29aQltTbAI5QKXqhnVNyLAGTeiU3UkErqiqplduV2jdj8l+ySL45yhq7z/GXN7Q1Rh6x38dRsxazwOTUfQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/client-ses@3.1087.0': - resolution: {integrity: sha512-mjJsyp0YMa9USrbnEnEecAjz64aBtH7j8fXbVb2LxwgWDPKhaa4zUZWzM97Yh8Gp5d/F4TOUK/jq2ywXC+B6lA==} + '@aws-sdk/client-bedrock-runtime@3.1136.0': + resolution: {integrity: sha512-/k+JZc/dWsw2WyRA9k03WVFUNXQyVDWQtcLOKVYJmIBprJg6TirrjVsMxist2UPGH3RFTvl+HG+Wne1PzDLJTg==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-ssm@3.1088.0': - resolution: {integrity: sha512-pGiDxOBGjUK+Sdl1M/+aCtp60YrS0mt1H1uoVC6cAWs2GR+BmWfBOpp5y6w6GnDOBoWVzemyAXunA3+y98joTw==} + '@aws-sdk/client-dynamodb@3.1136.0': + resolution: {integrity: sha512-EEgixP37uQV7UqFxl1JaWGYA7QQeeP0yKSN5uCkAbNw9gBifGGk2cqm8qt1Mz+kzw0OwpL8W445R1UT+RTRBhA==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-sts@3.1089.0': - resolution: {integrity: sha512-RBeHUUaDa0SFsgiczApWVsKwb1L76h9jySANarkunCuR0CMIQ7Qk+lVR6NGhL8D6fC/8pjP7BuZZ4wmrKc/W1g==} + '@aws-sdk/client-ses@3.1136.0': + resolution: {integrity: sha512-n/3eoHp60bidKgJD2GbLgQjVg1ggffiwuungtlxStBRDn8hgTMHuc6d/0b1khclmC8EYdI/BRL72mqguM8qDjg==} engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.975.2': - resolution: {integrity: sha512-iyeXwziyjJpixq5OmhsIyrSWx8vwcI7gDo4yRUC3EP7NQtOo9iAJiIEc3G+/HkhtNXqOhofiCK7Lc34Sq+fJWg==} + '@aws-sdk/client-ssm@3.1136.0': + resolution: {integrity: sha512-tMZyh47eKTo6HbHf5Gg8lHaYwowOp77YTMqfmys9ilpd7bQTq8PYH1Oqy4SxAIptcBe71uy1I7q3YziWVZZC6w==} engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.975.3': - resolution: {integrity: sha512-7ur3kCKuvPLqlsZ2XlvnNBVQ7KkpSu6Y6dOTwSPHLrFpTEfZM8isLBJc4cgv96WB7GifeVM436mpycwxBd2vEA==} + '@aws-sdk/client-sts@3.1136.0': + resolution: {integrity: sha512-6NfisbmH1dBbYy6UgLsaWpeVIfWqQc3j0GYLgV5ciDsthsYMcwlgZjfaoOVoctUhXzBU4Rw50GAqzDGTrgnS9A==} engines: {node: '>=20.0.0'} '@aws-sdk/core@3.978.0': resolution: {integrity: sha512-2yX9LUmxPklVjSGTb8dfnWRJSiFQ3TeH2nn7G1mdKHTfnabzF0+gfrS8rYfLWmZrQ8A3mEcxMJjRc51dL5KWaA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-env@3.972.58': - resolution: {integrity: sha512-vyGtvK1rY940eq7JT0yIGKuZ+2kpPSJcHibSvGlit5oiMFDamzC7cxBGLl4FLnd6suihMXDI2FSF2dL6TmBqPA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-env@3.972.59': - resolution: {integrity: sha512-Ny5e4Mfh3QPmiAc0AiUe+cbTXDlxkU3Rc+EpWOfyWeWEy6yp7Fa1KmfNeCc+1a8by9zQ9gtohmiQUkMPScF3ng==} - engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-env@3.972.71': resolution: {integrity: sha512-JN+JHruYZw3GUZB8YGAlDk4wTDPOEAEEdEzj5nS0xodWR4smzHsN7PnK2j6IeOsDIj2aqua5DSbhXl9Gtf90FQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.60': - resolution: {integrity: sha512-g9b9YzDrD5pcKiPBJfCSXRfFMrA39eR0guUhZ5SRm+7vMAVc43+effxbcamxBjSd5bUhrdKo5te/yQuWurLXLA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-http@3.972.61': - resolution: {integrity: sha512-8jAjgStl5Ytq4+HF3X/9f+EmRinaRbGRRtQGktlPfBRVx73H+R1y48vIeXerQtYGFaUqkEp3fT6jP854rVO2yQ==} - engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.73': resolution: {integrity: sha512-uyYYnJOnlis8uQzaYGPd7N1JoioCoNpXgnkXYixsWJXHXgXyYi8WXJSDfofxJeWfQIGWLe2Nwyq60Uc7MZdVOg==} engines: {node: '>=20.0.0'} @@ -418,58 +403,14 @@ packages: resolution: {integrity: sha512-i++ly+0Uxa+u3ebSSyr0S/3CFhFJDxCXT3+Zj+mW2bXenEx5bKGCdTIKFu39SgXBNhWDjex/8cXUx9MUTMCrTw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-ini@3.973.2': - resolution: {integrity: sha512-Yr7yxNyQ8aHt9Ww0RPFUZx+xiem+vl7vuwhP0tniTijoesJNV5jou9HCgVpI0GEPAF+89TkOvilE5uRrZJnjaw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-ini@3.973.3': - resolution: {integrity: sha512-WpuqYX4gGkx++fCTSWE8+41JzkZVcrI50SH48Ml4CsG1pyuHKyMmpw/FixBHDrmjoQ553PmeCLa/fZIcst+WyA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-ini@3.973.4': - resolution: {integrity: sha512-e6ZvVsj90aRALf1kHP+J4iqC1496ZpVgqI/+u0LJ5HL7q7ATauGy4gdDvRCP13L1pN/fMiZLah162PGIYkbUVQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-login@3.972.64': - resolution: {integrity: sha512-YQoSI4d6kXvoenoG/0Jv/PqaAuukHzGmGXGyHBQYeEUNsYovlNAn/Sw1wp/WQbhcQ3HsEMGgjEahvD3igz6ecQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-login@3.972.65': - resolution: {integrity: sha512-xr9rgjYEdmC2Tpg2lwt9o+nOEaK9Qpd+dBjzrVCuWWyQfvhO91Ezu0Hh9ts2VUxOZxmS/k5T9msa34e4R1bnrQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-login@3.972.66': - resolution: {integrity: sha512-g2fsqm87r/nKthLZ0VkkDBElkGg0PvSa8d97HQ6EilMbJTZ6hxa8FxkSZyJfgPfFdZn0TTmkOffQmTSUcAHIng==} - engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.78': resolution: {integrity: sha512-eUtswnXu0+Ii9ieRK+0L7aPFV3Z/dnW2VntJzjBP9xs8s+8p5nBNuymIXtXwZ+5r5+XJP3e32nMkuZ/r0HozEA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.68': - resolution: {integrity: sha512-4akjzW9CjorByYfqXBXmYUh/h7Io3U4DtVgGGh9TQraZ7ZlyJqNyHwDRGiUFnHD+BTOeTbCesCa4sJaK7BGZ7A==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-node@3.972.69': - resolution: {integrity: sha512-wbJGGesd0Tl18bmUcbj1xJ+e7CpuRJ6PIpMywLFuUttGy615lua87cJ0EA8pFpY/QgPuUXbnupWBtSPJ9tyZhg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-node@3.972.70': - resolution: {integrity: sha512-3xzvkGdykBunxqh8WudmUpSyLWvIhfI6aBQo1b5rb3mDO5mNLadK+0hiI0qBQBMVynJbfLO+Ajy9dztMwy9O8w==} - engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.83': resolution: {integrity: sha512-jdso7ejzfRnatxMUZK4S/U6KbaDPCvfIV4XL+IQAPFDBt5rj5Fq595euqlK8Le4lNCMFR9oUpt+1l0aMgaayOQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.58': - resolution: {integrity: sha512-1nYitRCaDmXWUrpBJt6WlcGjLx1JVsMY8rlYuHHsTYTSaYikbixYdQSyINN2VYq1F798uTO9qHAzytL25M8g3A==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-process@3.972.59': - resolution: {integrity: sha512-DlZF2/MhLlatDdlrIy3CUCpfdbLrKx+3SMjVo+WyHnPpwzkc/M3vwAHw4OVJf7DMvO+4vfRqSCMc/E9I1auN0g==} - engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.71': resolution: {integrity: sha512-lYmXJa4gvq4xN1lrT5NiP5vIYYKcGWAdj8y+8o6dlcateB5eF3Dn8DtmjjHKfMBrTPAMr2pebIiX/UOj8c1/UA==} engines: {node: '>=20.0.0'} @@ -478,113 +419,65 @@ packages: resolution: {integrity: sha512-6Jhcf4v0pSFdjk1EW2kvzuEBKD+UZ2uNcHUIglKKLndD20YhvkL2kdmDOV5/j4mYuWWwe/a1FQ1aomU86/Cg5Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.973.2': - resolution: {integrity: sha512-pjMLaLU/JZi5lVfmR14V1OZqRBTuMHf6AwGNZA0K9hK+JKtO3jcLBarfD8iq5oc8cSowvc/9R32sqMVXZPo6xQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-sso@3.973.3': - resolution: {integrity: sha512-hmdDHoy2G5Es2e8IgelNMYUuSQI6uCIAKZMJ2u2PdKDhxvbk1uWD/g4+R7R5c/tJfKEB1+KjjWiaoCr/S+ZTiQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-web-identity@3.972.64': - resolution: {integrity: sha512-7Buc7p0OvDHW7iBsu4b+YdS0WnaFBDGKDfbVQqaac9dkWiSiUtIoarBDsA1RmOVXZijaZJDoHJFIQiicQvWRlQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-web-identity@3.972.65': - resolution: {integrity: sha512-gHQb/Kt0chjk/JQDa/GJDqmAvEuVn8n7z10wK2h0LFM9TUDRkohgOO4aEF+s2sBLM0br7Cl5W6P7phgjrrJvLQ==} - engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.77': resolution: {integrity: sha512-uylIQSUWpfLuH2LovxEEfwzJGM/SabLOfLMg6YXu/E8jJEKUdpdILCVCQCdFvHyu/7dLJOHPMfrSwduxO56NkQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/dynamodb-codec@3.973.32': - resolution: {integrity: sha512-mc2IvGFtgNgYnySd1wWdx78flpHdAYvbl9C/tnAzGT0D0przwGeHSB6W3L8grldIXjAG1elWJdyDYiiZaz1dCw==} + '@aws-sdk/dynamodb-codec@3.973.45': + resolution: {integrity: sha512-WMnbfe3igJy14RRzEnLDW9G2V0WbrXdnp2UYAGYJIgbB1wR33bBle0dmbVnejs6sHJWfP2N1cAAx/QxXnoyK8w==} engines: {node: '>=20.0.0'} - '@aws-sdk/endpoint-cache@3.972.9': - resolution: {integrity: sha512-LFvdgq8SriaskUcjpBMDE7J2c9RmuT5v3gU36/znV71EU5DKUis4FmGFjCMelKCCViFeVrQADBAlIiOYRhEx6Q==} + '@aws-sdk/endpoint-cache@3.972.11': + resolution: {integrity: sha512-8q1ICxcDjHId3bBryuu/j+1L9y5/3uQnwzLDt5j2ElcjZSoWmFtymdJy7OjLrluSMe0Z4mq5bcH4fxBXvlEHfw==} engines: {node: '>=20.0.0'} - '@aws-sdk/eventstream-handler-node@3.972.27': - resolution: {integrity: sha512-F4vQtU+gCT6LmESV1sinN47WslDc/vEL1vWvKHeUA+OmuvWgY54Eljauu+15HaTX/g5MDHAdsHxRfZqlZP4LyQ==} + '@aws-sdk/eventstream-handler-node@3.972.34': + resolution: {integrity: sha512-cTeVzpu1xEAkryTZBYhGwnQ6gOGyp8ZYZvmn0Sg/nI/ABmy/CRHHxPDJDUi9PxwxUtGGaatvfRUB3FCgT/rSWw==} engines: {node: '>=20.0.0'} - '@aws-sdk/lib-dynamodb@3.1087.0': - resolution: {integrity: sha512-Xtx+KuCPvpluVj0WMpSRN4skxrjzlKvo6T+LwAZ6VOzbojlINSXWKuemsev5GVgbGqIZSsv3+/beI8Q3jGoymQ==} + '@aws-sdk/lib-dynamodb@3.1136.0': + resolution: {integrity: sha512-6F2BFM/u6GqfeVxp8YdmyfBIBQX76Dc+UTlxtf+Kbfsl+80UezRLkx1evF0GOUUqAeokaFbk8zjgU/lAQai3hg==} engines: {node: '>=20.0.0'} peerDependencies: - '@aws-sdk/client-dynamodb': ^3.1087.0 + '@aws-sdk/client-dynamodb': ^3.1136.0 - '@aws-sdk/middleware-endpoint-discovery@3.972.24': - resolution: {integrity: sha512-1NwwiqMZw5LMnFZ8LsPYkuVN+nFf5oWRxgeb4WfsyOw0MKcA8qGI8Yq4AjvEzWHzp1a1aq8TEMqqlh2IiKVKgQ==} + '@aws-sdk/middleware-endpoint-discovery@3.972.30': + resolution: {integrity: sha512-0hmD7/NG2NoVOVHvUb6rtY5POQYr+/9gdHvrYhIBA1zmCqKOBd5Gz3dL+iZ15FHOJbs/5kLplGoePc8PHTlzYA==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-eventstream@3.972.23': - resolution: {integrity: sha512-H4phGWCJ/K/VtOs68DTyl77zhNhf4rJ6Tf5IDsHts1cCcrB/FGO2f/8Tf2wBYNvzaaTDCFa4jtj/S0eWUd4DMg==} + '@aws-sdk/middleware-eventstream@3.972.29': + resolution: {integrity: sha512-dlRzHCgyB8W6hLuDC5pcT5q+ziPt00n4QGgGBE17ucLVU4zMa6lsbuUdQ2Pm75Z5VA8GF+R/+SgrRcaTdIzSIQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-websocket@3.972.40': - resolution: {integrity: sha512-xBUCdsjAq0mq7K6mYpwm7Ax12Bdu08kjmE5S7vOboHgUxRpcxxap5PqkR2MMpaeMYi1taV/dBL/z2DVs6ecJoQ==} + '@aws-sdk/middleware-websocket@3.972.53': + resolution: {integrity: sha512-bIrDaMENQmYRBHntOiOheqkiw5+fhKW4Lqb+mS1uqF0VwvdWI22fW2HFgWrng66CmYd+4k8ePlpj38sEfTuMLQ==} engines: {node: '>= 14.0.0'} - '@aws-sdk/nested-clients@3.997.32': - resolution: {integrity: sha512-6Yj2fr9XF67cndITea48rchTdVr3VGx6PN47bIKNinJAjLkmaIlz/4EBPCgJ8UmhVopiXmeAuPLI3+DXDDbMhQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/nested-clients@3.997.33': - resolution: {integrity: sha512-dVZOroI/r3/ENvqNGgjMPul+jjlz9GddfVusgTXlVjfZj5isibOxecLkGQbRPp8XOuX+RAfjXLFgPkD1JS5xrw==} - engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.997.45': resolution: {integrity: sha512-mooq9Q+jLa18VoM7HouczmslZU60iiB0aKc/Ztnq/luIL1ud0z4DnYprLR/ZO1gp331S9tJctM1HZr7u6YKBXQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.996.41': - resolution: {integrity: sha512-QMUytg+FQMGouc8gHS00KoYih3+N6cqmVI/pQGOIo7Nr7OpQaiXjSYOuL+vsPZ1tymY4LAQ8MYcHJmws5LRxng==} - engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.996.46': resolution: {integrity: sha512-L+2xZTye/2T96f3lwCws0Zw6GG2JHZW9e8FpVgGBeeExSKyeoZ6CWRpBml/7DNiK/O26jrgPM9F+Ay8VkgzUWQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.1087.0': - resolution: {integrity: sha512-umM+qNq16f2fH+VLM5MqXW4ORNQAjk+TOSto73xbUHcKaU41L48j786r3UWQYlejeJk37NlvRYgxBT+MBkfaYQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/token-providers@3.1088.0': - resolution: {integrity: sha512-4ObatWt2qpJg5FBk4LOOKrTQYzaqeewAtdO3r9ZO8lH9YqLtpTzLyIdy0mJ+nVdfYOnqISkKNfmzP22bNDhwyw==} - engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.1129.0': resolution: {integrity: sha512-Sbl3rpzQdsG4ZK2zh0JWUYyZPKKorJlVOddA2T0DVbKJFrsW8J6wgnslxxUH04+WaBMr4A1HzJZvZX0xUvkniA==} engines: {node: '>=20.0.0'} - '@aws-sdk/types@3.974.1': - resolution: {integrity: sha512-W0IQZR0eaBqlBFIIofMapaWkw1W0U+Xi4dvW+BqwmCEMd8Ng2U6IhkxuPSjMVnR8klLjfuS9PeZWUl1N6UaZdg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/types@3.974.2': - resolution: {integrity: sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA==} + '@aws-sdk/token-providers@3.1136.0': + resolution: {integrity: sha512-CHjdpFszuNTUEQ2z1F85pOiHxpLe0fDyvTUoNAZ7YczdTMEfU6TSA7FVZelAM67L/g6xcS31U64HuBl42dSKCA==} engines: {node: '>=20.0.0'} '@aws-sdk/types@3.974.5': resolution: {integrity: sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-dynamodb@3.996.6': - resolution: {integrity: sha512-xLimZjA/ebA7jZn4NNkvLgj9WRl14rhidGND6oPt14s7ywe3I64g9X+WJpBraU5UR7loRq2K1tAXZj0FXkWLZg==} + '@aws-sdk/util-dynamodb@3.996.9': + resolution: {integrity: sha512-16x2tRvl7OYpZ0W/DdFJieFriD13+RvuRBDbe5sj/tCEfK86HSGd7I2s5j0ivz8p6KWGkS+5wKRO9OliJkjUOQ==} engines: {node: '>=20.0.0'} peerDependencies: - '@aws-sdk/client-dynamodb': ^3.1082.0 - - '@aws-sdk/xml-builder@3.972.35': - resolution: {integrity: sha512-pXzaWe3evZhjxDXAlMnqISe/XefTCGwBJG4nFTXaWSgAnMkqPEhxEPqJNhhpGesEvKFhvNpnozJJ4GTL11bRYw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/xml-builder@3.972.36': - resolution: {integrity: sha512-RdGmS1GLrtaTOLE1ElSluMldNrpk9Emq6uYs8SS8iHlu5xTAmM9rRkM91o48+rIRryBtyO9t+uLYCoMG6jVMVA==} - engines: {node: '>=20.0.0'} + '@aws-sdk/client-dynamodb': ^3.1111.0 '@aws-sdk/xml-builder@3.972.40': resolution: {integrity: sha512-wlFmCIGUlwF4zx/kncw+bmxTQh1HeSJq4mYV/V5cZUSJadDP3kXvGW8Rn21cimj/7y9ju+47oYWXi97vF7czaA==} @@ -594,108 +487,29 @@ packages: resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==} engines: {node: '>=18.0.0'} - '@babel/code-frame@7.29.7': - resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.29.7': - resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.29.7': - resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.29.7': - resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.29.7': - resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} - engines: {node: '>=6.9.0'} - - '@babel/helper-globals@7.29.7': - resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.29.7': - resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.29.7': - resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.29.7': - resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.29.7': - resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.29.7': - resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-option@7.29.7': - resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.29.7': - resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.29.7': - resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/plugin-transform-react-jsx-self@7.29.7': - resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-source@7.29.7': - resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/runtime@7.29.7': resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} engines: {node: '>=6.9.0'} - '@babel/template@7.29.7': - resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.29.7': - resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.29.7': - resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} - engines: {node: '>=6.9.0'} - - '@base-ui-components/react@1.0.0-rc.0': - resolution: {integrity: sha512-9lhUFbJcbXvc9KulLev1WTFxS/alJRBWDH/ibKSQaNvmDwMFS2gKp1sTeeldYSfKuS/KC1w2MZutc0wHu2hRHQ==} + '@base-ui/react@1.8.0': + resolution: {integrity: sha512-P0/1sxo6SBVZOklKMIedvTWqw2s2IQzi9x5bIVsXu980cuSOD4NeuRSs+/L7LZQfDkZP/uRZyGPyfFl/B1oH+Q==} engines: {node: '>=14.0.0'} - deprecated: Package was renamed to @base-ui/react peerDependencies: + '@date-fns/tz': ^1.2.0 '@types/react': ^17 || ^18 || ^19 + date-fns: ^4.0.0 react: ^17 || ^18 || ^19 react-dom: ^17 || ^18 || ^19 peerDependenciesMeta: + '@date-fns/tz': + optional: true '@types/react': optional: true + date-fns: + optional: true - '@base-ui-components/utils@0.2.2': - resolution: {integrity: sha512-rNJCD6TFy3OSRDKVHJDzLpxO3esTV1/drRtWNUpe7rCpPN9HZVHUCuP+6rdDYDGWfXnQHbqi05xOyRP2iZAlkw==} - deprecated: Package was renamed to @base-ui/utils + '@base-ui/utils@0.4.0': + resolution: {integrity: sha512-bO9fz25kKtPf+aZVyfQrC0PDmJdmVni31W2hCS5/Owb+inwdIL3XU26pCPRPlt4LSxZrBgLwubXQXQlKaFEZzw==} peerDependencies: '@types/react': ^17 || ^18 || ^19 react: ^17 || ^18 || ^19 @@ -707,654 +521,232 @@ packages: '@borewit/text-codec@0.2.2': resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} - '@bubltec/mycota-auth@0.6.0': - resolution: {integrity: sha512-9DO8BHVEkhxFB6Zft9TFI3VItq8TwTrjzn6JB163oru/iwA7QzUeDL2gUKsslFo5JZlHR4FPWxKQPn59Xlbx2A==} - - '@bubltec/mycota-cdk@0.6.0': - resolution: {integrity: sha512-yMjAVOnYWoieDBNY9qp0PT1eTk1JUlOo5soVXbedowOAYMheqRMfuTGTfmL4P9JpJRAUxW00G8RbUcuaQvXxkg==} + '@bubltec/mycota-auth@1.0.0': + resolution: {integrity: sha512-ehIFcR9iBFVCW8yHr3YpUShfnH16JoBz812yq1cJHaYu7/8fSS6nkG7jheYer0rySFBEXUwD6otsljOatnts0A==} + peerDependencies: + '@nestjs/common': ^12.0.0 + '@nestjs/core': ^12.0.0 + '@nestjs/jwt': ^12.0.0 + '@nestjs/passport': ^12.0.0 + class-transformer: ^0.5.1 + class-validator: ^0.15.0 + passport: ^0.7.0 + reflect-metadata: ^0.2.2 + rxjs: ^7.8.0 + + '@bubltec/mycota-cdk@1.0.0': + resolution: {integrity: sha512-AF+4XFtyhXrfRYLTV3o5EME8a5YwEcWKY1j7i+/IY+eF89ivm37g05h47c9nzVDq12Fiya9uQOl+SLikuEKhkg==} peerDependencies: aws-cdk-lib: ^2.261.0 constructs: ^10.4.0 - '@bubltec/mycota-config@0.6.0': - resolution: {integrity: sha512-UrYK6Oz5Frn98yb2rV/VL6jhHjfH9RMxB4mYV9EE1ig5BWk9WK9M8u63tgxiDA4xIouT80TbQ1QFr9Vp5QEW8w==} + '@bubltec/mycota-config@1.0.0': + resolution: {integrity: sha512-HTscxO7N+iFecSzvmMY2DtWM4CVXXTZmdlslFqHl3nw6XQD8BH77dlmiFCdZEs6CavlqQThRra2H/ROc/gUVGg==} hasBin: true - '@bubltec/mycota-dynamo@0.6.0': - resolution: {integrity: sha512-qkP9vv+wiUXEiKqO+EnuQ4RMhE7XlhUshYcK833FK3Clz1UbahyRmByfTWnoeLjfkkep0Kl/6bj9iSGTtYYHWA==} - - '@bubltec/mycota-mail@0.6.0': - resolution: {integrity: sha512-8srkw5+3cFfaPAsv0Vh8QIx2aSo3ENUzO0P9ixZdpkS4o/t0Raq1M+bNjdoimQkiS179Me9VGL9aJPnKqL/y+A==} - - '@bubltec/mycota-professional-verification@0.6.0': - resolution: {integrity: sha512-RFRid9/dGe5/tLdtHt3dLtWl4ctjsjIadJKixYJwS/4BocGygg+6h/Da1/iTECEISEV4L5YsqAuRyoEC7nsR0Q==} + '@bubltec/mycota-dynamo@1.0.0': + resolution: {integrity: sha512-KyqvmWUxii9lAFyeZnbjJUCC2dSYh2UKHLOX6whbafhZuHAEC9LybTTGFBJXhHobKHz4eCpizx4aqnFPTT/tSg==} + peerDependencies: + '@nestjs/common': ^12.0.0 - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] + '@bubltec/mycota-mail@1.0.0': + resolution: {integrity: sha512-Hm91O1ZaXkdpYjohgyV5xYawHEYDQYvQUlKSxJuzWAYsngh7yfWITNRZ9DdRNWlyMGTowYud0QigIUhDWaskIA==} - '@esbuild/aix-ppc64@0.24.2': - resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] + '@bubltec/mycota-professional-verification@1.0.0': + resolution: {integrity: sha512-0eYXoTg70gNhVP+Jm1wk7dOWsr1Odzy1qvrm4LDA79pj/ev0siXk3SIj8o2/I+AOaci/82MYAp5yZrC1RHgPGA==} + peerDependencies: + '@nestjs/common': ^12.0.0 + class-transformer: ^0.5.1 + class-validator: ^0.15.0 - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + '@esbuild/aix-ppc64@0.28.2': + resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.28.1': - resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + '@esbuild/android-arm64@0.28.2': + resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==} engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.24.2': - resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} + '@esbuild/android-arm@0.28.2': + resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==} engines: {node: '>=18'} - cpu: [arm64] + cpu: [arm] os: [android] - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + '@esbuild/android-x64@0.28.2': + resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==} engines: {node: '>=18'} - cpu: [arm64] + cpu: [x64] os: [android] - '@esbuild/android-arm64@0.28.1': - resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + '@esbuild/darwin-arm64@0.28.2': + resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==} engines: {node: '>=18'} cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] + os: [darwin] - '@esbuild/android-arm@0.24.2': - resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} + '@esbuild/darwin-x64@0.28.2': + resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==} engines: {node: '>=18'} - cpu: [arm] - os: [android] + cpu: [x64] + os: [darwin] - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + '@esbuild/freebsd-arm64@0.28.2': + resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==} engines: {node: '>=18'} - cpu: [arm] - os: [android] + cpu: [arm64] + os: [freebsd] - '@esbuild/android-arm@0.28.1': - resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + '@esbuild/freebsd-x64@0.28.2': + resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==} engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} cpu: [x64] - os: [android] + os: [freebsd] - '@esbuild/android-x64@0.24.2': - resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} + '@esbuild/linux-arm64@0.28.2': + resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==} engines: {node: '>=18'} - cpu: [x64] - os: [android] + cpu: [arm64] + os: [linux] - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + '@esbuild/linux-arm@0.28.2': + resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==} engines: {node: '>=18'} - cpu: [x64] - os: [android] + cpu: [arm] + os: [linux] - '@esbuild/android-x64@0.28.1': - resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + '@esbuild/linux-ia32@0.28.2': + resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==} engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] + cpu: [ia32] + os: [linux] - '@esbuild/darwin-arm64@0.24.2': - resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} + '@esbuild/linux-loong64@0.28.2': + resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==} engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] + cpu: [loong64] + os: [linux] - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + '@esbuild/linux-mips64el@0.28.2': + resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==} engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] + cpu: [mips64el] + os: [linux] - '@esbuild/darwin-arm64@0.28.1': - resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + '@esbuild/linux-ppc64@0.28.2': + resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==} engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] + cpu: [ppc64] + os: [linux] - '@esbuild/darwin-x64@0.24.2': - resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} + '@esbuild/linux-riscv64@0.28.2': + resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==} engines: {node: '>=18'} - cpu: [x64] - os: [darwin] + cpu: [riscv64] + os: [linux] - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + '@esbuild/linux-s390x@0.28.2': + resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==} engines: {node: '>=18'} - cpu: [x64] - os: [darwin] + cpu: [s390x] + os: [linux] - '@esbuild/darwin-x64@0.28.1': - resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + '@esbuild/linux-x64@0.28.2': + resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==} engines: {node: '>=18'} cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] + os: [linux] - '@esbuild/freebsd-arm64@0.24.2': - resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} + '@esbuild/netbsd-arm64@0.28.2': + resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==} engines: {node: '>=18'} cpu: [arm64] - os: [freebsd] + os: [netbsd] - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + '@esbuild/netbsd-x64@0.28.2': + resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==} engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] + cpu: [x64] + os: [netbsd] - '@esbuild/freebsd-arm64@0.28.1': - resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + '@esbuild/openbsd-arm64@0.28.2': + resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==} engines: {node: '>=18'} cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] + os: [openbsd] - '@esbuild/freebsd-x64@0.24.2': - resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} + '@esbuild/openbsd-x64@0.28.2': + resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==} engines: {node: '>=18'} cpu: [x64] - os: [freebsd] + os: [openbsd] - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + '@esbuild/openharmony-arm64@0.28.2': + resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==} engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] + cpu: [arm64] + os: [openharmony] - '@esbuild/freebsd-x64@0.28.1': - resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + '@esbuild/sunos-x64@0.28.2': + resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==} engines: {node: '>=18'} cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] + os: [sunos] - '@esbuild/linux-arm64@0.24.2': - resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} + '@esbuild/win32-arm64@0.28.2': + resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==} engines: {node: '>=18'} cpu: [arm64] - os: [linux] + os: [win32] - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + '@esbuild/win32-ia32@0.28.2': + resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==} engines: {node: '>=18'} - cpu: [arm64] - os: [linux] + cpu: [ia32] + os: [win32] - '@esbuild/linux-arm64@0.28.1': - resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + '@esbuild/win32-x64@0.28.2': + resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==} engines: {node: '>=18'} - cpu: [arm64] - os: [linux] + cpu: [x64] + os: [win32] - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] + '@fastify/ajv-compiler@4.0.6': + resolution: {integrity: sha512-NtuzM0SfaMJbGlnjr9LWQUN5LzgSrbB8tf/wRZNas+4E1O/Nmzl53e7ruT61HDZyRCJGC6FxIogmNZO1c5ETBA==} - '@esbuild/linux-arm@0.24.2': - resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] + '@fastify/aws-lambda@6.4.1': + resolution: {integrity: sha512-eTCkZJ8b4NAyafxChyM1VSVMUK1KnlyXj7NBfrQm8dRcXj42X8je5poyaZDZ9T5XTyykl3oLMiI4IvZJWXzLsw==} - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] + '@fastify/cookie@11.1.2': + resolution: {integrity: sha512-Dtrpk/YOGUsbRMvP/8ZqPpwnMRv0qSqodFdoQ2B589Obc7jw4s4Qla+cV72Bsm7WsZJnqlYFX/i7uSBq0xzg6g==} - '@esbuild/linux-arm@0.28.1': - resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] + '@fastify/cors@11.3.0': + resolution: {integrity: sha512-ggQGua+xHv1MvePbPr0v//xLYEsCXbWspquXCJS9Ot5YoRXq8J8ZWzHnxDBVnbtXosvistXo6LtNzOJswf64Fw==} - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] + '@fastify/error@4.2.0': + resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==} - '@esbuild/linux-ia32@0.24.2': - resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] + '@fastify/fast-json-stringify-compiler@5.1.0': + resolution: {integrity: sha512-PxcYtKLbQ8Z+yApiqjK8FwxIwvEj38k2OiLc17u8dkJSlmfi2wHHPaSnaoqBPQqtvF8YVsDgDpP2snDCfFrpfw==} - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-ia32@0.28.1': - resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-loong64@0.24.2': - resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-loong64@0.28.1': - resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.24.2': - resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.28.1': - resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-ppc64@0.24.2': - resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-ppc64@0.28.1': - resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-riscv64@0.24.2': - resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-riscv64@0.28.1': - resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.24.2': - resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.28.1': - resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/linux-x64@0.24.2': - resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/linux-x64@0.28.1': - resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.24.2': - resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-arm64@0.28.1': - resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.24.2': - resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.28.1': - resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.24.2': - resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-arm64@0.28.1': - resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.24.2': - resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.28.1': - resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/openharmony-arm64@0.28.1': - resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/sunos-x64@0.24.2': - resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/sunos-x64@0.28.1': - resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-arm64@0.24.2': - resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-arm64@0.28.1': - resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-ia32@0.24.2': - resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-ia32@0.28.1': - resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.24.2': - resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.28.1': - resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@fastify/ajv-compiler@3.6.0': - resolution: {integrity: sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==} - - '@fastify/aws-lambda@4.1.0': - resolution: {integrity: sha512-293HSdtr4muZZi4UxjrDgddxlLRDbNxT5x/eOX78obMA1Du3tfpuP7WuyfnA4GXaeckj/soJ2jiuD2sM4VIW9Q==} + '@fastify/formbody@9.0.0': + resolution: {integrity: sha512-T/af26CSrUARBCvsEmv+DJLPfZlrRKESzqironxP1j7qzuLyKcoZtj6MuTGShuKx1THXugoie2oFbUJxXfGFzA==} - '@fastify/cookie@9.4.0': - resolution: {integrity: sha512-Th+pt3kEkh4MQD/Q2q1bMuJIB5NX/D5SwSpOKu3G/tjoGbwfpurIMJsWSPS0SJJ4eyjtmQ8OipDQspf8RbUOlg==} + '@fastify/forwarded@3.0.2': + resolution: {integrity: sha512-NE8HgKLgYejV9lDpqkEFaDKMLYelJBVfHekhB0UKvX0ghagXRJqg68feg8er1NPXxG4N9i6vPxzt8E+3wHfcmA==} - '@fastify/cors@9.0.1': - resolution: {integrity: sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==} + '@fastify/merge-json-schemas@0.2.1': + resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} - '@fastify/error@3.4.1': - resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} + '@fastify/middie@9.3.4': + resolution: {integrity: sha512-dd8phTnVWzx3iKPBKSvtRUT8+Igvy/MP+P5HcY2tjejEyeVbyjkD4HgzKessUObue5RRM5J6PZdxtAqgbn84yw==} - '@fastify/fast-json-stringify-compiler@4.3.0': - resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==} - - '@fastify/formbody@7.4.0': - resolution: {integrity: sha512-H3C6h1GN56/SMrZS8N2vCT2cZr7mIHzBHzOBa5OPpjfB/D6FzP9mMpE02ZzrFX0ANeh0BAJdoXKOF2e7IbV+Og==} - - '@fastify/merge-json-schemas@0.1.1': - resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} - - '@fastify/middie@8.3.3': - resolution: {integrity: sha512-+WHavMQr9CNTZoy2cjoDxoWp76kZ3JKjAtZj5sXNlxX5XBzHig0TeCPfPc+1+NQmliXtndT3PFwAjrQHE/6wnQ==} + '@fastify/proxy-addr@5.1.1': + resolution: {integrity: sha512-zv07Y9GEuDsJPegZoDFd4SDWaZOW8N2pa0GSrYmKpId/tjt1Hgo3BjZBVjdVpfVrHaA+Qv5jawtS2O50J5xM9g==} '@floating-ui/core@1.8.0': resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==} @@ -1381,8 +773,8 @@ packages: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} @@ -1391,14 +783,14 @@ packages: resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} engines: {node: '>=8'} - '@microsoft/tsdoc@0.15.1': - resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} + '@microsoft/tsdoc@0.16.0': + resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} - '@nestjs/common@10.4.22': - resolution: {integrity: sha512-fxJ4v85nDHaqT1PmfNCQ37b/jcv2OojtXTaK1P2uAXhzLf9qq6WNUOFvxBrV4fhQek1EQoT1o9oj5xAZmv3NRw==} + '@nestjs/common@12.0.3': + resolution: {integrity: sha512-Fosz6lHc9OagZNcF0LTrVHyJS8W7mtuNFBOo9RRccGwyeICBd0hiutjAi9zxnzBcP45RkYXeNB+idA/52jZhBQ==} peerDependencies: - class-transformer: '*' - class-validator: '*' + class-transformer: '>=0.4.1' + class-validator: '>=0.13.2' reflect-metadata: ^0.1.12 || ^0.2.0 rxjs: ^7.1.0 peerDependenciesMeta: @@ -1407,19 +799,20 @@ packages: class-validator: optional: true - '@nestjs/config@3.3.0': - resolution: {integrity: sha512-pdGTp8m9d0ZCrjTpjkUbZx6gyf2IKf+7zlkrPNMsJzYZ4bFRRTpXrnj+556/5uiI6AfL5mMrJc2u7dB6bvM+VA==} + '@nestjs/config@12.0.0': + resolution: {integrity: sha512-pG5+fFfCo3cdgVkLJLvvhUGfxEjwzv9hIAQ1aJVHvHlHVniDWfwX5pR/utgoAkJzSikv2oTR1BmIF03FXdi42Q==} peerDependencies: - '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + '@nestjs/common': ^11.0.0 || ^12.0.0 rxjs: ^7.1.0 - '@nestjs/core@10.4.22': - resolution: {integrity: sha512-6IX9+VwjiKtCjx+mXVPncpkQ5ZjKfmssOZPFexmT+6T9H9wZ3svpYACAo7+9e7Nr9DZSoRZw3pffkJP7Z0UjaA==} + '@nestjs/core@12.0.3': + resolution: {integrity: sha512-Ouv++gAXOL50S8K8n6AN19QGmw51rnIo6v7y9AqUYoaf0NcZlufTu5XTDeC2RtpMz8oXRr9nykBngRjflcoQKA==} + engines: {node: '>= 20'} peerDependencies: - '@nestjs/common': ^10.0.0 - '@nestjs/microservices': ^10.0.0 - '@nestjs/platform-express': ^10.0.0 - '@nestjs/websockets': ^10.0.0 + '@nestjs/common': ^12.0.0 + '@nestjs/microservices': ^12.0.0 + '@nestjs/platform-express': ^12.0.0 + '@nestjs/websockets': ^12.0.0 reflect-metadata: ^0.1.12 || ^0.2.0 rxjs: ^7.1.0 peerDependenciesMeta: @@ -1430,17 +823,18 @@ packages: '@nestjs/websockets': optional: true - '@nestjs/jwt@10.2.0': - resolution: {integrity: sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==} + '@nestjs/jwt@12.0.2': + resolution: {integrity: sha512-1crs22hB7pNf7FnfRRRXvFTo595Rgx+JLyIuWInsyd5Ov/z0N8CCJPqMlTy41D5XTWe8CVr9miwB+2OXxVX9RA==} peerDependencies: - '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 - '@nestjs/mapped-types@2.0.6': - resolution: {integrity: sha512-84ze+CPfp1OWdpRi1/lOu59hOhTz38eVzJvRKrg9ykRFwDz+XleKfMsG0gUqNZYFa6v53XYzeD+xItt8uDW7NQ==} + '@nestjs/mapped-types@12.0.0': + resolution: {integrity: sha512-aX7lxZcqXldtnSr0bgT2ZPQvpTpIwBMW1GMX29o4s3q02vmq6JoTYuPW0GwYXa8BiFMRX7WbGZVDA703pNqOMQ==} + engines: {node: '>=20.19.0'} peerDependencies: - '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + '@nestjs/common': ^10.0.0 || ^11.0.0 || ^12.0.0 class-transformer: ^0.4.0 || ^0.5.0 - class-validator: ^0.13.0 || ^0.14.0 + class-validator: ^0.13.0 || ^0.14.0 || ^0.15.0 reflect-metadata: ^0.1.12 || ^0.2.0 peerDependenciesMeta: class-transformer: @@ -1448,31 +842,32 @@ packages: class-validator: optional: true - '@nestjs/passport@10.0.3': - resolution: {integrity: sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==} + '@nestjs/passport@12.0.0': + resolution: {integrity: sha512-FM9ioo2Dyj+cC7aeO4g19ijAXoRaHlW/GQZFbgXsM4Z9pyQedA8yOseb7ivfqlPwUKJlH9PFgeWniu6c0vb6dw==} peerDependencies: - '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 - passport: ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0 + '@nestjs/common': ^11.0.0 || ^12.0.0 + passport: ^0.5.0 || ^0.6.0 || ^0.7.0 - '@nestjs/platform-fastify@10.4.22': - resolution: {integrity: sha512-Y/8wX43806NIAAIx7nWY3A7kSiZc5ivPfIl4RIgo4goxuwVOjAwgytBtPhgtyP/O1nrighbMXtgHh2e/kWnHGA==} + '@nestjs/platform-fastify@12.0.3': + resolution: {integrity: sha512-Cn8jR8jwPJBk7ftkzunplz0LHDahnq7urAO9VjOV0OWkk1YCwaFMm4CElSk3BwBiDwP177anJjJUbVxTlASk4A==} peerDependencies: - '@fastify/static': ^6.0.0 || ^7.0.0 - '@fastify/view': ^7.0.0 || ^8.0.0 - '@nestjs/common': ^10.0.0 - '@nestjs/core': ^10.0.0 + '@fastify/static': ^10.1.2 + '@fastify/view': ^10.0.0 || ^11.0.0 || ^12.0.0 + '@nestjs/common': ^12.0.0 + '@nestjs/core': ^12.0.0 peerDependenciesMeta: '@fastify/static': optional: true '@fastify/view': optional: true - '@nestjs/swagger@8.1.1': - resolution: {integrity: sha512-5Mda7H1DKnhKtlsb0C7PYshcvILv8UFyUotHzxmWh0G65Z21R3LZH/J8wmpnlzL4bmXIfr42YwbEwRxgzpJ5sQ==} + '@nestjs/swagger@12.0.1': + resolution: {integrity: sha512-fQ0WyutSSHedO9HzSkOFKFaRygYNGBno5EggcZljs+KL8tHzPPTO5oyJpaf3BoOKFGGsN/0B13EbIpH2pkPx8g==} + engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - '@fastify/static': ^6.0.0 || ^7.0.0 - '@nestjs/common': ^9.0.0 || ^10.0.0 - '@nestjs/core': ^9.0.0 || ^10.0.0 + '@fastify/static': ^8.0.0 || ^9.0.0 || ^10.0.0 + '@nestjs/common': ^12.0.0 + '@nestjs/core': ^12.0.0 class-transformer: '*' class-validator: '*' reflect-metadata: ^0.1.12 || ^0.2.0 @@ -1484,251 +879,249 @@ packages: class-validator: optional: true - '@nuxtjs/opencollective@0.3.2': - resolution: {integrity: sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==} - engines: {node: '>=8.0.0', npm: '>=5.0.0'} - hasBin: true + '@oxc-project/types@0.150.0': + resolution: {integrity: sha512-rDS5/31E9HfPl/CIzGrn0DOlvBbXFseQ5URJ9sYMfstbKLD/c6Gm9vmRzRGDdAXyOIL4zmO37lc9RIwYqVruZw==} - '@oxfmt/binding-android-arm-eabi@0.59.0': - resolution: {integrity: sha512-bNTnfbuG7sAwb2PakMNaDukx5kXeW9duXOBeWtTOiLz3fXz3q2DlWguufPZ+c2IHEVrRXHD+M4aUgEWm841LDA==} + '@oxfmt/binding-android-arm-eabi@0.68.0': + resolution: {integrity: sha512-dhfYPbzv/h9JgHjNkl2R6sOjUfxDyLGOZVb3g8/ScaTNwwJcYgmHh8kcYFDUhinuy1QAoANCWUvw1jlk+z6gAg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxfmt/binding-android-arm64@0.59.0': - resolution: {integrity: sha512-R/Sn7z52QtdAKNqQLLY0EK7hVMjXiz3XUlvoCFCm/60jgIzAnQtiqLKBCFaBkimCQL5rs2ezPMcicpjCsrl54Q==} + '@oxfmt/binding-android-arm64@0.68.0': + resolution: {integrity: sha512-v3Njdi6qY0O/5eGfg01ww2w6gTn2mUvZ72Bnx1/UN53A9wruh3Nk6otc3WkgJLkXD4Qgz1SOcVQieH1oD03V9Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxfmt/binding-darwin-arm64@0.59.0': - resolution: {integrity: sha512-vm/ynUqE4HjC0ZIEjmXv1UJu1/GngccQ+T+TJudTMxUxm6r+GQTg1TO3E5jJfI71pBaXxSzs1+vWHIwuilGHhw==} + '@oxfmt/binding-darwin-arm64@0.68.0': + resolution: {integrity: sha512-ei4MCMzHFREmZwPJ7KuWUB4kBuHdsgDrnXGJVcEAopU7fj7S42I8BChdFILWdHvhFqR08FLJtOfbZIr2CDw0cA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxfmt/binding-darwin-x64@0.59.0': - resolution: {integrity: sha512-uTtYDpLN/obfKVWGpgEc8BqYlLZBQTPz2uYEvLRy3HPZxjZ34wiFzukUBU2bf64JuCYZI//GTV1EOMmWlPjf/w==} + '@oxfmt/binding-darwin-x64@0.68.0': + resolution: {integrity: sha512-UrKgzZxYhwB9DSvTX+vdgl9M32wLUNKJcAKIoiyx/Kzn/zveqi7W6kYVcRroFMhS3Kwz0KhTk3WBeSuQn4YCTg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxfmt/binding-freebsd-x64@0.59.0': - resolution: {integrity: sha512-e2UnxL/ifStSPy8ffBCDbdy595SYsGy+U1pur4G65TuMmWxAMBzYGG7atZo/3mp515p8rZdsflxVD/E1FAdPLQ==} + '@oxfmt/binding-freebsd-x64@0.68.0': + resolution: {integrity: sha512-6jrEKgpJbilM1QaRv7hEtKXr4p4AK4jvvyOtajwyhu0kOz3e0O7OLnSTk6tBotRqCcUC4ehZRJ1Zx+Y99wieLw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxfmt/binding-linux-arm-gnueabihf@0.59.0': - resolution: {integrity: sha512-LtdeZ1l0urxte3VNi3g8cocZwv1xGM1NKHSgF/fJEEVhyQmlgGh7WFWKFd/pNuO7djfvPNtNO1+MS+FEWkgVSA==} + '@oxfmt/binding-linux-arm-gnueabihf@0.68.0': + resolution: {integrity: sha512-YOIVnKOBaLeGullskS179N12hjSAdFYnzLjOaKiLhAKNWgnShq9w4xRdtmUm6BlnP65l2/EA9Aw/KlftNxDM7Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxfmt/binding-linux-arm-musleabihf@0.59.0': - resolution: {integrity: sha512-dBTciSsj9GTMl7p+h2gMSI0hoPn2ijfc/dUsbnWsP0RbwgPl2r0C/5zkMb3Pb+gGj17LH7f1o4qLo9aes/pAvA==} + '@oxfmt/binding-linux-arm-musleabihf@0.68.0': + resolution: {integrity: sha512-xW5XoEHVNqydPBv2KXvk9lmEzyAlOQHVEazKoXUuAacqekjya+OdiaFjjEBl0oJD02raG8g3TRl9OVCh9PDIHA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxfmt/binding-linux-arm64-gnu@0.59.0': - resolution: {integrity: sha512-tXVdJ/JINsNWdponPHN0OuKHtC+HdpyoS9sd6IDPNiiEYsRki8b7tefRZ1iMnRkdbyT4SEbguWsr6o+5awvbPQ==} + '@oxfmt/binding-linux-arm64-gnu@0.68.0': + resolution: {integrity: sha512-QCvYwVVQieu6oyJglAgV9vH/YMDxZyR4cwVSYtoq9oOXd5N+D3TDUBjNwxFrLn5AdcJZOcvn/7IB17vJGp+2Og==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-arm64-musl@0.59.0': - resolution: {integrity: sha512-RRTq38i2zT5fnw6XGHjvT6w2mh6x/G3m6AZcAZ56OTDTT/lsOeYnG3SVjwmH40z5kPqF+lf+o35e6m6PpKy9Dw==} + '@oxfmt/binding-linux-arm64-musl@0.68.0': + resolution: {integrity: sha512-4TVz5iFQ8ndrHnhX50UXiz9BIWAtUSOHJ6Nus4qWFfJBXq/Ed/krXbF/ehJu42BXM5tIvBs99jNIM22s9agY5A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxfmt/binding-linux-ppc64-gnu@0.59.0': - resolution: {integrity: sha512-lD3k7glAJSaXW0D6xzu8VOZbYbosvy+0ktOVkfLEoQF5HJlMSxTQ2KNW0JO+08ccP/1ElOKktVEMI0fqRbVB4w==} + '@oxfmt/binding-linux-ppc64-gnu@0.68.0': + resolution: {integrity: sha512-qLe3ao0RP84bnPxBvRI+GnlK/jybo538NWu0Xrm+zYeTmJtpzqLhnnd5BH21NafqKnplbGZjtN1cnrOlWF73lw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-riscv64-gnu@0.59.0': - resolution: {integrity: sha512-WH5ZP1RbuHKBO/yfPRQKpNO/ijHcEDNbnmC4VPf/Bcd3+mbMAZpRiJWRa1PL5bREdIZZHo343mk3sqlc9x7Usw==} + '@oxfmt/binding-linux-riscv64-gnu@0.68.0': + resolution: {integrity: sha512-Yvyl7a6gbb0vM6r925KW2dO+/CmXySO5TVbcX7o/uZJ+d108HFOG0TxIyHApmn5USuj5mhDPxzhiVwOlGP7uSA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-riscv64-musl@0.59.0': - resolution: {integrity: sha512-743wOiaI9RZY4QVGkWkfGRavD5ZJUJ6gscFjVrVu1dP8AZh9jM+a6v3NhlR+OIzHdS6DhLM96w+gcVskskz7rw==} + '@oxfmt/binding-linux-riscv64-musl@0.68.0': + resolution: {integrity: sha512-mJlFuFVCxzrYM5sFStN433D/s/mb6Wq4aCQAM02vs/OudHywnaSAd2rb1vlYUJtqdYIciJtiasuxvfbYkv5fLg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxfmt/binding-linux-s390x-gnu@0.59.0': - resolution: {integrity: sha512-xjRXQsRnrRZCcCkIEnbd2lmsQNobtwwkJxdy2bWXhZ1lIN0ouZwsBXRsoovW3yATuziAYwr9HMiQuR/Cc75NIw==} + '@oxfmt/binding-linux-s390x-gnu@0.68.0': + resolution: {integrity: sha512-RlfSg++qs1hbKltRR6lYvV9EoI3MdlfSQD9w1hdHVYjHqjIn1tkH4FWOpMSmjKGN20zr+nI+W9o4ARogCDudGQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-x64-gnu@0.59.0': - resolution: {integrity: sha512-4hNjqq/Rbr9B+StY9zMMAfm72+mtM4v80xYL5Qkb59Qd72g2vJMI0iFlPj3kf6miMsie/yJ7rt4urJT292HBgA==} + '@oxfmt/binding-linux-x64-gnu@0.68.0': + resolution: {integrity: sha512-nyzRB9U+dlYUKu3pMo3afHzZBUv/oTHZMG36ZfJViNVfOIzp70Q4GS8FFRGgYJ/p0zcyDCgpBvYISOdJOMh+jQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-x64-musl@0.59.0': - resolution: {integrity: sha512-NH579iN8EVQYsWowUB8B5vFchcylJtwPVJ7NmUAqEQHNLfhPbDT3K56KrECNAkUN4QpF4qiMgN2vsfZwVvjm7g==} + '@oxfmt/binding-linux-x64-musl@0.68.0': + resolution: {integrity: sha512-iCx3sbZRIvGrL1RafphEiUKBaW1lc0/tAjKOIB/Wjw2+STRBEdu5+fH1Gc1faEWEmc2k5Ks4iUUV54Zd5C9a1A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxfmt/binding-openharmony-arm64@0.59.0': - resolution: {integrity: sha512-mzZy3Z5Aj1D75Aq9FVlmoRQH5ei8Ga4o/NZmlXkKyeZ5EmPrUXRR7c6BMBteV1ZuZ/356UYDuLRLjAMxTDTiBA==} + '@oxfmt/binding-openharmony-arm64@0.68.0': + resolution: {integrity: sha512-x2X5AZez7OgyLLFpwIgItoXBUqudDM7yiaTsxv8R8vKQ6e81l0jVw0NFeUCXzcl1sAJq8h+tC8N4mY8EiMeL4w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxfmt/binding-win32-arm64-msvc@0.59.0': - resolution: {integrity: sha512-0CpDJ1gE3jN1Gk6xms1Ie6LPfPcOtY4FAtoOmVLHQoAf8DvO2wd0DW2dIX2f7YTp5dxrr0ND8JeUEjm3DP3k5g==} + '@oxfmt/binding-win32-arm64-msvc@0.68.0': + resolution: {integrity: sha512-AHVPjXkenLPQUh6kB8zSC8pX2ct9r4T1Edk9r/RNJyov6wPsS5uAfYtipwG4chn6+3bPFG5rI/3DxEeH8vib1w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxfmt/binding-win32-ia32-msvc@0.59.0': - resolution: {integrity: sha512-zwdKBu3pt87uW0bRcywZb0oGMS7C6n87qogwRYFUgmk44T90ZzYlPjtlFYXs/DnBFrgNCvlHwCuWKfVWLeE7kw==} + '@oxfmt/binding-win32-ia32-msvc@0.68.0': + resolution: {integrity: sha512-n09SjEk5VH7z8Hl4WVP7hho+cCwGViENkQFiM45vbW85dJd7kEhWaHRUobaPzEmrWyu6uumd4EuNfNyDKLtzDA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxfmt/binding-win32-x64-msvc@0.59.0': - resolution: {integrity: sha512-dUUbZkKgWrmAeI/puzv4bxN8lzcYaFnQVwFTFtwO2Gp8M7lZGSE2qJjC58g518+1bltJ8mizjYwD0BGHym0l/w==} + '@oxfmt/binding-win32-x64-msvc@0.68.0': + resolution: {integrity: sha512-gPe+dJLXaPuWPWqlpklDAJp0k+K9KhQPYiQLHfb+i2rmFuUGfJ/5Qlj6tr1mO6of5g0DiLjG/XCFHIaPhotqqA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@oxlint/binding-android-arm-eabi@1.74.0': - resolution: {integrity: sha512-+gHd12muVI9ZLBaWLPkHt3Fj7jihFjgQ1MGtBaRL8vWrWrI0P7dLUty/cHrHS0oqPYIRgQUJsPu2CExQuMcwNw==} + '@oxlint/binding-android-arm-eabi@1.83.0': + resolution: {integrity: sha512-0yGY24EwsLk5YDe6F+VkmZyRHSwJDALa3nIrPpq7FXmp2lV2d0TzvBCGeZk+wgiULRGr5blhyr4QMp5KCXJUqA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxlint/binding-android-arm64@1.74.0': - resolution: {integrity: sha512-xjKdoMB+H+RCOByv/7l7nfIGW9mlOisqYdcyC75UqYuQecLpReAeEYUf2CNeDEI3KtmUgxpRw/+c63y4AeF/Bw==} + '@oxlint/binding-android-arm64@1.83.0': + resolution: {integrity: sha512-hHfJ0vc17A4iUjH5p9BsTUPYbYRNxGpvD2lbu1aBRk54bzNIx9o5TtYF39QPZcV95DagZd+4DEAw2RH3G2ZsMg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxlint/binding-darwin-arm64@1.74.0': - resolution: {integrity: sha512-iUK7wvc6sejMKsC+Pt67mntoF5weFcyEunhZfLJceU6gL419mexz5wBkSx/EnkFBExMLNtOi9fnDSc5xfK0IzQ==} + '@oxlint/binding-darwin-arm64@1.83.0': + resolution: {integrity: sha512-hsOjYjszLb/3zym/TkzUMPAoQlTJcuzSyEPOAyA+skXJIX9M0o+4JfOtqopX/Vf4hSLrJ98j0nvFo23gzk8auQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxlint/binding-darwin-x64@1.74.0': - resolution: {integrity: sha512-ggKc/tn5SJ1u2yG2izC6VKODfYKV8MQ2AicJlNzOjuyrC29udvOef6/JzK2r32xqCnBDLFouR1VCkjzEI0/N9Q==} + '@oxlint/binding-darwin-x64@1.83.0': + resolution: {integrity: sha512-mjh5oH2EA+wl5yRJYT9K9G61O2zFlpuv+yf2JwZOi0+dq2FnTUtm1h8i+5Ik0fXPWIu/k84I1psZR9aQsLAnyA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxlint/binding-freebsd-x64@1.74.0': - resolution: {integrity: sha512-u++dH/43jy9hTLbneaWlS0gla/Bp1JdwJ2zgevCl8nDFUh6qRCGMxcL0f0lb7By3A9p/LfFr+7cG4HU1hG856g==} + '@oxlint/binding-freebsd-x64@1.83.0': + resolution: {integrity: sha512-fNHr64/YaO8YssuoDVC8+F4Uk5enR86q5uxfHkQrjAPs1dbAILOrD2uaud+J7MO8Fx774g44ERLD0IGIvZE48w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxlint/binding-linux-arm-gnueabihf@1.74.0': - resolution: {integrity: sha512-Sj1zmtFDVTPeIbIz4ZfcXAbFHqCmKCXdCUlAJzvTF7I20NTH1RDpoF2PhkqNODutJzVhJYmm3oz0GwgY+tvE2g==} + '@oxlint/binding-linux-arm-gnueabihf@1.83.0': + resolution: {integrity: sha512-Qpwy3zzAwMj+8/lyYItHmkSMwbkprFNWTK7jPYDOxSyxEhaSLOWYUTCMkjF334J8/WD0nznCCsoBbIH6hpsuIw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm-musleabihf@1.74.0': - resolution: {integrity: sha512-//PKyQb/tQXcHArx2f7z+oVI/eMS2Jpv+edNuAtOrgIhWdGcpHxogveAxzmF2rpH1AIHp4Hq04RF/rgJdiICnQ==} + '@oxlint/binding-linux-arm-musleabihf@1.83.0': + resolution: {integrity: sha512-s+BirYLFq7JL2k9sP0XI3ZXJ9dYvJ8sX3jLCLoag7tt+zrSHpZxP0jqznfL+Gdgwu7ay0dYgGYJXrQvq3iWloA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm64-gnu@1.74.0': - resolution: {integrity: sha512-/k1Me+aX2tjuH10K62mLS0y8cLkJBHX6Ce0xPK+eWeel4bSdEGZ8dv4+hYMzg0GrSmjwy4yAYsDPeEeKBft/2w==} + '@oxlint/binding-linux-arm64-gnu@1.83.0': + resolution: {integrity: sha512-7lihXt3vKr+GIyapNbHrnFHm/biiW30le6Zv/DExbAFPF6YwCQXVFlONPFehxs0CpGO4CBfYPM9rdDT+XMoIlg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-arm64-musl@1.74.0': - resolution: {integrity: sha512-3tFSjBxc5D8/zvjEuLvOqcA8ZXKD0+6NuaVO/edeamNc49MoAsbfaC9s1UiwODwgF6slGaF8yJA2TPkukd77tg==} + '@oxlint/binding-linux-arm64-musl@1.83.0': + resolution: {integrity: sha512-q63JalLYVkZiZvls1z3PPUnpmQluOMXp0khqQMznCeAPLGydfNY8JhvuA4WlK57JfrvikU8wB5lPVveqpIXvew==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxlint/binding-linux-ppc64-gnu@1.74.0': - resolution: {integrity: sha512-9QggtPkSPXOCTu8Szis7auOK/sC7KdQaN+/TujP7YVVhzCAOhgdRfgv8uEz0r2tk5xdgus5rLYUrCDoZNtiRUw==} + '@oxlint/binding-linux-ppc64-gnu@1.83.0': + resolution: {integrity: sha512-krQmDF+dRbxvdqVPV88ZuOoPPu8X5BuqDA8Hd+qcS4YMRQCb+nexA57DazgGsc/rGdKBe3QmV0mnv0bdpW/p5g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-gnu@1.74.0': - resolution: {integrity: sha512-VM5VPUJ4DJIWiK+AZn8FScUqMr6OFrCAYybMYjEEi7W13ParI64MByiXTkKMqZpBmvQ9zxl9Ebq2VUOiZRJYUg==} + '@oxlint/binding-linux-riscv64-gnu@1.83.0': + resolution: {integrity: sha512-MmOl8Y6txEAXZU1RG8Rr264jQ6D7VPmqFsU/45x/FeWsGe32hklTqGrLE6UxHzp5Rjt0wP+20tY8YXKgSFB3mw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-musl@1.74.0': - resolution: {integrity: sha512-SaDY1gh9rOA592J54g+gu5hkOFFQBZsMmIYHs+NRHG+Uq0OxtuuCXMWQ3vu1830Eugv5uMXyjG+bv2Z9y4IXjw==} + '@oxlint/binding-linux-riscv64-musl@1.83.0': + resolution: {integrity: sha512-u1rMymh0W3JZkq370kzQsYPULGWqhE09pZRqnZvUSoYaI9pVO5yVX+iYIslmWuEgwuzH9YAaOsScJiobWCHoOw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxlint/binding-linux-s390x-gnu@1.74.0': - resolution: {integrity: sha512-ZATQeHZCyr6MbDveg0obD5sxLHFOghtOdC5jwVwYlvFWqtFOxctgFEG6Ef/64hYvZrWyhyCckB10AelqLopeDA==} + '@oxlint/binding-linux-s390x-gnu@1.83.0': + resolution: {integrity: sha512-y0zK3HNwGysu7rqtE+BQG/d0bx5gh/KwlOtghN8oWeK1KcWzeaLqtZrbm8owqdma1lFyrce/hTO5ismuNu+INQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-gnu@1.74.0': - resolution: {integrity: sha512-+aIvJyrdeD7LwCQ2WYLMUWNmnbeDRSPb40aBYtPjD9+PTqUwgJnk+HK5yLfSMeqXrMrDhE9uTmtt2y50tvjhHw==} + '@oxlint/binding-linux-x64-gnu@1.83.0': + resolution: {integrity: sha512-rS5gM0NgD7ngmuJmbIehsidtrOwKkLFwCQbKEeb9KuyQrrWNq5Zkn0uV6AYdXOMJ0grrWEiLwBuvMxt8w5vsNw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-musl@1.74.0': - resolution: {integrity: sha512-XyktaR8lhK2qWiCK0Tk8oYD+/cgn+oHA6ddRnxSSXUKkkojkV78CmShZUxQF+yrBFs0SuW+JBOPG6hecyc/iZg==} + '@oxlint/binding-linux-x64-musl@1.83.0': + resolution: {integrity: sha512-W2IH4EtpcPaWcvNGCA95YoDg4vxqE/ZiPCi3arrxEEpsK7+JQN9WYwrlYFx9pcdP6KPXqRqkv3zdQPHcx7b6YQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxlint/binding-openharmony-arm64@1.74.0': - resolution: {integrity: sha512-mzbjrPl4neaVUiJ1fUiEUxTGaSZBoiKtaoB6jmIpz9S+VOA2vDYmJpihQ82w6178V5jxziclTg8Cgj5yF6tTDg==} + '@oxlint/binding-openharmony-arm64@1.83.0': + resolution: {integrity: sha512-6LyKkUyoajssTPLlZmDbZIbu4IZ5B4bGuRUnBgCGpEvHP3FQMaYITncHA/unPUo7q+Z+pIu2HhdkQ+8d1SG7iA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxlint/binding-win32-arm64-msvc@1.74.0': - resolution: {integrity: sha512-vUAe9okpS2Oa5+lX67lqHMuNUvfkleRKwrUDJ/WJBsgmddvZ1mrsh2HVmuFDRzqFELhaJhFaCNOuR6a7L3rtIA==} + '@oxlint/binding-win32-arm64-msvc@1.83.0': + resolution: {integrity: sha512-Uz/fObEtF0jmNJQJ8CGRBKfefYstS0/wjD3s6IGzP8nUwsJykHQJBiN3npHwKiGRGn/vvBEgNr4B3cCzmmatvg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxlint/binding-win32-ia32-msvc@1.74.0': - resolution: {integrity: sha512-yyXXJyYYSXL4I8K8jAWjJs+J3fa9gH2JmEbo4f5adm+1tNC9itseicBNuwK7BDHvqQ5J534s+yDULu89vYL2ZQ==} + '@oxlint/binding-win32-ia32-msvc@1.83.0': + resolution: {integrity: sha512-u7XcvPW6Bk58tY5iWs2ESb0vJjoE/kuSpHxopbwp/p3ZtWVQXZ6wor5w3ssVTHOqd/v8b+QdhSFWQ4grEUNWpA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxlint/binding-win32-x64-msvc@1.74.0': - resolution: {integrity: sha512-VTC9IYTIMrVUk/i6Ms1ohzzDKZFkWn0KU2OBbPBzgmVZ2V30165T/zK4LztTr0Xgp9fZ1qQZ1rsZAu/rEmySlA==} + '@oxlint/binding-win32-x64-msvc@1.83.0': + resolution: {integrity: sha512-LZRubd7ph13QmAg4fFecTYVZkiYbROR2Htaxh/ufWRkDhPOm2wrwaEYR89e0YpPFD3dqBrPoxS7myBw5hmYA7Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -1736,151 +1129,109 @@ packages: '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} - '@playwright/test@1.61.1': - resolution: {integrity: sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig==} - engines: {node: '>=18'} + '@playwright/test@1.63.0': + resolution: {integrity: sha512-oxMK4vllB9RK5NQ2l1pq1IfOf2AvnEuj/vYGDj0H2nMtmtZpKtCwt/l00GEO6xjGfpBNAvjovvYdCm50dRQkpQ==} + engines: {node: '>=20'} hasBin: true - '@rolldown/pluginutils@1.0.0-beta.27': - resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} - - '@rollup/rollup-android-arm-eabi@4.62.2': - resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} + '@rolldown/binding-android-arm-eabi@1.2.9': + resolution: {integrity: sha512-tNISae1QEf/vkb3xkRcjV5SEdzPE97We5IVaa2Z8jSszQPZ8U60B/YCYpw4QI7VidYsBtKavczXf+DyDs9WGxw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.62.2': - resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} + '@rolldown/binding-android-arm64@1.2.9': + resolution: {integrity: sha512-YC8YsI30o606GTZi0VyzYlsDKFP8W61i/QzayHDkLbNEz/IShqAmTa+hsJRj13xTHA0H+6fk4b2UmGn+Q/cMlg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.62.2': - resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} + '@rolldown/binding-darwin-arm64@1.2.9': + resolution: {integrity: sha512-IwhlH3qK5urrY8hZiEgGkHKEFN901p/p2bjxCxJlr4GyNnF7wYpUvK+Y43uaRYuC4hpfjzbR3SJC3arX1jGvmw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.62.2': - resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} + '@rolldown/binding-darwin-x64@1.2.9': + resolution: {integrity: sha512-XxpJfVzFh+jilRxIXUqcfYAYcunIc/XEzIizsOL1fcJee5Sf7H3mH8WlLmfHfluz5amqR88QQo9izKtmMlavAw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.62.2': - resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.62.2': - resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} + '@rolldown/binding-freebsd-x64@1.2.9': + resolution: {integrity: sha512-kSfvhmgeWyfkbT3p/1s5vSgboogoah2zkm9fX2zjg2hHxSV7T4KhMWRUUaRk4OXNqoD3QAUeRqLcs1aZOK4U1g==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.62.2': - resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} + '@rolldown/binding-linux-arm-gnueabihf@1.2.9': + resolution: {integrity: sha512-1RVzG17pxqbTfYLC352JlLt6kKLG+6Hr30n8DlIJqsnV5luUDd2Qdx9Ayw1Cabfyb1K9k0jXEZ7evxkRoT+uiw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.62.2': - resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} - cpu: [arm] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-arm64-gnu@4.62.2': - resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} - cpu: [arm64] + '@rolldown/binding-linux-arm64-gnu@1.2.9': + resolution: {integrity: sha512-BXqPvZ2drqVD+/Z8UpKwcs4Mp7grM+eGFku4CAEKrEtcbAsUpzREphK1sogCRZGreVPiMkiiBtw0n3TPteuqvw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.62.2': - resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} + '@rolldown/binding-linux-arm64-musl@1.2.9': + resolution: {integrity: sha512-11vWvo8YDwLzukt27J3aYDWU+gg2P7J+ZOmiJ0hkF5BXZDW7pVya7r40MXDy6ya0i9KamoENSVKIugvJNgFXIA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.62.2': - resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.62.2': - resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.62.2': - resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-ppc64-musl@4.62.2': - resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} + '@rolldown/binding-linux-ppc64-gnu@1.2.9': + resolution: {integrity: sha512-a1tijMkdwsIARtc0F39ApURROkf3NwqinI6TOiSSWCTR7dT96dffNvMUtDHnq64wKNTIZOIlzKrFvvFUznJiyw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.62.2': - resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} - cpu: [riscv64] - os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.62.2': - resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.62.2': - resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} + '@rolldown/binding-linux-s390x-gnu@1.2.9': + resolution: {integrity: sha512-x6SQNdAvv4c3hWqTMaWuawzMX9myaCs/yEmlGsxJzkdClnHW7FbrjQuSiRDhuSYzEYoEMhsaJy9qHG/XNemJPQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.62.2': - resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} + '@rolldown/binding-linux-x64-gnu@1.2.9': + resolution: {integrity: sha512-9s0AZ8BFK5/n7B/TBoa2yJE3gI3KURrbXcPBlsAsvjU4VeJKgE90y1YtNxyEUIcHPQkg6/yfF3qihUrcM/Kf0Q==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.62.2': - resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} + '@rolldown/binding-linux-x64-musl@1.2.9': + resolution: {integrity: sha512-P7VWAmV+WdJluH7ovnRGoiv2i8To7GAZ+kGzfGup635cyL7SyYl3lSUaA3Gp5THf0n/Co5EyEqb2zbqq+nMOHQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.62.2': - resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.62.2': - resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} + '@rolldown/binding-openharmony-arm64@1.2.9': + resolution: {integrity: sha512-1qixtsE4BK8h+yS3BfmZ09UhA7O/N4IACva6YBr7EBvCJraByTuRcgOTaiA62Tm0vey3UcKXLOaoGHtYmNGEVg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.62.2': - resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} + '@rolldown/binding-win32-arm64-msvc@1.2.9': + resolution: {integrity: sha512-ok8IQjcEPs1AKZfuEUznVBrJw+gK4soq+bx8b1X2XoMqVClarc1q5JDmVtWXY1xfr6ZuHTAsPXHTgTrqKTZeww==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.62.2': - resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.62.2': - resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} + '@rolldown/binding-win32-x64-msvc@1.2.9': + resolution: {integrity: sha512-Ip2mXoU0hM0boq3Rf+ekuT653OROSo6aSYcPT1VHE4q52KvyxgFkQgrgb/IEsxOuvQ2fZZbs8khJAyCEPM24/g==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.62.2': - resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} - cpu: [x64] - os: [win32] + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} '@scarf/scarf@1.4.0': resolution: {integrity: sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==} @@ -1897,38 +1248,14 @@ packages: '@sinonjs/samsam@8.0.3': resolution: {integrity: sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==} - '@smithy/core@3.29.3': - resolution: {integrity: sha512-L+Ys6ecjk5vwPMAKHBpPKlJ3DkqwNcnfEISXBZIsVvWG/XKXfsAP8mwIYlTeLcd2ElHdesPI8OuOmJSFAPhm6A==} - engines: {node: '>=18.0.0'} - - '@smithy/core@3.29.4': - resolution: {integrity: sha512-G1GRglAabzEhqghJMBAd54FkRS7SAFGHEwbhcI9r+O+LIMuFsLyXkLZkCoFSgAglRu8s/URVXJB0hglq3ZipIg==} - engines: {node: '>=18.0.0'} - '@smithy/core@3.34.1': resolution: {integrity: sha512-dLcOUxz8YCv1RZUMKq6GbyUf95pLbrqh34bPvpCZ1+CByFF31BEAFewZjsGCnVsZTKdThNENfGyAgk2TJqVwSw==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.4.8': - resolution: {integrity: sha512-q9J7JTiXrAhB8sDp4px97uEPT7CwKH61Co78grdNQvU8QZAdiuaSRhP0tUVf2ogy36RZTrlMU1rBmDEH+cnkiA==} - engines: {node: '>=18.0.0'} - - '@smithy/credential-provider-imds@4.4.9': - resolution: {integrity: sha512-2nfV4qRKiYeXU4zD2vvSCfg5dfp/BuhrM73vt7q9gzBhxs4rbPxXY21wo+kyI3bRmXcEGRnCLTaW8O437jzHIg==} - engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.5.2': resolution: {integrity: sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.6.5': - resolution: {integrity: sha512-SuqeisTyPoiIPtIYru/sGxGyXzmZ+8nnFOhC+qRPglt06Ebd1yH//CDltZB2J/3WBNVhwfUaZ0EtHB3cm2X32g==} - engines: {node: '>=18.0.0'} - - '@smithy/fetch-http-handler@5.6.6': - resolution: {integrity: sha512-NHLgAlORUFZjn5ZfhYuyyKMlXA1WLYOdGxEhyNxrPpbJzoacGbl0chn1lN2KiZ8mpNVk0tV5607CSYlYs/OFgw==} - engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.8.0': resolution: {integrity: sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA==} engines: {node: '>=18.0.0'} @@ -1941,30 +1268,14 @@ packages: resolution: {integrity: sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==} engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.9.5': - resolution: {integrity: sha512-bNqdxTQTxmLbomSmlkZFz8L6B/feQ2HHzw4L2zY7Ecp2XffYAZq2uzdWDdxJHJFbEvqd+SRuluJso0P8+xPdbw==} - engines: {node: '>=18.0.0'} - - '@smithy/node-http-handler@4.9.6': - resolution: {integrity: sha512-odd+HYx3OLcXRSEz0ZeF3JQdSYdK8QnRgA2N87cPW7coWIbKfRk7a9VQjfeWQLqnzrDLk23KMEn46p8N7M/JFg==} - engines: {node: '>=18.0.0'} - '@smithy/protocol-http@5.6.2': resolution: {integrity: sha512-Asd04MaxODN6FNY8EPTeCAM4kPNi3jDUAjZU0Y4F9rHvpLUrrUo7KLcxFgSthywFr6dZfIyDLIJda6jxmVTk5w==} engines: {node: '>=18.0.0'} - '@smithy/signature-v4@5.6.5': - resolution: {integrity: sha512-MO5VEhwVl0BN7xVoVeNrZfiUFoQtqxUbgl6/RwOTlMMxCSjblG8twSrVTwz3J4w9WZxd2rBfBAUXjH77agspBg==} - engines: {node: '>=18.0.0'} - '@smithy/signature-v4@5.7.3': resolution: {integrity: sha512-7ImGm+FkHRLcBaRttIAMZ6bzJZWb2cJGoYjq46F2UjycujWzrL9GEN9h4w7eQyXJYnltrUhxbbieBAIRrdqpow==} engines: {node: '>=18.0.0'} - '@smithy/types@4.16.1': - resolution: {integrity: sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==} - engines: {node: '>=18.0.0'} - '@smithy/types@4.18.0': resolution: {integrity: sha512-CgB6HHWer/vrKps24ulRIbpcpb7K4xAU7SkZ7YHzBPlwHsvsrCJFEXK421s+cJzX+ZrqtA/TuU5w1HzI7k9N8A==} engines: {node: '>=18.0.0'} @@ -1977,69 +1288,72 @@ packages: resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} engines: {node: '>=14.0.0'} - '@tailwindcss/node@4.3.2': - resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - '@tailwindcss/oxide-android-arm64@4.3.2': - resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==} + '@tailwindcss/node@4.3.3': + resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} + + '@tailwindcss/oxide-android-arm64@4.3.3': + resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} engines: {node: '>= 20'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.3.2': - resolution: {integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==} + '@tailwindcss/oxide-darwin-arm64@4.3.3': + resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.3.2': - resolution: {integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==} + '@tailwindcss/oxide-darwin-x64@4.3.3': + resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} engines: {node: '>= 20'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.3.2': - resolution: {integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==} + '@tailwindcss/oxide-freebsd-x64@4.3.3': + resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': - resolution: {integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} engines: {node: '>= 20'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': - resolution: {integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==} + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-arm64-musl@4.3.2': - resolution: {integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==} + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [musl] - '@tailwindcss/oxide-linux-x64-gnu@4.3.2': - resolution: {integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==} + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-x64-musl@4.3.2': - resolution: {integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==} + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [musl] - '@tailwindcss/oxide-wasm32-wasi@4.3.2': - resolution: {integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==} + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -2050,87 +1364,81 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': - resolution: {integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==} + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} engines: {node: '>= 20'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.3.2': - resolution: {integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==} + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} engines: {node: '>= 20'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.3.2': - resolution: {integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==} + '@tailwindcss/oxide@4.3.3': + resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} engines: {node: '>= 20'} - '@tailwindcss/vite@4.3.2': - resolution: {integrity: sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==} + '@tailwindcss/vite@4.3.3': + resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==} peerDependencies: vite: ^5.2.0 || ^6 || ^7 || ^8 - '@tokenizer/inflate@0.2.7': - resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==} + '@tokenizer/inflate@0.4.1': + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} engines: {node: '>=18'} '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - '@turbo/darwin-64@2.10.5': - resolution: {integrity: sha512-ENvPwy3x5yS7MwNYHeWjqOBXkwIMp39Pd+/zXC6PoiNzF8EIvvLZOZZ+ny6L9x4WgS5vxUii2LM5gM+zjPdnWw==} + '@turbo/darwin-64@2.11.2': + resolution: {integrity: sha512-0pGfE4Lpxrbd+6gUD9z025Tn4z9uMaSNZ3VX0H/hkUPZkjY5xrCa1NfTqocs09NM5NiYE3wEVcoYBadrhayRCA==} cpu: [x64] os: [darwin] - '@turbo/darwin-arm64@2.10.5': - resolution: {integrity: sha512-rqROo9zsF/P9RqsdtbLD1nFJicjSrYyvQ9kNJC38AbxA3pAs6VAlATvtvOFx7bqOv6vicf20SP9kF33avJjy2w==} + '@turbo/darwin-arm64@2.11.2': + resolution: {integrity: sha512-Ub7hTbu0bPSiW156ciuLCexG5/SfuZM/QWeBBh9o8P4XyKiZwKqubT6Y9DdJjdp4ZY2wS47Prdl06Xxzt0q6zw==} cpu: [arm64] os: [darwin] - '@turbo/linux-64@2.10.5': - resolution: {integrity: sha512-RoSSiNFUxi27zLJuM9F6GyWWjHgLch9t6nwD6K0FkXRirZkTLlzIj6IhFnK8H9++nefLtdFqylE4vGjZAv6AAA==} + '@turbo/linux-64@2.11.2': + resolution: {integrity: sha512-8ipdmgmvSomfQ8E9afUsefO+BLO6QMW7srrHqMOCXD3BPX4FlYqqWAJY1GvbQotZMWKzNohdVkevrUYM6ZzYKA==} cpu: [x64] - os: [linux] + os: [android, linux] - '@turbo/linux-arm64@2.10.5': - resolution: {integrity: sha512-4ZComcpzmHGmVynQqvvi+iZOSq/tBvY1SltXB8g4NZRsrA01W8E+yRL8RNM+PLoyWsrCnJa8xa+DkWkv+xg4iQ==} + '@turbo/linux-arm64@2.11.2': + resolution: {integrity: sha512-tsftYXAzgc+GdosqyRP8+Zzk2evJ8ej7Otal7/DU+6GVekVZ3kqM/z7zlGuF4TSHeetWxX04KN1I64LkmvYzgg==} cpu: [arm64] - os: [linux] + os: [android, linux] - '@turbo/windows-64@2.10.5': - resolution: {integrity: sha512-eL2Iyj4DbMINq1Sr1w0iAi6nAiZOF16KSlRGwCJpVh+IWZeY33MAsLHVOBMj1xoFtncVJXclCVpTPL2nBoYkFg==} + '@turbo/windows-64@2.11.2': + resolution: {integrity: sha512-p5LDVcGmC8W6FCrJPehr1t0ZvYqM8xvG3Va+LkwtDMK3Rl0NhSsJOYbYZVBfMbkm+9RKcCvekFCbSVtQ9Eyuqg==} cpu: [x64] os: [win32] - '@turbo/windows-arm64@2.10.5': - resolution: {integrity: sha512-sog+wP+8YSJrdWZ/rUJg8xghVTrwoG+BrSlDQpnK5fzSgJHn1INRWXbVWRH0d3vX8dBI01E3yxXRre9Dn+OXQA==} + '@turbo/windows-arm64@2.11.2': + resolution: {integrity: sha512-u0M3m1aXo9lpDM/2iQhxlGzgWjHFq/MC4TqHn1YAvxk8g1wGtzRB2QBx/SLqRChhPhC29mzaB8eLcxKh/pcM1g==} cpu: [arm64] os: [win32] - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - - '@types/babel__generator@7.27.0': - resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} - - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - - '@types/babel__traverse@7.28.0': - resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} - '@types/body-parser@1.19.6': resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@types/express-serve-static-core@5.1.2': - resolution: {integrity: sha512-d3KvEXBSo/lOAMc2u6fkyDHBvetBHeqD7wm/AcXfLpSOQwlmG9D/aQ0SFswVjv05p7ullQS7Mjohj6/VdbZuTg==} + '@types/express-serve-static-core@5.1.3': + resolution: {integrity: sha512-dPfW8NFiOF4wOHc7+N/QSxlY9cfSsenewGbAz8C8U/MULPd/YZ27LvJUIlzaXie7e6Ove9YunJGgC9tbHD2cKw==} '@types/express@5.0.6': resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} @@ -2138,14 +1446,14 @@ packages: '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} - '@types/jsonwebtoken@9.0.5': - resolution: {integrity: sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==} + '@types/jsonwebtoken@9.0.10': + resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==} - '@types/node@22.20.2': - resolution: {integrity: sha512-xlvWf4Vs9n1PEVYwP1n4vvG07M6y8WgvJ2t0vbrWTmijsIHp1cS+uJ2kMIRdY3nHZK0nCYKrPeD171+SzF4/zw==} + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@26.6.1': - resolution: {integrity: sha512-VqGJBMCtdhqkBUCcBLvywI0NJ+KLuVzgNnlBUNFOQjqVxzo2lxLUNg1DSey8+u2u6ktswSAxg+s68QLzWHNOuA==} + '@types/node@26.6.2': + resolution: {integrity: sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==} '@types/oauth@0.9.6': resolution: {integrity: sha512-H9TRCVKBNOhZZmyHLqFt9drPM9l+ShWiqqJijU1B8P3DX3ub84NjxDuy+Hjrz+fEca5Kwip3qPMKNyiLgNJtIA==} @@ -2168,13 +1476,13 @@ packages: '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + '@types/react-dom@19.3.0': + resolution: {integrity: sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==} peerDependencies: - '@types/react': ^19.2.0 + '@types/react': ^19.3.0 - '@types/react@19.2.17': - resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} + '@types/react@19.3.0': + resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==} '@types/send@1.2.1': resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} @@ -2191,52 +1499,159 @@ packages: '@types/validator@13.15.10': resolution: {integrity: sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==} - '@vitejs/plugin-react@4.7.0': - resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@typescript/typescript-aix-ppc64@7.0.2': + resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} + engines: {node: '>=16.20.0'} + cpu: [ppc64] + os: [aix] + + '@typescript/typescript-darwin-arm64@7.0.2': + resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [darwin] + + '@typescript/typescript-darwin-x64@7.0.2': + resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [darwin] + + '@typescript/typescript-freebsd-arm64@7.0.2': + resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [freebsd] + + '@typescript/typescript-freebsd-x64@7.0.2': + resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [freebsd] + + '@typescript/typescript-linux-arm64@7.0.2': + resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [linux] + + '@typescript/typescript-linux-arm@7.0.2': + resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==} + engines: {node: '>=16.20.0'} + cpu: [arm] + os: [linux] + + '@typescript/typescript-linux-loong64@7.0.2': + resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==} + engines: {node: '>=16.20.0'} + cpu: [loong64] + os: [linux] + + '@typescript/typescript-linux-mips64el@7.0.2': + resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==} + engines: {node: '>=16.20.0'} + cpu: [mips64el] + os: [linux] + + '@typescript/typescript-linux-ppc64@7.0.2': + resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==} + engines: {node: '>=16.20.0'} + cpu: [ppc64] + os: [linux] + + '@typescript/typescript-linux-riscv64@7.0.2': + resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==} + engines: {node: '>=16.20.0'} + cpu: [riscv64] + os: [linux] + + '@typescript/typescript-linux-s390x@7.0.2': + resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==} + engines: {node: '>=16.20.0'} + cpu: [s390x] + os: [linux] + + '@typescript/typescript-linux-x64@7.0.2': + resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [linux] + + '@typescript/typescript-netbsd-arm64@7.0.2': + resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [netbsd] + + '@typescript/typescript-netbsd-x64@7.0.2': + resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [netbsd] + + '@typescript/typescript-openbsd-arm64@7.0.2': + resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [openbsd] + + '@typescript/typescript-openbsd-x64@7.0.2': + resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [openbsd] + + '@typescript/typescript-sunos-x64@7.0.2': + resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [sunos] + + '@typescript/typescript-win32-arm64@7.0.2': + resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [win32] + + '@typescript/typescript-win32-x64@7.0.2': + resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [win32] - '@vitest/expect@2.1.9': - resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==} + '@vitejs/plugin-react@6.1.1': + resolution: {integrity: sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + oxc-transform-react: ^0.145.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + oxc-transform-react: + optional: true - '@vitest/mocker@2.1.9': - resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==} + '@vitest/mocker@5.0.1': + resolution: {integrity: sha512-6K1DoBNAPGvuOcSsGA4D6x+5zEEff/KmOOP3uetT2TrGpVfI+HRHRnJJfKi5ib/g1vx8IYHQD8s0pbJz8WQI7Q==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@2.1.9': - resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==} - - '@vitest/runner@2.1.9': - resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==} - - '@vitest/snapshot@2.1.9': - resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==} - - '@vitest/spy@2.1.9': - resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==} - - '@vitest/utils@2.1.9': - resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} + '@vitest/spy@5.0.1': + resolution: {integrity: sha512-rbto/mF/SGERxEgYOek7Xm6B9b+y+mVoo+f4b2LymYO8zM1b7uB5nHuhVMTP2hxdzgxvGiZYGxGIaMvL5y180Q==} abstract-logging@2.0.1: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} - ajv-formats@2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -2248,10 +1663,6 @@ packages: ajv@8.20.0: resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -2263,15 +1674,16 @@ packages: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} - avvio@8.4.0: - resolution: {integrity: sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==} + avvio@9.3.0: + resolution: {integrity: sha512-g2tQ7LE7oOSqDfwEm3M+ZCMTJc7KiZCdJ4UwyZJb5ckTKyYu50OYmvv0mCFXPuYXoM4zkSt8zM9XQ9KCvxA74A==} - aws-cdk-lib@2.261.0: - resolution: {integrity: sha512-e52e3Abjg0HkuRWlWwtSv5+ZiMW1rhCDdL9ff7lzWXInU8xdfLJpuoimfa0IJwjiNGyphppgg52Azx9M80OA0g==} + aws-cdk-lib@2.270.0: + resolution: {integrity: sha512-xoO9FEqcVTTK39N6n+LxvAAsS5WZSGX/p+uv3l2W+LXDEIWctq6VECdluuFwdXnbyf4v4eIxo2btrkUepnEy0Q==} engines: {node: '>= 20.0.0'} peerDependencies: constructs: ^10.5.0 bundledDependencies: + - '@aws/cloudformation-validate' - '@balena/dockerignore' - '@aws-cdk/cloud-assembly-api' - case @@ -2284,8 +1696,8 @@ packages: - yaml - mime-types - aws-cdk@2.1131.0: - resolution: {integrity: sha512-02oAVG4IBFwPtPlDE95H8tDJFfDuxJLdvyrdav6rn72mup/LIZRCfp95IB9kfM+FL4vQ9gn/QCEI7y7aNDTpKA==} + aws-cdk@2.1142.0: + resolution: {integrity: sha512-gNOeii+avTJmOwfR8tVgraZ5A2EBC/529EXg7e+yBp8Zl608dAv5CtFRoJt8QoKiruiCwYr4HF6ClNAse/NkSg==} engines: {node: '>= 18.0.0'} hasBin: true @@ -2296,47 +1708,22 @@ packages: resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==} engines: {node: '>=6.0.0'} - baseline-browser-mapping@2.10.43: - resolution: {integrity: sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==} - engines: {node: '>=6.0.0'} - hasBin: true - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} bowser@2.14.1: resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} - browserslist@4.28.6: - resolution: {integrity: sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - - caniuse-lite@1.0.30001805: - resolution: {integrity: sha512-52noaS3DubycKSXaU30TwPGIp+POyQSUVa5jBEq3vkRkY0kjyb3LQgvhU6WGyCcyXqVLWO0Cw0Q6BSdD0kUfVA==} - - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - check-error@2.1.3: - resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} - engines: {node: '>= 16'} - cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} @@ -2347,37 +1734,20 @@ packages: class-transformer@0.5.1: resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} - class-validator@0.14.4: - resolution: {integrity: sha512-AwNusCCam51q703dW82x95tOqQp6oC9HNUl724KxJJOfnKscI8dOloXFgyez7LbTTKWuRBA37FScqVbJEoq8Yw==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + class-validator@0.15.1: + resolution: {integrity: sha512-LqoS80HBBSCVhz/3KloUly0ovokxpdOLR++Al3J3+dHXWt9sTKlKd4eYtoxhxyUjoe5+UcIM+5k9MIxyBWnRTw==} - consola@2.15.3: - resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} - - constructs@10.6.0: - resolution: {integrity: sha512-TxHOnBO5zMo/G76ykzGF/wMpEHu257TbWiIxP9K0Yv/+t70UzgBQiTqjkAsWOPC6jW91DzJI0+ehQV6xDRNBuQ==} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - cookie-signature@1.2.2: - resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} - engines: {node: '>=6.6.0'} - - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} + constructs@10.8.1: + resolution: {integrity: sha512-98yGXYyhePqPYh3cYu8nzBERmAhC0DONe3UD03okK0nehZ7hYP4wgZuf02a04+uOWxnTJ5Rpp5m0GRNpwyLGGA==} cookie@1.1.1: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} + cookie@2.0.1: + resolution: {integrity: sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==} + engines: {node: '>=22'} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -2401,8 +1771,8 @@ packages: supports-color: optional: true - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} detect-libc@2.1.2: @@ -2426,12 +1796,12 @@ packages: domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - dotenv-expand@10.0.0: - resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} + dotenv-expand@13.0.0: + resolution: {integrity: sha512-aBfBS8eYIeXmpHI9ThIlA7/WLq+SLt18iXUZhb52rW89QLKQFoIpPG1bPeewoPZsTyjSSO3T7234FBVUM1V2rA==} engines: {node: '>=12'} - dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + dotenv@17.4.2: + resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} engines: {node: '>=12'} duplexer@0.1.2: @@ -2440,14 +1810,11 @@ packages: ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} - electron-to-chromium@1.5.389: - resolution: {integrity: sha512-cEto7aeOqBfU1D+c5py5pE+ooscKE75JifxLBdFUZsqAxRS6y7kebtxAZvICszSl05gPjYHDTjY+lXpyGvpJbg==} - encoding-sniffer@0.2.1: resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} - enhanced-resolve@5.21.6: - resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} + enhanced-resolve@5.25.1: + resolution: {integrity: sha512-nGXts5znJzmWPu+mIE9izCOzdg63oJca2mDzGWWTth7sr4aCToKcoyFVBQwN75Ij5Pf6p510EwkTqViTRzDV+w==} engines: {node: '>=10.13.0'} entities@4.5.0: @@ -2462,33 +1829,17 @@ packages: resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} engines: {node: '>=0.12'} - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - - esbuild@0.24.2: - resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} - engines: {node: '>=18'} - hasBin: true + es-module-lexer@2.3.2: + resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} - hasBin: true + es-toolkit@1.51.0: + resolution: {integrity: sha512-zC2lQGkM7QX+Gm6iM3+WIdZJzthsEd14LvRNJneSO2hzyz/zNBENR8+YXWo1cKxgPBtV6ksPYHELbcwBRzmdCw==} - esbuild@0.28.1: - resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + esbuild@0.28.2: + resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==} engines: {node: '>=18'} hasBin: true - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -2499,17 +1850,14 @@ packages: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} - fast-content-type-parse@1.1.0: - resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} - fast-decode-uri-component@1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-json-stringify@5.16.1: - resolution: {integrity: sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==} + fast-json-stringify@7.0.1: + resolution: {integrity: sha512-eRSayARSbbwlBjpP4vnTTIRD5QPcIrmihPxDeN1DtKnHPg66UuJLx+8hlK1kaFdjvzyQ/dzALoi4vwAQ+T+iZA==} fast-querystring@1.1.2: resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} @@ -2517,17 +1865,17 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fast-uri@2.4.0: - resolution: {integrity: sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==} - fast-uri@3.1.3: resolution: {integrity: sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==} - fastify-plugin@4.5.1: - resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} + fast-uri@4.2.1: + resolution: {integrity: sha512-TmHQgewjHtMq1E5QKA0tOE0yeYGQs25KZC/ziJpubRtWI15W92e6vPFydWOeZBVROSHBYw/QhD9d5OefdD6LDg==} - fastify@4.28.1: - resolution: {integrity: sha512-kFWUtpNr4i7t5vY2EJPCN2KgMVpuqfU4NjnJNCgiNB900oiDeYqaNDRcAfeBbOF5hGixixxcKnOU4KN9z6QncQ==} + fastify-plugin@6.0.0: + resolution: {integrity: sha512-fZOty7z3O7vOliF6d8bHE3wiEh1KcNnKEQensSgTk9C1DvN6nRLS++XVd86v33Hw/8u9Un8A1zDrQ8ujcQDHEg==} + + fastify@5.12.5: + resolution: {integrity: sha512-OB2k1dlxs5/NAABqeKV2FUHkSD2BbENsCak8yULVcymn3fHIPDVa9TI3SDnJSWYSllZmSYuZXy2gTnsT+Sut1A==} fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -2541,29 +1889,17 @@ packages: picomatch: optional: true - fflate@0.8.3: - resolution: {integrity: sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==} - - file-type@20.4.1: - resolution: {integrity: sha512-hw9gNZXUfZ02Jo0uafWLaFVPter5/k2rfcrjFJJHX/77xtSDOfJuEFb6oKlFV86FLP1SuyHMW1PSk0U9M5tKkQ==} - engines: {node: '>=18'} - - find-my-way@8.2.2: - resolution: {integrity: sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA==} - engines: {node: '>=14'} + file-type@22.1.0: + resolution: {integrity: sha512-fbvf9u6jnHWr1EP6V8R99E9iLMhNLXgZkUzWBiPpJ5/89UJ/Atuxjn5YXR+XaZWo2hc2/8mGfTez+NDAgOcpLA==} + engines: {node: '>=22'} - forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} + find-my-way@9.9.0: + resolution: {integrity: sha512-sJsgZ1sQH2UDuowPuMKg8az7Qc8F0jnj+SKkFWU/+T0xcFlgV5skgXOGUqmQzOdmW6ALA7AhJINWx3qFBkbLHA==} + engines: {node: '>=20'} from@0.1.7: resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} - fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2573,10 +1909,6 @@ packages: resolution: {integrity: sha512-sQtrEfA+ez/3G0cCZecF70oqpCRttCexYUG4mUrtWL49ULUzUyxokt5kyqwtKzj1270RaKih+hcP3qLcumccow==} engines: {node: '>=10'} - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -2594,9 +1926,9 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} + ipaddr.js@2.5.0: + resolution: {integrity: sha512-aq+t5NAc+cS6rZQQVWC2x98CPqGtKKTMDd4Gaodv0wShnItdKg/51djkGJ1hqH+Oy0ivDftCbSLCQob8zso01w==} + engines: {node: '>= 10'} isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -2609,135 +1941,152 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} + js-yaml@5.4.1: + resolution: {integrity: sha512-28R/k+NAjeuf7+CKlTxWZVExJGwVVLwY06DgEnOMz2gEpfNkDcD7QvyiVPT0xy0XXhU8vHsd4Ot42OOPdJG7dQ==} hasBin: true - json-schema-ref-resolver@1.0.1: - resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} + json-schema-ref-resolver@3.0.0: + resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==} json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - jsonwebtoken@9.0.2: - resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + jsonwebtoken@9.0.3: + resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} engines: {node: '>=12', npm: '>=6'} just-extend@6.2.0: resolution: {integrity: sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==} - jwa@1.4.2: - resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==} + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} - jws@3.2.3: - resolution: {integrity: sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==} + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} - lefthook-darwin-arm64@1.13.6: - resolution: {integrity: sha512-m6Lb77VGc84/Qo21Lhq576pEvcgFCnvloEiP02HbAHcIXD0RTLy9u2yAInrixqZeaz13HYtdDaI7OBYAAdVt8A==} + lefthook-darwin-arm64@2.1.14: + resolution: {integrity: sha512-VMUAqY81+8ph7Mc0iROd3JWqj2sOuK7SYDyd8ZgzYVKChCt+Nnz8ehd4gUwprJy7QI28IFSUh1M3wnIRiYh+fA==} cpu: [arm64] os: [darwin] - lefthook-darwin-x64@1.13.6: - resolution: {integrity: sha512-CoRpdzanu9RK3oXR1vbEJA5LN7iB+c7hP+sONeQJzoOXuq4PNKVtEaN84Gl1BrVtCNLHWFAvCQaZPPiiXSy8qg==} + lefthook-darwin-x64@2.1.14: + resolution: {integrity: sha512-uSmjcPRU+yB+D6vk+u6WJDnyHlB+XIv1QZw97N2+qNGG2bNSLH/7MuJ6puCdJv+lVPBEO5wBjE3JIbaEzPOQCw==} cpu: [x64] os: [darwin] - lefthook-freebsd-arm64@1.13.6: - resolution: {integrity: sha512-X4A7yfvAJ68CoHTqP+XvQzdKbyd935sYy0bQT6Ajz7FL1g7hFiro8dqHSdPdkwei9hs8hXeV7feyTXbYmfjKQQ==} + lefthook-freebsd-arm64@2.1.14: + resolution: {integrity: sha512-po/pmjbp/7BjE9RFfeDnh+CeNsA0d+utppOYKB425I7mgI1GcmT8GAZ9DDut4DIutNjVqKL/lzrj+F87Gm40Rg==} cpu: [arm64] os: [freebsd] - lefthook-freebsd-x64@1.13.6: - resolution: {integrity: sha512-ai2m+Sj2kGdY46USfBrCqLKe9GYhzeq01nuyDYCrdGISePeZ6udOlD1k3lQKJGQCHb0bRz4St0r5nKDSh1x/2A==} + lefthook-freebsd-x64@2.1.14: + resolution: {integrity: sha512-+KiXiFjJf7YdHUYjzhDsklcA5bAFZN+pNcz/NbBftrhVTwzNALNoK+SYEKt+9QJsrzL6tpDWmHHFpeLGp+8t8w==} cpu: [x64] os: [freebsd] - lefthook-linux-arm64@1.13.6: - resolution: {integrity: sha512-cbo4Wtdq81GTABvikLORJsAWPKAJXE8Q5RXsICFUVznh5PHigS9dFW/4NXywo0+jfFPCT6SYds2zz4tCx6DA0Q==} + lefthook-linux-arm64@2.1.14: + resolution: {integrity: sha512-bjeJB16ftJaPWGTedssh8ZrqRy1ACfQuTV7a0O3NU1FoIsJtfHOm0o0mV4cPf4q+ZCVCwq1Xf2I11qUpuJFV4Q==} cpu: [arm64] os: [linux] - lefthook-linux-x64@1.13.6: - resolution: {integrity: sha512-uJl9vjCIIBTBvMZkemxCE+3zrZHlRO7Oc+nZJ+o9Oea3fu+W82jwX7a7clw8jqNfaeBS+8+ZEQgiMHWCloTsGw==} + lefthook-linux-x64@2.1.14: + resolution: {integrity: sha512-gYExzjU2w3uKrP1MklbHENS1cXUdCQRIiEJkykI7q4RjhIHi+mQEUAZLxZw93a6jE2pNWaO0me5tB8EbEt4/GQ==} cpu: [x64] os: [linux] - lefthook-openbsd-arm64@1.13.6: - resolution: {integrity: sha512-7r153dxrNRQ9ytRs2PmGKKkYdvZYFPre7My7XToSTiRu5jNCq++++eAKVkoyWPduk97dGIA+YWiEr5Noe0TK2A==} + lefthook-openbsd-arm64@2.1.14: + resolution: {integrity: sha512-MCW76gTlEMBF3Ds8O63UTxjaSguha/5zT0U3Vr719I1sXueSpttfRmm/5YfIB4MygB116yA/Vi+DsizT/X0kcg==} cpu: [arm64] os: [openbsd] - lefthook-openbsd-x64@1.13.6: - resolution: {integrity: sha512-Z+UhLlcg1xrXOidK3aLLpgH7KrwNyWYE3yb7ITYnzJSEV8qXnePtVu8lvMBHs/myzemjBzeIr/U/+ipjclR06g==} + lefthook-openbsd-x64@2.1.14: + resolution: {integrity: sha512-salAc1PAhLI6xrB9pth5UxALQlTOGvZAfaAvgFwixhkdu8D//uW8zS3faFq31ktd1bDAy5wDI8p9yg+fF5+2uA==} cpu: [x64] os: [openbsd] - lefthook-windows-arm64@1.13.6: - resolution: {integrity: sha512-Uxef6qoDxCmUNQwk8eBvddYJKSBFglfwAY9Y9+NnnmiHpWTjjYiObE9gT2mvGVpEgZRJVAatBXc+Ha5oDD/OgQ==} + lefthook-windows-arm64@2.1.14: + resolution: {integrity: sha512-q3JC6lBrYLzkhXEhfnmFxJF47gSd5JeDweH3aNrHoLGX/KkRiOrk9RSyoRwSuGq03EYxSkJhl1FLj2GUxF7VqQ==} cpu: [arm64] os: [win32] - lefthook-windows-x64@1.13.6: - resolution: {integrity: sha512-mOZoM3FQh3o08M8PQ/b3IYuL5oo36D9ehczIw1dAgp1Ly+Tr4fJ96A+4SEJrQuYeRD4mex9bR7Ps56I73sBSZA==} + lefthook-windows-x64@2.1.14: + resolution: {integrity: sha512-WwIxdwW1lDAaJUU3ETcKlCtdqluGr3Cy+LjKvP4QIQnFf0FEXL78THstIkZ6k6qhfUn7/WvyqSIf0cbTAKw2nQ==} cpu: [x64] os: [win32] - lefthook@1.13.6: - resolution: {integrity: sha512-ojj4/4IJ29Xn4drd5emqVgilegAPN3Kf0FQM2p/9+lwSTpU+SZ1v4Ig++NF+9MOa99UKY8bElmVrLhnUUNFh5g==} + lefthook@2.1.14: + resolution: {integrity: sha512-Y9TL1dmpRlIdSp73SJ6bb+xAZ4s2SinGTK3pgC9PRWMSjMr2iOfowPGnlSOfAo5fu6S5rdiItsQDxeLEWCGk4g==} hasBin: true libphonenumber-js@1.13.8: resolution: {integrity: sha512-80xal1m93rADejw2pMp2MSzFhHCPLEspjHxnH2UtqI+DgAmElsbmLMiqk9niwH9NWAfjsRtaJI+qBrOEmRx9nQ==} - light-my-request@5.14.0: - resolution: {integrity: sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==} - light-my-request@6.3.0: resolution: {integrity: sha512-bWTAPJmeWQH5suJNYwG0f5cs0p6ho9e6f1Ppoxv5qMosY+s9Ir2+ZLvvHcgA7VTDop4zl/NCHhOVVqU+kd++Ow==} + light-my-request@6.6.0: + resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} + lightningcss-android-arm64@1.32.0: resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + lightningcss-darwin-arm64@1.32.0: resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + lightningcss-darwin-x64@1.32.0: resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + lightningcss-freebsd-x64@1.32.0: resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + lightningcss-linux-arm-gnueabihf@1.32.0: resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + lightningcss-linux-arm64-gnu@1.32.0: resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} engines: {node: '>= 12.0.0'} @@ -2745,6 +2094,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} @@ -2752,6 +2108,13 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} @@ -2759,6 +2122,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} @@ -2766,22 +2136,49 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + lightningcss-win32-x64-msvc@1.32.0: resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + lightningcss@1.32.0: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + load-esm@1.0.3: + resolution: {integrity: sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==} + engines: {node: '>=13.2.0'} + lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} @@ -2803,32 +2200,23 @@ packages: lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magic-string@1.4.1: + resolution: {integrity: sha512-8lyCu36ErXR0J9uaGKlKQoiLZKmtI63YGLE8G2o9jyRPdr4X47LusSOwgOJOzcVtp81fTAAjxR7BwKz682Jhow==} + map-stream@0.1.0: resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} mnemonist@0.38.3: resolution: {integrity: sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==} - mnemonist@0.39.6: - resolution: {integrity: sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.16: - resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + nanoid@3.3.19: + resolution: {integrity: sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -2838,19 +2226,6 @@ packages: node-cleanup@2.1.2: resolution: {integrity: sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==} - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - - node-releases@2.0.51: - resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} - engines: {node: '>=18'} - nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -2860,15 +2235,16 @@ packages: obliterator@1.6.1: resolution: {integrity: sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==} - obliterator@2.0.5: - resolution: {integrity: sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==} + obug@2.2.1: + resolution: {integrity: sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==} + engines: {node: '>=12.20.0'} on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} - oxfmt@0.59.0: - resolution: {integrity: sha512-Xqk6cPZS1yMvVa7OAuenaDZUsgMDutvvbZ9/L5gSvAfW64+WN4HVhgipLj5rVERbYQt8fLs9TopyZ1rU1XEG/w==} + oxfmt@0.68.0: + resolution: {integrity: sha512-Z0XMofcXCGUXbcpBHnWyUiX93BGiw1B+lcHNbQDWEtOhX06ewoFfu4zXkyiLhRrNnMq0twqXRHUcJetf+GsiQQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -2880,12 +2256,12 @@ packages: vite-plus: optional: true - oxlint@1.74.0: - resolution: {integrity: sha512-odGl2s2x5IOJoj3A0v1k0PGBXVFBZeZ2+AK/+K2MJur7Ghi3bkyX5NuLUWHKqa4js1wjep3hJeuTQJOlr+4+dA==} + oxlint@1.83.0: + resolution: {integrity: sha512-cyDzSzaw3uzP0TeCeq3lLRPPoaUxkbB4ZOXj+kn+5r+BX9V+4bNVGk9lxer+WrgcpebH4JxLlJ3KQjveVztOLQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - oxlint-tsgolint: '>=0.24.0' + oxlint-tsgolint: '>=7.0.2001' vite-plus: '*' peerDependenciesMeta: oxlint-tsgolint: @@ -2926,22 +2302,9 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-to-regexp@3.3.0: - resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==} - - path-to-regexp@6.3.0: - resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} - path-to-regexp@8.4.2: resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} - pause-stream@0.0.11: resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} @@ -2951,8 +2314,8 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@4.0.5: - resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} engines: {node: '>=12'} pino-abstract-transport@2.0.0: @@ -2965,32 +2328,28 @@ packages: resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==} hasBin: true - playwright-core@1.61.1: - resolution: {integrity: sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==} - engines: {node: '>=18'} + playwright-core@1.63.0: + resolution: {integrity: sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==} + engines: {node: '>=20'} hasBin: true - playwright@1.61.1: - resolution: {integrity: sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==} - engines: {node: '>=18'} + playwright@1.63.0: + resolution: {integrity: sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==} + engines: {node: '>=20'} hasBin: true - postcss@8.5.19: - resolution: {integrity: sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ==} + postcss@8.5.28: + resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==} engines: {node: ^10 || ^12 || >=14} - process-warning@3.0.0: - resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} - process-warning@4.0.1: resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} process-warning@5.0.0: resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} + process-warning@5.1.0: + resolution: {integrity: sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==} ps-tree@1.2.0: resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} @@ -3000,24 +2359,20 @@ packages: quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} - react-dom@19.2.7: - resolution: {integrity: sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==} + react-dom@19.3.0: + resolution: {integrity: sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==} peerDependencies: - react: ^19.2.7 - - react-refresh@0.17.0: - resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} - engines: {node: '>=0.10.0'} + react: ^19.3.0 - react-router-dom@7.18.1: - resolution: {integrity: sha512-KaZh+X/6UtEp28x51AUYZDMg9NGoz2ja3dNHa+ta/tk40vCzKhQ/RypCWBMLbmDr6//E24Vv5uPsrqXFozdkAg==} + react-router-dom@7.18.4: + resolution: {integrity: sha512-yrfmJHIpDG7taCpqKjT1G5B6q3O2K+RN8/fgNf0lTjCwiPbQ0ei6vXX9ZjQR+7ld8Tr7Z5xmyMnZ8YJrphWQUw==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' react-dom: '>=18' - react-router@7.18.1: - resolution: {integrity: sha512-GDLgg3i3uM0aeJO3Fm+TCS+sDQ7gu12T6x0qdTEzcwqEfleci7JwugVNIF3U//0FWKnJT7ptG+20B2jfDqnZAg==} + react-router@7.18.4: + resolution: {integrity: sha512-PUPQcMhMGRAslLcvtlPz/kmzBEWPhLdgLFrL7pLNepBL6dX0lWj4WD2cUYVgYCuT3jxvghYFg81cDTj44DhetQ==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' @@ -3026,8 +2381,8 @@ packages: react-dom: optional: true - react@19.2.7: - resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} + react@19.3.0: + resolution: {integrity: sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==} engines: {node: '>=0.10.0'} real-require@0.2.0: @@ -3041,11 +2396,11 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - reselect@5.2.0: - resolution: {integrity: sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==} + reselect@5.3.0: + resolution: {integrity: sha512-XGoLeRAVzUTcJ1qkxPQhDJyIZ5d6zzZD9nT7AEZOaaU9UbWclhycElmhO+VD5bFeLuzhPBaOV2oXC8uG35ZSpg==} - ret@0.4.3: - resolution: {integrity: sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==} + ret@0.5.0: + resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} engines: {node: '>=10'} reusify@1.1.0: @@ -3055,9 +2410,9 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rollup@4.62.2: - resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} + rolldown@1.2.9: + resolution: {integrity: sha512-hx/Pv0N1haXRb11qkfnK5MXB/iqr7i0yjWQqmO9uHqZpBgQSqzc8UsSnEpalsh+j1I8qQ2CkXAkJC8Br3dKSlg==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true rxjs@7.8.2: @@ -3066,8 +2421,9 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safe-regex2@3.1.0: - resolution: {integrity: sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==} + safe-regex2@5.1.1: + resolution: {integrity: sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==} + hasBin: true safe-stable-stringify@2.5.0: resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} @@ -3076,15 +2432,11 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - - secure-json-parse@2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + scheduler@0.28.0: + resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==} - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true + secure-json-parse@4.1.0: + resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} semver@7.8.5: resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} @@ -3132,8 +2484,8 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.2.0: + resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} stream-combiner@0.0.4: resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} @@ -3150,14 +2502,11 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - swagger-ui-dist@5.18.2: - resolution: {integrity: sha512-J+y4mCw/zXh1FOj5wGJvnAajq6XgHOyywsa9yITmwxIlJbMqITq3gYRZHaeqLVH/eV/HOPphE6NjF+nbSNC5Zw==} + swagger-ui-dist@5.32.14: + resolution: {integrity: sha512-nOA2pSQhcmODMUQZpJHYKNuwniDUqcOWGNaSCOoZv12FdOSJ9JxV95HtyRGNMqEBj6h6lCNTy20TgZDYTSuUIg==} - tabbable@6.5.0: - resolution: {integrity: sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==} - - tailwindcss@4.3.2: - resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==} + tailwindcss@4.3.3: + resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} tapable@2.3.3: resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} @@ -3169,32 +2518,22 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinybench@6.1.4: + resolution: {integrity: sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==} + engines: {node: '>=20.0.0'} - tinyexec@0.3.2: - resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.3.0: + resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} + engines: {node: '>=18'} tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinypool@2.1.0: - resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} + tinypool@2.1.2: + resolution: {integrity: sha512-9YodfrxS9g9IbFr/KOjE5bAeJ0p61n3bW6mqvy0jtoeKd1kTW1Cxm0oulm6KX2lyM9Gl6WIe8nEbY7LWv5ZJww==} engines: {node: ^20.0.0 || >=22.0.0} - tinyrainbow@1.2.0: - resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} - engines: {node: '>=14.0.0'} - - tinyspy@3.0.2: - resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} - engines: {node: '>=14.0.0'} - toad-cache@3.7.4: resolution: {integrity: sha512-m1TdR/rvT7kgGJZhspNtXdsdYk0fddFpJJFlG5s+UkPFo6lkLoZ3YLOaovPYjq1R75NP5JfeTlSHaOsE09peCg==} engines: {node: '>=20'} @@ -3203,9 +2542,6 @@ packages: resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} engines: {node: '>=14.16'} - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tsc-watch@7.2.1: resolution: {integrity: sha512-FcntBnz5bXGQ/q265acfDzU7xi6R/sgwMokI+Iu293n14Wu8ovAtcwqNfU9vv/DM1THlnmmxatSSyGOvWsSblg==} engines: {node: '>=12.12.0'} @@ -3216,13 +2552,13 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.23.1: - resolution: {integrity: sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==} + tsx@4.23.13: + resolution: {integrity: sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==} engines: {node: '>=18.0.0'} hasBin: true - turbo@2.10.5: - resolution: {integrity: sha512-07Y/C7OUp23l4P92PJoYtFNbHjLhftrZH5Ce7dbczS4kX2Re+wtbXvZLoxn/pUtzgsQaRCBaRuZPJp4zmAn0WQ==} + turbo@2.11.2: + resolution: {integrity: sha512-s0GhnWXlAAN+wb2GRMQxnZgFweRWTAceRWW/4Lk9iHj7QuLZMjDxQQqu+Xoh7Nckuy8UiSim520w6yqP2+ertw==} hasBin: true type-detect@4.0.8: @@ -3233,9 +2569,9 @@ packages: resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} engines: {node: '>=4'} - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} + typescript@7.0.2: + resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} + engines: {node: '>=16.20.0'} hasBin: true uid2@0.0.4: @@ -3249,24 +2585,15 @@ packages: resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} engines: {node: '>=18'} - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@8.9.0: resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==} - undici@7.29.0: - resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} + undici@7.29.1: + resolution: {integrity: sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==} engines: {node: '>=20.18.1'} - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - use-sync-external-store@1.6.0: - resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + use-sync-external-store@1.7.0: + resolution: {integrity: sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -3278,67 +2605,34 @@ packages: resolution: {integrity: sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==} engines: {node: '>= 0.10'} - vite-node@2.1.9: - resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - - vite@5.4.21: - resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - - vite@6.4.3: - resolution: {integrity: sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vite@8.3.0: + resolution: {integrity: sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.7.1 + esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 terser: ^5.16.0 tsx: ^4.8.1 yaml: ^2.4.2 peerDependenciesMeta: '@types/node': optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true jiti: optional: true less: optional: true - lightningcss: - optional: true sass: optional: true sass-embedded: @@ -3354,23 +2648,39 @@ packages: yaml: optional: true - vitest@2.1.9: - resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==} - engines: {node: ^18.0.0 || >=20.0.0} + vitest@5.0.1: + resolution: {integrity: sha512-iA95lQbKEkvrtTkdAgnWbXfbipWiiWe/hDl2P5tMi6WFwD76G0NxXAGp/M9EOcYupeGJRr6wppMc7CoA41TQjg==} + engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 2.1.9 - '@vitest/ui': 2.1.9 + '@opentelemetry/api': ^1.9.0 + '@types/node': ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 5.0.1 + '@vitest/browser-preview': 5.0.1 + '@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0 + '@vitest/coverage-istanbul': 5.0.1 + '@vitest/coverage-v8': 5.0.1 + '@vitest/ui': 5.0.1 happy-dom: '*' jsdom: '*' + vite: ^6.4.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true + '@opentelemetry/api': + optional: true '@types/node': optional: true - '@vitest/browser': + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': optional: true '@vitest/ui': optional: true @@ -3379,9 +2689,6 @@ packages: jsdom: optional: true - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} @@ -3391,9 +2698,6 @@ packages: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -3404,26 +2708,23 @@ packages: engines: {node: '>=8'} hasBin: true - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - snapshots: - '@aws-cdk/asset-awscli-v1@2.2.282': {} + '@aws-cdk/asset-awscli-v1@2.2.292': {} - '@aws-cdk/asset-node-proxy-agent-v6@2.1.2': {} + '@aws-cdk/asset-node-proxy-agent-v6@2.1.3': {} - '@aws-cdk/cloud-assembly-schema@54.11.0': {} + '@aws-cdk/cloud-assembly-schema@54.24.0': {} '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.974.2 + '@aws-sdk/types': 3.974.5 tslib: 2.8.1 '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.974.2 + '@aws-sdk/types': 3.974.5 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -3438,88 +2739,66 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/client-bedrock-runtime@3.1087.0': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/credential-provider-node': 3.972.70 - '@aws-sdk/eventstream-handler-node': 3.972.27 - '@aws-sdk/middleware-eventstream': 3.972.23 - '@aws-sdk/middleware-websocket': 3.972.40 - '@aws-sdk/token-providers': 3.1087.0 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/fetch-http-handler': 5.6.6 - '@smithy/node-http-handler': 4.9.6 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/client-dynamodb@3.1087.0': - dependencies: - '@aws-sdk/core': 3.975.2 - '@aws-sdk/credential-provider-node': 3.972.68 - '@aws-sdk/dynamodb-codec': 3.973.32 - '@aws-sdk/middleware-endpoint-discovery': 3.972.24 - '@aws-sdk/types': 3.974.1 - '@smithy/core': 3.29.3 - '@smithy/fetch-http-handler': 5.6.5 - '@smithy/node-http-handler': 4.9.5 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/client-ses@3.1087.0': + '@aws-sdk/client-bedrock-runtime@3.1136.0': dependencies: - '@aws-sdk/core': 3.975.2 - '@aws-sdk/credential-provider-node': 3.972.68 - '@aws-sdk/types': 3.974.1 - '@smithy/core': 3.29.3 - '@smithy/fetch-http-handler': 5.6.5 - '@smithy/node-http-handler': 4.9.5 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.978.0 + '@aws-sdk/credential-provider-node': 3.972.83 + '@aws-sdk/eventstream-handler-node': 3.972.34 + '@aws-sdk/middleware-eventstream': 3.972.29 + '@aws-sdk/middleware-websocket': 3.972.53 + '@aws-sdk/token-providers': 3.1136.0 + '@aws-sdk/types': 3.974.5 + '@smithy/core': 3.34.1 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/client-ssm@3.1088.0': + '@aws-sdk/client-dynamodb@3.1136.0': dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/credential-provider-node': 3.972.69 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/fetch-http-handler': 5.6.6 - '@smithy/node-http-handler': 4.9.6 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.978.0 + '@aws-sdk/credential-provider-node': 3.972.83 + '@aws-sdk/dynamodb-codec': 3.973.45 + '@aws-sdk/middleware-endpoint-discovery': 3.972.30 + '@aws-sdk/types': 3.974.5 + '@smithy/core': 3.34.1 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/client-sts@3.1089.0': + '@aws-sdk/client-ses@3.1136.0': dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/credential-provider-node': 3.972.70 - '@aws-sdk/signature-v4-multi-region': 3.996.41 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/fetch-http-handler': 5.6.6 - '@smithy/node-http-handler': 4.9.6 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.978.0 + '@aws-sdk/credential-provider-node': 3.972.83 + '@aws-sdk/types': 3.974.5 + '@smithy/core': 3.34.1 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/core@3.975.2': + '@aws-sdk/client-ssm@3.1136.0': dependencies: - '@aws-sdk/types': 3.974.2 - '@aws-sdk/xml-builder': 3.972.35 - '@aws/lambda-invoke-store': 0.3.0 - '@smithy/core': 3.29.4 - '@smithy/signature-v4': 5.6.5 - '@smithy/types': 4.16.1 - bowser: 2.14.1 + '@aws-sdk/core': 3.978.0 + '@aws-sdk/credential-provider-node': 3.972.83 + '@aws-sdk/types': 3.974.5 + '@smithy/core': 3.34.1 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/core@3.975.3': + '@aws-sdk/client-sts@3.1136.0': dependencies: - '@aws-sdk/types': 3.974.2 - '@aws-sdk/xml-builder': 3.972.36 - '@aws/lambda-invoke-store': 0.3.0 - '@smithy/core': 3.29.4 - '@smithy/signature-v4': 5.6.5 - '@smithy/types': 4.16.1 - bowser: 2.14.1 + '@aws-sdk/core': 3.978.0 + '@aws-sdk/credential-provider-node': 3.972.83 + '@aws-sdk/signature-v4-multi-region': 3.996.46 + '@aws-sdk/types': 3.974.5 + '@smithy/core': 3.34.1 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 '@aws-sdk/core@3.978.0': @@ -3533,22 +2812,6 @@ snapshots: bowser: 2.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.58': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-env@3.972.59': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.71': dependencies: '@aws-sdk/core': 3.978.0 @@ -3557,26 +2820,6 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.60': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/fetch-http-handler': 5.6.6 - '@smithy/node-http-handler': 4.9.6 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-http@3.972.61': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/fetch-http-handler': 5.6.6 - '@smithy/node-http-handler': 4.9.6 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.73': dependencies: '@aws-sdk/core': 3.978.0 @@ -3603,81 +2846,6 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.973.2': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/credential-provider-env': 3.972.59 - '@aws-sdk/credential-provider-http': 3.972.61 - '@aws-sdk/credential-provider-login': 3.972.64 - '@aws-sdk/credential-provider-process': 3.972.59 - '@aws-sdk/credential-provider-sso': 3.973.3 - '@aws-sdk/credential-provider-web-identity': 3.972.65 - '@aws-sdk/nested-clients': 3.997.32 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/credential-provider-imds': 4.4.9 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-ini@3.973.3': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/credential-provider-env': 3.972.59 - '@aws-sdk/credential-provider-http': 3.972.61 - '@aws-sdk/credential-provider-login': 3.972.65 - '@aws-sdk/credential-provider-process': 3.972.59 - '@aws-sdk/credential-provider-sso': 3.973.3 - '@aws-sdk/credential-provider-web-identity': 3.972.65 - '@aws-sdk/nested-clients': 3.997.33 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/credential-provider-imds': 4.4.9 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-ini@3.973.4': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/credential-provider-env': 3.972.59 - '@aws-sdk/credential-provider-http': 3.972.61 - '@aws-sdk/credential-provider-login': 3.972.66 - '@aws-sdk/credential-provider-process': 3.972.59 - '@aws-sdk/credential-provider-sso': 3.973.3 - '@aws-sdk/credential-provider-web-identity': 3.972.65 - '@aws-sdk/nested-clients': 3.997.33 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/credential-provider-imds': 4.4.9 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-login@3.972.64': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/nested-clients': 3.997.33 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-login@3.972.65': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/nested-clients': 3.997.33 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-login@3.972.66': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/nested-clients': 3.997.33 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@aws-sdk/credential-provider-login@3.972.78': dependencies: '@aws-sdk/core': 3.978.0 @@ -3687,48 +2855,6 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-node@3.972.68': - dependencies: - '@aws-sdk/credential-provider-env': 3.972.58 - '@aws-sdk/credential-provider-http': 3.972.60 - '@aws-sdk/credential-provider-ini': 3.973.2 - '@aws-sdk/credential-provider-process': 3.972.58 - '@aws-sdk/credential-provider-sso': 3.973.2 - '@aws-sdk/credential-provider-web-identity': 3.972.64 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/credential-provider-imds': 4.4.8 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-node@3.972.69': - dependencies: - '@aws-sdk/credential-provider-env': 3.972.59 - '@aws-sdk/credential-provider-http': 3.972.61 - '@aws-sdk/credential-provider-ini': 3.973.3 - '@aws-sdk/credential-provider-process': 3.972.59 - '@aws-sdk/credential-provider-sso': 3.973.3 - '@aws-sdk/credential-provider-web-identity': 3.972.65 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/credential-provider-imds': 4.4.9 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-node@3.972.70': - dependencies: - '@aws-sdk/credential-provider-env': 3.972.59 - '@aws-sdk/credential-provider-http': 3.972.61 - '@aws-sdk/credential-provider-ini': 3.973.4 - '@aws-sdk/credential-provider-process': 3.972.59 - '@aws-sdk/credential-provider-sso': 3.973.3 - '@aws-sdk/credential-provider-web-identity': 3.972.65 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/credential-provider-imds': 4.4.9 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@aws-sdk/credential-provider-node@3.972.83': dependencies: '@aws-sdk/credential-provider-env': 3.972.71 @@ -3743,22 +2869,6 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-process@3.972.58': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-process@3.972.59': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@aws-sdk/credential-provider-process@3.972.71': dependencies: '@aws-sdk/core': 3.978.0 @@ -3777,44 +2887,6 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.973.2': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/nested-clients': 3.997.32 - '@aws-sdk/token-providers': 3.1087.0 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-sso@3.973.3': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/nested-clients': 3.997.33 - '@aws-sdk/token-providers': 3.1088.0 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-web-identity@3.972.64': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/nested-clients': 3.997.32 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-web-identity@3.972.65': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/nested-clients': 3.997.33 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@aws-sdk/credential-provider-web-identity@3.972.77': dependencies: '@aws-sdk/core': 3.978.0 @@ -3824,79 +2896,57 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/dynamodb-codec@3.973.32': + '@aws-sdk/dynamodb-codec@3.973.45': dependencies: - '@aws-sdk/core': 3.975.3 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.978.0 + '@smithy/core': 3.34.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/endpoint-cache@3.972.9': + '@aws-sdk/endpoint-cache@3.972.11': dependencies: mnemonist: 0.38.3 tslib: 2.8.1 - '@aws-sdk/eventstream-handler-node@3.972.27': - dependencies: - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/lib-dynamodb@3.1087.0(@aws-sdk/client-dynamodb@3.1087.0)': - dependencies: - '@aws-sdk/client-dynamodb': 3.1087.0 - '@aws-sdk/core': 3.975.2 - '@aws-sdk/util-dynamodb': 3.996.6(@aws-sdk/client-dynamodb@3.1087.0) - '@smithy/core': 3.29.3 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/middleware-endpoint-discovery@3.972.24': + '@aws-sdk/eventstream-handler-node@3.972.34': dependencies: - '@aws-sdk/endpoint-cache': 3.972.9 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 + '@aws-sdk/types': 3.974.5 + '@smithy/core': 3.34.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/middleware-eventstream@3.972.23': + '@aws-sdk/lib-dynamodb@3.1136.0(@aws-sdk/client-dynamodb@3.1136.0)': dependencies: - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 + '@aws-sdk/client-dynamodb': 3.1136.0 + '@aws-sdk/core': 3.978.0 + '@aws-sdk/util-dynamodb': 3.996.9(@aws-sdk/client-dynamodb@3.1136.0) + '@smithy/core': 3.34.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/middleware-websocket@3.972.40': + '@aws-sdk/middleware-endpoint-discovery@3.972.30': dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/fetch-http-handler': 5.6.6 - '@smithy/signature-v4': 5.6.5 - '@smithy/types': 4.16.1 + '@aws-sdk/endpoint-cache': 3.972.11 + '@aws-sdk/types': 3.974.5 + '@smithy/core': 3.34.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.997.32': + '@aws-sdk/middleware-eventstream@3.972.29': dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/signature-v4-multi-region': 3.996.41 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/fetch-http-handler': 5.6.6 - '@smithy/node-http-handler': 4.9.6 - '@smithy/types': 4.16.1 + '@aws-sdk/types': 3.974.5 + '@smithy/core': 3.34.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.997.33': + '@aws-sdk/middleware-websocket@3.972.53': dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/signature-v4-multi-region': 3.996.41 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/fetch-http-handler': 5.6.6 - '@smithy/node-http-handler': 4.9.6 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.978.0 + '@aws-sdk/types': 3.974.5 + '@smithy/core': 3.34.1 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/signature-v4': 5.7.3 + '@smithy/types': 4.18.0 tslib: 2.8.1 '@aws-sdk/nested-clients@3.997.45': @@ -3910,13 +2960,6 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.996.41': - dependencies: - '@aws-sdk/types': 3.974.2 - '@smithy/signature-v4': 5.6.5 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.996.46': dependencies: '@aws-sdk/types': 3.974.5 @@ -3924,24 +2967,6 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.1087.0': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/nested-clients': 3.997.33 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/token-providers@3.1088.0': - dependencies: - '@aws-sdk/core': 3.975.3 - '@aws-sdk/nested-clients': 3.997.33 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@aws-sdk/token-providers@3.1129.0': dependencies: '@aws-sdk/core': 3.978.0 @@ -3951,14 +2976,13 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/types@3.974.1': + '@aws-sdk/token-providers@3.1136.0': dependencies: - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/types@3.974.2': - dependencies: - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.978.0 + '@aws-sdk/nested-clients': 3.997.45 + '@aws-sdk/types': 3.974.5 + '@smithy/core': 3.34.1 + '@smithy/types': 4.18.0 tslib: 2.8.1 '@aws-sdk/types@3.974.5': @@ -3966,19 +2990,9 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@aws-sdk/util-dynamodb@3.996.6(@aws-sdk/client-dynamodb@3.1087.0)': + '@aws-sdk/util-dynamodb@3.996.9(@aws-sdk/client-dynamodb@3.1136.0)': dependencies: - '@aws-sdk/client-dynamodb': 3.1087.0 - tslib: 2.8.1 - - '@aws-sdk/xml-builder@3.972.35': - dependencies: - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@aws-sdk/xml-builder@3.972.36': - dependencies: - '@smithy/types': 4.16.1 + '@aws-sdk/client-dynamodb': 3.1136.0 tslib: 2.8.1 '@aws-sdk/xml-builder@3.972.40': @@ -3988,161 +3002,47 @@ snapshots: '@aws/lambda-invoke-store@0.3.0': {} - '@babel/code-frame@7.29.7': - dependencies: - '@babel/helper-validator-identifier': 7.29.7 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/compat-data@7.29.7': {} - - '@babel/core@7.29.7(supports-color@7.2.0)': - 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/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/helpers': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@7.2.0) - '@babel/types': 7.29.7 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@7.2.0) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.29.7': - dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/helper-compilation-targets@7.29.7': - dependencies: - '@babel/compat-data': 7.29.7 - '@babel/helper-validator-option': 7.29.7 - browserslist: 4.28.6 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-globals@7.29.7': {} - - '@babel/helper-module-imports@7.29.7(supports-color@7.2.0)': - dependencies: - '@babel/traverse': 7.29.7(supports-color@7.2.0) - '@babel/types': 7.29.7 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-module-imports': 7.29.7(supports-color@7.2.0) - '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.29.7': {} - - '@babel/helper-string-parser@7.29.7': {} - - '@babel/helper-validator-identifier@7.29.7': {} - - '@babel/helper-validator-option@7.29.7': {} - - '@babel/helpers@7.29.7': - dependencies: - '@babel/template': 7.29.7 - '@babel/types': 7.29.7 - - '@babel/parser@7.29.7': - dependencies: - '@babel/types': 7.29.7 - - '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/runtime@7.29.7': {} - '@babel/template@7.29.7': - dependencies: - '@babel/code-frame': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 - - '@babel/traverse@7.29.7(supports-color@7.2.0)': - 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.4.3(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/types@7.29.7': - dependencies: - '@babel/helper-string-parser': 7.29.7 - '@babel/helper-validator-identifier': 7.29.7 - - '@base-ui-components/react@1.0.0-rc.0(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@base-ui/react@1.8.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: '@babel/runtime': 7.29.7 - '@base-ui-components/utils': 0.2.2(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@floating-ui/react-dom': 2.1.9(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@base-ui/utils': 0.4.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@floating-ui/react-dom': 2.1.9(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@floating-ui/utils': 0.2.12 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - reselect: 5.2.0 - tabbable: 6.5.0 - use-sync-external-store: 1.6.0(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + use-sync-external-store: 1.7.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@base-ui-components/utils@0.2.2(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@base-ui/utils@0.4.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: '@babel/runtime': 7.29.7 '@floating-ui/utils': 0.2.12 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - reselect: 5.2.0 - use-sync-external-store: 1.6.0(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + reselect: 5.3.0 + use-sync-external-store: 1.7.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 '@borewit/text-codec@0.2.2': {} - '@bubltec/mycota-auth@0.6.0(@aws-sdk/client-dynamodb@3.1087.0)(supports-color@7.2.0)': - dependencies: - '@aws-sdk/client-bedrock-runtime': 3.1087.0 - '@aws-sdk/client-ses': 3.1087.0 - '@aws-sdk/lib-dynamodb': 3.1087.0(@aws-sdk/client-dynamodb@3.1087.0) - '@bubltec/mycota-config': 0.6.0 - '@bubltec/mycota-dynamo': 0.6.0(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) - '@bubltec/mycota-mail': 0.6.0 - '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) - '@nestjs/core': 10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/jwt': 10.2.0(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)) - '@nestjs/passport': 10.0.3(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0) + '@bubltec/mycota-auth@1.0.0(@aws-sdk/client-dynamodb@3.1136.0)(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/jwt@12.0.2(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)))(@nestjs/passport@12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0))(class-transformer@0.5.1)(class-validator@0.15.1)(passport@0.7.0)(reflect-metadata@0.2.2)(rxjs@7.8.2)': + dependencies: + '@aws-sdk/client-bedrock-runtime': 3.1136.0 + '@aws-sdk/client-ses': 3.1136.0 + '@aws-sdk/lib-dynamodb': 3.1136.0(@aws-sdk/client-dynamodb@3.1136.0) + '@bubltec/mycota-config': 1.0.0 + '@bubltec/mycota-dynamo': 1.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)) + '@bubltec/mycota-mail': 1.0.0 + '@nestjs/common': 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + '@nestjs/core': 12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/jwt': 12.0.2(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)) + '@nestjs/passport': 12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0) class-transformer: 0.5.1 - class-validator: 0.14.4 + class-validator: 0.15.1 passport: 0.7.0 passport-github2: 0.1.12 passport-google-oauth20: 2.0.0 @@ -4150,392 +3050,166 @@ snapshots: rxjs: 7.8.2 transitivePeerDependencies: - '@aws-sdk/client-dynamodb' - - '@nestjs/microservices' - - '@nestjs/platform-express' - - '@nestjs/websockets' - - encoding - - supports-color - '@bubltec/mycota-cdk@0.6.0(aws-cdk-lib@2.261.0(constructs@10.6.0))(constructs@10.6.0)': + '@bubltec/mycota-cdk@1.0.0(aws-cdk-lib@2.270.0(constructs@10.8.1))(constructs@10.8.1)': dependencies: - '@bubltec/mycota-config': 0.6.0 - aws-cdk-lib: 2.261.0(constructs@10.6.0) - constructs: 10.6.0 + '@bubltec/mycota-config': 1.0.0 + aws-cdk-lib: 2.270.0(constructs@10.8.1) + constructs: 10.8.1 - '@bubltec/mycota-config@0.6.0': + '@bubltec/mycota-config@1.0.0': dependencies: - '@aws-sdk/client-ssm': 3.1088.0 + '@aws-sdk/client-ssm': 3.1136.0 - '@bubltec/mycota-dynamo@0.6.0(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)': + '@bubltec/mycota-dynamo@1.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))': dependencies: - '@aws-sdk/client-dynamodb': 3.1087.0 - '@aws-sdk/lib-dynamodb': 3.1087.0(@aws-sdk/client-dynamodb@3.1087.0) - '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) - transitivePeerDependencies: - - class-transformer - - class-validator - - reflect-metadata - - rxjs - - supports-color + '@aws-sdk/client-dynamodb': 3.1136.0 + '@aws-sdk/lib-dynamodb': 3.1136.0(@aws-sdk/client-dynamodb@3.1136.0) + '@nestjs/common': 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) - '@bubltec/mycota-mail@0.6.0': {} + '@bubltec/mycota-mail@1.0.0': {} - '@bubltec/mycota-professional-verification@0.6.0(@aws-sdk/client-dynamodb@3.1087.0)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)': + '@bubltec/mycota-professional-verification@1.0.0(@aws-sdk/client-dynamodb@3.1136.0)(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/jwt@12.0.2(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)))(@nestjs/passport@12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0))(class-transformer@0.5.1)(class-validator@0.15.1)(passport@0.7.0)(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@bubltec/mycota-auth': 0.6.0(@aws-sdk/client-dynamodb@3.1087.0)(supports-color@7.2.0) - '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + '@bubltec/mycota-auth': 1.0.0(@aws-sdk/client-dynamodb@3.1136.0)(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/jwt@12.0.2(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)))(@nestjs/passport@12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0))(class-transformer@0.5.1)(class-validator@0.15.1)(passport@0.7.0)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) class-transformer: 0.5.1 - class-validator: 0.14.4 + class-validator: 0.15.1 transitivePeerDependencies: - '@aws-sdk/client-dynamodb' - - '@nestjs/microservices' - - '@nestjs/platform-express' - - '@nestjs/websockets' - - encoding - - reflect-metadata - - rxjs - - supports-color - - '@esbuild/aix-ppc64@0.21.5': - optional: true - - '@esbuild/aix-ppc64@0.24.2': - optional: true - - '@esbuild/aix-ppc64@0.25.12': - optional: true - - '@esbuild/aix-ppc64@0.28.1': - optional: true - - '@esbuild/android-arm64@0.21.5': - optional: true - - '@esbuild/android-arm64@0.24.2': - optional: true - - '@esbuild/android-arm64@0.25.12': - optional: true - - '@esbuild/android-arm64@0.28.1': - optional: true - - '@esbuild/android-arm@0.21.5': - optional: true - - '@esbuild/android-arm@0.24.2': - optional: true - - '@esbuild/android-arm@0.25.12': - optional: true - - '@esbuild/android-arm@0.28.1': - optional: true - - '@esbuild/android-x64@0.21.5': - optional: true - - '@esbuild/android-x64@0.24.2': - optional: true - - '@esbuild/android-x64@0.25.12': - optional: true - - '@esbuild/android-x64@0.28.1': - optional: true - - '@esbuild/darwin-arm64@0.21.5': - optional: true - - '@esbuild/darwin-arm64@0.24.2': - optional: true - - '@esbuild/darwin-arm64@0.25.12': - optional: true - - '@esbuild/darwin-arm64@0.28.1': - optional: true - - '@esbuild/darwin-x64@0.21.5': - optional: true - - '@esbuild/darwin-x64@0.24.2': - optional: true - - '@esbuild/darwin-x64@0.25.12': - optional: true - - '@esbuild/darwin-x64@0.28.1': - optional: true - - '@esbuild/freebsd-arm64@0.21.5': - optional: true - - '@esbuild/freebsd-arm64@0.24.2': - optional: true - - '@esbuild/freebsd-arm64@0.25.12': - optional: true - - '@esbuild/freebsd-arm64@0.28.1': - optional: true - - '@esbuild/freebsd-x64@0.21.5': - optional: true - - '@esbuild/freebsd-x64@0.24.2': - optional: true - - '@esbuild/freebsd-x64@0.25.12': - optional: true - - '@esbuild/freebsd-x64@0.28.1': - optional: true - - '@esbuild/linux-arm64@0.21.5': - optional: true - - '@esbuild/linux-arm64@0.24.2': - optional: true - - '@esbuild/linux-arm64@0.25.12': - optional: true - - '@esbuild/linux-arm64@0.28.1': - optional: true - - '@esbuild/linux-arm@0.21.5': - optional: true - - '@esbuild/linux-arm@0.24.2': - optional: true - - '@esbuild/linux-arm@0.25.12': - optional: true - - '@esbuild/linux-arm@0.28.1': - optional: true - - '@esbuild/linux-ia32@0.21.5': - optional: true - - '@esbuild/linux-ia32@0.24.2': - optional: true - - '@esbuild/linux-ia32@0.25.12': - optional: true - - '@esbuild/linux-ia32@0.28.1': - optional: true - - '@esbuild/linux-loong64@0.21.5': - optional: true - - '@esbuild/linux-loong64@0.24.2': - optional: true - - '@esbuild/linux-loong64@0.25.12': - optional: true - - '@esbuild/linux-loong64@0.28.1': - optional: true - - '@esbuild/linux-mips64el@0.21.5': - optional: true - - '@esbuild/linux-mips64el@0.24.2': - optional: true - - '@esbuild/linux-mips64el@0.25.12': - optional: true - - '@esbuild/linux-mips64el@0.28.1': - optional: true - - '@esbuild/linux-ppc64@0.21.5': - optional: true - - '@esbuild/linux-ppc64@0.24.2': - optional: true - - '@esbuild/linux-ppc64@0.25.12': - optional: true - - '@esbuild/linux-ppc64@0.28.1': - optional: true - - '@esbuild/linux-riscv64@0.21.5': - optional: true - - '@esbuild/linux-riscv64@0.24.2': - optional: true - - '@esbuild/linux-riscv64@0.25.12': - optional: true - - '@esbuild/linux-riscv64@0.28.1': - optional: true - - '@esbuild/linux-s390x@0.21.5': - optional: true - - '@esbuild/linux-s390x@0.24.2': - optional: true - - '@esbuild/linux-s390x@0.25.12': - optional: true - - '@esbuild/linux-s390x@0.28.1': - optional: true - - '@esbuild/linux-x64@0.21.5': - optional: true - - '@esbuild/linux-x64@0.24.2': - optional: true - - '@esbuild/linux-x64@0.25.12': - optional: true - - '@esbuild/linux-x64@0.28.1': - optional: true - - '@esbuild/netbsd-arm64@0.24.2': - optional: true - - '@esbuild/netbsd-arm64@0.25.12': - optional: true - - '@esbuild/netbsd-arm64@0.28.1': - optional: true - - '@esbuild/netbsd-x64@0.21.5': - optional: true - - '@esbuild/netbsd-x64@0.24.2': - optional: true - - '@esbuild/netbsd-x64@0.25.12': - optional: true + - '@nestjs/core' + - '@nestjs/jwt' + - '@nestjs/passport' + - passport + - reflect-metadata + - rxjs - '@esbuild/netbsd-x64@0.28.1': + '@esbuild/aix-ppc64@0.28.2': optional: true - '@esbuild/openbsd-arm64@0.24.2': + '@esbuild/android-arm64@0.28.2': optional: true - '@esbuild/openbsd-arm64@0.25.12': + '@esbuild/android-arm@0.28.2': optional: true - '@esbuild/openbsd-arm64@0.28.1': + '@esbuild/android-x64@0.28.2': optional: true - '@esbuild/openbsd-x64@0.21.5': + '@esbuild/darwin-arm64@0.28.2': optional: true - '@esbuild/openbsd-x64@0.24.2': + '@esbuild/darwin-x64@0.28.2': optional: true - '@esbuild/openbsd-x64@0.25.12': + '@esbuild/freebsd-arm64@0.28.2': optional: true - '@esbuild/openbsd-x64@0.28.1': + '@esbuild/freebsd-x64@0.28.2': optional: true - '@esbuild/openharmony-arm64@0.25.12': + '@esbuild/linux-arm64@0.28.2': optional: true - '@esbuild/openharmony-arm64@0.28.1': + '@esbuild/linux-arm@0.28.2': optional: true - '@esbuild/sunos-x64@0.21.5': + '@esbuild/linux-ia32@0.28.2': optional: true - '@esbuild/sunos-x64@0.24.2': + '@esbuild/linux-loong64@0.28.2': optional: true - '@esbuild/sunos-x64@0.25.12': + '@esbuild/linux-mips64el@0.28.2': optional: true - '@esbuild/sunos-x64@0.28.1': + '@esbuild/linux-ppc64@0.28.2': optional: true - '@esbuild/win32-arm64@0.21.5': + '@esbuild/linux-riscv64@0.28.2': optional: true - '@esbuild/win32-arm64@0.24.2': + '@esbuild/linux-s390x@0.28.2': optional: true - '@esbuild/win32-arm64@0.25.12': + '@esbuild/linux-x64@0.28.2': optional: true - '@esbuild/win32-arm64@0.28.1': + '@esbuild/netbsd-arm64@0.28.2': optional: true - '@esbuild/win32-ia32@0.21.5': + '@esbuild/netbsd-x64@0.28.2': optional: true - '@esbuild/win32-ia32@0.24.2': + '@esbuild/openbsd-arm64@0.28.2': optional: true - '@esbuild/win32-ia32@0.25.12': + '@esbuild/openbsd-x64@0.28.2': optional: true - '@esbuild/win32-ia32@0.28.1': + '@esbuild/openharmony-arm64@0.28.2': optional: true - '@esbuild/win32-x64@0.21.5': + '@esbuild/sunos-x64@0.28.2': optional: true - '@esbuild/win32-x64@0.24.2': + '@esbuild/win32-arm64@0.28.2': optional: true - '@esbuild/win32-x64@0.25.12': + '@esbuild/win32-ia32@0.28.2': optional: true - '@esbuild/win32-x64@0.28.1': + '@esbuild/win32-x64@0.28.2': optional: true - '@fastify/ajv-compiler@3.6.0': + '@fastify/ajv-compiler@4.0.6': dependencies: ajv: 8.20.0 - ajv-formats: 2.1.1(ajv@8.20.0) - fast-uri: 2.4.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 4.2.1 - '@fastify/aws-lambda@4.1.0': {} + '@fastify/aws-lambda@6.4.1': {} - '@fastify/cookie@9.4.0': + '@fastify/cookie@11.1.2': dependencies: - cookie-signature: 1.2.2 - fastify-plugin: 4.5.1 + cookie: 2.0.1 + fastify-plugin: 6.0.0 - '@fastify/cors@9.0.1': + '@fastify/cors@11.3.0': dependencies: - fastify-plugin: 4.5.1 - mnemonist: 0.39.6 + fastify-plugin: 6.0.0 + toad-cache: 3.7.4 - '@fastify/error@3.4.1': {} + '@fastify/error@4.2.0': {} - '@fastify/fast-json-stringify-compiler@4.3.0': + '@fastify/fast-json-stringify-compiler@5.1.0': dependencies: - fast-json-stringify: 5.16.1 + fast-json-stringify: 7.0.1 - '@fastify/formbody@7.4.0': + '@fastify/formbody@9.0.0': dependencies: fast-querystring: 1.1.2 - fastify-plugin: 4.5.1 + fastify-plugin: 6.0.0 - '@fastify/merge-json-schemas@0.1.1': + '@fastify/forwarded@3.0.2': {} + + '@fastify/merge-json-schemas@0.2.1': dependencies: - fast-deep-equal: 3.1.3 + dequal: 2.0.3 - '@fastify/middie@8.3.3': + '@fastify/middie@9.3.4': dependencies: - '@fastify/error': 3.4.1 - fastify-plugin: 4.5.1 - path-to-regexp: 6.3.0 + '@fastify/error': 4.2.0 + fastify-plugin: 6.0.0 + find-my-way: 9.9.0 + path-to-regexp: 8.4.2 reusify: 1.1.0 + '@fastify/proxy-addr@5.1.1': + dependencies: + '@fastify/forwarded': 3.0.2 + ipaddr.js: 2.5.0 + '@floating-ui/core@1.8.0': dependencies: '@floating-ui/utils': 0.2.12 @@ -4545,17 +3219,17 @@ snapshots: '@floating-ui/core': 1.8.0 '@floating-ui/utils': 0.2.12 - '@floating-ui/react-dom@2.1.9(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@floating-ui/react-dom@2.1.9(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: '@floating-ui/dom': 1.8.0 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) '@floating-ui/utils@0.2.12': {} '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/remapping@2.3.5': @@ -4565,303 +3239,270 @@ snapshots: '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/sourcemap-codec@1.6.0': {} '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 '@lukeed/csprng@1.1.0': {} - '@microsoft/tsdoc@0.15.1': {} + '@microsoft/tsdoc@0.16.0': {} - '@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)': + '@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)': dependencies: - file-type: 20.4.1(supports-color@7.2.0) + '@standard-schema/spec': 1.1.0 + file-type: 22.1.0(supports-color@7.2.0) iterare: 1.2.1 + load-esm: 1.0.3 reflect-metadata: 0.2.2 rxjs: 7.8.2 tslib: 2.8.1 uid: 2.0.2 optionalDependencies: class-transformer: 0.5.1 - class-validator: 0.14.4 + class-validator: 0.15.1 transitivePeerDependencies: - supports-color - '@nestjs/config@3.3.0(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(rxjs@7.8.2)': + '@nestjs/config@12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(rxjs@7.8.2)': dependencies: - '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) - dotenv: 16.4.5 - dotenv-expand: 10.0.0 - lodash: 4.17.21 + '@nestjs/common': 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + '@standard-schema/spec': 1.1.0 + dotenv: 17.4.2 + dotenv-expand: 13.0.0 + es-toolkit: 1.51.0 rxjs: 7.8.2 - '@nestjs/core@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/core@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) - '@nuxtjs/opencollective': 0.3.2 + '@nestjs/common': 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) fast-safe-stringify: 2.1.1 iterare: 1.2.1 - path-to-regexp: 3.3.0 + path-to-regexp: 8.4.2 reflect-metadata: 0.2.2 rxjs: 7.8.2 tslib: 2.8.1 uid: 2.0.2 - transitivePeerDependencies: - - encoding - '@nestjs/jwt@10.2.0(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))': + '@nestjs/jwt@12.0.2(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))': dependencies: - '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) - '@types/jsonwebtoken': 9.0.5 - jsonwebtoken: 9.0.2 + '@nestjs/common': 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + '@types/jsonwebtoken': 9.0.10 + jsonwebtoken: 9.0.3 - '@nestjs/mapped-types@2.0.6(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)': + '@nestjs/mapped-types@12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)': dependencies: - '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + '@nestjs/common': 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) reflect-metadata: 0.2.2 optionalDependencies: class-transformer: 0.5.1 - class-validator: 0.14.4 + class-validator: 0.15.1 - '@nestjs/passport@10.0.3(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0)': + '@nestjs/passport@12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(passport@0.7.0)': dependencies: - '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + '@nestjs/common': 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) passport: 0.7.0 - '@nestjs/platform-fastify@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))': + '@nestjs/platform-fastify@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))': dependencies: - '@fastify/cors': 9.0.1 - '@fastify/formbody': 7.4.0 - '@fastify/middie': 8.3.3 - '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) - '@nestjs/core': 10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2) - fastify: 4.28.1 - light-my-request: 6.3.0 - path-to-regexp: 3.3.0 + '@fastify/cors': 11.3.0 + '@fastify/formbody': 9.0.0 + '@fastify/middie': 9.3.4 + '@nestjs/common': 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + '@nestjs/core': 12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2) + fast-querystring: 1.1.2 + fastify: 5.12.5 + find-my-way: 9.9.0 + light-my-request: 6.6.0 + path-to-regexp: 8.4.2 tslib: 2.8.1 - '@nestjs/swagger@8.1.1(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)': + '@nestjs/swagger@12.0.1(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)': dependencies: - '@microsoft/tsdoc': 0.15.1 - '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) - '@nestjs/core': 10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/mapped-types': 2.0.6(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2) - js-yaml: 4.1.0 - lodash: 4.17.21 - path-to-regexp: 3.3.0 + '@microsoft/tsdoc': 0.16.0 + '@nestjs/common': 12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) + '@nestjs/core': 12.0.3(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/mapped-types': 12.0.0(@nestjs/common@12.0.3(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2) + '@standard-schema/spec': 1.1.0 + es-toolkit: 1.51.0 + js-yaml: 5.4.1 + path-to-regexp: 8.4.2 reflect-metadata: 0.2.2 - swagger-ui-dist: 5.18.2 + swagger-ui-dist: 5.32.14 optionalDependencies: class-transformer: 0.5.1 - class-validator: 0.14.4 + class-validator: 0.15.1 - '@nuxtjs/opencollective@0.3.2': - dependencies: - chalk: 4.1.2 - consola: 2.15.3 - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding + '@oxc-project/types@0.150.0': {} - '@oxfmt/binding-android-arm-eabi@0.59.0': + '@oxfmt/binding-android-arm-eabi@0.68.0': optional: true - '@oxfmt/binding-android-arm64@0.59.0': + '@oxfmt/binding-android-arm64@0.68.0': optional: true - '@oxfmt/binding-darwin-arm64@0.59.0': + '@oxfmt/binding-darwin-arm64@0.68.0': optional: true - '@oxfmt/binding-darwin-x64@0.59.0': + '@oxfmt/binding-darwin-x64@0.68.0': optional: true - '@oxfmt/binding-freebsd-x64@0.59.0': + '@oxfmt/binding-freebsd-x64@0.68.0': optional: true - '@oxfmt/binding-linux-arm-gnueabihf@0.59.0': + '@oxfmt/binding-linux-arm-gnueabihf@0.68.0': optional: true - '@oxfmt/binding-linux-arm-musleabihf@0.59.0': + '@oxfmt/binding-linux-arm-musleabihf@0.68.0': optional: true - '@oxfmt/binding-linux-arm64-gnu@0.59.0': + '@oxfmt/binding-linux-arm64-gnu@0.68.0': optional: true - '@oxfmt/binding-linux-arm64-musl@0.59.0': + '@oxfmt/binding-linux-arm64-musl@0.68.0': optional: true - '@oxfmt/binding-linux-ppc64-gnu@0.59.0': + '@oxfmt/binding-linux-ppc64-gnu@0.68.0': optional: true - '@oxfmt/binding-linux-riscv64-gnu@0.59.0': + '@oxfmt/binding-linux-riscv64-gnu@0.68.0': optional: true - '@oxfmt/binding-linux-riscv64-musl@0.59.0': + '@oxfmt/binding-linux-riscv64-musl@0.68.0': optional: true - '@oxfmt/binding-linux-s390x-gnu@0.59.0': + '@oxfmt/binding-linux-s390x-gnu@0.68.0': optional: true - '@oxfmt/binding-linux-x64-gnu@0.59.0': + '@oxfmt/binding-linux-x64-gnu@0.68.0': optional: true - '@oxfmt/binding-linux-x64-musl@0.59.0': + '@oxfmt/binding-linux-x64-musl@0.68.0': optional: true - '@oxfmt/binding-openharmony-arm64@0.59.0': + '@oxfmt/binding-openharmony-arm64@0.68.0': optional: true - '@oxfmt/binding-win32-arm64-msvc@0.59.0': + '@oxfmt/binding-win32-arm64-msvc@0.68.0': optional: true - '@oxfmt/binding-win32-ia32-msvc@0.59.0': + '@oxfmt/binding-win32-ia32-msvc@0.68.0': optional: true - '@oxfmt/binding-win32-x64-msvc@0.59.0': + '@oxfmt/binding-win32-x64-msvc@0.68.0': optional: true - '@oxlint/binding-android-arm-eabi@1.74.0': + '@oxlint/binding-android-arm-eabi@1.83.0': optional: true - '@oxlint/binding-android-arm64@1.74.0': + '@oxlint/binding-android-arm64@1.83.0': optional: true - '@oxlint/binding-darwin-arm64@1.74.0': + '@oxlint/binding-darwin-arm64@1.83.0': optional: true - '@oxlint/binding-darwin-x64@1.74.0': + '@oxlint/binding-darwin-x64@1.83.0': optional: true - '@oxlint/binding-freebsd-x64@1.74.0': + '@oxlint/binding-freebsd-x64@1.83.0': optional: true - '@oxlint/binding-linux-arm-gnueabihf@1.74.0': + '@oxlint/binding-linux-arm-gnueabihf@1.83.0': optional: true - '@oxlint/binding-linux-arm-musleabihf@1.74.0': + '@oxlint/binding-linux-arm-musleabihf@1.83.0': optional: true - '@oxlint/binding-linux-arm64-gnu@1.74.0': + '@oxlint/binding-linux-arm64-gnu@1.83.0': optional: true - '@oxlint/binding-linux-arm64-musl@1.74.0': + '@oxlint/binding-linux-arm64-musl@1.83.0': optional: true - '@oxlint/binding-linux-ppc64-gnu@1.74.0': + '@oxlint/binding-linux-ppc64-gnu@1.83.0': optional: true - '@oxlint/binding-linux-riscv64-gnu@1.74.0': + '@oxlint/binding-linux-riscv64-gnu@1.83.0': optional: true - '@oxlint/binding-linux-riscv64-musl@1.74.0': + '@oxlint/binding-linux-riscv64-musl@1.83.0': optional: true - '@oxlint/binding-linux-s390x-gnu@1.74.0': + '@oxlint/binding-linux-s390x-gnu@1.83.0': optional: true - '@oxlint/binding-linux-x64-gnu@1.74.0': + '@oxlint/binding-linux-x64-gnu@1.83.0': optional: true - '@oxlint/binding-linux-x64-musl@1.74.0': + '@oxlint/binding-linux-x64-musl@1.83.0': optional: true - '@oxlint/binding-openharmony-arm64@1.74.0': + '@oxlint/binding-openharmony-arm64@1.83.0': optional: true - '@oxlint/binding-win32-arm64-msvc@1.74.0': + '@oxlint/binding-win32-arm64-msvc@1.83.0': optional: true - '@oxlint/binding-win32-ia32-msvc@1.74.0': + '@oxlint/binding-win32-ia32-msvc@1.83.0': optional: true - '@oxlint/binding-win32-x64-msvc@1.74.0': + '@oxlint/binding-win32-x64-msvc@1.83.0': optional: true '@pinojs/redact@0.4.0': {} - '@playwright/test@1.61.1': + '@playwright/test@1.63.0': dependencies: - playwright: 1.61.1 - - '@rolldown/pluginutils@1.0.0-beta.27': {} - - '@rollup/rollup-android-arm-eabi@4.62.2': - optional: true - - '@rollup/rollup-android-arm64@4.62.2': - optional: true - - '@rollup/rollup-darwin-arm64@4.62.2': - optional: true - - '@rollup/rollup-darwin-x64@4.62.2': - optional: true - - '@rollup/rollup-freebsd-arm64@4.62.2': - optional: true - - '@rollup/rollup-freebsd-x64@4.62.2': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.62.2': - optional: true + playwright: 1.63.0 - '@rollup/rollup-linux-arm-musleabihf@4.62.2': + '@rolldown/binding-android-arm-eabi@1.2.9': optional: true - '@rollup/rollup-linux-arm64-gnu@4.62.2': + '@rolldown/binding-android-arm64@1.2.9': optional: true - '@rollup/rollup-linux-arm64-musl@4.62.2': + '@rolldown/binding-darwin-arm64@1.2.9': optional: true - '@rollup/rollup-linux-loong64-gnu@4.62.2': + '@rolldown/binding-darwin-x64@1.2.9': optional: true - '@rollup/rollup-linux-loong64-musl@4.62.2': + '@rolldown/binding-freebsd-x64@1.2.9': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.62.2': + '@rolldown/binding-linux-arm-gnueabihf@1.2.9': optional: true - '@rollup/rollup-linux-ppc64-musl@4.62.2': + '@rolldown/binding-linux-arm64-gnu@1.2.9': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.62.2': + '@rolldown/binding-linux-arm64-musl@1.2.9': optional: true - '@rollup/rollup-linux-riscv64-musl@4.62.2': + '@rolldown/binding-linux-ppc64-gnu@1.2.9': optional: true - '@rollup/rollup-linux-s390x-gnu@4.62.2': + '@rolldown/binding-linux-s390x-gnu@1.2.9': optional: true - '@rollup/rollup-linux-x64-gnu@4.62.2': + '@rolldown/binding-linux-x64-gnu@1.2.9': optional: true - '@rollup/rollup-linux-x64-musl@4.62.2': + '@rolldown/binding-linux-x64-musl@1.2.9': optional: true - '@rollup/rollup-openbsd-x64@4.62.2': + '@rolldown/binding-openharmony-arm64@1.2.9': optional: true - '@rollup/rollup-openharmony-arm64@4.62.2': + '@rolldown/binding-win32-arm64-msvc@1.2.9': optional: true - '@rollup/rollup-win32-arm64-msvc@4.62.2': + '@rolldown/binding-win32-x64-msvc@1.2.9': optional: true - '@rollup/rollup-win32-ia32-msvc@4.62.2': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.62.2': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.62.2': - optional: true + '@rolldown/pluginutils@1.0.1': {} '@scarf/scarf@1.4.0': {} @@ -4882,51 +3523,17 @@ snapshots: '@sinonjs/commons': 3.0.1 type-detect: 4.1.0 - '@smithy/core@3.29.3': - dependencies: - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@smithy/core@3.29.4': - dependencies: - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@smithy/core@3.34.1': dependencies: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.4.8': - dependencies: - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@smithy/credential-provider-imds@4.4.9': - dependencies: - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@smithy/credential-provider-imds@4.5.2': dependencies: '@smithy/core': 3.34.1 '@smithy/types': 4.18.0 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.6.5': - dependencies: - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@smithy/fetch-http-handler@5.6.6': - dependencies: - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@smithy/fetch-http-handler@5.8.0': dependencies: '@smithy/core': 3.34.1 @@ -4943,39 +3550,17 @@ snapshots: '@smithy/types': 4.18.0 tslib: 2.8.1 - '@smithy/node-http-handler@4.9.5': - dependencies: - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - - '@smithy/node-http-handler@4.9.6': - dependencies: - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@smithy/protocol-http@5.6.2': dependencies: '@smithy/core': 3.34.1 tslib: 2.8.1 - '@smithy/signature-v4@5.6.5': - dependencies: - '@smithy/core': 3.29.4 - '@smithy/types': 4.16.1 - tslib: 2.8.1 - '@smithy/signature-v4@5.7.3': dependencies: '@smithy/core': 3.34.1 '@smithy/types': 4.18.0 tslib: 2.8.1 - '@smithy/types@4.16.1': - dependencies: - tslib: 2.8.1 - '@smithy/types@4.18.0': dependencies: tslib: 2.8.1 @@ -4990,137 +3575,124 @@ snapshots: '@smithy/util-buffer-from': 2.2.0 tslib: 2.8.1 - '@tailwindcss/node@4.3.2': + '@standard-schema/spec@1.1.0': {} + + '@tailwindcss/node@4.3.3': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.21.6 + enhanced-resolve: 5.25.1 jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.3.2 + tailwindcss: 4.3.3 - '@tailwindcss/oxide-android-arm64@4.3.2': + '@tailwindcss/oxide-android-arm64@4.3.3': optional: true - '@tailwindcss/oxide-darwin-arm64@4.3.2': + '@tailwindcss/oxide-darwin-arm64@4.3.3': optional: true - '@tailwindcss/oxide-darwin-x64@4.3.2': + '@tailwindcss/oxide-darwin-x64@4.3.3': optional: true - '@tailwindcss/oxide-freebsd-x64@4.3.2': + '@tailwindcss/oxide-freebsd-x64@4.3.3': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.3.2': + '@tailwindcss/oxide-linux-x64-musl@4.3.3': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.3.2': + '@tailwindcss/oxide-wasm32-wasi@4.3.3': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': optional: true - '@tailwindcss/oxide@4.3.2': + '@tailwindcss/oxide@4.3.3': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.3.2 - '@tailwindcss/oxide-darwin-arm64': 4.3.2 - '@tailwindcss/oxide-darwin-x64': 4.3.2 - '@tailwindcss/oxide-freebsd-x64': 4.3.2 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.2 - '@tailwindcss/oxide-linux-arm64-gnu': 4.3.2 - '@tailwindcss/oxide-linux-arm64-musl': 4.3.2 - '@tailwindcss/oxide-linux-x64-gnu': 4.3.2 - '@tailwindcss/oxide-linux-x64-musl': 4.3.2 - '@tailwindcss/oxide-wasm32-wasi': 4.3.2 - '@tailwindcss/oxide-win32-arm64-msvc': 4.3.2 - '@tailwindcss/oxide-win32-x64-msvc': 4.3.2 - - '@tailwindcss/vite@4.3.2(vite@6.4.3(@types/node@26.6.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1))': - dependencies: - '@tailwindcss/node': 4.3.2 - '@tailwindcss/oxide': 4.3.2 - tailwindcss: 4.3.2 - vite: 6.4.3(@types/node@26.6.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1) - - '@tokenizer/inflate@0.2.7(supports-color@7.2.0)': + '@tailwindcss/oxide-android-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-x64': 4.3.3 + '@tailwindcss/oxide-freebsd-x64': 4.3.3 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-x64-musl': 4.3.3 + '@tailwindcss/oxide-wasm32-wasi': 4.3.3 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 + + '@tailwindcss/vite@4.3.3(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13))': + dependencies: + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + tailwindcss: 4.3.3 + vite: 8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13) + + '@tokenizer/inflate@0.4.1(supports-color@7.2.0)': dependencies: debug: 4.4.3(supports-color@7.2.0) - fflate: 0.8.3 token-types: 6.1.2 transitivePeerDependencies: - supports-color '@tokenizer/token@0.3.0': {} - '@turbo/darwin-64@2.10.5': + '@turbo/darwin-64@2.11.2': optional: true - '@turbo/darwin-arm64@2.10.5': + '@turbo/darwin-arm64@2.11.2': optional: true - '@turbo/linux-64@2.10.5': + '@turbo/linux-64@2.11.2': optional: true - '@turbo/linux-arm64@2.10.5': + '@turbo/linux-arm64@2.11.2': optional: true - '@turbo/windows-64@2.10.5': + '@turbo/windows-64@2.11.2': optional: true - '@turbo/windows-arm64@2.10.5': + '@turbo/windows-arm64@2.11.2': optional: true - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 - '@types/babel__generator': 7.27.0 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.28.0 - - '@types/babel__generator@7.27.0': - dependencies: - '@babel/types': 7.29.7 - - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 - - '@types/babel__traverse@7.28.0': - dependencies: - '@babel/types': 7.29.7 - '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.20.2 + '@types/node': 26.6.2 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 '@types/connect@3.4.38': dependencies: - '@types/node': 22.20.2 + '@types/node': 26.6.2 + + '@types/deep-eql@4.0.2': {} '@types/estree@1.0.9': {} - '@types/express-serve-static-core@5.1.2': + '@types/express-serve-static-core@5.1.3': dependencies: - '@types/node': 22.20.2 + '@types/node': 26.6.2 '@types/qs': 6.15.1 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -5128,26 +3700,25 @@ snapshots: '@types/express@5.0.6': dependencies: '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 5.1.2 + '@types/express-serve-static-core': 5.1.3 '@types/serve-static': 2.2.0 '@types/http-errors@2.0.5': {} - '@types/jsonwebtoken@9.0.5': + '@types/jsonwebtoken@9.0.10': dependencies: - '@types/node': 22.20.2 + '@types/ms': 2.1.0 + '@types/node': 26.6.2 - '@types/node@22.20.2': - dependencies: - undici-types: 6.21.0 + '@types/ms@2.1.0': {} - '@types/node@26.6.1': + '@types/node@26.6.2': dependencies: undici-types: 8.9.0 '@types/oauth@0.9.6': dependencies: - '@types/node': 22.20.2 + '@types/node': 26.6.2 '@types/passport-github2@1.2.9': dependencies: @@ -5175,22 +3746,22 @@ snapshots: '@types/range-parser@1.2.7': {} - '@types/react-dom@19.2.3(@types/react@19.2.17)': + '@types/react-dom@19.3.0(@types/react@19.3.0)': dependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@types/react@19.2.17': + '@types/react@19.3.0': dependencies: csstype: 3.2.3 '@types/send@1.2.1': dependencies: - '@types/node': 22.20.2 + '@types/node': 26.6.2 '@types/serve-static@2.2.0': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.20.2 + '@types/node': 26.6.2 '@types/sinon@17.0.4': dependencies: @@ -5200,63 +3771,83 @@ snapshots: '@types/validator@13.15.10': {} - '@vitejs/plugin-react@4.7.0(supports-color@7.2.0)(vite@6.4.3(@types/node@26.6.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@rolldown/pluginutils': 1.0.0-beta.27 - '@types/babel__core': 7.20.5 - react-refresh: 0.17.0 - vite: 6.4.3(@types/node@26.6.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1) - transitivePeerDependencies: - - supports-color + '@typescript/typescript-aix-ppc64@7.0.2': + optional: true - '@vitest/expect@2.1.9': - dependencies: - '@vitest/spy': 2.1.9 - '@vitest/utils': 2.1.9 - chai: 5.3.3 - tinyrainbow: 1.2.0 + '@typescript/typescript-darwin-arm64@7.0.2': + optional: true - '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@26.6.1)(lightningcss@1.32.0))': - dependencies: - '@vitest/spy': 2.1.9 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 5.4.21(@types/node@26.6.1)(lightningcss@1.32.0) + '@typescript/typescript-darwin-x64@7.0.2': + optional: true - '@vitest/pretty-format@2.1.9': - dependencies: - tinyrainbow: 1.2.0 + '@typescript/typescript-freebsd-arm64@7.0.2': + optional: true - '@vitest/runner@2.1.9': - dependencies: - '@vitest/utils': 2.1.9 - pathe: 1.1.2 + '@typescript/typescript-freebsd-x64@7.0.2': + optional: true - '@vitest/snapshot@2.1.9': - dependencies: - '@vitest/pretty-format': 2.1.9 - magic-string: 0.30.21 - pathe: 1.1.2 + '@typescript/typescript-linux-arm64@7.0.2': + optional: true + + '@typescript/typescript-linux-arm@7.0.2': + optional: true + + '@typescript/typescript-linux-loong64@7.0.2': + optional: true + + '@typescript/typescript-linux-mips64el@7.0.2': + optional: true + + '@typescript/typescript-linux-ppc64@7.0.2': + optional: true + + '@typescript/typescript-linux-riscv64@7.0.2': + optional: true + + '@typescript/typescript-linux-s390x@7.0.2': + optional: true + + '@typescript/typescript-linux-x64@7.0.2': + optional: true + + '@typescript/typescript-netbsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-netbsd-x64@7.0.2': + optional: true + + '@typescript/typescript-openbsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-openbsd-x64@7.0.2': + optional: true + + '@typescript/typescript-sunos-x64@7.0.2': + optional: true + + '@typescript/typescript-win32-arm64@7.0.2': + optional: true + + '@typescript/typescript-win32-x64@7.0.2': + optional: true - '@vitest/spy@2.1.9': + '@vitejs/plugin-react@6.1.1(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13))': dependencies: - tinyspy: 3.0.2 + '@rolldown/pluginutils': 1.0.1 + vite: 8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13) - '@vitest/utils@2.1.9': + '@vitest/mocker@5.0.1(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13))': dependencies: - '@vitest/pretty-format': 2.1.9 - loupe: 3.2.1 - tinyrainbow: 1.2.0 + '@jridgewell/trace-mapping': 0.3.31 + '@vitest/spy': 5.0.1 + estree-walker: 3.0.3 + magic-string: 1.4.1 + optionalDependencies: + vite: 8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13) - abstract-logging@2.0.1: {} + '@vitest/spy@5.0.1': {} - ajv-formats@2.1.1(ajv@8.20.0): - optionalDependencies: - ajv: 8.20.0 + abstract-logging@2.0.1: {} ajv-formats@3.0.1(ajv@8.20.0): optionalDependencies: @@ -5269,29 +3860,25 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - argparse@2.0.1: {} assertion-error@2.0.1: {} atomic-sleep@1.0.0: {} - avvio@8.4.0: + avvio@9.3.0: dependencies: - '@fastify/error': 3.4.1 + '@fastify/error': 4.2.0 fastq: 1.20.1 - aws-cdk-lib@2.261.0(constructs@10.6.0): + aws-cdk-lib@2.270.0(constructs@10.8.1): dependencies: - '@aws-cdk/asset-awscli-v1': 2.2.282 - '@aws-cdk/asset-node-proxy-agent-v6': 2.1.2 - '@aws-cdk/cloud-assembly-schema': 54.11.0 - constructs: 10.6.0 + '@aws-cdk/asset-awscli-v1': 2.2.292 + '@aws-cdk/asset-node-proxy-agent-v6': 2.1.3 + '@aws-cdk/cloud-assembly-schema': 54.24.0 + constructs: 10.8.1 - aws-cdk@2.1131.0: {} + aws-cdk@2.1142.0: {} aws-sdk-client-mock@4.1.0: dependencies: @@ -5301,42 +3888,15 @@ snapshots: base64url@3.0.1: {} - baseline-browser-mapping@2.10.43: {} - boolbase@1.0.0: {} bowser@2.14.1: {} - browserslist@4.28.6: - dependencies: - baseline-browser-mapping: 2.10.43 - caniuse-lite: 1.0.30001805 - electron-to-chromium: 1.5.389 - node-releases: 2.0.51 - update-browserslist-db: 1.2.3(browserslist@4.28.6) - buffer-equal-constant-time@1.0.1: {} buffer-from@1.1.2: {} - cac@6.7.14: {} - - caniuse-lite@1.0.30001805: {} - - chai@5.3.3: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.3 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - check-error@2.1.3: {} + chai@6.2.2: {} cheerio-select@2.1.0: dependencies: @@ -5358,35 +3918,23 @@ snapshots: parse5: 7.3.0 parse5-htmlparser2-tree-adapter: 7.1.0 parse5-parser-stream: 7.1.2 - undici: 7.29.0 + undici: 7.29.1 whatwg-mimetype: 4.0.0 class-transformer@0.5.1: {} - class-validator@0.14.4: + class-validator@0.15.1: dependencies: '@types/validator': 13.15.10 libphonenumber-js: 1.13.8 validator: 13.15.35 - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - consola@2.15.3: {} - - constructs@10.6.0: {} - - convert-source-map@2.0.0: {} - - cookie-signature@1.2.2: {} - - cookie@0.7.2: {} + constructs@10.8.1: {} cookie@1.1.1: {} + cookie@2.0.1: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -5411,7 +3959,7 @@ snapshots: optionalDependencies: supports-color: 7.2.0 - deep-eql@5.0.2: {} + dequal@2.0.3: {} detect-libc@2.1.2: {} @@ -5435,9 +3983,11 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 - dotenv-expand@10.0.0: {} + dotenv-expand@13.0.0: + dependencies: + dotenv: 17.4.2 - dotenv@16.4.5: {} + dotenv@17.4.2: {} duplexer@0.1.2: {} @@ -5445,14 +3995,12 @@ snapshots: dependencies: safe-buffer: 5.2.1 - electron-to-chromium@1.5.389: {} - encoding-sniffer@0.2.1: dependencies: iconv-lite: 0.6.3 whatwg-encoding: 3.1.1 - enhanced-resolve@5.21.6: + enhanced-resolve@5.25.1: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -5463,121 +4011,38 @@ snapshots: entities@7.0.1: {} - es-module-lexer@1.7.0: {} + es-module-lexer@2.3.2: {} - esbuild@0.21.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - - esbuild@0.24.2: - optionalDependencies: - '@esbuild/aix-ppc64': 0.24.2 - '@esbuild/android-arm': 0.24.2 - '@esbuild/android-arm64': 0.24.2 - '@esbuild/android-x64': 0.24.2 - '@esbuild/darwin-arm64': 0.24.2 - '@esbuild/darwin-x64': 0.24.2 - '@esbuild/freebsd-arm64': 0.24.2 - '@esbuild/freebsd-x64': 0.24.2 - '@esbuild/linux-arm': 0.24.2 - '@esbuild/linux-arm64': 0.24.2 - '@esbuild/linux-ia32': 0.24.2 - '@esbuild/linux-loong64': 0.24.2 - '@esbuild/linux-mips64el': 0.24.2 - '@esbuild/linux-ppc64': 0.24.2 - '@esbuild/linux-riscv64': 0.24.2 - '@esbuild/linux-s390x': 0.24.2 - '@esbuild/linux-x64': 0.24.2 - '@esbuild/netbsd-arm64': 0.24.2 - '@esbuild/netbsd-x64': 0.24.2 - '@esbuild/openbsd-arm64': 0.24.2 - '@esbuild/openbsd-x64': 0.24.2 - '@esbuild/sunos-x64': 0.24.2 - '@esbuild/win32-arm64': 0.24.2 - '@esbuild/win32-ia32': 0.24.2 - '@esbuild/win32-x64': 0.24.2 - - esbuild@0.25.12: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 - - esbuild@0.28.1: + es-toolkit@1.51.0: {} + + esbuild@0.28.2: 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 - - escalade@3.2.0: {} + '@esbuild/aix-ppc64': 0.28.2 + '@esbuild/android-arm': 0.28.2 + '@esbuild/android-arm64': 0.28.2 + '@esbuild/android-x64': 0.28.2 + '@esbuild/darwin-arm64': 0.28.2 + '@esbuild/darwin-x64': 0.28.2 + '@esbuild/freebsd-arm64': 0.28.2 + '@esbuild/freebsd-x64': 0.28.2 + '@esbuild/linux-arm': 0.28.2 + '@esbuild/linux-arm64': 0.28.2 + '@esbuild/linux-ia32': 0.28.2 + '@esbuild/linux-loong64': 0.28.2 + '@esbuild/linux-mips64el': 0.28.2 + '@esbuild/linux-ppc64': 0.28.2 + '@esbuild/linux-riscv64': 0.28.2 + '@esbuild/linux-s390x': 0.28.2 + '@esbuild/linux-x64': 0.28.2 + '@esbuild/netbsd-arm64': 0.28.2 + '@esbuild/netbsd-x64': 0.28.2 + '@esbuild/openbsd-arm64': 0.28.2 + '@esbuild/openbsd-x64': 0.28.2 + '@esbuild/openharmony-arm64': 0.28.2 + '@esbuild/sunos-x64': 0.28.2 + '@esbuild/win32-arm64': 0.28.2 + '@esbuild/win32-ia32': 0.28.2 + '@esbuild/win32-x64': 0.28.2 estree-walker@3.0.3: dependencies: @@ -5595,20 +4060,17 @@ snapshots: expect-type@1.4.0: {} - fast-content-type-parse@1.1.0: {} - fast-decode-uri-component@1.0.1: {} fast-deep-equal@3.1.3: {} - fast-json-stringify@5.16.1: + fast-json-stringify@7.0.1: dependencies: - '@fastify/merge-json-schemas': 0.1.1 + '@fastify/merge-json-schemas': 0.2.1 ajv: 8.20.0 ajv-formats: 3.0.1(ajv@8.20.0) - fast-deep-equal: 3.1.3 - fast-uri: 2.4.0 - json-schema-ref-resolver: 1.0.1 + fast-uri: 4.2.1 + json-schema-ref-resolver: 3.0.0 rfdc: 1.4.1 fast-querystring@1.1.2: @@ -5617,28 +4079,27 @@ snapshots: fast-safe-stringify@2.1.1: {} - fast-uri@2.4.0: {} - fast-uri@3.1.3: {} - fastify-plugin@4.5.1: {} + fast-uri@4.2.1: {} - fastify@4.28.1: + fastify-plugin@6.0.0: {} + + fastify@5.12.5: dependencies: - '@fastify/ajv-compiler': 3.6.0 - '@fastify/error': 3.4.1 - '@fastify/fast-json-stringify-compiler': 4.3.0 + '@fastify/ajv-compiler': 4.0.6 + '@fastify/error': 4.2.0 + '@fastify/fast-json-stringify-compiler': 5.1.0 + '@fastify/proxy-addr': 5.1.1 abstract-logging: 2.0.1 - avvio: 8.4.0 - fast-content-type-parse: 1.1.0 - fast-json-stringify: 5.16.1 - find-my-way: 8.2.2 - light-my-request: 5.14.0 + avvio: 9.3.0 + fast-json-stringify: 7.0.1 + find-my-way: 9.9.0 + light-my-request: 6.3.0 pino: 9.14.0 - process-warning: 3.0.0 - proxy-addr: 2.0.7 + process-warning: 5.1.0 rfdc: 1.4.1 - secure-json-parse: 2.7.0 + secure-json-parse: 4.1.0 semver: 7.8.5 toad-cache: 3.7.4 @@ -5646,41 +4107,32 @@ snapshots: dependencies: reusify: 1.1.0 - fdir@6.5.0(picomatch@4.0.5): + fdir@6.5.0(picomatch@4.0.7): optionalDependencies: - picomatch: 4.0.5 + picomatch: 4.0.7 - fflate@0.8.3: {} - - file-type@20.4.1(supports-color@7.2.0): + file-type@22.1.0(supports-color@7.2.0): dependencies: - '@tokenizer/inflate': 0.2.7(supports-color@7.2.0) + '@tokenizer/inflate': 0.4.1(supports-color@7.2.0) strtok3: 10.3.5 token-types: 6.1.2 uint8array-extras: 1.5.0 transitivePeerDependencies: - supports-color - find-my-way@8.2.2: + find-my-way@9.9.0: dependencies: fast-deep-equal: 3.1.3 fast-querystring: 1.1.2 - safe-regex2: 3.1.0 - - forwarded@0.2.0: {} + safe-regex2: 5.1.1 from@0.1.7: {} - fsevents@2.3.2: - optional: true - fsevents@2.3.3: optional: true fuse.js@7.5.0: {} - gensync@1.0.0-beta.2: {} - graceful-fs@4.2.11: {} has-flag@4.0.0: {} @@ -5698,7 +4150,7 @@ snapshots: ieee754@1.2.1: {} - ipaddr.js@1.9.1: {} + ipaddr.js@2.5.0: {} isexe@2.0.0: {} @@ -5706,25 +4158,19 @@ snapshots: jiti@2.7.0: {} - js-tokens@4.0.0: {} - - js-yaml@4.1.0: + js-yaml@5.4.1: dependencies: argparse: 2.0.1 - jsesc@3.1.0: {} - - json-schema-ref-resolver@1.0.1: + json-schema-ref-resolver@3.0.0: dependencies: - fast-deep-equal: 3.1.3 + dequal: 2.0.3 json-schema-traverse@1.0.0: {} - json5@2.2.3: {} - - jsonwebtoken@9.0.2: + jsonwebtoken@9.0.3: dependencies: - jws: 3.2.3 + jws: 4.0.1 lodash.includes: 4.3.0 lodash.isboolean: 3.0.3 lodash.isinteger: 4.0.4 @@ -5737,69 +4183,69 @@ snapshots: just-extend@6.2.0: {} - jwa@1.4.2: + jwa@2.0.1: dependencies: buffer-equal-constant-time: 1.0.1 ecdsa-sig-formatter: 1.0.11 safe-buffer: 5.2.1 - jws@3.2.3: + jws@4.0.1: dependencies: - jwa: 1.4.2 + jwa: 2.0.1 safe-buffer: 5.2.1 - lefthook-darwin-arm64@1.13.6: + lefthook-darwin-arm64@2.1.14: optional: true - lefthook-darwin-x64@1.13.6: + lefthook-darwin-x64@2.1.14: optional: true - lefthook-freebsd-arm64@1.13.6: + lefthook-freebsd-arm64@2.1.14: optional: true - lefthook-freebsd-x64@1.13.6: + lefthook-freebsd-x64@2.1.14: optional: true - lefthook-linux-arm64@1.13.6: + lefthook-linux-arm64@2.1.14: optional: true - lefthook-linux-x64@1.13.6: + lefthook-linux-x64@2.1.14: optional: true - lefthook-openbsd-arm64@1.13.6: + lefthook-openbsd-arm64@2.1.14: optional: true - lefthook-openbsd-x64@1.13.6: + lefthook-openbsd-x64@2.1.14: optional: true - lefthook-windows-arm64@1.13.6: + lefthook-windows-arm64@2.1.14: optional: true - lefthook-windows-x64@1.13.6: + lefthook-windows-x64@2.1.14: optional: true - lefthook@1.13.6: + lefthook@2.1.14: 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 + lefthook-darwin-arm64: 2.1.14 + lefthook-darwin-x64: 2.1.14 + lefthook-freebsd-arm64: 2.1.14 + lefthook-freebsd-x64: 2.1.14 + lefthook-linux-arm64: 2.1.14 + lefthook-linux-x64: 2.1.14 + lefthook-openbsd-arm64: 2.1.14 + lefthook-openbsd-x64: 2.1.14 + lefthook-windows-arm64: 2.1.14 + lefthook-windows-x64: 2.1.14 libphonenumber-js@1.13.8: {} - light-my-request@5.14.0: + light-my-request@6.3.0: dependencies: - cookie: 0.7.2 - process-warning: 3.0.0 + cookie: 1.1.1 + process-warning: 4.0.1 set-cookie-parser: 2.7.2 - light-my-request@6.3.0: + light-my-request@6.6.0: dependencies: cookie: 1.1.1 process-warning: 4.0.1 @@ -5808,36 +4254,69 @@ snapshots: lightningcss-android-arm64@1.32.0: optional: true + lightningcss-android-arm64@1.33.0: + optional: true + lightningcss-darwin-arm64@1.32.0: optional: true + lightningcss-darwin-arm64@1.33.0: + optional: true + lightningcss-darwin-x64@1.32.0: optional: true + lightningcss-darwin-x64@1.33.0: + optional: true + lightningcss-freebsd-x64@1.32.0: optional: true + lightningcss-freebsd-x64@1.33.0: + optional: true + lightningcss-linux-arm-gnueabihf@1.32.0: optional: true + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + lightningcss-linux-arm64-gnu@1.32.0: optional: true + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + lightningcss-linux-arm64-musl@1.32.0: optional: true + lightningcss-linux-arm64-musl@1.33.0: + optional: true + lightningcss-linux-x64-gnu@1.32.0: optional: true + lightningcss-linux-x64-gnu@1.33.0: + optional: true + lightningcss-linux-x64-musl@1.32.0: optional: true + lightningcss-linux-x64-musl@1.33.0: + optional: true + lightningcss-win32-arm64-msvc@1.32.0: optional: true + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + lightningcss-win32-x64-msvc@1.32.0: optional: true + lightningcss-win32-x64-msvc@1.33.0: + optional: true + lightningcss@1.32.0: dependencies: detect-libc: 2.1.2 @@ -5854,6 +4333,24 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + load-esm@1.0.3: {} + lodash.includes@4.3.0: {} lodash.isboolean@3.0.3: {} @@ -5868,17 +4365,13 @@ snapshots: lodash.once@4.1.1: {} - lodash@4.17.21: {} - - loupe@3.2.1: {} - - lru-cache@5.1.1: + magic-string@0.30.21: dependencies: - yallist: 3.1.1 + '@jridgewell/sourcemap-codec': 1.6.0 - magic-string@0.30.21: + magic-string@1.4.1: dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 map-stream@0.1.0: {} @@ -5886,13 +4379,9 @@ snapshots: dependencies: obliterator: 1.6.1 - mnemonist@0.39.6: - dependencies: - obliterator: 2.0.5 - ms@2.1.3: {} - nanoid@3.3.16: {} + nanoid@3.3.19: {} nise@6.1.5: dependencies: @@ -5903,12 +4392,6 @@ snapshots: node-cleanup@2.1.2: {} - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - - node-releases@2.0.51: {} - nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -5917,55 +4400,55 @@ snapshots: obliterator@1.6.1: {} - obliterator@2.0.5: {} + obug@2.2.1: {} on-exit-leak-free@2.1.2: {} - oxfmt@0.59.0: + oxfmt@0.68.0: dependencies: - tinypool: 2.1.0 + tinypool: 2.1.2 optionalDependencies: - '@oxfmt/binding-android-arm-eabi': 0.59.0 - '@oxfmt/binding-android-arm64': 0.59.0 - '@oxfmt/binding-darwin-arm64': 0.59.0 - '@oxfmt/binding-darwin-x64': 0.59.0 - '@oxfmt/binding-freebsd-x64': 0.59.0 - '@oxfmt/binding-linux-arm-gnueabihf': 0.59.0 - '@oxfmt/binding-linux-arm-musleabihf': 0.59.0 - '@oxfmt/binding-linux-arm64-gnu': 0.59.0 - '@oxfmt/binding-linux-arm64-musl': 0.59.0 - '@oxfmt/binding-linux-ppc64-gnu': 0.59.0 - '@oxfmt/binding-linux-riscv64-gnu': 0.59.0 - '@oxfmt/binding-linux-riscv64-musl': 0.59.0 - '@oxfmt/binding-linux-s390x-gnu': 0.59.0 - '@oxfmt/binding-linux-x64-gnu': 0.59.0 - '@oxfmt/binding-linux-x64-musl': 0.59.0 - '@oxfmt/binding-openharmony-arm64': 0.59.0 - '@oxfmt/binding-win32-arm64-msvc': 0.59.0 - '@oxfmt/binding-win32-ia32-msvc': 0.59.0 - '@oxfmt/binding-win32-x64-msvc': 0.59.0 - - oxlint@1.74.0: + '@oxfmt/binding-android-arm-eabi': 0.68.0 + '@oxfmt/binding-android-arm64': 0.68.0 + '@oxfmt/binding-darwin-arm64': 0.68.0 + '@oxfmt/binding-darwin-x64': 0.68.0 + '@oxfmt/binding-freebsd-x64': 0.68.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.68.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.68.0 + '@oxfmt/binding-linux-arm64-gnu': 0.68.0 + '@oxfmt/binding-linux-arm64-musl': 0.68.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.68.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.68.0 + '@oxfmt/binding-linux-riscv64-musl': 0.68.0 + '@oxfmt/binding-linux-s390x-gnu': 0.68.0 + '@oxfmt/binding-linux-x64-gnu': 0.68.0 + '@oxfmt/binding-linux-x64-musl': 0.68.0 + '@oxfmt/binding-openharmony-arm64': 0.68.0 + '@oxfmt/binding-win32-arm64-msvc': 0.68.0 + '@oxfmt/binding-win32-ia32-msvc': 0.68.0 + '@oxfmt/binding-win32-x64-msvc': 0.68.0 + + oxlint@1.83.0: optionalDependencies: - '@oxlint/binding-android-arm-eabi': 1.74.0 - '@oxlint/binding-android-arm64': 1.74.0 - '@oxlint/binding-darwin-arm64': 1.74.0 - '@oxlint/binding-darwin-x64': 1.74.0 - '@oxlint/binding-freebsd-x64': 1.74.0 - '@oxlint/binding-linux-arm-gnueabihf': 1.74.0 - '@oxlint/binding-linux-arm-musleabihf': 1.74.0 - '@oxlint/binding-linux-arm64-gnu': 1.74.0 - '@oxlint/binding-linux-arm64-musl': 1.74.0 - '@oxlint/binding-linux-ppc64-gnu': 1.74.0 - '@oxlint/binding-linux-riscv64-gnu': 1.74.0 - '@oxlint/binding-linux-riscv64-musl': 1.74.0 - '@oxlint/binding-linux-s390x-gnu': 1.74.0 - '@oxlint/binding-linux-x64-gnu': 1.74.0 - '@oxlint/binding-linux-x64-musl': 1.74.0 - '@oxlint/binding-openharmony-arm64': 1.74.0 - '@oxlint/binding-win32-arm64-msvc': 1.74.0 - '@oxlint/binding-win32-ia32-msvc': 1.74.0 - '@oxlint/binding-win32-x64-msvc': 1.74.0 + '@oxlint/binding-android-arm-eabi': 1.83.0 + '@oxlint/binding-android-arm64': 1.83.0 + '@oxlint/binding-darwin-arm64': 1.83.0 + '@oxlint/binding-darwin-x64': 1.83.0 + '@oxlint/binding-freebsd-x64': 1.83.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.83.0 + '@oxlint/binding-linux-arm-musleabihf': 1.83.0 + '@oxlint/binding-linux-arm64-gnu': 1.83.0 + '@oxlint/binding-linux-arm64-musl': 1.83.0 + '@oxlint/binding-linux-ppc64-gnu': 1.83.0 + '@oxlint/binding-linux-riscv64-gnu': 1.83.0 + '@oxlint/binding-linux-riscv64-musl': 1.83.0 + '@oxlint/binding-linux-s390x-gnu': 1.83.0 + '@oxlint/binding-linux-x64-gnu': 1.83.0 + '@oxlint/binding-linux-x64-musl': 1.83.0 + '@oxlint/binding-openharmony-arm64': 1.83.0 + '@oxlint/binding-win32-arm64-msvc': 1.83.0 + '@oxlint/binding-win32-ia32-msvc': 1.83.0 + '@oxlint/binding-win32-x64-msvc': 1.83.0 parse5-htmlparser2-tree-adapter@7.1.0: dependencies: @@ -6006,16 +4489,8 @@ snapshots: path-key@3.1.1: {} - path-to-regexp@3.3.0: {} - - path-to-regexp@6.3.0: {} - path-to-regexp@8.4.2: {} - pathe@1.1.2: {} - - pathval@2.0.1: {} - pause-stream@0.0.11: dependencies: through: 2.3.8 @@ -6024,7 +4499,7 @@ snapshots: picocolors@1.1.1: {} - picomatch@4.0.5: {} + picomatch@4.0.7: {} pino-abstract-transport@2.0.0: dependencies: @@ -6046,30 +4521,23 @@ snapshots: sonic-boom: 4.2.1 thread-stream: 3.2.0 - playwright-core@1.61.1: {} + playwright-core@1.63.0: {} - playwright@1.61.1: + playwright@1.63.0: dependencies: - playwright-core: 1.61.1 - optionalDependencies: - fsevents: 2.3.2 + playwright-core: 1.63.0 - postcss@8.5.19: + postcss@8.5.28: dependencies: - nanoid: 3.3.16 + nanoid: 3.3.19 picocolors: 1.1.1 source-map-js: 1.2.1 - process-warning@3.0.0: {} - process-warning@4.0.1: {} process-warning@5.0.0: {} - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 + process-warning@5.1.0: {} ps-tree@1.2.0: dependencies: @@ -6077,28 +4545,26 @@ snapshots: quick-format-unescaped@4.0.4: {} - react-dom@19.2.7(react@19.2.7): + react-dom@19.3.0(react@19.3.0): dependencies: - react: 19.2.7 - scheduler: 0.27.0 - - react-refresh@0.17.0: {} + react: 19.3.0 + scheduler: 0.28.0 - react-router-dom@7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + react-router-dom@7.18.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0): dependencies: - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - react-router: 7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + react-router: 7.18.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0) - react-router@7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + react-router@7.18.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0): dependencies: cookie: 1.1.1 - react: 19.2.7 + react: 19.3.0 set-cookie-parser: 2.7.2 optionalDependencies: - react-dom: 19.2.7(react@19.2.7) + react-dom: 19.3.0(react@19.3.0) - react@19.2.7: {} + react@19.3.0: {} real-require@0.2.0: {} @@ -6106,44 +4572,34 @@ snapshots: require-from-string@2.0.2: {} - reselect@5.2.0: {} + reselect@5.3.0: {} - ret@0.4.3: {} + ret@0.5.0: {} reusify@1.1.0: {} rfdc@1.4.1: {} - rollup@4.62.2: + rolldown@1.2.9: dependencies: - '@types/estree': 1.0.9 + '@oxc-project/types': 0.150.0 + '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.62.2 - '@rollup/rollup-android-arm64': 4.62.2 - '@rollup/rollup-darwin-arm64': 4.62.2 - '@rollup/rollup-darwin-x64': 4.62.2 - '@rollup/rollup-freebsd-arm64': 4.62.2 - '@rollup/rollup-freebsd-x64': 4.62.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 - '@rollup/rollup-linux-arm-musleabihf': 4.62.2 - '@rollup/rollup-linux-arm64-gnu': 4.62.2 - '@rollup/rollup-linux-arm64-musl': 4.62.2 - '@rollup/rollup-linux-loong64-gnu': 4.62.2 - '@rollup/rollup-linux-loong64-musl': 4.62.2 - '@rollup/rollup-linux-ppc64-gnu': 4.62.2 - '@rollup/rollup-linux-ppc64-musl': 4.62.2 - '@rollup/rollup-linux-riscv64-gnu': 4.62.2 - '@rollup/rollup-linux-riscv64-musl': 4.62.2 - '@rollup/rollup-linux-s390x-gnu': 4.62.2 - '@rollup/rollup-linux-x64-gnu': 4.62.2 - '@rollup/rollup-linux-x64-musl': 4.62.2 - '@rollup/rollup-openbsd-x64': 4.62.2 - '@rollup/rollup-openharmony-arm64': 4.62.2 - '@rollup/rollup-win32-arm64-msvc': 4.62.2 - '@rollup/rollup-win32-ia32-msvc': 4.62.2 - '@rollup/rollup-win32-x64-gnu': 4.62.2 - '@rollup/rollup-win32-x64-msvc': 4.62.2 - fsevents: 2.3.3 + '@rolldown/binding-android-arm-eabi': 1.2.9 + '@rolldown/binding-android-arm64': 1.2.9 + '@rolldown/binding-darwin-arm64': 1.2.9 + '@rolldown/binding-darwin-x64': 1.2.9 + '@rolldown/binding-freebsd-x64': 1.2.9 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.9 + '@rolldown/binding-linux-arm64-gnu': 1.2.9 + '@rolldown/binding-linux-arm64-musl': 1.2.9 + '@rolldown/binding-linux-ppc64-gnu': 1.2.9 + '@rolldown/binding-linux-s390x-gnu': 1.2.9 + '@rolldown/binding-linux-x64-gnu': 1.2.9 + '@rolldown/binding-linux-x64-musl': 1.2.9 + '@rolldown/binding-openharmony-arm64': 1.2.9 + '@rolldown/binding-win32-arm64-msvc': 1.2.9 + '@rolldown/binding-win32-x64-msvc': 1.2.9 rxjs@7.8.2: dependencies: @@ -6151,19 +4607,17 @@ snapshots: safe-buffer@5.2.1: {} - safe-regex2@3.1.0: + safe-regex2@5.1.1: dependencies: - ret: 0.4.3 + ret: 0.5.0 safe-stable-stringify@2.5.0: {} safer-buffer@2.1.2: {} - scheduler@0.27.0: {} + scheduler@0.28.0: {} - secure-json-parse@2.7.0: {} - - semver@6.3.1: {} + secure-json-parse@4.1.0: {} semver@7.8.5: {} @@ -6207,7 +4661,7 @@ snapshots: stackback@0.0.2: {} - std-env@3.10.0: {} + std-env@4.2.0: {} stream-combiner@0.0.4: dependencies: @@ -6223,13 +4677,11 @@ snapshots: dependencies: has-flag: 4.0.0 - swagger-ui-dist@5.18.2: + swagger-ui-dist@5.32.14: dependencies: '@scarf/scarf': 1.4.0 - tabbable@6.5.0: {} - - tailwindcss@4.3.2: {} + tailwindcss@4.3.3: {} tapable@2.3.3: {} @@ -6239,22 +4691,16 @@ snapshots: through@2.3.8: {} - tinybench@2.9.0: {} + tinybench@6.1.4: {} - tinyexec@0.3.2: {} + tinyexec@1.3.0: {} tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 - - tinypool@1.1.1: {} - - tinypool@2.1.0: {} + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 - tinyrainbow@1.2.0: {} - - tinyspy@3.0.2: {} + tinypool@2.1.2: {} toad-cache@3.7.4: {} @@ -6264,38 +4710,57 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 - tr46@0.0.3: {} - - tsc-watch@7.2.1(typescript@5.9.3): + tsc-watch@7.2.1(typescript@7.0.2): dependencies: cross-spawn: 7.0.6 node-cleanup: 2.1.2 ps-tree: 1.2.0 string-argv: 0.3.2 - typescript: 5.9.3 + typescript: 7.0.2 tslib@2.8.1: {} - tsx@4.23.1: + tsx@4.23.13: dependencies: - esbuild: 0.28.1 + esbuild: 0.28.2 optionalDependencies: fsevents: 2.3.3 - turbo@2.10.5: + turbo@2.11.2: optionalDependencies: - '@turbo/darwin-64': 2.10.5 - '@turbo/darwin-arm64': 2.10.5 - '@turbo/linux-64': 2.10.5 - '@turbo/linux-arm64': 2.10.5 - '@turbo/windows-64': 2.10.5 - '@turbo/windows-arm64': 2.10.5 + '@turbo/darwin-64': 2.11.2 + '@turbo/darwin-arm64': 2.11.2 + '@turbo/linux-64': 2.11.2 + '@turbo/linux-arm64': 2.11.2 + '@turbo/windows-64': 2.11.2 + '@turbo/windows-arm64': 2.11.2 type-detect@4.0.8: {} type-detect@4.1.0: {} - typescript@5.9.3: {} + typescript@7.0.2: + optionalDependencies: + '@typescript/typescript-aix-ppc64': 7.0.2 + '@typescript/typescript-darwin-arm64': 7.0.2 + '@typescript/typescript-darwin-x64': 7.0.2 + '@typescript/typescript-freebsd-arm64': 7.0.2 + '@typescript/typescript-freebsd-x64': 7.0.2 + '@typescript/typescript-linux-arm': 7.0.2 + '@typescript/typescript-linux-arm64': 7.0.2 + '@typescript/typescript-linux-loong64': 7.0.2 + '@typescript/typescript-linux-mips64el': 7.0.2 + '@typescript/typescript-linux-ppc64': 7.0.2 + '@typescript/typescript-linux-riscv64': 7.0.2 + '@typescript/typescript-linux-s390x': 7.0.2 + '@typescript/typescript-linux-x64': 7.0.2 + '@typescript/typescript-netbsd-arm64': 7.0.2 + '@typescript/typescript-netbsd-x64': 7.0.2 + '@typescript/typescript-openbsd-arm64': 7.0.2 + '@typescript/typescript-openbsd-x64': 7.0.2 + '@typescript/typescript-sunos-x64': 7.0.2 + '@typescript/typescript-win32-arm64': 7.0.2 + '@typescript/typescript-win32-x64': 7.0.2 uid2@0.0.4: {} @@ -6305,105 +4770,52 @@ snapshots: uint8array-extras@1.5.0: {} - undici-types@6.21.0: {} - undici-types@8.9.0: {} - undici@7.29.0: {} + undici@7.29.1: {} - update-browserslist-db@1.2.3(browserslist@4.28.6): + use-sync-external-store@1.7.0(react@19.3.0): dependencies: - browserslist: 4.28.6 - escalade: 3.2.0 - picocolors: 1.1.1 - - use-sync-external-store@1.6.0(react@19.2.7): - dependencies: - react: 19.2.7 + react: 19.3.0 utils-merge@1.0.1: {} validator@13.15.35: {} - vite-node@2.1.9(@types/node@26.6.1)(lightningcss@1.32.0)(supports-color@7.2.0): - dependencies: - cac: 6.7.14 - debug: 4.4.3(supports-color@7.2.0) - es-module-lexer: 1.7.0 - pathe: 1.1.2 - vite: 5.4.21(@types/node@26.6.1)(lightningcss@1.32.0) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - vite@5.4.21(@types/node@26.6.1)(lightningcss@1.32.0): + vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13): dependencies: - esbuild: 0.21.5 - postcss: 8.5.19 - rollup: 4.62.2 - optionalDependencies: - '@types/node': 26.6.1 - fsevents: 2.3.3 - lightningcss: 1.32.0 - - vite@6.4.3(@types/node@26.6.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1): - dependencies: - esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 - postcss: 8.5.19 - rollup: 4.62.2 + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.28 + rolldown: 1.2.9 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 26.6.1 + '@types/node': 26.6.2 + esbuild: 0.28.2 fsevents: 2.3.3 jiti: 2.7.0 - lightningcss: 1.32.0 - tsx: 4.23.1 - - vitest@2.1.9(@types/node@26.6.1)(lightningcss@1.32.0)(supports-color@7.2.0): - dependencies: - '@vitest/expect': 2.1.9 - '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@26.6.1)(lightningcss@1.32.0)) - '@vitest/pretty-format': 2.1.9 - '@vitest/runner': 2.1.9 - '@vitest/snapshot': 2.1.9 - '@vitest/spy': 2.1.9 - '@vitest/utils': 2.1.9 - chai: 5.3.3 - debug: 4.4.3(supports-color@7.2.0) + tsx: 4.23.13 + + vitest@5.0.1(@types/node@26.6.2)(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)): + dependencies: + '@types/chai': 5.2.3 + '@vitest/mocker': 5.0.1(vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13)) + chai: 6.2.2 + es-module-lexer: 2.3.2 expect-type: 1.4.0 - magic-string: 0.30.21 - pathe: 1.1.2 - std-env: 3.10.0 - tinybench: 2.9.0 - tinyexec: 0.3.2 - tinypool: 1.1.1 - tinyrainbow: 1.2.0 - vite: 5.4.21(@types/node@26.6.1)(lightningcss@1.32.0) - vite-node: 2.1.9(@types/node@26.6.1)(lightningcss@1.32.0)(supports-color@7.2.0) + magic-string: 1.4.1 + obug: 2.2.1 + picomatch: 4.0.7 + std-env: 4.2.0 + tinybench: 6.1.4 + tinyexec: 1.3.0 + tinyglobby: 0.2.17 + vite: 8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 26.6.1 + '@types/node': 26.6.2 transitivePeerDependencies: - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - webidl-conversions@3.0.1: {} whatwg-encoding@3.1.1: dependencies: @@ -6411,11 +4823,6 @@ snapshots: whatwg-mimetype@4.0.0: {} - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - which@2.0.2: dependencies: isexe: 2.0.0 @@ -6424,5 +4831,3 @@ snapshots: dependencies: siginfo: 2.0.0 stackback: 0.0.2 - - yallist@3.1.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c1ec6cc..7a6ffeb 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -10,6 +10,11 @@ allowBuilds: '@scarf/scarf': false esbuild: true lefthook: true +# Pin exact versions when adding dependencies. Kept in sync with .npmrc. +saveExact: true +# Fail (not just warn) when the running Node does not satisfy `engines` (Node 26). +# Only this setting works: pnpm 11 ignores `engine-strict` in .npmrc. +engineStrict: true # Install native optional deps for both Mac arches so a Rosetta Node # (leftover Homebrew at /usr/local) and nvm's arm64 Node can share # the same node_modules. See pnpm.io/settings#supportedarchitectures. @@ -26,3 +31,9 @@ supportedArchitectures: minimumReleaseAgeExclude: - '@bubltec/*' - '@types/node@26.6.1' +# @nestjs/platform-fastify pins `fastify` to an exact version as a regular +# dependency, so the app's own `fastify` would otherwise install a second copy +# and the Fastify plugin types (@fastify/cookie) stop lining up. Keep this equal +# to the `fastify` version in apps/bff/package.json. +overrides: + fastify: 5.12.5