From ea4e146407bc8b37b4ca138cc95b70b4256485bc Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 16:10:09 -0400 Subject: [PATCH 01/16] fixes and changes, adding solution architecture rules --- .../bff-typescript-cdk-best-practices.mdc | 260 ++++++++++++++++++ apps/bff/src/app.module.ts | 2 +- .../src/contributions/contributions.module.ts | 7 +- .../contributions.pipeline.spec.ts | 12 +- .../contributions.service.spec.ts | 144 ++++++++-- .../contributions/contributions.service.ts | 188 ++++++------- .../dynamo-pending-contribution.store.ts | 126 +++++++++ .../pending-contribution.store.ts | 19 ++ .../professional-verification.controller.ts | 58 ++++ .../professional-verification.module.ts | 9 + .../src/users/hydrating-users.service.spec.ts | 56 ++++ apps/bff/src/users/hydrating-users.service.ts | 126 +++++++++ apps/bff/src/users/users.module.ts | 8 + apps/scraper/src/contribution.spec.ts | 6 +- apps/scraper/src/contribution.ts | 111 ++++++-- apps/scraper/src/run.spec.ts | 9 +- apps/web/src/pages/ModerationPage.tsx | 17 +- docs/architecture.md | 18 +- docs/verification-flow.md | 5 +- .../src/contribution-queue.spec.ts | 86 ++++++ .../shared-types/src/contribution-queue.ts | 79 ++++++ packages/shared-types/src/index.ts | 1 + packages/shared-types/src/thing-identity.ts | 47 ++++ 23 files changed, 1217 insertions(+), 177 deletions(-) create mode 100644 .cursor/rules/bff-typescript-cdk-best-practices.mdc create mode 100644 apps/bff/src/contributions/dynamo-pending-contribution.store.ts create mode 100644 apps/bff/src/contributions/pending-contribution.store.ts create mode 100644 apps/bff/src/professional-verification/professional-verification.controller.ts create mode 100644 apps/bff/src/professional-verification/professional-verification.module.ts create mode 100644 apps/bff/src/users/hydrating-users.service.spec.ts create mode 100644 apps/bff/src/users/hydrating-users.service.ts create mode 100644 apps/bff/src/users/users.module.ts create mode 100644 packages/shared-types/src/contribution-queue.spec.ts create mode 100644 packages/shared-types/src/contribution-queue.ts 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..8582776 --- /dev/null +++ b/.cursor/rules/bff-typescript-cdk-best-practices.mdc @@ -0,0 +1,260 @@ +--- +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/ +├── .nvmrc +├── .oxfmtrc.json +├── .oxlintrc.json +├── CLAUDE.md +├── 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 | +| `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` | Local Node version | +| `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. + +## 3. BFF Practices (NestJS + Fastify on Lambda) + +### Requests and validation + +* The global `ValidationPipe` runs with `whitelist: true, transform: true`. Consequences you must design for: + * **Every DTO property needs at least one validator decorator,** otherwise `whitelist` silently strips it. + * **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. + +### 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()` so the 60s cache does not serve stale rows. +* 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). + +## 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. +* 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 (`lambda-canary.ts` is the model: the reason, the migration caveat, and the failure mode are all written down). +* **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 `live` alias, never `$LATEST`. Prod uses a canary with an alarm that rolls back; dev uses all-at-once. +* **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 (recommended, not adopted yet) + +* **(recommended)** Add `aws-cdk-lib/assertions` tests under `infra/cdk` for the properties that matter: prod tables `RETAIN` + PITR on, Lambda role has no `*` actions, canary configured for prod. Run them in the turbo `test` task. +* **(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. + +## 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:`). + +### 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. +* Pin third-party actions to a major version at minimum. + +## 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 `live` alias** bypasses canary and rollback. +* **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. + +By following these practices, you keep the BFF, shared packages, and infrastructure consistent, secure, cheap to run, and easy to change. 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/contributions/contributions.module.ts b/apps/bff/src/contributions/contributions.module.ts index 305dd99..b39cf1f 100644 --- a/apps/bff/src/contributions/contributions.module.ts +++ b/apps/bff/src/contributions/contributions.module.ts @@ -1,6 +1,8 @@ import { Module } from '@nestjs/common'; import { ContributionsController } from './contributions.controller.js'; import { ContributionsService } from './contributions.service.js'; +import { PendingContributionStore } from './pending-contribution.store.js'; +import { DynamoPendingContributionStore } from './dynamo-pending-contribution.store.js'; import { ThingsModule } from '../things/things.module.js'; import { SearchModule } from '../search/search.module.js'; @@ -8,6 +10,9 @@ import { SearchModule } from '../search/search.module.js'; @Module({ imports: [ThingsModule, SearchModule], controllers: [ContributionsController], - providers: [ContributionsService], + providers: [ + { provide: PendingContributionStore, useClass: DynamoPendingContributionStore }, + ContributionsService, + ], }) export class ContributionsModule {} diff --git a/apps/bff/src/contributions/contributions.pipeline.spec.ts b/apps/bff/src/contributions/contributions.pipeline.spec.ts index 90e5ec0..bcf9345 100644 --- a/apps/bff/src/contributions/contributions.pipeline.spec.ts +++ b/apps/bff/src/contributions/contributions.pipeline.spec.ts @@ -8,9 +8,10 @@ import { ValidationPipe } from '@nestjs/common'; import { describe, expect, it, vi } from 'vitest'; import { mockAws } from '../test-utils.js'; import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; -import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb'; +import { DynamoDBDocumentClient, PutCommand, QueryCommand } from '@aws-sdk/lib-dynamodb'; import { CreateContributionDto } from './dto/create-contribution.dto.js'; import { ContributionsService } from './contributions.service.js'; +import { DynamoPendingContributionStore } from './dynamo-pending-contribution.store.js'; import type { SearchService } from '../search/search.service.js'; const pipe = new ValidationPipe({ whitelist: true, transform: true }); @@ -33,6 +34,7 @@ describe('Contributions POST pipeline (ValidationPipe → propose → PutCommand it('matches the deploy e2e submit body and produces a plain Put item', async () => { 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/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/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/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/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/docs/architecture.md b/docs/architecture.md index ed45696..cad8e21 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -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/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/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, + }; +} From ea4ea8b60dfcf598d7655952bc327347be7728af Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 16:15:48 -0400 Subject: [PATCH 02/16] refactor: replace SAM AutoPublishAlias with a native CDK alias and canary The SAM transform (AWS::Serverless-2016-10-31 plus L1 property overrides) needed a one-time manual `aws lambda delete-alias` and had already required five follow-up fixes (#41, #42, #44, #45, #46) for alias-migration cycles and a silently no-op'd invoke permission. publishCurrentAlias now uses lambda.Alias and, only when a canary is requested, codedeploy.LambdaDeploymentGroup with two rollback alarms (alias Errors, and new-version Errors so an old-version error cannot fail a good deploy). Prod keeps the 10%/5min canary. Dev and the SES forwarder cut over immediately with no CodeDeploy deployment, so dev deploys no longer wait on a canary that provides no value there. The alias is named `current`, not `live`: the SAM-managed `live` alias still exists on the deployed functions, and CloudFormation creates before it deletes, so reusing the name would 409 and bring the manual step back. Also drops the BTFP_INVOKE_ALIAS env var (only existed to dodge "version exists") and the fromFunctionAttributes(sameEnvironment) workaround; a real Alias grants invoke permission natively. Adds the repo's first CDK tests (vitest + aws-cdk-lib/assertions) covering the alias, the canary group and alarms, and the absence of the SAM Transform. Deploy note: `cdk diff BtfpDev/Api` shows BffFunction as a replacement (SAM Serverless::Function -> Lambda::Function). The function has an auto-generated name, so CloudFormation creates the new one first. The log group name will change. Prod's first deploy of this is not a canary (new alias on a new function), so review the prod-diff job before approving. --- docs/architecture.md | 2 +- docs/ci-cd.md | 6 +- docs/infra.md | 30 +++--- infra/cdk/lib/api-stack.ts | 11 +- infra/cdk/lib/email-stack.ts | 8 +- infra/cdk/lib/lambda-canary.spec.ts | 57 +++++++++++ infra/cdk/lib/lambda-canary.ts | 151 +++++++++++++--------------- infra/cdk/package.json | 4 +- infra/cdk/vitest.config.ts | 7 ++ pnpm-lock.yaml | 3 + 10 files changed, 166 insertions(+), 113 deletions(-) create mode 100644 infra/cdk/lib/lambda-canary.spec.ts create mode 100644 infra/cdk/vitest.config.ts diff --git a/docs/architecture.md b/docs/architecture.md index cad8e21..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. 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..925042b 100644 --- a/docs/infra.md +++ b/docs/infra.md @@ -32,31 +32,27 @@ 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` +### Lambda alias and canary -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: +`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. -```bash -aws lambda delete-alias --function-name --name live -``` +- **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). -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. +This is plain CDK constructs (`lambda.Alias` + `codedeploy.LambdaDeploymentGroup`) — no SAM +transform. The behavior is covered by `infra/cdk/lib/lambda-canary.spec.ts`. ## Budget (rough, at low/unknown traffic) diff --git a/infra/cdk/lib/api-stack.ts b/infra/cdk/lib/api-stack.ts index fd8e07b..73a66d1 100644 --- a/infra/cdk/lib/api-stack.ts +++ b/infra/cdk/lib/api-stack.ts @@ -20,7 +20,8 @@ import { ROOT_DOMAIN, SES_FROM_ADDRESS, } from './config.js'; -import { publishLiveAlias } from './lambda-canary.js'; +import * as codedeploy from 'aws-cdk-lib/aws-codedeploy'; +import { publishCurrentAlias } from './lambda-canary.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -94,8 +95,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,8 +135,8 @@ 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), }); 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..90ad62a 100644 --- a/infra/cdk/lib/email-stack.ts +++ b/infra/cdk/lib/email-stack.ts @@ -15,7 +15,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)); @@ -99,7 +99,7 @@ export class EmailStack extends cdk.Stack { }, }); - const live = publishLiveAlias(forwarderFn, { type: 'AllAtOnce' }); + const current = publishCurrentAlias(forwarderFn); mailBucket.grantRead(forwarderFn); forwarderFn.addToRolePolicy( @@ -109,7 +109,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 +128,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..adfa27b 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" @@ -16,7 +17,8 @@ "@types/node": "^26.6.1", "aws-cdk": "^2.1131.0", "tsx": "^4.19.0", - "typescript": "^5.8.0" + "typescript": "^5.8.0", + "vitest": "^2.1.0" }, "dependencies": { "@aws-sdk/client-ssm": "^3.716.0", 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/pnpm-lock.yaml b/pnpm-lock.yaml index a1a3619..d42f006 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -320,6 +320,9 @@ importers: typescript: specifier: ^5.8.0 version: 5.9.3 + vitest: + specifier: ^2.1.0 + version: 2.1.9(@types/node@26.6.1)(lightningcss@1.32.0)(supports-color@7.2.0) packages/config: {} From 073b47bea961f01407f8444fad3a8a902fcd2a37 Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 16:19:45 -0400 Subject: [PATCH 03/16] fix: fail closed on missing secrets and CORS origin in production buildMycotaAuthConfig fell back to 'change-me-in-local-env' for JWT_SECRET, and enableCors fell back to origin: true (reflect any origin) with credentials enabled. In a deployed stage where the env var was ever unset (CI defaults the JWT secrets to REPLACE_BEFORE_DEPLOYING_* placeholders), that meant silently running with a publicly known signing secret, or an open credentialed CORS policy. Outside production behavior is unchanged. In production a missing or placeholder JWT_SECRET / WEB_ORIGIN now throws at startup, so a bad deploy fails loudly (and trips the prod canary alarm) instead of running insecurely. Verified before changing: both deployed stages currently have a real JWT_SECRET and WEB_ORIGIN set, so this does not affect a running stage. --- apps/bff/src/app.ts | 3 ++- apps/bff/src/env.spec.ts | 45 +++++++++++++++++++++++++++++++++++ apps/bff/src/env.ts | 32 +++++++++++++++++++++++++ apps/bff/src/mycota-config.ts | 5 ++-- 4 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 apps/bff/src/env.spec.ts create mode 100644 apps/bff/src/env.ts diff --git a/apps/bff/src/app.ts b/apps/bff/src/app.ts index 89cc51c..86e8fcb 100644 --- a/apps/bff/src/app.ts +++ b/apps/bff/src/app.ts @@ -5,6 +5,7 @@ import { ValidationPipe } from '@nestjs/common'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import fastifyCookie from '@fastify/cookie'; import { AppModule } from './app.module.js'; +import { corsOrigin } from './env.js'; import { StageErrorFilter } from './filters/stage-error.filter.js'; export async function createApp(adapter: FastifyAdapter): Promise { @@ -34,7 +35,7 @@ export async function createApp(adapter: FastifyAdapter): Promise 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/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', From 39cb35b0956c0fbf7e4f9563980605d98e019898 Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 16:22:08 -0400 Subject: [PATCH 04/16] fix: reject unknown request fields, and fix edits losing their target thing Turn on forbidNonWhitelisted so an undeclared field is a 400 instead of being silently stripped. Silent stripping is the bug class behind the repeated POST /contributions failures (#22-#26), and it was hiding a second, real bug: SubmitPage put `thingId` inside the contribution payload rather than passing it as api.submitContribution's second argument. CreateThingDto has no thingId, so whitelist stripped it and every "edit an existing entry" was proposed as a brand-new thing with no link to the entry being edited (relying only on a name match in findDuplicate). The page now passes editingId as the top-level thingId the DTO actually declares. Audited every body-accepting endpoint against what the web app really sends (email sign-in, professional verification, quiz, contributions); they all match their DTOs exactly, so strict mode is safe. The MCP controller takes a union type and is not validated by the pipe. The pipe options now live in one exported constant used by both app.ts and the DTO specs, replacing a hand-copied config in the spec that could drift. New specs cover a missing payload, a thingId nested in payload, and unknown top-level fields, plus the valid edit shape. Not exercised in a browser: the edit form needs a signed-in session and a running backend. Covered by the DTO contract tests and typecheck instead. --- apps/bff/src/app.ts | 3 +- .../create-contribution.dto.spec.ts | 39 +++++++++++++------ apps/bff/src/validation.ts | 15 +++++++ apps/web/src/pages/SubmitPage.tsx | 24 ++++++------ 4 files changed, 57 insertions(+), 24 deletions(-) create mode 100644 apps/bff/src/validation.ts diff --git a/apps/bff/src/app.ts b/apps/bff/src/app.ts index 86e8fcb..dc56fea 100644 --- a/apps/bff/src/app.ts +++ b/apps/bff/src/app.ts @@ -7,6 +7,7 @@ import fastifyCookie from '@fastify/cookie'; import { AppModule } from './app.module.js'; import { corsOrigin } from './env.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, { @@ -38,7 +39,7 @@ export async function createApp(adapter: FastifyAdapter): Promise + 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/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/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'); From 636e8828e398f59c0c523975eeae9f8090299fdb Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 16:30:03 -0400 Subject: [PATCH 05/16] feat: structured JSON logging and readable stack traces for the BFF Diagnosing the last prod-shaped incident from CloudWatch was slow: stack traces pointed at minified lambda.js:687:76249, Nest log contexts were mangled to "[e]", and every stack was split across separate log events. In production the BFF now logs one JSON object per line (level, time, requestId, context, message, stack) via JsonLogger, so a stack stays inside one event. The Lambda handler runs each invocation inside an AsyncLocalStorage context carrying awsRequestId, so every line, including cold-start logs, is tagged with its request. Local dev keeps Nest's readable console logger; LOG_LEVEL=debug enables debug lines. The bundle now keeps class names (Nest prints them as the log context) and the image ships lambda.js.map so NODE_OPTIONS=--enable-source-maps can map frames back to src/*.ts (the env var is set in the follow-up infra change). Verified against the built bundle in production mode: JSON lines with the right request ids and readable contexts, one event per error, source-mapped frames, and a placeholder JWT_SECRET or missing WEB_ORIGIN aborts startup. --- apps/bff/Dockerfile | 4 +- apps/bff/scripts/build-lambda.mjs | 3 + apps/bff/src/app.ts | 5 +- apps/bff/src/lambda.ts | 10 ++-- apps/bff/src/logging/json-logger.spec.ts | 74 ++++++++++++++++++++++++ apps/bff/src/logging/json-logger.ts | 68 ++++++++++++++++++++++ apps/bff/src/logging/request-context.ts | 4 ++ 7 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 apps/bff/src/logging/json-logger.spec.ts create mode 100644 apps/bff/src/logging/json-logger.ts create mode 100644 apps/bff/src/logging/request-context.ts 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/scripts/build-lambda.mjs b/apps/bff/scripts/build-lambda.mjs index cb6c21e..1d24b16 100644 --- a/apps/bff/scripts/build-lambda.mjs +++ b/apps/bff/scripts/build-lambda.mjs @@ -36,6 +36,9 @@ await build({ ], 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.ts b/apps/bff/src/app.ts index dc56fea..65fc510 100644 --- a/apps/bff/src/app.ts +++ b/apps/bff/src/app.ts @@ -5,13 +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 } from './env.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); 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 }>(); From 640357b810abd89657f85e182515c537657e73e9 Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 16:41:00 -0400 Subject: [PATCH 06/16] docs: make .cursor/rules the source of truth for agent instructions CLAUDE.md held the detailed procedure while .cursor/rules/sync-before-code-changes deferred to it ("Follow CLAUDE.md"), so the same guidance lived in two places. Move all of it into Cursor rules split by topic and reduce CLAUDE.md and the new AGENTS.md to pointers. - sync-before-code-changes (always): the fetch/compare/PR-merged decision checklist and the merge/rebase guard, now self-contained. - recover-from-merged-branch: the stash-and-restart sequence. Corrected while moving it: the old order (`git checkout main` then `git fetch . origin/main:main`) fails because git refuses to fetch into the checked-out branch, so main is now fast-forwarded before switching to it. CLAUDE.md imports both with @ so Claude Code still loads them every session; AGENTS.md indexes all rules (including bff-typescript-cdk-best-practices) for other tools and points at .claude/skills and the sibling mycota repo. --- .cursor/rules/recover-from-merged-branch.mdc | 28 +++++++++++++ .cursor/rules/sync-before-code-changes.mdc | 32 +++++++++++---- AGENTS.md | 23 +++++++++++ CLAUDE.md | 41 ++++---------------- 4 files changed, 82 insertions(+), 42 deletions(-) create mode 100644 .cursor/rules/recover-from-merged-branch.mdc create mode 100644 AGENTS.md 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/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. From 99f6562759d7cf08a7be25b06ff8fac97fe1dbf7 Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 16:47:51 -0400 Subject: [PATCH 07/16] chore: upgrade dependencies to latest, except the NestJS/Fastify set that waits on mycota Everything that does not depend on the @bubltec/mycota-* packages moves to the registry's latest. NestJS, Fastify, @fastify/*, class-validator and mycota itself are deliberately held back: mycota 0.6.0 pins NestJS 10 as a hard dependency, so the app cannot move first without ending up with two Nest copies. That set is prepared separately and lands once mycota's Nest 12 release is published. Major bumps: - TypeScript 5.9 -> 7.0, vitest 2 -> 5, vite 6 -> 8, @vitejs/plugin-react 4 -> 6, oxfmt 0.59 -> 0.68, lefthook 1 -> 2, esbuild 0.24 -> 0.28, @types/node 26.6.2 - aws-cdk-lib 2.261 -> 2.270, aws-cdk, constructs, aws-sdk clients, playwright, react 19.3, react-router, tailwind, oxlint, turbo, tsx - @base-ui-components/react (deprecated, renamed) -> @base-ui/react 1.8.0 Changes the new toolchain required: - packages/config/tsconfig-node.json: "types": ["node"]. TypeScript 7 no longer auto-includes every @types/* package, so process/console/fetch/URL were unresolved in every Node workspace. - Five web components: import path @base-ui-components/react -> @base-ui/react. No API or type changes were needed. - data/seed/src/scrape-vetmeds.ts: one line wrapped by the newer oxfmt. Verified: typecheck (10 tasks), build, lint, format, and unit tests (137 across bff, scraper, shared-types, seed, infra) all pass. The e2e workspace is not part of this check (CI excludes it; it needs a browser and a deployed target). aws-cdk-lib: synthesized every stack before and after and diffed the templates. Data, DNS, CI and Scraper are unchanged apart from the CDKMetadata version stamp. Api Version/Alias hashes differ only because the bundle was rebuilt by the new compiler. Each Web stack's BucketDeployment handler picks up the library's newer bundled code. No unexpected infrastructure changes. base-ui: verified in a browser against a mock API. Select (opens, options, selection updates the app), Combobox (typing filters to one option, popup-open state), and Dialog (opens centered with backdrop, focus enters the input, Escape closes and focus returns to the trigger) all behave correctly with no console warnings. --- apps/bff/package.json | 26 +- apps/e2e/package.json | 10 +- apps/scraper/package.json | 24 +- apps/web/package.json | 26 +- apps/web/src/components/BreedSelect.tsx | 2 +- apps/web/src/components/EmailSignInDialog.tsx | 2 +- apps/web/src/components/PetTypeSelect.tsx | 2 +- .../ProfessionalVerificationDialog.tsx | 2 +- apps/web/src/components/QuizDialog.tsx | 2 +- data/seed/package.json | 16 +- data/seed/src/scrape-vetmeds.ts | 4 +- infra/cdk/package.json | 18 +- package.json | 10 +- packages/config/tsconfig-node.json | 3 +- packages/shared-types/package.json | 4 +- pnpm-lock.yaml | 4423 ++++++----------- 16 files changed, 1538 insertions(+), 3036 deletions(-) diff --git a/apps/bff/package.json b/apps/bff/package.json index 0f83963..3f1cae9 100644 --- a/apps/bff/package.json +++ b/apps/bff/package.json @@ -10,11 +10,11 @@ "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", @@ -31,21 +31,21 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "fastify": "^4.28.1", - "fuse.js": "^7.0.0", + "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.1" + "rxjs": "^7.8.2" }, "devDependencies": { - "aws-sdk-client-mock": "^4.1.0", - "@types/node": "^26.6.1", + "@types/node": "^26.6.2", "@types/passport-github2": "^1.2.9", - "@types/passport-google-oauth20": "^2.0.16", - "esbuild": "^0.24.2", + "@types/passport-google-oauth20": "^2.0.17", + "aws-sdk-client-mock": "^4.1.0", + "esbuild": "^0.28.2", "tsc-watch": "^7.2.1", - "typescript": "^5.8.0", - "vitest": "^2.1.0" + "typescript": "^7.0.2", + "vitest": "^5.0.1" } } diff --git a/apps/e2e/package.json b/apps/e2e/package.json index 985cf1c..61316f8 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..8a94409 100644 --- a/apps/scraper/package.json +++ b/apps/scraper/package.json @@ -11,21 +11,21 @@ }, "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-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", + "@types/node": "^26.6.2", "aws-sdk-client-mock": "^4.1.0", - "esbuild": "^0.24.2", - "typescript": "^5.8.0", - "vitest": "^2.1.0" + "esbuild": "^0.28.2", + "typescript": "^7.0.2", + "vitest": "^5.0.1" } } diff --git a/apps/web/package.json b/apps/web/package.json index d7bcc02..a521083 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/data/seed/package.json b/data/seed/package.json index 4440a12..0462d0f 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", + "@types/node": "^26.6.2", "aws-sdk-client-mock": "^4.1.0", - "tsx": "^4.19.0", - "typescript": "^5.8.0", - "vitest": "^2.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/infra/cdk/package.json b/infra/cdk/package.json index adfa27b..128d95c 100644 --- a/infra/cdk/package.json +++ b/infra/cdk/package.json @@ -14,18 +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", - "vitest": "^2.1.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", + "@aws-sdk/client-ssm": "^3.1136.0", + "@aws-sdk/client-sts": "^3.1136.0", "@bubltec/mycota-cdk": "0.6.0", - "aws-cdk-lib": "^2.261.0", - "constructs": "^10.4.0", + "aws-cdk-lib": "^2.270.0", + "constructs": "^10.8.1", "source-map-support": "^0.5.21" } } diff --git a/package.json b/package.json index b069763..dd338fd 100644 --- a/package.json +++ b/package.json @@ -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..e3bb107 100644 --- a/packages/shared-types/package.json +++ b/packages/shared-types/package.json @@ -17,7 +17,7 @@ "test": "vitest run" }, "devDependencies": { - "typescript": "^5.8.0", - "vitest": "^2.1.0" + "typescript": "^7.0.2", + "vitest": "^5.0.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d42f006..263b496 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,50 +9,50 @@ 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) + version: 0.6.0(@aws-sdk/client-dynamodb@3.1136.0)(supports-color@7.2.0) '@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) '@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) + version: 0.6.0(@aws-sdk/client-dynamodb@3.1136.0)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) '@fastify/aws-lambda': specifier: ^4.1.0 version: 4.1.0 @@ -90,7 +90,7 @@ importers: specifier: ^4.28.1 version: 4.28.1 fuse.js: - specifier: ^7.0.0 + specifier: ^7.5.0 version: 7.5.0 passport: specifier: ^0.7.0 @@ -105,52 +105,52 @@ importers: 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 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 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) + 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: @@ -158,146 +158,146 @@ importers: 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 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 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) + version: 0.6.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 version: 0.5.21 @@ -309,42 +309,42 @@ 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: ^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/config: {} packages/shared-types: devDependencies: 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 @@ -361,58 +361,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'} @@ -421,58 +397,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'} @@ -481,113 +413,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==} @@ -597,108 +481,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 @@ -732,620 +537,176 @@ packages: '@bubltec/mycota-professional-verification@0.6.0': resolution: {integrity: sha512-RFRid9/dGe5/tLdtHt3dLtWl4ctjsjIadJKixYJwS/4BocGygg+6h/Da1/iTECEISEV4L5YsqAuRyoEC7nsR0Q==} - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - - '@esbuild/aix-ppc64@0.24.2': - resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@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@3.6.0': + resolution: {integrity: sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==} - '@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@4.1.0': + resolution: {integrity: sha512-293HSdtr4muZZi4UxjrDgddxlLRDbNxT5x/eOX78obMA1Du3tfpuP7WuyfnA4GXaeckj/soJ2jiuD2sM4VIW9Q==} - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] + '@fastify/cookie@9.4.0': + resolution: {integrity: sha512-Th+pt3kEkh4MQD/Q2q1bMuJIB5NX/D5SwSpOKu3G/tjoGbwfpurIMJsWSPS0SJJ4eyjtmQ8OipDQspf8RbUOlg==} - '@esbuild/linux-arm@0.28.1': - resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] + '@fastify/cors@9.0.1': + resolution: {integrity: sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==} - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-ia32@0.24.2': - resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@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/cookie@9.4.0': - resolution: {integrity: sha512-Th+pt3kEkh4MQD/Q2q1bMuJIB5NX/D5SwSpOKu3G/tjoGbwfpurIMJsWSPS0SJJ4eyjtmQ8OipDQspf8RbUOlg==} - - '@fastify/cors@9.0.1': - resolution: {integrity: sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==} - - '@fastify/error@3.4.1': - resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} + '@fastify/error@3.4.1': + resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} '@fastify/fast-json-stringify-compiler@4.3.0': resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==} @@ -1384,8 +745,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==} @@ -1492,246 +853,249 @@ packages: engines: {node: '>=8.0.0', npm: '>=5.0.0'} hasBin: true - '@oxfmt/binding-android-arm-eabi@0.59.0': - resolution: {integrity: sha512-bNTnfbuG7sAwb2PakMNaDukx5kXeW9duXOBeWtTOiLz3fXz3q2DlWguufPZ+c2IHEVrRXHD+M4aUgEWm841LDA==} + '@oxc-project/types@0.150.0': + resolution: {integrity: sha512-rDS5/31E9HfPl/CIzGrn0DOlvBbXFseQ5URJ9sYMfstbKLD/c6Gm9vmRzRGDdAXyOIL4zmO37lc9RIwYqVruZw==} + + '@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] @@ -1739,151 +1103,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==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.62.2': - resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} + '@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: [musl] - '@rollup/rollup-linux-arm64-gnu@4.62.2': - resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} + '@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==} @@ -1900,38 +1222,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'} @@ -1944,30 +1242,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'} @@ -1980,69 +1262,69 @@ packages: resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} engines: {node: '>=14.0.0'} - '@tailwindcss/node@4.3.2': - resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==} + '@tailwindcss/node@4.3.3': + resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} - '@tailwindcss/oxide-android-arm64@4.3.2': - resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==} + '@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: @@ -2053,24 +1335,24 @@ 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 @@ -2081,59 +1363,53 @@ packages: '@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==} @@ -2144,11 +1420,8 @@ packages: '@types/jsonwebtoken@9.0.5': resolution: {integrity: sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==} - '@types/node@22.20.2': - resolution: {integrity: sha512-xlvWf4Vs9n1PEVYwP1n4vvG07M6y8WgvJ2t0vbrWTmijsIHp1cS+uJ2kMIRdY3nHZK0nCYKrPeD171+SzF4/zw==} - - '@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==} @@ -2171,13 +1444,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==} @@ -2194,40 +1467,155 @@ 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==} @@ -2269,12 +1657,13 @@ packages: avvio@8.4.0: resolution: {integrity: sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==} - 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 @@ -2287,8 +1676,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 @@ -2299,47 +1688,26 @@ 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==} @@ -2363,11 +1731,8 @@ packages: 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==} + constructs@10.8.1: + resolution: {integrity: sha512-98yGXYyhePqPYh3cYu8nzBERmAhC0DONe3UD03okK0nehZ7hYP4wgZuf02a04+uOWxnTJ5Rpp5m0GRNpwyLGGA==} cookie-signature@1.2.2: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} @@ -2404,10 +1769,6 @@ packages: supports-color: optional: true - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -2443,14 +1804,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: @@ -2465,33 +1823,14 @@ 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 - - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} - hasBin: true + es-module-lexer@2.3.2: + resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} - 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==} @@ -2562,11 +1901,6 @@ packages: 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} @@ -2576,10 +1910,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==} @@ -2612,29 +1942,16 @@ 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'} - hasBin: true - json-schema-ref-resolver@1.0.1: resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} 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==} engines: {node: '>=12', npm: '>=6'} @@ -2648,58 +1965,58 @@ packages: jws@3.2.3: resolution: {integrity: sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==} - 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: @@ -2717,30 +2034,60 @@ packages: 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'} @@ -2748,6 +2095,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'} @@ -2755,6 +2109,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'} @@ -2762,6 +2123,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'} @@ -2769,22 +2137,45 @@ 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'} + lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} @@ -2809,15 +2200,12 @@ packages: 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==} @@ -2830,8 +2218,8 @@ packages: 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 @@ -2850,10 +2238,6 @@ packages: 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==} @@ -2866,12 +2250,16 @@ packages: 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: @@ -2883,12 +2271,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: @@ -2938,13 +2326,6 @@ packages: 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==} @@ -2958,6 +2339,10 @@ packages: resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} + engines: {node: '>=12'} + pino-abstract-transport@2.0.0: resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} @@ -2968,18 +2353,18 @@ 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: @@ -3003,24 +2388,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: ^19.3.0 - react-refresh@0.17.0: - resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} - engines: {node: '>=0.10.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' @@ -3029,8 +2410,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: @@ -3044,8 +2425,8 @@ 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==} @@ -3058,9 +2439,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: @@ -3079,16 +2460,12 @@ 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==} + scheduler@0.28.0: + resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==} secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - semver@7.8.5: resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} engines: {node: '>=10'} @@ -3135,8 +2512,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==} @@ -3156,11 +2533,8 @@ packages: swagger-ui-dist@5.18.2: resolution: {integrity: sha512-J+y4mCw/zXh1FOj5wGJvnAajq6XgHOyywsa9yITmwxIlJbMqITq3gYRZHaeqLVH/eV/HOPphE6NjF+nbSNC5Zw==} - 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==} @@ -3172,32 +2546,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'} @@ -3219,13 +2583,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: @@ -3236,9 +2600,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: @@ -3252,24 +2616,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 @@ -3281,67 +2636,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: @@ -3357,23 +2679,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 @@ -3407,26 +2745,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 @@ -3441,88 +2776,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': @@ -3536,22 +2849,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 @@ -3560,26 +2857,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 @@ -3606,81 +2883,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 @@ -3690,48 +2892,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 @@ -3746,22 +2906,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 @@ -3780,44 +2924,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 @@ -3827,79 +2933,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': @@ -3913,13 +2997,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 @@ -3927,24 +3004,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 @@ -3954,14 +3013,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': @@ -3969,19 +3027,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)': - dependencies: - '@aws-sdk/client-dynamodb': 3.1087.0 - tslib: 2.8.1 - - '@aws-sdk/xml-builder@3.972.35': + '@aws-sdk/util-dynamodb@3.996.9(@aws-sdk/client-dynamodb@3.1136.0)': 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': @@ -3991,512 +3039,176 @@ 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) - class-transformer: 0.5.1 - class-validator: 0.14.4 - passport: 0.7.0 - passport-github2: 0.1.12 - passport-google-oauth20: 2.0.0 - reflect-metadata: 0.2.2 - 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)': - dependencies: - '@bubltec/mycota-config': 0.6.0 - aws-cdk-lib: 2.261.0(constructs@10.6.0) - constructs: 10.6.0 - - '@bubltec/mycota-config@0.6.0': - dependencies: - '@aws-sdk/client-ssm': 3.1088.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)': - 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 - - '@bubltec/mycota-mail@0.6.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-auth@0.6.0(@aws-sdk/client-dynamodb@3.1136.0)(supports-color@7.2.0)': 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) - class-transformer: 0.5.1 - class-validator: 0.14.4 - 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 + '@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': 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) + class-transformer: 0.5.1 + class-validator: 0.14.4 + passport: 0.7.0 + passport-github2: 0.1.12 + passport-google-oauth20: 2.0.0 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + transitivePeerDependencies: + - '@aws-sdk/client-dynamodb' + - '@nestjs/microservices' + - '@nestjs/platform-express' + - '@nestjs/websockets' + - encoding + - supports-color - '@esbuild/netbsd-arm64@0.25.12': - optional: true + '@bubltec/mycota-cdk@0.6.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.270.0(constructs@10.8.1) + constructs: 10.8.1 - '@esbuild/netbsd-arm64@0.28.1': - optional: true + '@bubltec/mycota-config@0.6.0': + dependencies: + '@aws-sdk/client-ssm': 3.1136.0 - '@esbuild/netbsd-x64@0.21.5': - optional: true + '@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)': + dependencies: + '@aws-sdk/client-dynamodb': 3.1136.0 + '@aws-sdk/lib-dynamodb': 3.1136.0(@aws-sdk/client-dynamodb@3.1136.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 - '@esbuild/netbsd-x64@0.24.2': - optional: true + '@bubltec/mycota-mail@0.6.0': {} - '@esbuild/netbsd-x64@0.25.12': - optional: true + '@bubltec/mycota-professional-verification@0.6.0(@aws-sdk/client-dynamodb@3.1136.0)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)': + dependencies: + '@bubltec/mycota-auth': 0.6.0(@aws-sdk/client-dynamodb@3.1136.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) + class-transformer: 0.5.1 + class-validator: 0.14.4 + transitivePeerDependencies: + - '@aws-sdk/client-dynamodb' + - '@nestjs/microservices' + - '@nestjs/platform-express' + - '@nestjs/websockets' + - encoding + - reflect-metadata + - rxjs + - supports-color - '@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': @@ -4548,17 +3260,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': @@ -4568,12 +3280,12 @@ 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': {} @@ -4669,202 +3381,174 @@ snapshots: transitivePeerDependencies: - encoding - '@oxfmt/binding-android-arm-eabi@0.59.0': + '@oxc-project/types@0.150.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 - - '@rollup/rollup-linux-arm-musleabihf@4.62.2': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.62.2': - optional: true + playwright: 1.63.0 - '@rollup/rollup-linux-arm64-musl@4.62.2': + '@rolldown/binding-android-arm-eabi@1.2.9': optional: true - '@rollup/rollup-linux-loong64-gnu@4.62.2': + '@rolldown/binding-android-arm64@1.2.9': optional: true - '@rollup/rollup-linux-loong64-musl@4.62.2': + '@rolldown/binding-darwin-arm64@1.2.9': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.62.2': + '@rolldown/binding-darwin-x64@1.2.9': optional: true - '@rollup/rollup-linux-ppc64-musl@4.62.2': + '@rolldown/binding-freebsd-x64@1.2.9': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.62.2': + '@rolldown/binding-linux-arm-gnueabihf@1.2.9': optional: true - '@rollup/rollup-linux-riscv64-musl@4.62.2': + '@rolldown/binding-linux-arm64-gnu@1.2.9': optional: true - '@rollup/rollup-linux-s390x-gnu@4.62.2': + '@rolldown/binding-linux-arm64-musl@1.2.9': optional: true - '@rollup/rollup-linux-x64-gnu@4.62.2': + '@rolldown/binding-linux-ppc64-gnu@1.2.9': optional: true - '@rollup/rollup-linux-x64-musl@4.62.2': + '@rolldown/binding-linux-s390x-gnu@1.2.9': optional: true - '@rollup/rollup-openbsd-x64@4.62.2': + '@rolldown/binding-linux-x64-gnu@1.2.9': optional: true - '@rollup/rollup-openharmony-arm64@4.62.2': + '@rolldown/binding-linux-x64-musl@1.2.9': optional: true - '@rollup/rollup-win32-arm64-msvc@4.62.2': + '@rolldown/binding-openharmony-arm64@1.2.9': optional: true - '@rollup/rollup-win32-ia32-msvc@4.62.2': + '@rolldown/binding-win32-arm64-msvc@1.2.9': optional: true - '@rollup/rollup-win32-x64-gnu@4.62.2': + '@rolldown/binding-win32-x64-msvc@1.2.9': optional: true - '@rollup/rollup-win32-x64-msvc@4.62.2': - optional: true + '@rolldown/pluginutils@1.0.1': {} '@scarf/scarf@1.4.0': {} @@ -4885,51 +3569,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 @@ -4946,39 +3596,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 @@ -4993,73 +3621,73 @@ snapshots: '@smithy/util-buffer-from': 2.2.0 tslib: 2.8.1 - '@tailwindcss/node@4.3.2': + '@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) + '@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.2.7(supports-color@7.2.0)': dependencies: @@ -5071,59 +3699,45 @@ snapshots: '@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 @@ -5131,26 +3745,22 @@ 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': dependencies: - '@types/node': 22.20.2 + '@types/node': 26.6.2 - '@types/node@22.20.2': - dependencies: - undici-types: 6.21.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: @@ -5178,22 +3788,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: @@ -5203,57 +3813,81 @@ 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 - '@vitest/spy@2.1.9': + '@typescript/typescript-win32-arm64@7.0.2': + optional: true + + '@typescript/typescript-win32-x64@7.0.2': + optional: true + + '@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) + + '@vitest/spy@5.0.1': {} abstract-logging@2.0.1: {} @@ -5287,14 +3921,14 @@ snapshots: '@fastify/error': 3.4.1 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: @@ -5304,43 +3938,21 @@ 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 + chai@6.2.2: {} chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - check-error@2.1.3: {} - cheerio-select@2.1.0: dependencies: boolbase: 1.0.0 @@ -5361,7 +3973,7 @@ 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: {} @@ -5380,9 +3992,7 @@ snapshots: consola@2.15.3: {} - constructs@10.6.0: {} - - convert-source-map@2.0.0: {} + constructs@10.8.1: {} cookie-signature@1.2.2: {} @@ -5414,8 +4024,6 @@ snapshots: optionalDependencies: supports-color: 7.2.0 - deep-eql@5.0.2: {} - detect-libc@2.1.2: {} diff@5.2.2: {} @@ -5448,14 +4056,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 @@ -5466,121 +4072,36 @@ 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: + esbuild@0.28.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: - 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: @@ -5674,16 +4195,11 @@ snapshots: 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: {} @@ -5709,22 +4225,16 @@ snapshots: jiti@2.7.0: {} - js-tokens@4.0.0: {} - js-yaml@4.1.0: dependencies: argparse: 2.0.1 - jsesc@3.1.0: {} - json-schema-ref-resolver@1.0.1: dependencies: fast-deep-equal: 3.1.3 json-schema-traverse@1.0.0: {} - json5@2.2.3: {} - jsonwebtoken@9.0.2: dependencies: jws: 3.2.3 @@ -5751,48 +4261,48 @@ snapshots: jwa: 1.4.2 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: {} @@ -5811,36 +4321,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 @@ -5857,6 +4400,22 @@ 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 + lodash.includes@4.3.0: {} lodash.isboolean@3.0.3: {} @@ -5873,15 +4432,13 @@ snapshots: 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: {} @@ -5895,7 +4452,7 @@ snapshots: ms@2.1.3: {} - nanoid@3.3.16: {} + nanoid@3.3.19: {} nise@6.1.5: dependencies: @@ -5910,8 +4467,6 @@ snapshots: dependencies: whatwg-url: 5.0.0 - node-releases@2.0.51: {} - nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -5922,53 +4477,55 @@ snapshots: 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: @@ -6015,10 +4572,6 @@ snapshots: path-to-regexp@8.4.2: {} - pathe@1.1.2: {} - - pathval@2.0.1: {} - pause-stream@0.0.11: dependencies: through: 2.3.8 @@ -6029,6 +4582,8 @@ snapshots: picomatch@4.0.5: {} + picomatch@4.0.7: {} + pino-abstract-transport@2.0.0: dependencies: split2: 4.2.0 @@ -6049,17 +4604,15 @@ 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 @@ -6080,28 +4633,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: {} @@ -6109,7 +4660,7 @@ snapshots: require-from-string@2.0.2: {} - reselect@5.2.0: {} + reselect@5.3.0: {} ret@0.4.3: {} @@ -6117,36 +4668,26 @@ snapshots: 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: @@ -6162,12 +4703,10 @@ snapshots: safer-buffer@2.1.2: {} - scheduler@0.27.0: {} + scheduler@0.28.0: {} secure-json-parse@2.7.0: {} - semver@6.3.1: {} - semver@7.8.5: {} set-cookie-parser@2.7.2: {} @@ -6210,7 +4749,7 @@ snapshots: stackback@0.0.2: {} - std-env@3.10.0: {} + std-env@4.2.0: {} stream-combiner@0.0.4: dependencies: @@ -6230,9 +4769,7 @@ snapshots: dependencies: '@scarf/scarf': 1.4.0 - tabbable@6.5.0: {} - - tailwindcss@4.3.2: {} + tailwindcss@4.3.3: {} tapable@2.3.3: {} @@ -6242,22 +4779,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: {} - - tinyrainbow@1.2.0: {} - - tinyspy@3.0.2: {} + tinypool@2.1.2: {} toad-cache@3.7.4: {} @@ -6269,36 +4800,57 @@ snapshots: 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: {} @@ -6308,103 +4860,52 @@ snapshots: uint8array-extras@1.5.0: {} - undici-types@6.21.0: {} - undici-types@8.9.0: {} - undici@7.29.0: {} - - update-browserslist-db@1.2.3(browserslist@4.28.6): - dependencies: - browserslist: 4.28.6 - escalade: 3.2.0 - picocolors: 1.1.1 + undici@7.29.1: {} - use-sync-external-store@1.6.0(react@19.2.7): + use-sync-external-store@1.7.0(react@19.3.0): 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): - 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): + vite@8.3.0(@types/node@26.6.2)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.13): 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: {} @@ -6427,5 +4928,3 @@ snapshots: dependencies: siginfo: 2.0.0 stackback: 0.0.2 - - yallist@3.1.1: {} From d7cb73bf079a2f9e059d0f636dc521c9081cf362 Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 16:56:50 -0400 Subject: [PATCH 08/16] chore: save exact versions, and read the Node version from .nvmrc in CI - Add .npmrc with save-exact=true and `saveExact: true` in pnpm-workspace.yaml. Both are needed: tested against pnpm 11.20, `.npmrc` alone is ignored (a bare `pnpm add x` still wrote a caret range) while the workspace setting works. The .npmrc keeps npm and older pnpm consistent. This affects new additions; the existing ranges are pinned in the follow-up upgrade change. - CI and deploy workflows use `node-version-file: .nvmrc` instead of a hard-coded `node-version: 26` (7 places), so the Node version is changed in one place. --- .github/workflows/ci.yml | 2 +- .github/workflows/deploy.yml | 12 ++++++------ .npmrc | 4 ++++ pnpm-workspace.yaml | 2 ++ 4 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 .npmrc 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/pnpm-workspace.yaml b/pnpm-workspace.yaml index c1ec6cc..4bf7c4a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -10,6 +10,8 @@ allowBuilds: '@scarf/scarf': false esbuild: true lefthook: true +# Pin exact versions when adding dependencies. Kept in sync with .npmrc. +saveExact: 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. From 80334b5763099a1e86016cebc2cac4f8f29d044e Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 16:59:37 -0400 Subject: [PATCH 09/16] chore: pin every dependency to an exact version, and declare @types/node in shared-types Follows the save-exact setting: convert the existing caret ranges in all package.json files (89 specs) to exact versions. Each one is pinned to the version that is actually installed (read from `pnpm ls`), not to the floor of its old range. That matters: stripping the caret would have silently downgraded four packages (@nestjs/common, @nestjs/core and @nestjs/platform-fastify to 10.4.0, and class-validator to 0.14.1, instead of the installed 10.4.22 and 0.14.4). No resolved version changes from the pinning itself: the lockfile diff for it contains only `specifier:` lines. Also fixes a latent bug from the TypeScript 7 upgrade: packages/shared-types extends the Node tsconfig preset (which now sets "types": ["node"]) but never declared @types/node. It only compiled because a hoisted copy happened to exist at the repo root, so the previous commit passed by luck and failed after a clean reinstall (TS2688 "Cannot find type definition file for 'node'"). It is now an explicit devDependency. Verified from scratch: wiped every node_modules, `pnpm install --frozen-lockfile`, then typecheck, build and test across all workspaces except e2e (16 tasks). --- apps/bff/package.json | 62 ++++----- apps/e2e/package.json | 10 +- apps/scraper/package.json | 28 ++--- apps/web/package.json | 26 ++-- data/seed/package.json | 18 +-- infra/cdk/package.json | 20 +-- package.json | 10 +- packages/shared-types/package.json | 5 +- pnpm-lock.yaml | 195 ++++++++++++++--------------- 9 files changed, 186 insertions(+), 188 deletions(-) diff --git a/apps/bff/package.json b/apps/bff/package.json index 3f1cae9..462a285 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.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", + "@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.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" + "@fastify/aws-lambda": "4.1.0", + "@fastify/cookie": "9.4.0", + "@nestjs/common": "10.4.22", + "@nestjs/config": "3.3.0", + "@nestjs/core": "10.4.22", + "@nestjs/jwt": "10.2.0", + "@nestjs/passport": "10.0.3", + "@nestjs/platform-fastify": "10.4.22", + "@nestjs/swagger": "8.1.1", + "class-transformer": "0.5.1", + "class-validator": "0.14.4", + "fastify": "4.28.1", + "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": { - "@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" + "@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/e2e/package.json b/apps/e2e/package.json index 61316f8..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.1136.0" + "@aws-sdk/client-bedrock-runtime": "3.1136.0" }, "devDependencies": { - "@playwright/test": "^1.63.0", - "@types/node": "^26.6.2", - "tsx": "^4.23.13", - "typescript": "^7.0.2" + "@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 8a94409..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.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", + "@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.6.2", - "@smithy/signature-v4": "^5.7.3", - "playwright-core": "^1.63.0" + "@smithy/protocol-http": "5.6.2", + "@smithy/signature-v4": "5.7.3", + "playwright-core": "1.63.0" }, "devDependencies": { - "@types/node": "^26.6.2", - "aws-sdk-client-mock": "^4.1.0", - "esbuild": "^0.28.2", - "typescript": "^7.0.2", - "vitest": "^5.0.1" + "@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/web/package.json b/apps/web/package.json index a521083..5ae2432 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -10,21 +10,21 @@ "prerender": "node scripts/prerender.mjs" }, "dependencies": { - "@base-ui/react": "^1.8.0", + "@base-ui/react": "1.8.0", "@btfp/shared-types": "workspace:*", - "react": "^19.3.0", - "react-dom": "^19.3.0", - "react-router-dom": "^7.18.4" + "react": "19.3.0", + "react-dom": "19.3.0", + "react-router-dom": "7.18.4" }, "devDependencies": { - "@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" + "@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/data/seed/package.json b/data/seed/package.json index 0462d0f..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.1136.0", - "@aws-sdk/client-dynamodb": "^3.1136.0", - "@aws-sdk/lib-dynamodb": "^3.1136.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.2.0" + "cheerio": "1.2.0" }, "devDependencies": { - "@types/node": "^26.6.2", - "aws-sdk-client-mock": "^4.1.0", - "tsx": "^4.23.13", - "typescript": "^7.0.2", - "vitest": "^5.0.1" + "@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/infra/cdk/package.json b/infra/cdk/package.json index 128d95c..d1d0bfc 100644 --- a/infra/cdk/package.json +++ b/infra/cdk/package.json @@ -14,18 +14,18 @@ "devDependencies": { "@btfp/bff": "workspace:*", "@btfp/scraper": "workspace:*", - "@types/node": "^26.6.2", - "aws-cdk": "^2.1142.0", - "tsx": "^4.23.13", - "typescript": "^7.0.2", - "vitest": "^5.0.1" + "@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.1136.0", - "@aws-sdk/client-sts": "^3.1136.0", + "@aws-sdk/client-ssm": "3.1136.0", + "@aws-sdk/client-sts": "3.1136.0", "@bubltec/mycota-cdk": "0.6.0", - "aws-cdk-lib": "^2.270.0", - "constructs": "^10.8.1", - "source-map-support": "^0.5.21" + "aws-cdk-lib": "2.270.0", + "constructs": "10.8.1", + "source-map-support": "0.5.21" } } diff --git a/package.json b/package.json index dd338fd..d11af0f 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,10 @@ "mycota:pull": "bash scripts/mycota-pull.sh" }, "devDependencies": { - "lefthook": "^2.1.14", - "oxfmt": "^0.68.0", - "oxlint": "^1.83.0", - "turbo": "^2.11.2", - "typescript": "^7.0.2" + "lefthook": "2.1.14", + "oxfmt": "0.68.0", + "oxlint": "1.83.0", + "turbo": "2.11.2", + "typescript": "7.0.2" } } diff --git a/packages/shared-types/package.json b/packages/shared-types/package.json index e3bb107..fd0c207 100644 --- a/packages/shared-types/package.json +++ b/packages/shared-types/package.json @@ -17,7 +17,8 @@ "test": "vitest run" }, "devDependencies": { - "typescript": "^7.0.2", - "vitest": "^5.0.1" + "@types/node": "26.6.2", + "typescript": "7.0.2", + "vitest": "5.0.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 263b496..19d1c60 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,37 +9,37 @@ importers: .: devDependencies: lefthook: - specifier: ^2.1.14 + specifier: 2.1.14 version: 2.1.14 oxfmt: - specifier: ^0.68.0 + specifier: 0.68.0 version: 0.68.0 oxlint: - specifier: ^1.83.0 + specifier: 1.83.0 version: 1.83.0 turbo: - specifier: ^2.11.2 + specifier: 2.11.2 version: 2.11.2 typescript: - specifier: ^7.0.2 + specifier: 7.0.2 version: 7.0.2 apps/bff: dependencies: '@aws-sdk/client-bedrock-runtime': - specifier: ^3.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/client-dynamodb': - specifier: ^3.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/client-ses': - specifier: ^3.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/client-ssm': - specifier: ^3.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/lib-dynamodb': - specifier: ^3.1136.0 + specifier: 3.1136.0 version: 3.1136.0(@aws-sdk/client-dynamodb@3.1136.0) '@btfp/shared-types': specifier: workspace:* @@ -54,252 +54,252 @@ importers: specifier: 0.6.0 version: 0.6.0(@aws-sdk/client-dynamodb@3.1136.0)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0) '@fastify/aws-lambda': - specifier: ^4.1.0 + specifier: 4.1.0 version: 4.1.0 '@fastify/cookie': - specifier: ^9.4.0 + specifier: 9.4.0 version: 9.4.0 '@nestjs/common': - specifier: ^10.4.0 + specifier: 10.4.22 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) '@nestjs/config': - specifier: ^3.3.0 + 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) '@nestjs/core': - specifier: ^10.4.0 + specifier: 10.4.22 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) '@nestjs/jwt': - specifier: ^10.2.0 + 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)) '@nestjs/passport': - specifier: ^10.0.3 + 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) '@nestjs/platform-fastify': - specifier: ^10.4.0 + specifier: 10.4.22 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)) '@nestjs/swagger': - specifier: ^8.1.1 + 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) class-transformer: - specifier: ^0.5.1 + specifier: 0.5.1 version: 0.5.1 class-validator: - specifier: ^0.14.1 + specifier: 0.14.4 version: 0.14.4 fastify: - specifier: ^4.28.1 + specifier: 4.28.1 version: 4.28.1 fuse.js: - specifier: ^7.5.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.2 + specifier: 7.8.2 version: 7.8.2 devDependencies: '@types/node': - specifier: ^26.6.2 + 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.17 + 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.28.2 + specifier: 0.28.2 version: 0.28.2 tsc-watch: - specifier: ^7.2.1 + specifier: 7.2.1 version: 7.2.1(typescript@7.0.2) typescript: - specifier: ^7.0.2 + specifier: 7.0.2 version: 7.0.2 vitest: - specifier: ^5.0.1 + 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.1136.0 + specifier: 3.1136.0 version: 3.1136.0 devDependencies: '@playwright/test': - specifier: ^1.63.0 + specifier: 1.63.0 version: 1.63.0 '@types/node': - specifier: ^26.6.2 + specifier: 26.6.2 version: 26.6.2 tsx: - specifier: ^4.23.13 + specifier: 4.23.13 version: 4.23.13 typescript: - specifier: ^7.0.2 + 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.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/client-bedrock-runtime': - specifier: ^3.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/client-dynamodb': - specifier: ^3.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/credential-provider-node': - specifier: ^3.972.83 + specifier: 3.972.83 version: 3.972.83 '@aws-sdk/lib-dynamodb': - specifier: ^3.1136.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.6.2 + specifier: 5.6.2 version: 5.6.2 '@smithy/signature-v4': - specifier: ^5.7.3 + specifier: 5.7.3 version: 5.7.3 playwright-core: - specifier: ^1.63.0 + specifier: 1.63.0 version: 1.63.0 devDependencies: '@types/node': - specifier: ^26.6.2 + 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.28.2 + specifier: 0.28.2 version: 0.28.2 typescript: - specifier: ^7.0.2 + specifier: 7.0.2 version: 7.0.2 vitest: - specifier: ^5.0.1 + 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/react': - specifier: ^1.8.0 + 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.3.0 + specifier: 19.3.0 version: 19.3.0 react-dom: - specifier: ^19.3.0 + specifier: 19.3.0 version: 19.3.0(react@19.3.0) react-router-dom: - specifier: ^7.18.4 + 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.63.0 + specifier: 1.63.0 version: 1.63.0 '@tailwindcss/vite': - specifier: ^4.3.3 + 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.2 + specifier: 26.6.2 version: 26.6.2 '@types/react': - specifier: ^19.3.0 + specifier: 19.3.0 version: 19.3.0 '@types/react-dom': - specifier: ^19.3.0 + specifier: 19.3.0 version: 19.3.0(@types/react@19.3.0) '@vitejs/plugin-react': - specifier: ^6.1.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.3.3 + specifier: 4.3.3 version: 4.3.3 typescript: - specifier: ^7.0.2 + specifier: 7.0.2 version: 7.0.2 vite: - specifier: ^8.3.0 + 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.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/client-dynamodb': - specifier: ^3.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/lib-dynamodb': - specifier: ^3.1136.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.2.0 + specifier: 1.2.0 version: 1.2.0 devDependencies: '@types/node': - specifier: ^26.6.2 + 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.23.13 + specifier: 4.23.13 version: 4.23.13 typescript: - specifier: ^7.0.2 + specifier: 7.0.2 version: 7.0.2 vitest: - specifier: ^5.0.1 + 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.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@aws-sdk/client-sts': - specifier: ^3.1136.0 + specifier: 3.1136.0 version: 3.1136.0 '@bubltec/mycota-cdk': specifier: 0.6.0 version: 0.6.0(aws-cdk-lib@2.270.0(constructs@10.8.1))(constructs@10.8.1) aws-cdk-lib: - specifier: ^2.270.0 + specifier: 2.270.0 version: 2.270.0(constructs@10.8.1) constructs: - specifier: ^10.8.1 + 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,30 +309,33 @@ importers: specifier: workspace:* version: link:../../apps/scraper '@types/node': - specifier: ^26.6.2 + specifier: 26.6.2 version: 26.6.2 aws-cdk: - specifier: ^2.1142.0 + specifier: 2.1142.0 version: 2.1142.0 tsx: - specifier: ^4.23.13 + specifier: 4.23.13 version: 4.23.13 typescript: - specifier: ^7.0.2 + specifier: 7.0.2 version: 7.0.2 vitest: - specifier: ^5.0.1 + 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: ^7.0.2 + specifier: 7.0.2 version: 7.0.2 vitest: - specifier: ^5.0.1 + 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: @@ -2335,10 +2338,6 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@4.0.5: - resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} - engines: {node: '>=12'} - picomatch@4.0.7: resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} engines: {node: '>=12'} @@ -4170,9 +4169,9 @@ 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: {} @@ -4580,8 +4579,6 @@ snapshots: picocolors@1.1.1: {} - picomatch@4.0.5: {} - picomatch@4.0.7: {} pino-abstract-transport@2.0.0: @@ -4785,8 +4782,8 @@ snapshots: tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 tinypool@2.1.2: {} From f15ff99d29bea780fe01bd1e7aaf0fb72885b09a Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 17:05:33 -0400 Subject: [PATCH 10/16] docs: correct the architecture rule and record what we learned The rule I wrote earlier praised things that turned out to be weak and did not cover what changed since. Corrections: - lambda-canary.ts is no longer "the model": the SAM transform it used was replaced by a native alias and deployment group, and the rule now says why (five follow-up fixes and a manual migration step). The alias is `current`, not `live`. - SearchService.invalidate() only clears the cache in one container; stated. - Validation: the pipe options are one exported constant, and unknown fields are a 400 (forbidNonWhitelisted) rather than silently dropped. - Fail-closed configuration is now enforced (requireInProduction, corsOrigin), not just advised. - CDK tests exist now; "verification" says so, and requires a before/after synth diff for aws-cdk-lib bumps. Added: logging and alerts, the TypeScript 7 `types`/@types/node requirement, exact-pin policy (pin to the installed version, never strip the caret), the mycota peer-dependency and "upgrade mycota first" workflow, the single Fastify override, Node from .nvmrc, the pnpm 11 quirks (.npmrc save-exact is ignored; the env prefix is pnpm_config_), and four new pitfalls, including the ESM-first `import.meta.url` bundle crash that no unit test could catch. Also a Known Deviations section listing what the repo still does not do (plaintext JWT/Brave env vars, actions pinned by tag not SHA, default oxlint rules, full-table Scan, single AWS account, DTO/shared-types duplication) and the two pieces of work that are written but not yet committed or released. --- .../bff-typescript-cdk-best-practices.mdc | 70 +++++++++++++++---- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/.cursor/rules/bff-typescript-cdk-best-practices.mdc b/.cursor/rules/bff-typescript-cdk-best-practices.mdc index 8582776..3e60138 100644 --- a/.cursor/rules/bff-typescript-cdk-best-practices.mdc +++ b/.cursor/rules/bff-typescript-cdk-best-practices.mdc @@ -72,10 +72,11 @@ root-project/ │ ├── config/ │ └── shared-types/ ├── scripts/ +├── .npmrc ├── .nvmrc ├── .oxfmtrc.json ├── .oxlintrc.json -├── CLAUDE.md +├── AGENTS.md / CLAUDE.md # pointers only; the rules live in .cursor/rules/ ├── lefthook.yml ├── package.json ├── pnpm-lock.yaml @@ -92,13 +93,14 @@ Each file owns one concern. Put a setting in the most specific place that owns i | 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 | +| `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` | Local Node version | +| `.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 @@ -128,13 +130,15 @@ Each file owns one concern. Put a setting in the most specific place that owns i * 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` runs with `whitelist: true, transform: true`. Consequences you must design for: - * **Every DTO property needs at least one validator decorator,** otherwise `whitelist` silently strips it. +* 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`. @@ -148,14 +152,14 @@ Each file owns one concern. Put a setting in the most specific place that owns i ### 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. +* 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()` so the 60s cache does not serve stale rows. +* 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 @@ -165,10 +169,17 @@ Each file owns one concern. Put a setting in the most specific place that owns i * 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. +* 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. @@ -192,17 +203,19 @@ Each file owns one concern. Put a setting in the most specific place that owns i ### Resources -* Prefer L2 constructs. Drop to L1 or `addPropertyOverride` only when no L2 covers it, and isolate it in a documented helper (`lambda-canary.ts` is the model: the reason, the migration caveat, and the failure mode are all written down). +* 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 `live` alias, never `$LATEST`. Prod uses a canary with an alarm that rolls back; dev uses all-at-once. +* **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 (recommended, not adopted yet) +### Verification -* **(recommended)** Add `aws-cdk-lib/assertions` tests under `infra/cdk` for the properties that matter: prod tables `RETAIN` + PITR on, Lambda role has no `*` actions, canary configured for prod. Run them in the turbo `test` task. +* 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. @@ -214,6 +227,8 @@ Each file owns one concern. Put a setting in the most specific place that owns i * 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 @@ -223,6 +238,15 @@ Each file owns one concern. Put a setting in the most specific place that owns i * `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`. @@ -235,7 +259,8 @@ Each file owns one concern. Put a setting in the most specific place that owns i * 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. -* Pin third-party actions to a major version at minimum. +* 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 @@ -250,11 +275,28 @@ Each file owns one concern. Put a setting in the most specific place that owns i * **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 `live` alias** bypasses canary and rollback. +* **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. +* **NestJS 12 / Fastify 5 are prepared on branch `chore/nest-12-upgrade` but not released.** It waits on the mycota major release and needs its lockfile regenerated afterwards. + By following these practices, you keep the BFF, shared packages, and infrastructure consistent, secure, cheap to run, and easy to change. From 1a8112942962f697befb0a4e8de663b9f5c03e7b Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 17:14:56 -0400 Subject: [PATCH 11/16] chore: require Node 26 and enforce it The root `engines` still said >=24 although .nvmrc, CI, the Lambda image and @types/node are all Node 26. Raise it to >=26 and set `engineStrict` so a wrong Node version fails the install instead of only warning. Only `engineStrict` in pnpm-workspace.yaml is honored by pnpm 11; `engine-strict` in .npmrc is ignored. Verified: install under strict engines, then typecheck, build and test across all workspaces except e2e. --- package.json | 2 +- pnpm-workspace.yaml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d11af0f..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": { diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4bf7c4a..80641c8 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -12,6 +12,9 @@ allowBuilds: 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. From e24ab4c50535b9576eb40f5c827c61137491ef27 Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 17:02:49 -0400 Subject: [PATCH 12/16] chore: upgrade to NestJS 12, Fastify 5 and class-validator 0.15 (mycota 1.0.0) Bumped, all as exact pins: - @nestjs/common, core, platform-fastify 10.4 -> 12.0.3; @nestjs/jwt 12.0.2, @nestjs/passport 12.0.0, @nestjs/config 3.3 -> 12.0.0, @nestjs/swagger 8 -> 12.0.1 - fastify 4 -> 5.12.5, @fastify/cookie 9 -> 11.1.2, @fastify/aws-lambda 4 -> 6.4.1 - class-validator 0.14 -> 0.15.1 - @bubltec/mycota-auth, -dynamo, -professional-verification, -cdk -> 1.0.0 mycota 1.0.0 declares NestJS and class-validator as peer dependencies, so this app owns the single copy. Confirmed in the regenerated lockfile and with `pnpm why`: one @nestjs/common@12.0.3, one fastify, one class-validator, no Nest 10 entries, and every mycota package resolves to the published 1.0.0. Two things this upgrade required: 1. Bundle crashed at startup. @nestjs/swagger 12 is ESM-first and runs `createRequire(import.meta.url)` at load time; esbuild turns import.meta into an empty object in our CommonJS bundle, so it threw and the Lambda could not start (every cold start would have failed). Typecheck and unit tests cannot catch this. build-lambda.mjs now defines import.meta.url via a banner. The UI asset lookup after it only runs from SwaggerModule.setup, which we never call. 2. Two Fastify copies. @nestjs/platform-fastify pins fastify to an exact version as a regular dependency, so the app's own fastify installed a second copy and the @fastify/cookie plugin types stopped lining up (TS2345). A workspace override keeps a single copy; keep it equal to apps/bff's fastify version. No application code changes were needed. Verified from a wiped node_modules with `pnpm install --frozen-lockfile` against the published packages: - typecheck, build, lint, format and unit tests pass (16 turbo tasks, twice) - the real production Lambda bundle, driven with real requests: swagger document generates (200); mycota's JwtAuthGuard and VerifiedGuard resolve through DI and reject anonymous callers (401); mycota's own DTO is validated by class-validator (400 "email must be an email"), which only works with a single copy; strict forbidNonWhitelisted applies to that DTO too (400); unknown routes 404; no error-level log events - cdk synth: every stack identical to before except the Api stacks' image-derived Version/Alias hashes --- apps/bff/package.json | 28 +- apps/bff/scripts/build-lambda.mjs | 5 + infra/cdk/package.json | 2 +- pnpm-lock.yaml | 818 +++++++++++++----------------- pnpm-workspace.yaml | 6 + 5 files changed, 388 insertions(+), 471 deletions(-) diff --git a/apps/bff/package.json b/apps/bff/package.json index 462a285..c319c4d 100644 --- a/apps/bff/package.json +++ b/apps/bff/package.json @@ -16,21 +16,21 @@ "@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.22", - "@nestjs/config": "3.3.0", - "@nestjs/core": "10.4.22", - "@nestjs/jwt": "10.2.0", - "@nestjs/passport": "10.0.3", - "@nestjs/platform-fastify": "10.4.22", - "@nestjs/swagger": "8.1.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.14.4", - "fastify": "4.28.1", + "class-validator": "0.15.1", + "fastify": "5.12.5", "fuse.js": "7.5.0", "passport": "0.7.0", "passport-github2": "0.1.12", diff --git a/apps/bff/scripts/build-lambda.mjs b/apps/bff/scripts/build-lambda.mjs index 1d24b16..a187545 100644 --- a/apps/bff/scripts/build-lambda.mjs +++ b/apps/bff/scripts/build-lambda.mjs @@ -34,6 +34,11 @@ 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 diff --git a/infra/cdk/package.json b/infra/cdk/package.json index d1d0bfc..6644ae2 100644 --- a/infra/cdk/package.json +++ b/infra/cdk/package.json @@ -23,7 +23,7 @@ "dependencies": { "@aws-sdk/client-ssm": "3.1136.0", "@aws-sdk/client-sts": "3.1136.0", - "@bubltec/mycota-cdk": "0.6.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/pnpm-lock.yaml b/pnpm-lock.yaml index 19d1c60..3981b44 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + fastify: 5.12.5 + importers: .: @@ -45,50 +48,50 @@ importers: specifier: workspace:* version: link:../../packages/shared-types '@bubltec/mycota-auth': - specifier: 0.6.0 - version: 0.6.0(@aws-sdk/client-dynamodb@3.1136.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.1136.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.22 - 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.22 - 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.22 - 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 version: 0.5.1 class-validator: - specifier: 0.14.4 - 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.5.0 version: 7.5.0 @@ -290,8 +293,8 @@ importers: specifier: 3.1136.0 version: 3.1136.0 '@bubltec/mycota-cdk': - specifier: 0.6.0 - version: 0.6.0(aws-cdk-lib@2.270.0(constructs@10.8.1))(constructs@10.8.1) + 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.270.0 version: 2.270.0(constructs@10.8.1) @@ -518,27 +521,43 @@ 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-dynamo@1.0.0': + resolution: {integrity: sha512-KyqvmWUxii9lAFyeZnbjJUCC2dSYh2UKHLOX6whbafhZuHAEC9LybTTGFBJXhHobKHz4eCpizx4aqnFPTT/tSg==} + peerDependencies: + '@nestjs/common': ^12.0.0 - '@bubltec/mycota-mail@0.6.0': - resolution: {integrity: sha512-8srkw5+3cFfaPAsv0Vh8QIx2aSo3ENUzO0P9ixZdpkS4o/t0Raq1M+bNjdoimQkiS179Me9VGL9aJPnKqL/y+A==} + '@bubltec/mycota-mail@1.0.0': + resolution: {integrity: sha512-Hm91O1ZaXkdpYjohgyV5xYawHEYDQYvQUlKSxJuzWAYsngh7yfWITNRZ9DdRNWlyMGTowYud0QigIUhDWaskIA==} - '@bubltec/mycota-professional-verification@0.6.0': - resolution: {integrity: sha512-RFRid9/dGe5/tLdtHt3dLtWl4ctjsjIadJKixYJwS/4BocGygg+6h/Da1/iTECEISEV4L5YsqAuRyoEC7nsR0Q==} + '@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.28.2': resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==} @@ -696,32 +715,38 @@ packages: cpu: [x64] os: [win32] - '@fastify/ajv-compiler@3.6.0': - resolution: {integrity: sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==} + '@fastify/ajv-compiler@4.0.6': + resolution: {integrity: sha512-NtuzM0SfaMJbGlnjr9LWQUN5LzgSrbB8tf/wRZNas+4E1O/Nmzl53e7ruT61HDZyRCJGC6FxIogmNZO1c5ETBA==} + + '@fastify/aws-lambda@6.4.1': + resolution: {integrity: sha512-eTCkZJ8b4NAyafxChyM1VSVMUK1KnlyXj7NBfrQm8dRcXj42X8je5poyaZDZ9T5XTyykl3oLMiI4IvZJWXzLsw==} + + '@fastify/cookie@11.1.2': + resolution: {integrity: sha512-Dtrpk/YOGUsbRMvP/8ZqPpwnMRv0qSqodFdoQ2B589Obc7jw4s4Qla+cV72Bsm7WsZJnqlYFX/i7uSBq0xzg6g==} - '@fastify/aws-lambda@4.1.0': - resolution: {integrity: sha512-293HSdtr4muZZi4UxjrDgddxlLRDbNxT5x/eOX78obMA1Du3tfpuP7WuyfnA4GXaeckj/soJ2jiuD2sM4VIW9Q==} + '@fastify/cors@11.3.0': + resolution: {integrity: sha512-ggQGua+xHv1MvePbPr0v//xLYEsCXbWspquXCJS9Ot5YoRXq8J8ZWzHnxDBVnbtXosvistXo6LtNzOJswf64Fw==} - '@fastify/cookie@9.4.0': - resolution: {integrity: sha512-Th+pt3kEkh4MQD/Q2q1bMuJIB5NX/D5SwSpOKu3G/tjoGbwfpurIMJsWSPS0SJJ4eyjtmQ8OipDQspf8RbUOlg==} + '@fastify/error@4.2.0': + resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==} - '@fastify/cors@9.0.1': - resolution: {integrity: sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==} + '@fastify/fast-json-stringify-compiler@5.1.0': + resolution: {integrity: sha512-PxcYtKLbQ8Z+yApiqjK8FwxIwvEj38k2OiLc17u8dkJSlmfi2wHHPaSnaoqBPQqtvF8YVsDgDpP2snDCfFrpfw==} - '@fastify/error@3.4.1': - resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} + '@fastify/formbody@9.0.0': + resolution: {integrity: sha512-T/af26CSrUARBCvsEmv+DJLPfZlrRKESzqironxP1j7qzuLyKcoZtj6MuTGShuKx1THXugoie2oFbUJxXfGFzA==} - '@fastify/fast-json-stringify-compiler@4.3.0': - resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==} + '@fastify/forwarded@3.0.2': + resolution: {integrity: sha512-NE8HgKLgYejV9lDpqkEFaDKMLYelJBVfHekhB0UKvX0ghagXRJqg68feg8er1NPXxG4N9i6vPxzt8E+3wHfcmA==} - '@fastify/formbody@7.4.0': - resolution: {integrity: sha512-H3C6h1GN56/SMrZS8N2vCT2cZr7mIHzBHzOBa5OPpjfB/D6FzP9mMpE02ZzrFX0ANeh0BAJdoXKOF2e7IbV+Og==} + '@fastify/merge-json-schemas@0.2.1': + resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} - '@fastify/merge-json-schemas@0.1.1': - resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} + '@fastify/middie@9.3.4': + resolution: {integrity: sha512-dd8phTnVWzx3iKPBKSvtRUT8+Igvy/MP+P5HcY2tjejEyeVbyjkD4HgzKessUObue5RRM5J6PZdxtAqgbn84yw==} - '@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==} @@ -758,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: @@ -774,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: @@ -797,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: @@ -815,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 @@ -851,11 +879,6 @@ 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==} @@ -1265,6 +1288,9 @@ packages: resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} engines: {node: '>=14.0.0'} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@tailwindcss/node@4.3.3': resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} @@ -1359,8 +1385,8 @@ packages: 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': @@ -1420,8 +1446,11 @@ 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/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} '@types/node@26.6.2': resolution: {integrity: sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==} @@ -1623,14 +1652,6 @@ packages: 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: @@ -1642,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==} @@ -1657,8 +1674,8 @@ 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.270.0: resolution: {integrity: sha512-xoO9FEqcVTTK39N6n+LxvAAsS5WZSGX/p+uv3l2W+LXDEIWctq6VECdluuFwdXnbyf4v4eIxo2btrkUepnEy0Q==} @@ -1707,10 +1724,6 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} @@ -1721,34 +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==} - - consola@2.15.3: - resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} + class-validator@0.15.1: + resolution: {integrity: sha512-LqoS80HBBSCVhz/3KloUly0ovokxpdOLR++Al3J3+dHXWt9sTKlKd4eYtoxhxyUjoe5+UcIM+5k9MIxyBWnRTw==} constructs@10.8.1: resolution: {integrity: sha512-98yGXYyhePqPYh3cYu8nzBERmAhC0DONe3UD03okK0nehZ7hYP4wgZuf02a04+uOWxnTJ5Rpp5m0GRNpwyLGGA==} - 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'} - 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'} @@ -1772,6 +1771,10 @@ packages: supports-color: optional: true + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -1793,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: @@ -1829,6 +1832,9 @@ packages: es-module-lexer@2.3.2: resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} + es-toolkit@1.51.0: + resolution: {integrity: sha512-zC2lQGkM7QX+Gm6iM3+WIdZJzthsEd14LvRNJneSO2hzyz/zNBENR8+YXWo1cKxgPBtV6ksPYHELbcwBRzmdCw==} + esbuild@0.28.2: resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==} engines: {node: '>=18'} @@ -1844,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==} @@ -1862,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==} @@ -1886,20 +1889,13 @@ 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==} @@ -1930,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==} @@ -1945,28 +1941,28 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + 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==} - 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@2.1.14: resolution: {integrity: sha512-VMUAqY81+8ph7Mc0iROd3JWqj2sOuK7SYDyd8ZgzYVKChCt+Nnz8ehd4gUwprJy7QI28IFSUh1M3wnIRiYh+fA==} @@ -2025,12 +2021,12 @@ packages: 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'} @@ -2179,6 +2175,10 @@ packages: 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==} @@ -2200,9 +2200,6 @@ packages: lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -2215,9 +2212,6 @@ packages: 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==} @@ -2232,15 +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 - nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -2250,9 +2235,6 @@ 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'} @@ -2320,12 +2302,6 @@ 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==} @@ -2366,18 +2342,14 @@ packages: 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==} @@ -2427,8 +2399,8 @@ packages: 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: @@ -2449,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==} @@ -2462,8 +2435,8 @@ packages: scheduler@0.28.0: resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==} - secure-json-parse@2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + secure-json-parse@4.1.0: + resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} semver@7.8.5: resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} @@ -2529,8 +2502,8 @@ 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==} tailwindcss@4.3.3: resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} @@ -2569,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'} @@ -2719,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'} @@ -2731,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'} @@ -3065,20 +3029,20 @@ snapshots: '@borewit/text-codec@0.2.2': {} - '@bubltec/mycota-auth@0.6.0(@aws-sdk/client-dynamodb@3.1136.0)(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)': 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': 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-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 @@ -3086,51 +3050,39 @@ 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.270.0(constructs@10.8.1))(constructs@10.8.1)': + '@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 + '@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.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.1136.0 '@aws-sdk/lib-dynamodb': 3.1136.0(@aws-sdk/client-dynamodb@3.1136.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 + '@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.1136.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.1136.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 + - '@nestjs/core' + - '@nestjs/jwt' + - '@nestjs/passport' + - passport - reflect-metadata - rxjs - - supports-color '@esbuild/aix-ppc64@0.28.2': optional: true @@ -3210,46 +3162,54 @@ snapshots: '@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/forwarded@3.0.2': {} - '@fastify/merge-json-schemas@0.1.1': + '@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 @@ -3288,97 +3248,92 @@ snapshots: '@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 - - '@nuxtjs/opencollective@0.3.2': - dependencies: - chalk: 4.1.2 - consola: 2.15.3 - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding + class-validator: 0.15.1 '@oxc-project/types@0.150.0': {} @@ -3620,6 +3575,8 @@ snapshots: '@smithy/util-buffer-from': 2.2.0 tslib: 2.8.1 + '@standard-schema/spec@1.1.0': {} + '@tailwindcss/node@4.3.3': dependencies: '@jridgewell/remapping': 2.3.5 @@ -3688,10 +3645,9 @@ snapshots: 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.2.7(supports-color@7.2.0)': + '@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 @@ -3749,10 +3705,13 @@ snapshots: '@types/http-errors@2.0.5': {} - '@types/jsonwebtoken@9.0.5': + '@types/jsonwebtoken@9.0.10': dependencies: + '@types/ms': 2.1.0 '@types/node': 26.6.2 + '@types/ms@2.1.0': {} + '@types/node@26.6.2': dependencies: undici-types: 8.9.0 @@ -3890,10 +3849,6 @@ snapshots: abstract-logging@2.0.1: {} - ajv-formats@2.1.1(ajv@8.20.0): - optionalDependencies: - ajv: 8.20.0 - ajv-formats@3.0.1(ajv@8.20.0): optionalDependencies: ajv: 8.20.0 @@ -3905,19 +3860,15 @@ 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.270.0(constructs@10.8.1): @@ -3947,11 +3898,6 @@ snapshots: chai@6.2.2: {} - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - cheerio-select@2.1.0: dependencies: boolbase: 1.0.0 @@ -3977,28 +3923,18 @@ snapshots: 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.8.1: {} - cookie-signature@1.2.2: {} - - cookie@0.7.2: {} - cookie@1.1.1: {} + cookie@2.0.1: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -4023,6 +3959,8 @@ snapshots: optionalDependencies: supports-color: 7.2.0 + dequal@2.0.3: {} + detect-libc@2.1.2: {} diff@5.2.2: {} @@ -4045,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: {} @@ -4073,6 +4013,8 @@ snapshots: es-module-lexer@2.3.2: {} + es-toolkit@1.51.0: {} + esbuild@0.28.2: optionalDependencies: '@esbuild/aix-ppc64': 0.28.2 @@ -4118,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: @@ -4140,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 @@ -4173,24 +4111,20 @@ snapshots: optionalDependencies: 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: {} @@ -4216,7 +4150,7 @@ snapshots: ieee754@1.2.1: {} - ipaddr.js@1.9.1: {} + ipaddr.js@2.5.0: {} isexe@2.0.0: {} @@ -4224,19 +4158,19 @@ snapshots: jiti@2.7.0: {} - js-yaml@4.1.0: + js-yaml@5.4.1: dependencies: argparse: 2.0.1 - 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: {} - 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 @@ -4249,15 +4183,15 @@ 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@2.1.14: @@ -4305,13 +4239,13 @@ snapshots: 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 @@ -4415,6 +4349,8 @@ snapshots: 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: {} @@ -4429,8 +4365,6 @@ snapshots: lodash.once@4.1.1: {} - lodash@4.17.21: {} - magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.6.0 @@ -4445,10 +4379,6 @@ snapshots: dependencies: obliterator: 1.6.1 - mnemonist@0.39.6: - dependencies: - obliterator: 2.0.5 - ms@2.1.3: {} nanoid@3.3.19: {} @@ -4462,10 +4392,6 @@ snapshots: node-cleanup@2.1.2: {} - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -4474,8 +4400,6 @@ snapshots: obliterator@1.6.1: {} - obliterator@2.0.5: {} - obug@2.2.1: {} on-exit-leak-free@2.1.2: {} @@ -4565,10 +4489,6 @@ snapshots: path-key@3.1.1: {} - path-to-regexp@3.3.0: {} - - path-to-regexp@6.3.0: {} - path-to-regexp@8.4.2: {} pause-stream@0.0.11: @@ -4613,16 +4533,11 @@ snapshots: 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: @@ -4659,7 +4574,7 @@ snapshots: reselect@5.3.0: {} - ret@0.4.3: {} + ret@0.5.0: {} reusify@1.1.0: {} @@ -4692,9 +4607,9 @@ 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: {} @@ -4702,7 +4617,7 @@ snapshots: scheduler@0.28.0: {} - secure-json-parse@2.7.0: {} + secure-json-parse@4.1.0: {} semver@7.8.5: {} @@ -4762,7 +4677,7 @@ 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 @@ -4795,8 +4710,6 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 - tr46@0.0.3: {} - tsc-watch@7.2.1(typescript@7.0.2): dependencies: cross-spawn: 7.0.6 @@ -4904,19 +4817,12 @@ snapshots: transitivePeerDependencies: - msw - webidl-conversions@3.0.1: {} - whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 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 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 80641c8..7a6ffeb 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -31,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 From a4af2f71aeede851898fbdd7ab31dce003ed9b3d Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 17:22:53 -0400 Subject: [PATCH 13/16] fix: stop vitest collecting the Lambda build's temporary output `pnpm build` in apps/bff compiles into .tsc-out (see scripts/build-lambda.mjs) while turbo runs the tests in parallel. Vitest 3+ no longer excludes build output, so it collected half-written .tsc-out/*.spec.js copies and failed with "Cannot find module". It had only passed before by timing. Reproduced by running the tests while a build was in progress (failures), and confirmed fixed the same way (8 files, 37 tests pass). Also two forced full turbo runs, both 16/16. apps/bff/vitest.config.ts excludes .tsc-out and dist*. --- apps/bff/vitest.config.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 apps/bff/vitest.config.ts 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*/**'] }, +}); From 0eb00c19c279d6bc601a4646e7699787ca74200c Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 17:23:15 -0400 Subject: [PATCH 14/16] docs: drop the resolved Nest 12 note from Known Deviations --- .cursor/rules/bff-typescript-cdk-best-practices.mdc | 1 - 1 file changed, 1 deletion(-) diff --git a/.cursor/rules/bff-typescript-cdk-best-practices.mdc b/.cursor/rules/bff-typescript-cdk-best-practices.mdc index 3e60138..64dce65 100644 --- a/.cursor/rules/bff-typescript-cdk-best-practices.mdc +++ b/.cursor/rules/bff-typescript-cdk-best-practices.mdc @@ -297,6 +297,5 @@ Things this rule asks for that the repo does not do yet. Do not copy these as pa * **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. -* **NestJS 12 / Fastify 5 are prepared on branch `chore/nest-12-upgrade` but not released.** It waits on the mycota major release and needs its lockfile regenerated afterwards. By following these practices, you keep the BFF, shared packages, and infrastructure consistent, secure, cheap to run, and easy to change. From 7dd9b4b34c3f1599d87ddcf8a15a5fdb2f979bde Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 17:23:49 -0400 Subject: [PATCH 15/16] docs and fixes --- docs/infra.md | 14 +++++++++++ infra/cdk/lib/api-stack.ts | 45 ++++++++++++++++++++++++++++++++++++ infra/cdk/lib/email-stack.ts | 5 ++++ 3 files changed, 64 insertions(+) diff --git a/docs/infra.md b/docs/infra.md index 925042b..c457309 100644 --- a/docs/infra.md +++ b/docs/infra.md @@ -54,6 +54,20 @@ canary never sees user traffic. 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) | Item | Cost | diff --git a/infra/cdk/lib/api-stack.ts b/infra/cdk/lib/api-stack.ts index 73a66d1..7e4151b 100644 --- a/infra/cdk/lib/api-stack.ts +++ b/infra/cdk/lib/api-stack.ts @@ -14,13 +14,19 @@ 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 * 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)); @@ -78,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, @@ -139,6 +153,37 @@ export class ApiStack extends cdk.Stack { 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)); + } + + // HttpLambdaIntegration.grantInvoke is a no-op when the target is an + // imported/SAM alias (fn.functionArn is a token, so CDK skips + // addPermission). Prod is 500 on every /api/* because :live has no + // resource policy. This CfnPermission is a real stack resource on the + // alias the HTTP API invokes. + new lambda.CfnPermission(this, 'HttpApiInvokeAlias', { + action: 'lambda:InvokeFunction', + functionName: current.functionArn, + principal: 'apigateway.amazonaws.com', + sourceArn: `arn:aws:execute-api:${this.region}:${this.account}:${this.httpApi.apiId}/*/*`, + }); + 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 90ad62a..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 { @@ -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}`, From c3d88b7250d42d99f8de5511a438b7e2be1b9486 Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 20 Sep 2026 17:27:29 -0400 Subject: [PATCH 16/16] fix: remove the redundant HttpApiInvokeAlias CfnPermission Its comment described the old SAM/imported alias, where CDK skipped addPermission because the alias ARN was a token, so the HTTP API had no invoke permission. With the native lambda.Alias, HttpLambdaIntegration already creates that permission itself, so this was a second, duplicate resource policy statement on the same alias. Verified by synthesizing: Dev and Prod each still have exactly one AWS::Lambda::Permission for the API, and it targets the current alias. --- infra/cdk/lib/api-stack.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/infra/cdk/lib/api-stack.ts b/infra/cdk/lib/api-stack.ts index 7e4151b..554816e 100644 --- a/infra/cdk/lib/api-stack.ts +++ b/infra/cdk/lib/api-stack.ts @@ -172,18 +172,6 @@ export class ApiStack extends cdk.Stack { }).addAlarmAction(new cloudwatchActions.SnsAction(alerts)); } - // HttpLambdaIntegration.grantInvoke is a no-op when the target is an - // imported/SAM alias (fn.functionArn is a token, so CDK skips - // addPermission). Prod is 500 on every /api/* because :live has no - // resource policy. This CfnPermission is a real stack resource on the - // alias the HTTP API invokes. - new lambda.CfnPermission(this, 'HttpApiInvokeAlias', { - action: 'lambda:InvokeFunction', - functionName: current.functionArn, - principal: 'apigateway.amazonaws.com', - sourceArn: `arn:aws:execute-api:${this.region}:${this.account}:${this.httpApi.apiId}/*/*`, - }); - new cdk.CfnOutput(this, 'HttpApiUrl', { value: this.httpApi.apiEndpoint }); } }