diff --git a/.circleci/config.yml b/.circleci/config.yml index 9faeca6..75c0c49 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,91 +1,123 @@ version: 2.1 - executors: - build: + reviewed: docker: - - image: cimg/python:3.13.2-browsers - resource_class: medium - + - image: cimg/aws@sha256:4cf3768db00ddf9bc439b8c84e8a60c11a14edf81c8baf76f74132144f8340d5 commands: - install-dependencies: + checkout-source: + steps: + - run: + name: Check out the exact public source commit over HTTPS + command: | + set -euo pipefail + [[ "$CIRCLE_SHA1" =~ ^[0-9a-f]{40}$ ]] + export GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null GIT_TERMINAL_PROMPT=0 + git init --quiet . + git remote add origin https://github.com/topcoder-platform/forms-api-v6.git + git -c credential.helper= fetch --quiet --depth 1 origin "$CIRCLE_SHA1" + git checkout --quiet --detach FETCH_HEAD + test "$(git rev-parse HEAD)" = "$CIRCLE_SHA1" + checkout-suite: steps: - - run: - name: Install build and deployment dependencies - command: | - sudo apt-get update -qq - sudo apt-get install -y -qq jq python3-pip - pip install boto3 awscli - + - run: + name: Verify deployment suite v2.0.5 + command: | + set -euo pipefail + git init --quiet /tmp/tc-deploy-scripts + git -C /tmp/tc-deploy-scripts remote add origin https://github.com/topcoder-platform/tc-deploy-scripts.git + git -C /tmp/tc-deploy-scripts fetch --quiet --depth 1 origin refs/tags/v2.0.5 + git -C /tmp/tc-deploy-scripts checkout --quiet --detach FETCH_HEAD + test "$(git -C /tmp/tc-deploy-scripts rev-parse HEAD)" = bff574ab5c0b46773e25d2af1eff76675fba2ba5 jobs: + build: + executor: reviewed + steps: + - checkout-source + - setup_remote_docker + - checkout-suite + - run: + name: Build committed source without AWS or broker credentials + command: | + set -euo pipefail + python3 -I /tmp/tc-deploy-scripts/build_image.py --target runtime --image forms-api-v6:candidate + python3 -I /tmp/tc-deploy-scripts/build_image.py --target migrate --image forms-api-v6:migrate-candidate + mkdir -p /tmp/release + docker save --output /tmp/release/image.tar forms-api-v6:candidate forms-api-v6:migrate-candidate + no_output_timeout: 30m + - persist_to_workspace: + root: /tmp/release + paths: + - image.tar deploy: - executor: build + executor: reviewed parameters: - deploy_env: - type: enum - enum: [DEV, PROD] environment: type: enum - enum: [dev, production] + enum: + - dev + - prod environment: - AWS_REGION: us-east-1 - AWS_DEFAULT_REGION: us-east-1 - AWS_STS_REGIONAL_ENDPOINTS: regional - APPNAME: forms-api-v6 + DEPLOY_ENV: << parameters.environment >> + steps: + - checkout-source + - setup_remote_docker + - checkout-suite + - attach_workspace: + at: /tmp/release + - run: + name: Promote a scanned digest with repository-bound OIDC + command: | + set +x + set -euo pipefail + test -f "deploy/${DEPLOY_ENV}.json" + docker load --input /tmp/release/image.tar + python3 -I deploy/release.py "deploy/${DEPLOY_ENV}.json" + no_output_timeout: 45m + deployment-checks: + executor: reviewed steps: - - checkout - - setup_remote_docker - - install-dependencies - - run: - name: Verify first-release activation and rollback handling - command: python3 -m unittest discover -s deploy/tests - - run: - name: Build runtime and one-shot migration images - command: | - docker buildx build --load --target migrate -t forms-api-v6:migrate-candidate . - docker buildx build --load --target runtime -t forms-api-v6:latest . - - run: - name: Migrate and deploy using the Topcoder deployment suite - no_output_timeout: 35m - command: | - git clone --quiet --depth 1 --branch v1.4.20 https://github.com/topcoder-platform/tc-deploy-scripts ../buildscript - test "$(git -C ../buildscript rev-parse HEAD)" = 5f3745c35463ce0e2475c12269aa7a2b446456e5 - cp ../buildscript/{master_deploy,buildenv,awsconfiguration,psvar-processor}.sh . - ./awsconfiguration.sh << parameters.deploy_env >> - set +x - source awsenvconf - ./psvar-processor.sh -t appenv -p "/config/${APPNAME}/deployvar" - source deployvar_env - python3 -u deploy/release.py << parameters.environment >> "<< parameters.environment >>-${CIRCLE_SHA1}-${CIRCLE_BUILD_NUM}" - ./master_deploy.sh \ - -d ECS \ - -e << parameters.deploy_env >> \ - -t latest \ - -j "/config/${APPNAME}/appvar,/config/common/global-appvar" \ - -i "$APPNAME" \ - -p FARGATE - python3 -u deploy/activate.py - - store_artifacts: - path: deploy/release-<< parameters.environment >>.json - destination: release - + - checkout-source + - checkout-suite + - run: + name: Test migration, activation and rollback gates + command: python3 -m unittest discover -s deploy/tests -q workflows: - build-and-deploy: + release: jobs: - - deploy: - name: deploy-dev - context: org-global - deploy_env: DEV - environment: dev - serial-group: << pipeline.project.slug >>/deploy-dev - filters: - branches: - only: develop - - deploy: - name: deploy-production - context: org-global - deploy_env: PROD - environment: production - serial-group: << pipeline.project.slug >>/deploy-production - filters: - branches: - only: master + - deployment-checks + - build: + requires: + - deployment-checks + - deploy: + name: deploy-dev + environment: dev + requires: + - build + context: forms-api-v6-dev-deploy + serial-group: << pipeline.project.slug >>/deploy-dev + filters: + branches: + only: develop + tags: + ignore: /.*/ + - approve-prod: + type: approval + requires: + - build + filters: + branches: + only: master + tags: + ignore: /.*/ + - deploy: + name: deploy-prod + environment: prod + requires: + - approve-prod + context: forms-api-v6-prod-deploy + serial-group: << pipeline.project.slug >>/deploy-prod + filters: + branches: + only: master + tags: + ignore: /.*/ diff --git a/.gitignore b/.gitignore index 740fea4..cad6ff8 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,7 @@ src/generated/ __pycache__/ *.pyc + +# Infrastructure definitions and detailed AWS inventories are maintained privately. +/deploy/iam/ +/deploy/*-baseline.json diff --git a/.nvmrc b/.nvmrc index 60bb1e6..63f87c2 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -26.8.1 +26.12.1 diff --git a/Dockerfile b/Dockerfile index d33bbb1..b89e1ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,31 +1,44 @@ -FROM node:26.8.1-bookworm-slim AS base -RUN apt-get update && apt-get install -y --no-install-recommends openssl ca-certificates && rm -rf /var/lib/apt/lists/* -RUN npm install --global pnpm@11.21.0 +ARG NODE_VERSION=26.12.1 +FROM node:${NODE_VERSION}-alpine AS dependencies +RUN apk add --no-cache openssl ca-certificates \ + && npm install --global pnpm@11.21.0 WORKDIR /app COPY deploy/certs/us-east-1-bundle.pem /app/deploy/certs/us-east-1-bundle.pem ENV NODE_EXTRA_CA_CERTS=/app/deploy/certs/us-east-1-bundle.pem - -FROM base AS dependencies COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ +COPY tools ./tools RUN pnpm install --frozen-lockfile FROM dependencies AS build COPY . . -RUN pnpm build - -# Separate one-shot migration image: runtime does not ship the Prisma CLI or CMS dev dependencies. -FROM build AS migrate -CMD ["pnpm", "migrate:deploy"] +RUN pnpm lint && pnpm build && pnpm typecheck && pnpm test && pnpm test:dependency-compat FROM dependencies AS production-dependencies RUN pnpm prune --prod -FROM base AS runtime +FROM alpine:3.24 AS runtime-base +ARG NODE_VERSION ENV NODE_ENV=production -COPY --from=production-dependencies --chown=node:node /app/node_modules ./node_modules -COPY --from=build --chown=node:node /app/dist/src ./dist/src -COPY --chown=node:node package.json ./ -USER node +WORKDIR /app +RUN apk upgrade --no-cache \ + && apk add --no-cache openssl ca-certificates "nodejs-current~${NODE_VERSION%%.*}" \ + && addgroup -S -g 10001 app \ + && adduser -S -D -u 10001 -G app app +COPY deploy/certs/us-east-1-bundle.pem /app/deploy/certs/us-east-1-bundle.pem +ENV NODE_EXTRA_CA_CERTS=/app/deploy/certs/us-east-1-bundle.pem +USER app + +# One-shot migration image; invoke the installed CLI without shipping npm/pnpm. +FROM runtime-base AS migrate +COPY --from=build --chown=app:app /app/node_modules ./node_modules +COPY --chown=app:app package.json prisma.config.ts ./ +COPY --chown=app:app prisma ./prisma +CMD ["node", "node_modules/prisma/build/index.js", "migrate", "deploy"] + +FROM runtime-base AS runtime +COPY --from=production-dependencies --chown=app:app /app/node_modules ./node_modules +COPY --from=build --chown=app:app /app/dist/src ./dist/src +COPY --chown=app:app package.json ./ EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=15s CMD ["node", "-e", "fetch('http://127.0.0.1:'+(process.env.PORT||3000)+'/v6/health/ready').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] CMD ["node", "dist/src/main.js"] diff --git a/README.md b/README.md index 82749b9..c98c3c1 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ All tables and views live in the `forms` schema; dev uses the shared `topcoder-s ## Stack -- Node **26.8.1**, pinned in `.nvmrc` and Docker; current release verified against the [Node release listing](https://nodejs.org/en/download/current) on September 9, 2026. +- Node **26.12.1**, pinned in `.nvmrc` and the Docker build. - NestJS **11.1.28**, matching the other v6 services and the supported peer range of Nest Throttler. - TypeScript **5.9.3**, strict checking and decorator metadata. - Prisma **7.10.0**, generated TypeScript client and `@prisma/adapter-pg`. @@ -106,3 +106,32 @@ Coverage includes actual PostgreSQL writes, all field types, SQL views, CSV outp Forms portal endpoints, inclusive UTC date filtering, and full CSV exports are specified in [docs/api.md](docs/api.md). The dev and production `/lets-talk` migration, Kafka contract, seed command, and rollout order are in [docs/lets-talk.md](docs/lets-talk.md). + +## Shared authentication and bus client (v6 refresh) + +This branch uses `tc-core-library-js` **4.0.0-rc.1**. Use its named +`createJwtVerifier` / `createJwtAuthenticator`, `createM2MClient`, and +`createBusApiClient` exports for shared authentication and bus API publishing. +Service-specific roles, scopes, sessions and ownership checks remain in this service. +The former bus wrapper dependency and local JWT cryptography must not be reintroduced. + +RSA verification requires an exact configured issuer and audience (`JWT_AUDIENCE` +for client tokens, `AUTH0_AUDIENCE` for machine/API tokens, or this service's explicit +issuer-policy settings). HMAC secrets must be at least 32 bytes; no default secret +is supplied. Expiry is enforced. Machine identity comes from the shared verifier, +not the presence of scopes. Supply real development credentials through the service's +existing environment configuration before deployment. + +Bus publishers use `createBusApiClient(config).postEvent(event)` with the existing +event envelope and optional key. Configure `BUSAPI_URL` for v6 and the existing +OAuth credentials/token provider. The client uses bounded HTTPS requests and does +not retry POSTs automatically. Application retry/outbox behavior remains local. + +See the [core migration guide](https://github.com/topcoder-platform/tc-core-library-js/blob/v4.0.0-rc.1/MIGRATION.md) +for the API mapping, compatibility requirements, and rollout scope. + +## Security maintenance + +The runtime and one-shot migration images use Alpine 3.24's patched Node 26 package and run as UID 10001. The runtime contains only production dependencies and compiled code. Migration tasks invoke the installed Prisma CLI directly with Node; npm and pnpm are not shipped in either final image. The RDS CA bundle and `NODE_EXTRA_CA_CERTS` remain configured in both images. + +The lockfile pins patched dependencies and an immutable shared core revision. `pnpm test:dependency-compat` verifies the legacy matcher adapter. Integration fixtures use real RS256 machine tokens with an isolated JWKS endpoint, so the shared verifier's issuer, signature, audience, and machine-identity restrictions remain enabled. diff --git a/deploy/MIGRATION.md b/deploy/MIGRATION.md new file mode 100644 index 0000000..9918997 --- /dev/null +++ b/deploy/MIGRATION.md @@ -0,0 +1,44 @@ +# OIDC deployment migration + +This change replaces the Auth0 credential broker and SSM-to-shell deployment path with [tc-deploy-scripts v2.0.5](https://github.com/topcoder-platform/tc-deploy-scripts/releases/tag/v2.0.5), fetched by tag and verified against commit `bff574ab5c0b46773e25d2af1eff76675fba2ba5`. Build and deployment run in separate jobs. The deployer cannot read Parameter Store, Secrets Manager or decrypt KMS data, including through another assumed role. ECS continues resolving the existing runtime secret references using the execution role. + +## Production target + +The read-only inventory on 2026-11-03 verified account `409275337247`, cluster `topcoder-infrastructure`, service `forms-api-v6`, family `forms-api-v6`, and container `forms-api-v6`. `prod.json` preserves the observed task/execution roles and names the proposed service-specific deployment role. [prod-baseline.json](https://github.com/topcoder-platform/v6-services-iac/blob/main/services/forms-api-v6/deploy/prod-baseline.json) records references only; it contains no parameter values. Do not recreate the service or replace its complete task definition from this baseline. + +## Infrastructure prerequisites, applied separately by an administrator + +1. In each account, register the CircleCI OIDC issuer `https://oidc.circleci.com/org/947bef5e-1669-415d-b83c-4fc85155b7df` with client ID `947bef5e-1669-415d-b83c-4fc85155b7df`. The current production account has only the legacy Auth0 provider. Do not remove that provider until all its consumers have migrated. +2. Review and install [iam/prod-role.cloudformation.json](https://github.com/topcoder-platform/v6-services-iac/blob/main/services/forms-api-v6/deploy/iam/prod-role.cloudformation.json) with an administrator/IaC identity. It creates the proposed deployment role and applies the same least-privilege policy as a permissions boundary. The trust binds this CircleCI project, repository, checkout branch and configuration branch. It does not grant infrastructure creation to CircleCI. The role and matching boundary include `inspector2:ListFindings` and `inspector2:ListCoverage` restricted to the deployment region; these scan-metadata APIs require `Resource: "*"`. Secret-access denies remain explicit. +3. Configure ECR repository `forms-api-v6` with unconditional `IMMUTABLE` tags and supported scanning. Preserve existing enhanced scanning where enabled. Existing tags are not retagged. The release fails for MEDIUM/HIGH/CRITICAL/UNDEFINED findings, failed scans, or a mismatched digest. +4. In the infrastructure that owns the task definition, add the reviewed container check from `prod-healthcheck.json`, keeping all roles, runtime secret references, resources, mounts and sidecars. Verify the health endpoint against the running container in dev first. Preserve circuit-breaker rollback; the Forms-specific first-activation rule is described below. Remove any `RESET_DB` secret binding and plaintext secret environment entries before adoption. Keep the execution role's runtime read permissions scoped to the references that service needs. +5. Create restricted `forms-api-v6-dev-deploy` and `forms-api-v6-prod-deploy` CircleCI contexts without Auth0/static AWS credentials. Restrict production to the reviewed `master` checkout and configuration ref, authorized operators, and approval job. Remove legacy credentials from project settings too: removing `org-global` alone does not remove project-level variables. Confirm `CIRCLE_OIDC_TOKEN_V3` is issued. Disable secret access for forks and SSH debugging in deployment jobs. + +## Development acceptance before merge/release + +Read-only inventory on 2026-11-04 verified `dev.json` against the actual development service, task/execution roles and image repositories. This PR targets `develop`. Matching IAM templates and detailed baselines remain private. **Keep this PR in draft until the service-specific prerequisites below are complete.** No AWS or CircleCI resources were provisioned by this refresh. + +- Install the service deployment role and matching permissions boundary. +- Create the restricted empty CircleCI deployment context. +- Review and install the dev container health-check proposal; preserve all other task configuration. +- Verify one-shot migration secret/execution-role grants and migration-before-runtime promotion in dev. + +Run the shared offline suite, validate the CircleCI config and IAM policies, and test a dev release plus an unhealthy-image rollback. Verify CloudTrail contains no SSM/Secrets Manager calls from the deployment principal. Remove its old broker grants only after migration. Check the runtime secret references and roles stayed unchanged. Production requires the manual approval job and a passing digest/scan/health verification. + +The pinned executor is `cimg/aws@sha256:4cf3768db00ddf9bc439b8c84e8a60c11a14edf81c8baf76f74132144f8340d5`. Python/AWS CLI/Buildx/Git compatibility was tested with the shared offline suite. No package installation or service build runs in the deployment job. The Dockerfile retains the existing in-image quality gates. This PR does not deploy, change IAM, rotate credentials, or claim a successful live rollout. + +## Forms migration and first activation + +The adapter preserves the stable-stack/environment/bootstrap checks, runs the separate migration image as a private one-shot task, and requires exit code zero plus the exact scanned image digest before runtime promotion. Both images are built without credentials and scanned before either executes. The migration image runs as non-root. The only added permissions are the exact migration task family and read access to the existing Forms stack; the deployment role still cannot read parameter values. ECS resolves the migration database secret through the existing execution role. + +Unlike the default CLI, this reviewed adapter retains Forms first activation: an existing zero-capacity service is started at one replica only after the infrastructure bootstrap and migration gates pass. Existing positive capacity is preserved. Runtime read-back, concurrency, digest/health and rollback checks must pass. Migration waiting is bounded to 15 minutes and runtime observation to 20 minutes, within the one-hour STS session; a timeout fails without pretending the rollout succeeded. Test both first activation and failed migration in dev. + +## Infrastructure source + +IAM templates and detailed AWS baselines are maintained in the private [v6-services-iac service directory](https://github.com/topcoder-platform/v6-services-iac/tree/main/services/forms-api-v6). Provision infrastructure separately with an administrator identity; application CI does not fetch that repository or install IAM. Required application manifests and health-check proposals remain here. + +## Dev branch refresh + +This PR targets `develop` and preserves its current application/dependency fixes. The shared suite is v2.0.5 (82 offline tests); service-specific adapters and their tests remain part of review. Keep this PR in draft until its documented infrastructure and integration prerequisites are met. Updating these files does not provision AWS or CircleCI resources. + +Source checkout uses the public HTTPS repository and verifies the exact CircleCI commit, avoiding dependency on failing SSH checkout keys. No GitHub token is added to build or deployment contexts. diff --git a/deploy/activate.py b/deploy/activate.py index 4f53e29..bdfda6e 100644 --- a/deploy/activate.py +++ b/deploy/activate.py @@ -6,7 +6,6 @@ """ import os -import boto3 from release import wait_until @@ -65,14 +64,7 @@ def is_stable(): def main(): - """Read CircleCI/deployvar settings and activate the expected image; errors propagate.""" - session = boto3.Session(region_name=os.environ.get('AWS_REGION', 'us-east-1')) - account = session.client('sts').get_caller_identity()['Account'] - image = (f'{account}.dkr.ecr.{session.region_name}.amazonaws.com/' - f'{os.environ["AWS_REPOSITORY"]}:{os.environ["CIRCLE_BUILD_NUM"]}') - service = activate_service(session.client('ecs'), os.environ['AWS_ECS_CLUSTER'], - os.environ['AWS_ECS_SERVICE'], image) - print('Verified running release: ' + service['taskDefinition'], flush=True) + raise RuntimeError('Activation is now part of deploy/release.py after the scanned migration gate.') if __name__ == '__main__': diff --git a/deploy/dev-healthcheck.json b/deploy/dev-healthcheck.json new file mode 100644 index 0000000..caf0f82 --- /dev/null +++ b/deploy/dev-healthcheck.json @@ -0,0 +1,14 @@ +{ + "forms-api-v6": { + "command": [ + "CMD", + "node", + "-e", + "const r=require('node:http').get(\"http://127.0.0.1:3000/v6/forms/health/ready\",r=>{r.resume();process.exit(r.statusCode>=200&&r.statusCode<300?0:1)});r.setTimeout(4000,()=>{r.destroy();process.exit(1)});r.on('error',()=>process.exit(1))" + ], + "interval": 30, + "timeout": 5, + "retries": 3, + "startPeriod": 120 + } +} diff --git a/deploy/dev.json b/deploy/dev.json new file mode 100644 index 0000000..f4d6eb0 --- /dev/null +++ b/deploy/dev.json @@ -0,0 +1,19 @@ +{ + "schemaVersion": 2, + "environment": "dev", + "accountId": "811668436784", + "region": "us-east-1", + "deployRoleArn": "arn:aws:iam::811668436784:role/forms-api-v6-dev-deploy", + "taskRoleArn": "arn:aws:iam::811668436784:role/forms-api-v6-dev-TaskRole-14rblBbkqXuT", + "executionRoleArn": "arn:aws:iam::811668436784:role/ecsTaskExecutionRole", + "cluster": "topcoder-infrastructure", + "service": "forms-api-v6", + "taskFamily": "forms-api-v6", + "circleciOrgId": "947bef5e-1669-415d-b83c-4fc85155b7df", + "circleciProjectId": "ac910b17-c01b-494f-876b-43fddd16f82b", + "repository": "github.com/topcoder-platform/forms-api-v6", + "branch": "develop", + "images": { + "forms-api-v6": "forms-api-v6" + } +} diff --git a/deploy/prod-healthcheck.json b/deploy/prod-healthcheck.json new file mode 100644 index 0000000..77f215a --- /dev/null +++ b/deploy/prod-healthcheck.json @@ -0,0 +1,14 @@ +{ + "forms-api-v6": { + "command": [ + "CMD", + "node", + "-e", + "const r=require('node:http').get('http://127.0.0.1:3000/v6/forms/health/ready',r=>{r.resume();process.exit(r.statusCode>=200&&r.statusCode<300?0:1)});r.setTimeout(4000,()=>{r.destroy();process.exit(1)});r.on('error',()=>process.exit(1))" + ], + "interval": 30, + "timeout": 5, + "retries": 3, + "startPeriod": 120 + } +} diff --git a/deploy/prod.json b/deploy/prod.json new file mode 100644 index 0000000..eb8ab99 --- /dev/null +++ b/deploy/prod.json @@ -0,0 +1,19 @@ +{ + "schemaVersion": 2, + "environment": "prod", + "accountId": "409275337247", + "region": "us-east-1", + "deployRoleArn": "arn:aws:iam::409275337247:role/forms-api-v6-prod-deploy", + "taskRoleArn": "arn:aws:iam::409275337247:role/forms-api-v6-production-TaskRole-9CWeN3VGr09Z", + "executionRoleArn": "arn:aws:iam::409275337247:role/ecsTaskExecutionRole", + "cluster": "topcoder-infrastructure", + "service": "forms-api-v6", + "taskFamily": "forms-api-v6", + "circleciOrgId": "947bef5e-1669-415d-b83c-4fc85155b7df", + "circleciProjectId": "ac910b17-c01b-494f-876b-43fddd16f82b", + "repository": "github.com/topcoder-platform/forms-api-v6", + "branch": "master", + "images": { + "forms-api-v6": "forms-api-v6" + } +} diff --git a/deploy/release.py b/deploy/release.py index 389575d..edd0444 100644 --- a/deploy/release.py +++ b/deploy/release.py @@ -1,112 +1,163 @@ #!/usr/bin/env python3 -"""Run the migration gate before the shared Topcoder ECS deployment script. - -CLI: release.py dev|production IMAGE_TAG [MIGRATION_IMAGE]. -Requires inherited AWS credentials, boto3, and Docker. Pushes the prebuilt migration -image to ECR and runs it as a private one-shot ECS task. Raises on failures so -CircleCI stops before master_deploy.sh promotes the runtime image. -""" -import base64 -import copy +"""Scan both images, run the one-shot migration, then promote/activate Forms.""" +from copy import deepcopy import json import os from pathlib import Path -import re -import subprocess import sys +import tempfile import time -import boto3 +sys.path.insert(0, '/tmp/tc-deploy-scripts') +import tcdeploy as d -def wait_until(description, check, seconds=1800): - """Poll a live deployment check every 15 seconds, returning its truthy result. - - Inputs are a progress label, callable, and timeout. Check exceptions propagate; - timeout raises RuntimeError without restarting the observed deployment. - """ +def wait_until(description, check, seconds=900): deadline = time.monotonic() + seconds while time.monotonic() < deadline: result = check() if result: return result - print(f'Waiting for {description}...', flush=True) - time.sleep(15) - raise RuntimeError(f'Timed out observing {description}; inspect the existing AWS operation before retrying.') + time.sleep(10) + raise d.DeployError('Timed out: ' + description) -def main(): - """Validate CLI arguments and environment, run migrations, and save evidence. - - Returns None on success; AWS, Docker, and failed migration - errors propagate. Credentials are passed through stdin/environment, never argv. - """ - if len(sys.argv) not in (3, 4) or sys.argv[1] not in ('dev', 'production'): - raise RuntimeError(__doc__) - environment, tag = sys.argv[1:3] - if not re.fullmatch(r'[A-Za-z0-9_][A-Za-z0-9_.-]{0,110}', tag): - raise RuntimeError('Invalid immutable release tag.') - local_migration = sys.argv[3] if len(sys.argv) == 4 else 'forms-api-v6:migrate-candidate' - session = boto3.Session(region_name=os.environ.get('AWS_REGION', 'us-east-1')) - account = session.client('sts').get_caller_identity()['Account'] - if (account == '811668436784') != (environment == 'dev'): - raise RuntimeError('AWS account does not match the selected deployment environment.') - cfn, ecs, ecr = [session.client(name) for name in ['cloudformation', 'ecs', 'ecr']] - stack_name = f'forms-api-v6-{environment}' - stack = cfn.describe_stacks(StackName=stack_name)['Stacks'][0] - if stack['StackStatus'] not in ('CREATE_COMPLETE', 'UPDATE_COMPLETE', 'UPDATE_ROLLBACK_COMPLETE'): - raise RuntimeError('Existing stack is not stable; inspect it before releasing.') - settings = {x['ParameterKey']: x['ParameterValue'] for x in stack['Parameters']} - if settings['Environment'] != environment or settings['BootstrapOnly'] != 'false': - raise RuntimeError('Stack environment or bootstrap state does not permit deployment.') - output = {x['OutputKey']: x['OutputValue'] for x in stack['Outputs']} - repository = output['RepositoryUri'] - authorization = ecr.get_authorization_token()['authorizationData'][0] - user, password = base64.b64decode(authorization['authorizationToken']).decode().split(':', 1) - subprocess.run(['docker', 'login', '--username', user, '--password-stdin', authorization['proxyEndpoint']], - input=password, text=True, check=True, stdout=subprocess.DEVNULL) - destination = f'{repository}:{tag}-migrate' - subprocess.run(['docker', 'tag', local_migration, destination], check=True) - subprocess.run(['docker', 'push', destination], check=True) - digest = ecr.describe_images(repositoryName='forms-api-v6', imageIds=[{'imageTag': tag + '-migrate'}])['imageDetails'][0]['imageDigest'] - migration_image = f'{repository}@{digest}' - service = ecs.describe_services(cluster=settings['ClusterName'], services=[output['ServiceName']])['services'][0] - current = ecs.describe_task_definition(taskDefinition=service['taskDefinition'])['taskDefinition'] - allowed = {'family', 'taskRoleArn', 'executionRoleArn', 'networkMode', 'containerDefinitions', - 'volumes', 'placementConstraints', 'requiresCompatibilities', 'cpu', 'memory', 'runtimePlatform', 'ephemeralStorage'} - migration = {k: copy.deepcopy(v) for k, v in current.items() if k in allowed} - migration['family'] = 'forms-api-v6-migrate' - container = migration['containerDefinitions'][0] - container['image'] = migration_image +def stack_settings(aws, m): + environment = 'production' if m['environment'] == 'prod' else 'dev' + stack_name = 'forms-api-v6-' + environment + stacks = aws.call('cloudformation', 'describe-stacks', StackName=stack_name).get('Stacks', []) + d.require(len(stacks) == 1, 'Expected the existing Forms stack') + stack = stacks[0] + d.require(stack.get('StackStatus') in ('CREATE_COMPLETE', 'UPDATE_COMPLETE', 'UPDATE_ROLLBACK_COMPLETE'), 'Forms stack is not stable') + settings = {v['ParameterKey']: v['ParameterValue'] for v in stack.get('Parameters', [])} + output = {v['OutputKey']: v['OutputValue'] for v in stack.get('Outputs', [])} + d.require(settings.get('Environment') == environment and settings.get('BootstrapOnly') == 'false', 'Complete Forms infrastructure bootstrap before releasing') + d.require(settings.get('ClusterName') == m['cluster'] and output.get('ServiceName') == m['service'], 'Forms stack target differs from manifest') + d.require(settings.get('ParameterPrefix') == '/config/forms-api-v6/appvar', 'Unexpected migration secret namespace') + d.require(output.get('RepositoryUri') == f"{m['accountId']}.dkr.ecr.{m['region']}.amazonaws.com/forms-api-v6", 'Unexpected Forms repository') + return settings + + +def read_service(aws, m): + result = aws.call('ecs', 'describe-services', cluster=m['cluster'], services=[m['service']]) + d.require(not result.get('failures') and len(result.get('services', [])) == 1, 'Expected the existing Forms service') + service = result['services'][0] + d.require(service.get('status') == 'ACTIVE' and service.get('desiredCount', -1) >= 0, 'Forms service is not active') + d.require(service.get('serviceArn') == d.arn(m, 'ecs', f"service/{m['cluster']}/{m['service']}"), 'Unexpected service ARN') + d.require(service.get('deploymentController', {}).get('type', 'ECS') == 'ECS', 'Forms requires ECS rolling deployment') + breaker = service.get('deploymentConfiguration', {}).get('deploymentCircuitBreaker') + d.require(isinstance(breaker, dict) and breaker.get('enable') is True and breaker.get('rollback') is True, 'Enable Forms circuit-breaker rollback') + return service + + +def initial_stable(service, definition): + d.require(service.get('taskDefinition') == definition, 'Concurrent Forms deployment detected') + deployments = service.get('deployments', []) + d.require(not any(x.get('rolloutState') == 'FAILED' for x in deployments), 'Forms rollout failed') + return (len(deployments) == 1 and deployments[0].get('rolloutState') == 'COMPLETED' + and deployments[0].get('taskDefinition') == definition + and service.get('runningCount') == service['desiredCount'] + and service.get('pendingCount') == 0) + + +def migration_request(m, task, tags, image): + # Validate exact roles, runtime settings, health checks and secret references + # before deriving a separate one-shot definition from this service. + request = d.task_request(m, task, tags, {'forms-api-v6': image}) + request['family'] = 'forms-api-v6-migrate' + containers = request['containerDefinitions'] + d.require(len(containers) == 1 and containers[0]['name'] == 'forms-api-v6', 'Unexpected Forms containers') + container = containers[0] container['readonlyRootFilesystem'] = False container.pop('healthCheck', None) container['portMappings'] = [] - container['secrets'] = [{'name': 'DATABASE_URL', 'valueFrom': settings['ParameterPrefix'] + '/MIGRATION_DATABASE_URL'}] - container['command'] = ['/bin/sh', '-c', 'pnpm migrate:deploy'] - migration_definition = ecs.register_task_definition(**migration)['taskDefinition']['taskDefinitionArn'] - result = ecs.run_task(cluster=settings['ClusterName'], taskDefinition=migration_definition, - launchType='FARGATE', networkConfiguration=service['networkConfiguration'], - startedBy='forms-release') - if result.get('failures') or not result.get('tasks'): - raise RuntimeError('ECS could not start the migration task.') - migration_arn = result['tasks'][0]['taskArn'] - print('Migration task: ' + migration_arn, flush=True) - - def migration_finished(): - """Read this migration task; return the stopped task, or None while live.""" - tasks = ecs.describe_tasks(cluster=settings['ClusterName'], tasks=[migration_arn])['tasks'] - if not tasks: - raise RuntimeError('Migration task handle is missing; inspect ECS before retrying.') - return tasks[0] if tasks[0]['lastStatus'] == 'STOPPED' else None - - completed = wait_until('migration task ' + migration_arn, migration_finished) - if any(c.get('exitCode') != 0 for c in completed['containers']): - raise RuntimeError('Migration failed; inspect the migration task logs. Runtime was not promoted.') - evidence = {'environment': environment, 'tag': tag, 'migrationImage': migration_image, - 'migrationTask': migration_arn, 'stack': stack_name} - Path('deploy/release-' + environment + '.json').write_text(json.dumps(evidence, indent=2) + '\n') - print(json.dumps(evidence, indent=2)) + container['secrets'] = [{'name': 'DATABASE_URL', 'valueFrom': '/config/forms-api-v6/appvar/MIGRATION_DATABASE_URL'}] + container['environment'] = [v for v in container.get('environment', []) if v['name'] != 'DATABASE_URL'] + container['command'] = ['node', 'node_modules/prisma/build/index.js', 'migrate', 'deploy'] + return request + + +def migrate(aws, m, service, task, tags, image): + request = migration_request(m, task, tags, image) + definition = aws.call('ecs', 'register-task-definition', **request)['taskDefinition']['taskDefinitionArn'] + d.require(definition.startswith(d.arn(m, 'ecs', 'task-definition/forms-api-v6-migrate:')), 'Unexpected migration family') + result = aws.call('ecs', 'run-task', cluster=m['cluster'], taskDefinition=definition, + launchType='FARGATE', networkConfiguration=service['networkConfiguration'], startedBy='forms-release') + d.require(not result.get('failures') and len(result.get('tasks', [])) == 1, 'Migration task could not start') + task_arn = result['tasks'][0]['taskArn'] + + def stopped(): + result = aws.call('ecs', 'describe-tasks', cluster=m['cluster'], tasks=[task_arn]) + d.require(not result.get('failures') and len(result.get('tasks', [])) == 1, 'Migration task is missing') + current = result['tasks'][0] + d.require(current.get('taskDefinitionArn') == definition, 'Migration task revision differs') + return current if current.get('lastStatus') == 'STOPPED' else None + + completed = wait_until('Forms migration', stopped) + containers = completed.get('containers', []) + d.require(len(containers) == 1 and containers[0].get('exitCode') == 0 + and containers[0].get('imageDigest') == image.rsplit('@', 1)[1], + 'Migration failed or executed an unexpected image; runtime was not promoted') + return task_arn + + +def promote(aws, m, previous, task, tags, image): + d.require(initial_stable(read_service(aws, m), previous['taskDefinition']), 'Service changed during migration') + request = d.task_request(m, task, tags, {'forms-api-v6': image}) + definition = aws.call('ecs', 'register-task-definition', **request)['taskDefinition']['taskDefinitionArn'] + d.require(definition.startswith(d.arn(m, 'ecs', 'task-definition/' + m['taskFamily'] + ':')), 'Unexpected runtime family') + saved = aws.call('ecs', 'describe-task-definition', taskDefinition=definition, include=['TAGS']) + actual = {k: v for k, v in saved['taskDefinition'].items() if k in d.TASK_FIELDS} + actual['tags'] = sorted(saved.get('tags', []), key=lambda x: x['key']) + expected = deepcopy(request) + expected['tags'] = sorted(expected.get('tags', []), key=lambda x: x['key']) + d.require(actual == expected, 'Registered Forms runtime differs from the requested definition') + d.require(initial_stable(read_service(aws, m), previous['taskDefinition']), 'Concurrent Forms release before activation') + updated = aws.call('ecs', 'update-service', cluster=m['cluster'], service=m['service'], + taskDefinition=definition, desiredCount=max(1, previous['desiredCount'])) + d.require(updated.get('service', {}).get('taskDefinition') == definition, 'ECS did not accept the Forms revision') + + def healthy(): + current = d.read_service(aws, m) + return (d.stable(current, definition) and + d.verify_running(aws, m, definition, {'forms-api-v6': image}, current['desiredCount'])) + + wait_until('healthy Forms runtime', healthy, seconds=1200) + return definition + + +def release(aws, m, publisher, release_tag): + stack_settings(aws, m) + previous = read_service(aws, m) + d.require(initial_stable(previous, previous['taskDefinition']), 'Forms must be stable before release') + response = aws.call('ecs', 'describe-task-definition', taskDefinition=previous['taskDefinition'], include=['TAGS']) + task, tags = response['taskDefinition'], response.get('tags', []) + migration_request(m, task, tags, 'preflight@sha256:' + '0' * 64) + deadline = time.monotonic() + 900 + runtime = publisher.publish('forms-api-v6', 'forms-api-v6:candidate', release_tag, deadline) + migration = publisher.publish('forms-api-v6', 'forms-api-v6:migrate-candidate', release_tag + '-migrate', deadline) + d.require(initial_stable(read_service(aws, m), previous['taskDefinition']), 'Service changed during image publication') + migration_task = migrate(aws, m, previous, task, tags, migration) + definition = promote(aws, m, previous, task, tags, runtime) + return {'service': m['service'], 'taskDefinition': definition, 'migrationTask': migration_task, 'image': runtime} + + +def main(): + m = d.read_manifest(sys.argv[1]) + d.require(m['service'] == 'forms-api-v6' and set(m['images']) == {'forms-api-v6'}, 'Expected Forms manifest') + d.require(os.environ.get('CIRCLE_BRANCH') == m['branch'] and not os.environ.get('CIRCLE_TAG'), 'Wrong deployment branch') + d.require(os.environ.get('CIRCLE_PROJECT_USERNAME', '') + '/' + os.environ.get('CIRCLE_PROJECT_REPONAME', '') == m['repository'].removeprefix('github.com/'), 'Wrong deployment repository') + tag = os.environ.get('CIRCLE_SHA1', '') + '-' + os.environ.get('CIRCLE_BUILD_NUM', '') + d.require(d.re.fullmatch(r'[a-f0-9]{40}-[0-9]{1,12}', tag), 'Invalid release identity') + aws = d.authenticate(m, os.environ.get('CIRCLE_OIDC_TOKEN_V3'), ['ecs:RunTask', 'cloudformation:DescribeStacks']) + with tempfile.TemporaryDirectory(prefix='forms-release-') as directory: + result = release(aws, m, d.Publisher(aws, m, directory), tag) + print(json.dumps(result)) if __name__ == '__main__': - main() + try: + main() + except (d.DeployError, ValueError, KeyError, TypeError, OSError, IndexError): + print('Forms release stopped; inspect the migration or ECS rollout. No secret values were fetched.', file=sys.stderr) + sys.exit(1) diff --git a/deploy/tests/test_oidc_release.py b/deploy/tests/test_oidc_release.py new file mode 100644 index 0000000..cfa816f --- /dev/null +++ b/deploy/tests/test_oidc_release.py @@ -0,0 +1,141 @@ +"""Migration/activation regressions without AWS credentials or network access.""" +from copy import deepcopy +import json +from pathlib import Path +import sys +import unittest +from unittest.mock import Mock, patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import release as r + + +class ReleaseTests(unittest.TestCase): + def setUp(self): + self.m = json.loads((Path(__file__).resolve().parents[1] / 'prod.json').read_text()) + self.image = 'registry/forms-api-v6@sha256:' + 'a' * 64 + self.old = r.d.arn(self.m, 'ecs', 'task-definition/forms-api-v6:1') + self.new = r.d.arn(self.m, 'ecs', 'task-definition/forms-api-v6:2') + self.task = { + 'family': 'forms-api-v6', 'status': 'ACTIVE', 'networkMode': 'awsvpc', + 'requiresCompatibilities': ['FARGATE'], + 'taskRoleArn': self.m['taskRoleArn'], 'executionRoleArn': self.m['executionRoleArn'], + 'containerDefinitions': [{'name': 'forms-api-v6', 'image': 'old', + 'readonlyRootFilesystem': True, 'portMappings': [{'containerPort': 3000}], + 'healthCheck': {'command': ['CMD', 'healthcheck']}, + 'secrets': [{'name': 'DATABASE_URL', 'valueFrom': '/runtime/database'}, + {'name': 'AUTH_SECRET', 'valueFrom': '/runtime/auth'}]}], + } + self.previous = { + 'status': 'ACTIVE', 'serviceArn': r.d.arn(self.m, 'ecs', f"service/{self.m['cluster']}/{self.m['service']}"), + 'taskDefinition': self.old, 'desiredCount': 2, 'runningCount': 2, 'pendingCount': 0, + 'deploymentConfiguration': {'deploymentCircuitBreaker': {'enable': True, 'rollback': True}}, + 'deployments': [{'taskDefinition': self.old, 'rolloutState': 'COMPLETED'}], + 'networkConfiguration': {'awsvpcConfiguration': {'subnets': ['private'], 'assignPublicIp': 'DISABLED'}}, + } + + def test_migration_has_only_its_runtime_database_reference(self): + original = deepcopy(self.task) + request = r.migration_request(self.m, self.task, [], self.image) + container = request['containerDefinitions'][0] + self.assertEqual(request['family'], 'forms-api-v6-migrate') + self.assertEqual(request['executionRoleArn'], self.m['executionRoleArn']) + self.assertEqual(container['secrets'], [{'name': 'DATABASE_URL', 'valueFrom': '/config/forms-api-v6/appvar/MIGRATION_DATABASE_URL'}]) + self.assertNotIn('healthCheck', container) + self.assertEqual(container['command'], ['node', 'node_modules/prisma/build/index.js', 'migrate', 'deploy']) + self.assertNotIn('tags', request) + self.assertEqual(self.task, original) + + def test_wrong_role_stops_before_a_migration_can_run(self): + self.task['executionRoleArn'] = 'unexpected' + with self.assertRaises(r.d.DeployError): + r.migration_request(self.m, self.task, [], self.image) + + def test_zero_capacity_is_only_an_initial_state(self): + self.previous.update(desiredCount=0, runningCount=0) + self.assertTrue(r.initial_stable(self.previous, self.old)) + self.assertFalse(r.d.stable(self.previous, self.old)) + + def test_incomplete_stack_bootstrap_blocks_release(self): + aws = Mock() + aws.call.return_value = {'Stacks': [{'StackStatus': 'UPDATE_COMPLETE', 'Parameters': [ + {'ParameterKey': 'Environment', 'ParameterValue': 'production'}, + {'ParameterKey': 'BootstrapOnly', 'ParameterValue': 'true'}, + ]}]} + with self.assertRaisesRegex(r.d.DeployError, 'bootstrap'): + r.stack_settings(aws, self.m) + + def migration_aws(self, exit_code=0, digest=None): + aws = Mock() + definition = r.d.arn(self.m, 'ecs', 'task-definition/forms-api-v6-migrate:4') + def call(api_service, operation, **kwargs): + if operation == 'register-task-definition': + return {'taskDefinition': {'taskDefinitionArn': definition}} + if operation == 'run-task': + self.assertEqual(kwargs['networkConfiguration'], self.previous['networkConfiguration']) + return {'tasks': [{'taskArn': 'migration-task'}]} + if operation == 'describe-tasks': + return {'tasks': [{'taskDefinitionArn': definition, 'lastStatus': 'STOPPED', + 'containers': [{'exitCode': exit_code, 'imageDigest': digest or 'sha256:' + 'a' * 64}]}]} + self.fail('Unexpected AWS operation: ' + operation) + aws.call.side_effect = call + return aws + + def test_failed_or_wrong_image_migration_never_promotes(self): + for code, digest in ((1, None), (0, 'sha256:' + 'b' * 64)): + with self.subTest(code=code, digest=digest), self.assertRaises(r.d.DeployError): + r.migrate(self.migration_aws(code, digest), self.m, self.previous, self.task, [], self.image) + + def test_successful_migration_uses_the_private_service_network(self): + self.assertEqual(r.migrate(self.migration_aws(), self.m, self.previous, self.task, [], self.image), 'migration-task') + + def test_migration_failure_stops_release_before_runtime_registration(self): + aws = Mock() + aws.call.return_value = {'taskDefinition': self.task} + publisher = Mock() + publisher.publish.return_value = self.image + with patch.object(r, 'stack_settings'), patch.object(r, 'read_service', return_value=self.previous), \ + patch.object(r, 'migrate', side_effect=r.d.DeployError('migration failed')), patch.object(r, 'promote') as promote: + with self.assertRaises(r.d.DeployError): + r.release(aws, self.m, publisher, 'a' * 40 + '-1') + self.assertEqual(publisher.publish.call_count, 2) + promote.assert_not_called() + + def test_activation_preserves_positive_capacity_and_starts_zero_at_one(self): + for desired in (0, 3): + with self.subTest(desired=desired): + previous = deepcopy(self.previous) + previous.update(desiredCount=desired, runningCount=desired) + request = r.d.task_request(self.m, self.task, [], {'forms-api-v6': self.image}) + aws = Mock() + def call(api_service, operation, **kwargs): + if operation == 'register-task-definition': + self.assertNotIn('tags', kwargs) + return {'taskDefinition': {'taskDefinitionArn': self.new}} + if operation == 'describe-task-definition': + return {'taskDefinition': {k: v for k, v in request.items() if k != 'tags'}, 'tags': []} + if operation == 'update-service': + self.assertEqual(kwargs['desiredCount'], max(1, desired)) + return {'service': {'taskDefinition': self.new}} + self.fail('Unexpected AWS operation: ' + operation) + aws.call.side_effect = call + with patch.object(r, 'read_service', return_value=previous), \ + patch.object(r.d, 'read_service'), patch.object(r.d, 'stable', return_value=True), \ + patch.object(r.d, 'verify_running', return_value=True): + self.assertEqual(r.promote(aws, self.m, previous, self.task, [], self.image), self.new) + + def test_optional_circuit_breaker_fields_preserve_safety_flags(self): + self.previous['deploymentConfiguration']['deploymentCircuitBreaker'].update(resetOnHealthyTask=True, thresholdConfiguration={'minimumFailureThreshold': 3}) + aws = Mock() + aws.call.return_value = {'services': [self.previous]} + self.assertEqual(r.read_service(aws, self.m), self.previous) + for flag in ('enable', 'rollback'): + with self.subTest(flag=flag): + self.previous['deploymentConfiguration']['deploymentCircuitBreaker'][flag] = False + with self.assertRaises(r.d.DeployError): + r.read_service(aws, self.m) + self.previous['deploymentConfiguration']['deploymentCircuitBreaker'][flag] = True + + +if __name__ == '__main__': + unittest.main() diff --git a/docs/data-model.md b/docs/data-model.md index c4ae0c5..083dd74 100644 --- a/docs/data-model.md +++ b/docs/data-model.md @@ -134,6 +134,13 @@ enabled. Migration `20261022010000_lets_talk_classification` seeds the Let's tal classify and label flows disabled; forms-processor-v6 ADR 0001 and its `examples/lets-talk-shadow-mode.sql` / `lets-talk-cutover.sql` describe the rollout. +Migration `20261102010000_space_tech_challenge_email` seeds `space-tech-challenge-email`, +which emails every `space_tech_challenge` submission to a fixed list, with the submitter's +`email` answer as reply-to. It is disabled with empty settings: forms-processor-v6 supplies +the recipients and template from `SPACE_TECH_CHALLENGE_RECIPIENTS` and +`SPACE_TECH_CHALLENGE_TEMPLATE_ID`. Enable it in SQL after both are set and the processor +is redeployed. + Processor events contain answers and must be included in personal-data retention and erasure procedures separately from `Submission`. Deleting a ProcessorEvent cascades its delivery records and removes deduplication protection, so retain it diff --git a/eslint.config.mjs b/eslint.config.mjs index 84edd59..ab0fc11 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -8,5 +8,6 @@ export default tseslint.config( }, js.configs.recommended, ...tseslint.configs.recommended, + { files: ['tools/**/*.cjs'], languageOptions: { sourceType: 'commonjs' }, rules: { '@typescript-eslint/no-require-imports': 'off' } }, { languageOptions: { globals: { ...globals.node, ...globals.browser } } }, ); diff --git a/examples/space-tech-challenge.json b/examples/space-tech-challenge.json new file mode 100644 index 0000000..28efa36 --- /dev/null +++ b/examples/space-tech-challenge.json @@ -0,0 +1,36 @@ +{ + "title": "Share your space-data challenge", + "description": "", + "successMessage": "Thanks for sharing your challenge. We'll get back to you within 48 hours on whether it's a fit.", + "access": "ANONYMOUS", + "fields": [ + { + "key": "full_name", + "label": "Full Name", + "type": "TEXT", + "required": true, + "maxLength": 200 + }, + { + "key": "company", + "label": "Company", + "type": "TEXT", + "required": true, + "maxLength": 200 + }, + { + "key": "email", + "label": "Work Email", + "type": "EMAIL", + "required": true, + "maxLength": 254 + }, + { + "key": "challenge", + "label": "Which challenge are you trying to solve?", + "type": "TEXTAREA", + "required": true, + "maxLength": 5000 + } + ] +} diff --git a/package.json b/package.json index 80cb598..ce1a114 100644 --- a/package.json +++ b/package.json @@ -22,16 +22,17 @@ "migrate:deploy": "prisma migrate deploy", "migrate:dev": "prisma migrate dev", "test": "vitest run", - "test:integration": "vitest run --config vitest.integration.config.mts" + "test:integration": "vitest run --config vitest.integration.config.mts", + "test:dependency-compat": "node --test tools/minimatch-compat/index.test.cjs" }, "dependencies": { - "@nestjs/common": "11.1.28", - "@nestjs/core": "11.1.28", - "@nestjs/platform-express": "11.1.28", + "@nestjs/common": "11.2.8", + "@nestjs/core": "11.2.8", + "@nestjs/platform-express": "11.2.8", "@nestjs/swagger": "11.4.6", "@nestjs/throttler": "6.5.0", - "@prisma/adapter-pg": "7.10.0", - "@prisma/client": "7.10.0", + "@prisma/adapter-pg": "7.10.1", + "@prisma/client": "7.10.1", "class-transformer": "0.5.1", "class-validator": "0.14.4", "dotenv": "17.2.3", @@ -42,12 +43,11 @@ "pg": "8.23.0", "reflect-metadata": "0.2.2", "rxjs": "7.8.2", - "tc-bus-api-wrapper": "github:topcoder-platform/tc-bus-api-wrapper#297a9c0adcdb97661257e7825bee9c3f5578b833", - "tc-core-library-js": "github:topcoder-platform/tc-core-library-js#323567bc50e433ae488b656f9f94e821ebaf3062" + "tc-core-library-js": "https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/58de37670180e183e8378c3d203df0112a0414f6" }, "devDependencies": { "@eslint/js": "9.39.2", - "@nestjs/testing": "11.1.28", + "@nestjs/testing": "11.2.8", "@swc/core": "1.15.11", "@types/express": "5.0.6", "@types/jsonwebtoken": "9.0.10", @@ -58,19 +58,19 @@ "@types/supertest": "6.0.3", "eslint": "9.39.2", "globals": "16.5.0", - "jsdom": "27.4.0", + "jsdom": "30.1.3", "nock": "14.0.16", - "payload": "3.87.1", + "payload": "3.92.1", "prettier": "3.8.1", - "prisma": "7.10.0", + "prisma": "7.10.1", "react": "19.2.8", "react-dom": "19.2.8", "supertest": "7.2.2", "ts-node": "10.9.2", "tsx": "4.22.4", "typescript": "5.9.3", - "typescript-eslint": "8.54.0", + "typescript-eslint": "8.72.1", "unplugin-swc": "1.5.9", - "vitest": "4.0.18" + "vitest": "4.1.12" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 60ca14a..ee60c90 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,33 +5,52 @@ settings: excludeLinksFromLockfile: false overrides: - tc-core-library-js: github:topcoder-platform/tc-core-library-js#323567bc50e433ae488b656f9f94e821ebaf3062 + body-parser@^2: 2.4.0 + proxy-addr: 2.0.8 + qs: 6.16.1 + multer: 2.5.0 + deepmerge-ts: 8.0.2 + js-yaml@^3: 3.15.2 + js-yaml@^4: 4.3.2 + js-yaml@^5: 5.5.0 + undici@^7: 7.30.1 + undici@^8: 8.12.3 + fast-uri: 3.1.9 + brace-expansion@^1: 1.1.21 + brace-expansion@^2: 2.1.7 + brace-expansion@>=3: 5.0.12 + source-map-js: 1.2.2 + minimatch@<9: file:tools/minimatch-compat + minimatch@>=9: 11.0.1 + glob@>=9: 14.0.2 + vite: 7.3.7 + mysql2: 3.23.1 importers: .: dependencies: '@nestjs/common': - specifier: 11.1.28 - version: 11.1.28(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: 11.2.8 + version: 11.2.8(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': - specifier: 11.1.28 - version: 11.1.28(@nestjs/common@11.1.28(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/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) + specifier: 11.2.8 + version: 11.2.8(@nestjs/common@11.2.8(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/platform-express@11.2.8)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/platform-express': - specifier: 11.1.28 - version: 11.1.28(@nestjs/common@11.1.28(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@11.1.28)(supports-color@7.2.0) + specifier: 11.2.8 + version: 11.2.8(@nestjs/common@11.2.8(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@11.2.8)(supports-color@7.2.0) '@nestjs/swagger': specifier: 11.4.6 - version: 11.4.6(@nestjs/common@11.1.28(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@11.1.28)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2) + version: 11.4.6(@nestjs/common@11.2.8(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@11.2.8)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2) '@nestjs/throttler': specifier: 6.5.0 - version: 6.5.0(@nestjs/common@11.1.28(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@11.1.28)(reflect-metadata@0.2.2) + version: 6.5.0(@nestjs/common@11.2.8(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@11.2.8)(reflect-metadata@0.2.2) '@prisma/adapter-pg': - specifier: 7.10.0 - version: 7.10.0 + specifier: 7.10.1 + version: 7.10.1 '@prisma/client': - specifier: 7.10.0 - version: 7.10.0(prisma@7.10.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@5.9.3))(typescript@5.9.3) + specifier: 7.10.1 + version: 7.10.1(prisma@7.10.1(@types/node@26.0.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@5.9.3))(typescript@5.9.3) class-transformer: specifier: 0.5.1 version: 0.5.1 @@ -62,19 +81,16 @@ importers: rxjs: specifier: 7.8.2 version: 7.8.2 - tc-bus-api-wrapper: - specifier: github:topcoder-platform/tc-bus-api-wrapper#297a9c0adcdb97661257e7825bee9c3f5578b833 - version: '@topcoder-platform/topcoder-bus-api-wrapper@https://codeload.github.com/topcoder-platform/tc-bus-api-wrapper/tar.gz/297a9c0adcdb97661257e7825bee9c3f5578b833(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0)' tc-core-library-js: - specifier: github:topcoder-platform/tc-core-library-js#323567bc50e433ae488b656f9f94e821ebaf3062 - version: https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/323567bc50e433ae488b656f9f94e821ebaf3062(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0) + specifier: https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/58de37670180e183e8378c3d203df0112a0414f6 + version: https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/58de37670180e183e8378c3d203df0112a0414f6(supports-color@7.2.0) devDependencies: '@eslint/js': specifier: 9.39.2 version: 9.39.2 '@nestjs/testing': - specifier: 11.1.28 - version: 11.1.28(@nestjs/common@11.1.28(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@11.1.28)(@nestjs/platform-express@11.1.28) + specifier: 11.2.8 + version: 11.2.8(@nestjs/common@11.2.8(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@11.2.8)(@nestjs/platform-express@11.2.8) '@swc/core': specifier: 1.15.11 version: 1.15.11 @@ -106,20 +122,20 @@ importers: specifier: 16.5.0 version: 16.5.0 jsdom: - specifier: 27.4.0 - version: 27.4.0(@noble/hashes@1.8.0)(supports-color@7.2.0) + specifier: 30.1.3 + version: 30.1.3(@noble/hashes@1.8.0) nock: specifier: 14.0.16 version: 14.0.16 payload: - specifier: 3.87.1 - version: 3.87.1(graphql@16.14.2)(supports-color@7.2.0)(typescript@5.9.3) + specifier: 3.92.1 + version: 3.92.1(graphql@16.14.2)(supports-color@7.2.0)(typescript@5.9.3) prettier: specifier: 3.8.1 version: 3.8.1 prisma: - specifier: 7.10.0 - version: 7.10.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@5.9.3) + specifier: 7.10.1 + version: 7.10.1(@types/node@26.0.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@5.9.3) react: specifier: 19.2.8 version: 19.2.8 @@ -139,74 +155,74 @@ importers: specifier: 5.9.3 version: 5.9.3 typescript-eslint: - specifier: 8.54.0 - version: 8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + specifier: 8.72.1 + version: 8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) unplugin-swc: specifier: 1.5.9 version: 1.5.9(@swc/core@1.15.11)(rollup@4.63.1) vitest: - specifier: 4.0.18 - version: 4.0.18(@types/node@26.0.0)(jiti@2.7.0)(jsdom@27.4.0(@noble/hashes@1.8.0)(supports-color@7.2.0))(tsx@4.22.4) + specifier: 4.1.12 + version: 4.1.12(@types/node@26.0.0)(jsdom@30.1.3(@noble/hashes@1.8.0))(vite@7.3.7(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4)) packages: - '@acemir/cssom@0.9.31': - resolution: {integrity: sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==} - '@apidevtools/json-schema-ref-parser@11.9.3': resolution: {integrity: sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==} engines: {node: '>= 16'} - '@asamuzakjp/css-color@4.1.2': - resolution: {integrity: sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==} - - '@asamuzakjp/dom-selector@6.8.1': - resolution: {integrity: sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==} + '@asamuzakjp/css-color@7.1.9': + resolution: {integrity: sha512-vZ6JQVq8Ivgz6b/IBlAf90wZviXdluY13cQOPO+nJHbmXwGrPl2GcpqUY7a55/8ZVdfONXpCFMpRijOBCHNlcQ==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} - '@asamuzakjp/nwsapi@2.3.9': - resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@asamuzakjp/dom-selector@10.0.5': + resolution: {integrity: sha512-EgmJ7oEaGQECTn3H3wmnQpEy4hKY66VvM7VQndwPIQob3p877BgbyOUE3EX0LgXQCciF2H8KMdR+RznqjMNOLw==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} '@borewit/text-codec@0.2.2': resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + '@bramus/specificity@2.4.3': + resolution: {integrity: sha512-0GEz8qJWokkUVYQYRukmkSHIFNoBH8QTreeHrAFbvz1XFYc3Y+puhMs8PQ5x8GNugiC2l5jvDBXKLbBIByeSBw==} + hasBin: true + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@csstools/color-helpers@6.1.1': - resolution: {integrity: sha512-gLNsunvwf3mCi5u5o46/Z/JcJMnhbHSaZ69rkgPzNM3J4s8hWwpPUQB6/tt0EDFyCiWzxANlx+2LJwpYj4zS1w==} + '@csstools/color-helpers@6.1.2': + resolution: {integrity: sha512-grhRy3OKmniaAEKXMjua5z/EODX0MSqBGjunw8+j/3HQjOnahs2AGhvEOIYVUWcU6ScApbhLhVrQTX8XqrMrow==} engines: {node: '>=20.19.0'} - '@csstools/css-calc@3.3.0': - resolution: {integrity: sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==} + '@csstools/css-calc@3.4.3': + resolution: {integrity: sha512-iex20d8CHVkyvg6B7UKV7uHnI2Bqo9g+EFfT9E0y+GvTvhZ/DwONJ+9aKb1dlqm0ZiGsL5RXjp0fCoJYnkeDjA==} engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-parser-algorithms': ^4.0.0 - '@csstools/css-tokenizer': ^4.0.0 + '@csstools/css-parser-algorithms': ^4.0.2 + '@csstools/css-tokenizer': ^4.0.2 - '@csstools/css-color-parser@4.2.2': - resolution: {integrity: sha512-3QKjR/vxyjcSXBLgb6lP0S3MGdvwbmqSsvLPbYdVORqPDc8FX1HAJ0Spk38bxaRXgvENTA47tlhhbb5Z2e8hEg==} + '@csstools/css-color-parser@4.2.7': + resolution: {integrity: sha512-zgm9yjQz5iJB4VL8RyVwd71TWB8Q89FSxt/NzXoWqPSkEBOVtn9L6vAPtSc9hpKfB0Awo/AL2VKFHjYetBLFHQ==} engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-parser-algorithms': ^4.0.0 - '@csstools/css-tokenizer': ^4.0.0 + '@csstools/css-parser-algorithms': ^4.0.2 + '@csstools/css-tokenizer': ^4.0.2 - '@csstools/css-parser-algorithms@4.0.0': - resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + '@csstools/css-parser-algorithms@4.0.2': + resolution: {integrity: sha512-40cSKyMvK+tq4qz6Awrlye2WGuOKt3FwPgtGg6KTfbHOWNw+Rk1rzbAtZnZ6IBhsY491HLRnDXwoyBAijmmILA==} engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-tokenizer': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.2 - '@csstools/css-syntax-patches-for-csstree@1.1.12': - resolution: {integrity: sha512-3vLQK+dXxhBMR2Wx99PTCifE+vHtW2ndZWyla8yK813ev6oGhyn8Lja8jCyGAWTJ+LEYZK7EVtJxrDj8ztevJw==} + '@csstools/css-syntax-patches-for-csstree@1.1.16': + resolution: {integrity: sha512-LsDbJPP/B8cPasUJyTA5S99F7C4G93ngW8hUluXz8CFeOaaRnBPtBiIlvgcPYU0HmHNz8CXg+1vwFrIB4F6Dgw==} peerDependencies: css-tree: ^3.2.1 peerDependenciesMeta: css-tree: optional: true - '@csstools/css-tokenizer@4.0.0': - resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + '@csstools/css-tokenizer@4.0.2': + resolution: {integrity: sha512-OoKoR0f76dCY666JlcbhmVTs2drYj1GUXZTYTcbUgJjh9Nv41aFfZ21bPQTERm5+L5cBDo466NltB2lplS5GBw==} engines: {node: '>=20.19.0'} '@electric-sql/pglite-socket@0.1.3': @@ -426,25 +442,14 @@ packages: '@noble/hashes': optional: true - '@hapi/address@5.1.1': - resolution: {integrity: sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==} - engines: {node: '>=14.0.0'} - - '@hapi/formula@3.0.2': - resolution: {integrity: sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw==} - - '@hapi/hoek@11.0.7': - resolution: {integrity: sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==} - - '@hapi/pinpoint@2.0.1': - resolution: {integrity: sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==} - - '@hapi/tlds@1.1.7': - resolution: {integrity: sha512-MgNjRwy9Ti92yVAixLmDc8dd1bJIKwO9qlWCfFQRwRmUEDPQHYn4G6hwPFvFGUTzAa0FsS+inMjLin7GnyBRhA==} - engines: {node: '>=14.0.0'} - - '@hapi/topo@6.0.2': - resolution: {integrity: sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==} + '@exodus/bytes@1.16.0': + resolution: {integrity: sha512-IcpW84uEn3N7ETtNZMlxKhfl6Pec8rUNGOTBtWbK1FKhJxIFAptZyVrvVRVBimAJxJCgc3PxepxkdWWG4DVzfA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true '@humanfs/core@0.19.2': resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} @@ -466,6 +471,9 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@isaacs/nonrecursive-glob-match@1.0.3': + resolution: {integrity: sha512-SI7kyKHq4XXDRozw+r9GlRZkia1ZkFrpLW98r2IC2Bpr8YkFGE3fvjzmxCG0x78A++69HmDNrDvSMYBZmHGpKA==} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -506,8 +514,8 @@ packages: os: [linux] libc: [glibc] - '@nestjs/common@11.1.28': - resolution: {integrity: sha512-bRImsxibie+AM7xjdwcrm/gr5YeacI65kSBNzTufa1Ib5iwziaY/lqMtRh9THq6pbV4e1HP9aI2ZxGUumnmaoQ==} + '@nestjs/common@11.2.8': + resolution: {integrity: sha512-5NobtSscYwgS9r2p+ADCJCu9Fy164wRuGVTUJxoa5I3rLIVjRFWFlV+UA37bKf8Om+4tSGJe4j92zOVnISbdbw==} peerDependencies: class-transformer: '>=0.4.1' class-validator: '>=0.13.2' @@ -519,8 +527,8 @@ packages: class-validator: optional: true - '@nestjs/core@11.1.28': - resolution: {integrity: sha512-06m63xIRj8+l8uOeh/8LnYupGubkyu4f+bPKIadaSui6vK9KpXgoz7HveT1yOVLcEt0M0oCOEW5EuEXZkEmBBQ==} + '@nestjs/core@11.2.8': + resolution: {integrity: sha512-XzD1okTrM160+8M9mWWorEUlFPK6ZMjTy6pVxVOOdxSdqu+QWKKx9kI2Y0yVrvEmi/0HPFUErqi9PCKFZYYZfg==} engines: {node: '>= 20'} peerDependencies: '@nestjs/common': ^11.0.0 @@ -550,8 +558,8 @@ packages: class-validator: optional: true - '@nestjs/platform-express@11.1.28': - resolution: {integrity: sha512-hU+9Sz4m+onHrR5AmelI59QKmY/Re546bPnygnpqqeQdHDiJpBgjWbL4t6Jr73CBpS60cpyng7WzjgphNB9iwA==} + '@nestjs/platform-express@11.2.8': + resolution: {integrity: sha512-aSAAz8E31qv+sDsL0s7Cw/HoXmeM0TVf35ny17BjLL10c2PgFDp2vunycL7muVyp3/IP5TStMb3Ia4B/RTNHZA==} peerDependencies: '@nestjs/common': ^11.0.0 '@nestjs/core': ^11.0.0 @@ -573,8 +581,8 @@ packages: class-validator: optional: true - '@nestjs/testing@11.1.28': - resolution: {integrity: sha512-B+VgRxeLaH7jkOMgAyUP3N3rpFlisQ7JRxixRbgHvG6a0VgKbbkNSofKExexCgKmQQak80undb3+2kE1lUBmRQ==} + '@nestjs/testing@11.2.8': + resolution: {integrity: sha512-ng3NlbDHehZ6I14R41Q5KFTEfRSkBSKEjnUTwMVCD1oc6KWnzmwW3Ct8BcS15WlGlxC6gmKCibJle9eclvaOaA==} peerDependencies: '@nestjs/common': ^11.0.0 '@nestjs/core': ^11.0.0 @@ -612,20 +620,20 @@ packages: '@paralleldrive/cuid2@2.3.1': resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} - '@payloadcms/translations@3.87.1': - resolution: {integrity: sha512-swZ8KcJh4gc2saiII74ltsAjLhLk6HXvHchuHmBItVmV2jTdtcmiH2kACSekFeCEJvt2FbM1FUWSataVousejw==} + '@payloadcms/translations@3.92.1': + resolution: {integrity: sha512-VeL+mP/Q9Q1akTINDognLlVf3MhF+0ZhiVhxiE2DkavD7kaM1olMqdMJqOSGIYMgk7dgm9e7X2cWk0r0TzE0hw==} '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} - '@prisma/adapter-pg@7.10.0': - resolution: {integrity: sha512-N7nwSor0HO1Kz6xBv0TPAjAPysKK0fac6p4fVN3ensLOuzc/83Fgmln5k92eK/cvzqdkSR/2kkAqlbcdwVrwpw==} + '@prisma/adapter-pg@7.10.1': + resolution: {integrity: sha512-EP9ruPYHjKP80WZlb5qVaEXKgZjJieBFjAxcBtQnDAHD6+16UN4keVmBh6L/RUpuDQT2FQRbvKNgq5d4Ix+IkQ==} - '@prisma/client-runtime-utils@7.10.0': - resolution: {integrity: sha512-cnCy7lUV8/CctgKVEmqAbSLAmwqJdE/qAlqTBk/0NDk59zEb2cZ0M0M0E4vVPnqbSEYudRroQDvOWfUZH6RIfw==} + '@prisma/client-runtime-utils@7.10.1': + resolution: {integrity: sha512-AzoATVIgmO3lcZfM443+9SI7+cyLMW2+Psw4op8WQHpHvHCX//CKxv8fwhiL0yGWF8DjdQrFewxrZo5McBdB8g==} - '@prisma/client@7.10.0': - resolution: {integrity: sha512-Ubw/QS9JGIBSBUsyxAUQuK/Jcu0Tsva7le7QbLd91Kix9yJvYDdj5QkwgEbbZniH80dd+sziQcALPc+HnvQC8Q==} + '@prisma/client@7.10.1': + resolution: {integrity: sha512-5tgAbFGh//zVOC6WPNVgziOErJHYkUE+wmqCwbIyq6IrTXUYtv9y2iBFGh/Owo99Mx0+cr0j1FOrxkYBMuyhaQ==} engines: {node: ^20.19 || ^22.12 || >=24.0} peerDependencies: prisma: '*' @@ -636,11 +644,11 @@ packages: typescript: optional: true - '@prisma/config@7.10.0': - resolution: {integrity: sha512-Rcg828gIRE3HOQ3pOATFjV5d/P0U9OIobxhd/IMxlfWjA4vru0eGwb0AIwFw0rmcLMVShohZYWPixVxkBHsxUA==} + '@prisma/config@7.10.1': + resolution: {integrity: sha512-+0swF5ELUa3P/9cIR26+gpYjjCbGE0qvEBZhV4zMDkYsrtHjZ884MQbOnWFWXj600N0sSJNnHbtBqe12yDngWg==} - '@prisma/debug@7.10.0': - resolution: {integrity: sha512-caygJKtltmRIgdJ3jRpkOr7yM4DW6zxo5uOmojKWFb3asnxWoRkQOwZmXBgD8FZp4htrX+nMpcWqDwzlQ1+Y4g==} + '@prisma/debug@7.10.1': + resolution: {integrity: sha512-eFCAkGZ13D/qPg48JBlG5IWi9cSBBOC7oG3abDPcAkYioDWlIjh0YJJLK2J7qo5S+xWWD8I6egAN/8KbCaiMCA==} '@prisma/debug@7.2.0': resolution: {integrity: sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==} @@ -648,20 +656,20 @@ packages: '@prisma/dev@0.24.17': resolution: {integrity: sha512-UvdZzmpFwknnfreh6Jije84ekkYGPYEJhXG1tFzCsCfQyzJifrOo38eZc0qajzvaC6OLUOrN9ML5XfCnEZL9DA==} - '@prisma/driver-adapter-utils@7.10.0': - resolution: {integrity: sha512-u8zkcRLlaryO652T4qavBg0HmzNW5tSKdsCn6hc1PhWAp/J6k0vrxLuUs+b9o+HcjsK7Dfa01o4OFSn0frauJA==} + '@prisma/driver-adapter-utils@7.10.1': + resolution: {integrity: sha512-DJ4c6xvVnm3s9ZUyql9nCUicADSqyvH+CjXRCM9L6m5zJxCNmebCElG6X4irICq3rosBwlX+S19Dxq/4IrZk3A==} - '@prisma/engines-version@7.10.0-4.0edf323efd1d98336f3f0a68684b56f689b900d3': - resolution: {integrity: sha512-8OJ6RuZTZ06eFUOtBwxVmv8XMmOW6HWN5F+uxUbZkGxR0Bfab1dfAdXaHPmR5mb59E+fmUo8IOzXlbLY1SClbw==} + '@prisma/engines-version@8.1.0-1.d1b3f377ca835d73fd50954a5e22128b9ebdd6b8': + resolution: {integrity: sha512-XjXmwjN2NE340RpXoXv8ZF8aNAvr0FE+7gNfkKeW6vyjXs7F8uxvEbWQoVrhioXDQoIsnNmv7r+wxvzfdEZaWA==} - '@prisma/engines@7.10.0': - resolution: {integrity: sha512-KNumN6NHFwybvfdYzTee9pqwx5PvknpWAaHn6L5NsbrKdl+SQrsVZs9opKs6U6SAsvB26HDt3WybRjOhgoWOYQ==} + '@prisma/engines@7.10.1': + resolution: {integrity: sha512-R6/ghv1Bu36FhCdQLFof1pNtyoWoeDzJLYeTKjgqb4eGtOAJx7ZqJtcm4pzkahLfZ9rYz8AkmsMDwkyiYbXPCQ==} - '@prisma/fetch-engine@7.10.0': - resolution: {integrity: sha512-Zqyu8DY14t6W/xwmAxUYWCXtHrvQnSvT644EAZSsdM8NSmCS74vJJbBKdVsK3ucFpnUWkEpbO1a0CxJXrg130g==} + '@prisma/fetch-engine@7.10.1': + resolution: {integrity: sha512-qZezeaExLWG2ptbHOrMxdiWluKHgqEclTdJbvY6pk6+Wg7EiVkeq5U3cXz9ti8nd0bngNvsDgledLHVRg5LF1w==} - '@prisma/get-platform@7.10.0': - resolution: {integrity: sha512-0bra1LFYi8xNw0yqV62bHJNQk4BKleOngZiqPWIQc7a3+9q6rqsnqJ15BuepP8943PFMvtmgnP52juZsyYkA6w==} + '@prisma/get-platform@7.10.1': + resolution: {integrity: sha512-iVnghHne5vcaobBjPVCMEjh5r/1UCj394EIGTUclasFRatpR/MQwcM2veLv5kgoFSyYP54nch/lNFCQRYcDxvg==} '@prisma/get-platform@7.2.0': resolution: {integrity: sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==} @@ -994,9 +1002,8 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - '@topcoder-platform/topcoder-bus-api-wrapper@https://codeload.github.com/topcoder-platform/tc-bus-api-wrapper/tar.gz/297a9c0adcdb97661257e7825bee9c3f5578b833': - resolution: {gitHosted: true, tarball: https://codeload.github.com/topcoder-platform/tc-bus-api-wrapper/tar.gz/297a9c0adcdb97661257e7825bee9c3f5578b833} - version: 1.2.0 + '@topcoder/minimatch-compat@file:tools/minimatch-compat': + resolution: {directory: tools/minimatch-compat, type: directory} '@tsconfig/node10@1.0.13': resolution: {integrity: sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==} @@ -1129,63 +1136,63 @@ packages: '@types/validator@13.15.10': resolution: {integrity: sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==} - '@typescript-eslint/eslint-plugin@8.54.0': - resolution: {integrity: sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==} + '@typescript-eslint/eslint-plugin@8.72.1': + resolution: {integrity: sha512-5CokTWXpmbylfFabsbvHC0CAw3XLaGnoa+nFJX5FR592h/LoZsENUE6p/rg5xvkKrFEXz6pYmgI29AgXc2N3BQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.54.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/parser': ^8.72.1 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.54.0': - resolution: {integrity: sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==} + '@typescript-eslint/parser@8.72.1': + resolution: {integrity: sha512-ZGwZP4OCfyA0AQTpEAMWz+rtX01DRhQWW5hB0ucKDEIX5U7jdmPSaMx94rQfaPAQzIYz2BimOgKOJtjfpRFQ9g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.54.0': - resolution: {integrity: sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==} + '@typescript-eslint/project-service@8.72.1': + resolution: {integrity: sha512-fAuVMkwdO/huI8nyo/WKnNKf6Gag93S56Rh3Ts5mGcavwSdaN8tRg1gCeIGX8PF+nzp1BjGfO4gHhGzW1J6jTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.54.0': - resolution: {integrity: sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==} + '@typescript-eslint/scope-manager@8.72.1': + resolution: {integrity: sha512-lC/t6eMCZZQAAKZEYGL6RDVSuFehpdmMT6h+nJIjIa6oylN/PwDgDVtEIbB7O9xFfZYtZAYLoLlDNWKJhtF+uQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.54.0': - resolution: {integrity: sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==} + '@typescript-eslint/tsconfig-utils@8.72.1': + resolution: {integrity: sha512-e4D5R5vpeAEPBxT2BAzsFQL3sbwyeeeo5+aczgNSRK1V734jE7pTqaGFU+fXapWEQwnZbpFaTn32+Z8DwS6OTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.54.0': - resolution: {integrity: sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==} + '@typescript-eslint/type-utils@8.72.1': + resolution: {integrity: sha512-iY2wlmyrXJmx4yxUGP3aYCFF3cA/6ShddOKmLU2dx7LnEykbAM8WThlxZEfd1NddqceF6eJmZUayxx9oKIYNlg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.54.0': - resolution: {integrity: sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==} + '@typescript-eslint/types@8.72.1': + resolution: {integrity: sha512-LmE5IhQet1BWOWEXqBrVtBPsMAOQ6Nzk35d+WLh3mk4EUF33sqlfxjio1MdYeSvKSG5skactKKuixBIKXhL4Rw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.54.0': - resolution: {integrity: sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==} + '@typescript-eslint/typescript-estree@8.72.1': + resolution: {integrity: sha512-DAlUoUV93hIvrtIQLwCbmZQYVZwOMhiHJrOVUUIWicFZaIYjTRqlY3I/NZevfkLmSqkNHRu2qYDcq9lrn16oOQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.54.0': - resolution: {integrity: sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==} + '@typescript-eslint/utils@8.72.1': + resolution: {integrity: sha512-5v5liypurJBFHCBNqh/RjsymAD+VWcE0djuGY/BUqp5fC3Qn+luWDEksjuTtWjPn6i5zQlUtkZCRG/CYG0yCkA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.54.0': - resolution: {integrity: sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==} + '@typescript-eslint/visitor-keys@8.72.1': + resolution: {integrity: sha512-SB8xqipSzZHUePCCLNeYxqnxq83X61/qzNhjQGbTfjxGZIeOEP7tBgWYX05Tcd6CgE02WdTJnh5b8kMZJ/+bnQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@visx/curve@4.0.1-alpha.0': @@ -1223,34 +1230,34 @@ packages: '@visx/vendor@4.0.0-alpha.0': resolution: {integrity: sha512-6I+MuqXBcv9jnlcVowHoHKSdk9gXTWkHLKyqBwRWg7LY6A3Ei8SHfubpqGV5rBUSppxMq2RszPJUS6w+H0YgmQ==} - '@vitest/expect@4.0.18': - resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==} + '@vitest/expect@4.1.12': + resolution: {integrity: sha512-vFlTt+YEu9WBpNjdGayNmlMVzrWPi1+sv853/7t2FU7hpO5gAFBKHzQmkCq5Xjpr+evegF2994LQT3hF3mRlqQ==} - '@vitest/mocker@4.0.18': - resolution: {integrity: sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==} + '@vitest/mocker@4.1.12': + resolution: {integrity: sha512-fKShNpKZzupWZuY0z7egydvL0sqW4INEZBEExMBMAa6izlENEVHwoXgdaTCaBZ5fwlr4xf2o1wXC83n9RpO+NA==} peerDependencies: msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0-0 + vite: 7.3.7 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@4.0.18': - resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==} + '@vitest/pretty-format@4.1.12': + resolution: {integrity: sha512-XW9O8+Mxx4VpCtkYdMJLZQQwsVryP9wk7cPKDxtXFfwSak6yRh5+2fep/Y0XF/ElBvJHq8bcYdi6aeuai0opZA==} - '@vitest/runner@4.0.18': - resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==} + '@vitest/runner@4.1.12': + resolution: {integrity: sha512-NKlVKCr5QnCe8jijdMnmkpHHU+WTqiLFR6G0pHji9uRjXK9xJl1k1nTw6F3pOOj2PDcsDt2GKQMI7wIsaT491w==} - '@vitest/snapshot@4.0.18': - resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==} + '@vitest/snapshot@4.1.12': + resolution: {integrity: sha512-ko1y1Qgb/slzQ9mr+b89Cuqud8WG1TKtsPD8r7ZUBdvVOGt85Af2HwCqHujrhwJq95hs/9RM7fcAPg57o1vlzw==} - '@vitest/spy@4.0.18': - resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==} + '@vitest/spy@4.1.12': + resolution: {integrity: sha512-RGq9x4JNGNTZHEJxvN0oSiJjeSCExm0n2gZKKJZHY9cX5AVA6M7VJILBT3ZJ/tJ/0J9uWT7fETV9/btoi//vSg==} - '@vitest/utils@4.0.18': - resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} + '@vitest/utils@4.1.12': + resolution: {integrity: sha512-Q3awXrwOfEV+qc3WmO5ONyE0yO7Q1gQ9/oyHxGLZ/pl7N3NO/ZztqQwKLuwMkV+CA1JYSIeO3gkHnRDIo4AVaA==} accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} @@ -1270,10 +1277,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - agent-base@7.1.4: - resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} - engines: {node: '>= 14'} - ajv@6.15.0: resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} @@ -1296,6 +1299,9 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + argparse@3.0.4: + resolution: {integrity: sha512-fwWK3Zq22l4XJJjx5mcBHGikIk+hJqO+32dPm0Jur7+rtG5x1scOjSfdT9ZKeWHPpsya/l0HHK4tDImBkTrtvA==} + asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} @@ -1314,15 +1320,9 @@ packages: resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==} engines: {node: '>= 6.0.0'} - axios@0.30.3: - resolution: {integrity: sha512-5/tmEb6TmE/ax3mdXBc/Mi6YdPGxQsv+0p5YlciXWt3PHIn0VamqCXhRMtScnwY3lbgSXLneOuXAKUhgmSRpwg==} - - backoff@2.5.0: - resolution: {integrity: sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==} - engines: {node: '>= 0.6'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} better-result@2.10.0: resolution: {integrity: sha512-oQhh0y1qo2/ZKdAAEvHZAqKKiHOFU5k/bW96fE2ScgQOVkJRiHwB+nOS1SgFsYqRlxMDWvefXi9Q3px7QvgNDw==} @@ -1330,15 +1330,13 @@ packages: bidi-js@1.1.0: resolution: {integrity: sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==} - body-parser@2.3.0: - resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} + body-parser@2.4.0: + resolution: {integrity: sha512-Ifk1KcLrxaGt1occQagQNFNNOqRt1LFuehEnHHzB8Z6cRgIxRU1TBaiIsUiCdA+gy5PL7Y1IX31DNKkRmxtXjQ==} engines: {node: '>=18'} - brace-expansion@1.1.18: - resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==} - - brace-expansion@2.1.4: - resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==} + brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} bson-objectid@2.0.4: resolution: {integrity: sha512-vgnKAUzcDoa+AeyYwXCoHyF2q6u/8H46dxu5JN+4/TZeq/Dlinn0K6GvxsCLb3LHUJl0m/TLiEK31kUwtgocMQ==} @@ -1346,14 +1344,6 @@ packages: 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==} - - bunyan@1.8.15: - resolution: {integrity: sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==} - engines: {'0': node >=0.10.0} - hasBin: true - busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -1407,9 +1397,6 @@ packages: classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} - codependency@2.1.0: - resolution: {integrity: sha512-JIdmYkE8Z6jwH1OUf4a5H5jk9YShPQkaYPUAiN+ktyChmPP77LGbeKrxWGPqdCnpTmt0hRIn8TXBVu01U3HDhg==} - color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1427,13 +1414,6 @@ packages: component-emitter@1.3.1: resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - concat-stream@2.0.0: - resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} - engines: {'0': node >= 6.0} - confbox@0.2.4: resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} @@ -1455,6 +1435,9 @@ packages: resolution: {integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==} engines: {node: '>=18'} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie-signature@1.2.2: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} @@ -1485,10 +1468,6 @@ packages: resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - cssstyle@5.3.7: - resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==} - engines: {node: '>=20'} - csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -1540,9 +1519,9 @@ packages: resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} engines: {node: '>=12'} - data-urls@6.0.1: - resolution: {integrity: sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==} - engines: {node: '>=20'} + data-urls@8.0.0: + resolution: {integrity: sha512-JQUCCK+/CAGbGGx618PlFZMXH81Jtj7t73CHv9dd/zVWvxgGT2zLFRjnKb+Ng46GIwcy+f7f88qd4duqllK+WQ==} + engines: {node: ^22.14.0 || >=24.0.0} dataloader@2.2.3: resolution: {integrity: sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==} @@ -1568,9 +1547,9 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - deepmerge-ts@7.1.5: - resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==} - engines: {node: '>=16.0.0'} + deepmerge-ts@8.0.2: + resolution: {integrity: sha512-uqbvqLUMrc6p0MO+WBRtTxY55hmyh94WRwI5a++PZe54X+bfVh59FSN7uWCBCW1CCVjzjnrwzfI8zidE2obMMw==} + engines: {node: '>=16.9.0'} deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} @@ -1612,10 +1591,6 @@ packages: resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} engines: {node: '>=12'} - dtrace-provider@0.8.8: - resolution: {integrity: sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==} - engines: {node: '>=0.10'} - dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -1659,8 +1634,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-module-lexer@2.3.2: + resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} @@ -1694,6 +1669,10 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + eslint@9.39.2: resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1771,8 +1750,8 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fast-uri@3.1.7: - resolution: {integrity: sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==} + fast-uri@3.1.9: + resolution: {integrity: sha512-hS/0Wt3Ya043oKXs0sIxrMpKQITXhMLIrVAKKXi4gozGC9v7YRWVnXIZzjNPTO02M9BdxLCWqK1yRXgNziVyJQ==} fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} @@ -1810,15 +1789,6 @@ packages: flatted@3.4.4: resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} - follow-redirects@1.16.0: - resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -1872,10 +1842,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@6.0.4: - resolution: {integrity: sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==} - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -1924,26 +1890,18 @@ packages: help-me@5.0.0: resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} - html-encoding-sniffer@6.0.0: - resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + html-encoding-sniffer@7.0.0: + resolution: {integrity: sha512-UikN5yr7xsCDAq87Or5or0PAlD3HJJOKVzM05az588WnpDJ4Ux7a2A53Qi6gofGg2/EtvF/H4hCi/TXfCW4Y6w==} + engines: {node: ^22.13.0 || >=24.0.0} http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} - http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - http-status@2.1.0: resolution: {integrity: sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==} engines: {node: '>= 0.4.0'} - https-proxy-agent@7.0.6: - resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} - engines: {node: '>= 14'} - iconv-lite@0.7.3: resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} engines: {node: '>=0.10.0'} @@ -1972,10 +1930,6 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -2022,10 +1976,6 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true - joi@18.2.9: - resolution: {integrity: sha512-2mD929bUVKUhOLQQEVhlf6EZ0Mlo0DeRb5MO7cViR9AXLtBauuccEtB1py9Ocxpo/P7ucnh442iY/iOwrh3IQw==} - engines: {node: '>= 20'} - jose@4.15.9: resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} @@ -2043,15 +1993,15 @@ packages: resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} hasBin: true - js-yaml@5.2.1: - resolution: {integrity: sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==} + js-yaml@5.5.0: + resolution: {integrity: sha512-paNr4LFIFPjeeSmwNYdrb8FafLLG/Cr2Af3GjbsHJ5CxIjH4r0c2emlmRdAtpPAieP1gRVzk6buBbVP5gBMGAg==} hasBin: true - jsdom@27.4.0: - resolution: {integrity: sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + jsdom@30.1.3: + resolution: {integrity: sha512-hQMUPvRgN7KxsfIytDQji7bimuJeRQa6Qo5+iuiZQk5CafeRxLIA10/cG5YCBFNpD9RO3oqIiN4CO1Y44kxqXg==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} peerDependencies: - canvas: ^3.0.0 + canvas: ^3.2.3 peerDependenciesMeta: canvas: optional: true @@ -2148,8 +2098,8 @@ packages: long@5.3.2: resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} - lru-cache@11.5.2: - resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + lru-cache@11.5.3: + resolution: {integrity: sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==} engines: {node: 20 || >=22} lru-cache@6.0.0: @@ -2192,9 +2142,6 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - millisecond@0.1.2: - resolution: {integrity: sha512-BJ8XtxY+woL+5TkP6uS6XvOArm0JVrX2otkgtWZseHpIax0oOOPW3cnwhOjRqbEJg7YRO/BDF7fO/PTWNT3T9Q==} - mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -2216,45 +2163,30 @@ packages: engines: {node: '>=4.0.0'} hasBin: true - minimatch@3.1.5: - resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} - - minimatch@9.0.9: - resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@11.0.1: + resolution: {integrity: sha512-t+Vn6DX4wPCxS23y03C0uhF7S1jpi1GfqPrnlEipCJaA2ykiNbMkVlDutZtmvLfRcUN6R8AYVlzTsQrT4RZoLQ==} + engines: {node: 18 || 20 || >=22} minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - moment@2.31.0: - resolution: {integrity: sha512-0acOTfMiWOheYS4eoWb80yYMb/JLvVv9SHbs2PehaDzfUG0Bw855SKyk0IKTnPGa5+U2bmi3W68l1+sGLX/pvw==} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - multer@2.2.0: - resolution: {integrity: sha512-6rdyFg2kLrMh9Jee7/BMPuV9lEAd7lLW2YUpF9/YxR7njyoUwwQ0ZPh3TaIY50Sw6vlyD2HW3wGOkTS4P79xrQ==} + multer@2.5.0: + resolution: {integrity: sha512-BsqOzYGVq49JcW2IzoSAxeKYRevb+dGGPPWleOR8Lrlk4igwxu1/9pwSXlByhCb7MVZDrNJFC0IBP5/O5nLYRw==} engines: {node: '>= 10.16.0'} - mv@2.1.1: - resolution: {integrity: sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==} - engines: {node: '>=0.8.0'} - - mysql2@3.15.3: - resolution: {integrity: sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==} + mysql2@3.23.1: + resolution: {integrity: sha512-tTuRnC7qCet2IOfSNMYZ5SwXuBnfvBPAcIA28P0gtruXyZlU1LMxA6uha32kYypoFgyYklMqhLWwt4laYwXR/Q==} engines: {node: '>= 8.0'} + peerDependencies: + '@types/node': '>= 8' named-placeholders@1.1.6: resolution: {integrity: sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==} engines: {node: '>=8.0.0'} - nan@2.29.0: - resolution: {integrity: sha512-GlGk3HIvitbvs+LT3g6XUP1kpirKNvmDFwF/bmo6XNWSb/eYEs/O4bfgIEIXCZ+lIOTS5xNwDvSGMw6FJdAhtA==} - nanoid@3.3.18: resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2263,10 +2195,6 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - ncp@2.0.0: - resolution: {integrity: sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==} - hasBin: true - negotiator@1.1.0: resolution: {integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==} engines: {node: '>=18'} @@ -2331,10 +2259,6 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2348,9 +2272,9 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - payload@3.87.1: - resolution: {integrity: sha512-0dvxM5CaywBwJJBH+9a+JNIBMjUJQJEMCaxB+lkV4I0PL8rIU8tAno+i3cXS7UF7Qwcm1kpqTrxRoiA37HIOiw==} - engines: {node: ^18.20.2 || >=20.9.0} + payload@3.92.1: + resolution: {integrity: sha512-IBwuxbr7b1fX+Ub3qxzCru8EBrAb7AUatZHJSFW6Tv6o3LgjJE4ehsBmHcUqcxdQteaGOfcuw6DWAFKwq65yuQ==} + engines: {node: ^22.23.4 || >=24.22.1} hasBin: true peerDependencies: graphql: ^16.8.1 @@ -2448,10 +2372,6 @@ packages: resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==} engines: {node: '>=12'} - precond@0.2.3: - resolution: {integrity: sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==} - engines: {node: '>= 0.6'} - prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2461,8 +2381,8 @@ packages: engines: {node: '>=14'} hasBin: true - prisma@7.10.0: - resolution: {integrity: sha512-o0ornyJOWgygVAzGCpr8PdXV8EJLHyVGDDUr/voBQt8Azzw8cYTByzzPGcA/m4tCkPcnJA8raEOv2CslsKhPEw==} + prisma@7.10.1: + resolution: {integrity: sha512-GoVeErHGGtsSjsflQ1r2BA3RKTXtxNraQJz8OLkLhoLr7OgCscdx4qw4WMM4HnERYc+a1cq2VnMNbep+vOjNcQ==} engines: {node: ^20.19 || ^22.12 || >=24.0} hasBin: true peerDependencies: @@ -2484,13 +2404,10 @@ packages: proper-lockfile@4.1.2: resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + proxy-addr@2.0.8: + resolution: {integrity: sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==} engines: {node: '>= 0.10'} - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} @@ -2505,17 +2422,13 @@ packages: resolution: {integrity: sha512-eZ7l+0ZVy3He9c85pEM9KEBR9DFA4jrmWvIjm9wpcHvScwc/vgZDl2TNOF0pm0JsWKw24XBUZOY0Wxn7/nvJnw==} engines: {node: '>=18'} - qs@6.16.0: - resolution: {integrity: sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==} + qs@6.16.1: + resolution: {integrity: sha512-5Px6J7rfHBAGUhNQ3es4YzcOdBBw0SDcVtThJml4RdnKw4tKs2epA0kPZ+K8X+WiHktT93RHVcQ/3ym5aTCgtg==} engines: {node: '>=0.6'} quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} - r7insight_node@2.1.1: - resolution: {integrity: sha512-xx0kgFxSHWY9aG1109uv4w2b+JLwHseSowOWo1bzCTDBpUk3er2rZdtQ90mAjUYbkh6Hus9DAwWvmHsX5pHaIQ==} - engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} - range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -2540,10 +2453,6 @@ packages: resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==} engines: {node: '>=0.10.0'} - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - readdirp@5.1.1: resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==} engines: {node: '>= 20.19.0'} @@ -2552,9 +2461,6 @@ packages: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} - reconnect-core@1.3.0: - resolution: {integrity: sha512-+gLKwmyRf2tjl6bLR03DoeWELzyN6LW9Xgr3vh7NXHHwPi0JC0N2TwPyf90oUEBkCRcD+bgQ+s3HORoG3nwHDg==} - reflect-metadata@0.2.2: resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} @@ -2580,11 +2486,6 @@ packages: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} - rimraf@2.4.5: - resolution: {integrity: sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - robust-predicates@3.0.3: resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} @@ -2603,9 +2504,6 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safe-json-stringify@1.2.0: - resolution: {integrity: sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==} - safe-regex2@5.1.1: resolution: {integrity: sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==} hasBin: true @@ -2620,6 +2518,10 @@ packages: sanitize-filename@1.6.3: resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==} + sax@1.6.1: + resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} + engines: {node: '>=11.0.0'} + saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -2630,10 +2532,6 @@ packages: secure-json-parse@4.1.0: resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - semver@7.8.5: resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} engines: {node: '>=10'} @@ -2643,9 +2541,6 @@ packages: resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} - seq-queue@0.0.5: - resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==} - serve-static@2.2.1: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} @@ -2693,17 +2588,17 @@ packages: sonic-boom@4.2.1: resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + source-map-js@1.2.2: + resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} engines: {node: '>=0.10.0'} split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - sqlstring@2.3.3: - resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} - engines: {node: '>= 0.6'} + sql-escaper@1.5.2: + resolution: {integrity: sha512-6CKD38c31SENivxOADeMNLdukOnUxUcflKtzVWzace7Riv1v7cAEym5Cx9Q7gYZ3ezIJI7ZpqecQq8cqNeSSFg==} + engines: {bun: '>=1.0.0', deno: '>=2.0.0', node: '>=12.0.0'} stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -2715,6 +2610,9 @@ packages: std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.3.0: + resolution: {integrity: sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==} + streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -2722,9 +2620,6 @@ packages: strict-event-emitter@0.5.1: resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -2752,13 +2647,10 @@ packages: swagger-ui-dist@5.32.8: resolution: {integrity: sha512-dgMdWXIgnI4zX4OPhKEdWnlDODbgm8W3AX0Ivn/BBqcUh6xZsBxhZMnvk6DJyRz1BTrj8dPxtarmEGgkz30oyA==} - symbol-tree@3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - - tc-core-library-js@https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/323567bc50e433ae488b656f9f94e821ebaf3062: - resolution: {gitHosted: true, tarball: https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/323567bc50e433ae488b656f9f94e821ebaf3062} - version: 3.0.1 - engines: {node: '>= 14'} + tc-core-library-js@https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/58de37670180e183e8378c3d203df0112a0414f6: + resolution: {tarball: https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/58de37670180e183e8378c3d203df0112a0414f6} + version: 4.0.0-rc.2 + engines: {node: '>=22.13'} thread-stream@3.2.0: resolution: {integrity: sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==} @@ -2797,9 +2689,9 @@ packages: resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} engines: {node: '>=16'} - tr46@6.0.0: - resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} - engines: {node: '>=20'} + tr46@7.0.0: + resolution: {integrity: sha512-BcDSDW+SIGWVOns1Zm6Yg91q9AEj7eaID0QDY9oIqJD1A8dscNwMcl9Sms2DeuWCNov1X0/oXanHGYQBSLwZsg==} + engines: {node: ^22.14.0 || >=24.0.0} truncate-utf8-bytes@1.0.2: resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==} @@ -2840,6 +2732,11 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tsx@4.23.15: + resolution: {integrity: sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -2852,15 +2749,12 @@ packages: resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} engines: {node: '>= 18'} - typedarray@0.0.6: - resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - - typescript-eslint@8.54.0: - resolution: {integrity: sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ==} + typescript-eslint@8.72.1: + resolution: {integrity: sha512-3Li9FfPmQp45nxEtFD1ZCrYFI3cYK5kpyNtmm1H7lMagm8u9sy6PTjy3ytwQZs7KNukOyKFHAZ6z6GjYFeaeXw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} @@ -2878,10 +2772,14 @@ packages: undici-types@8.3.0: resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} - undici@7.29.0: - resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} + undici@7.30.1: + resolution: {integrity: sha512-03KrMbjIFDWQR5RNPrSw3bd1r12JpyFQl9/yxjUbJtqkjmllqC5lFjZh6ujeuJCKr8EOQvRW872Oy/az+nLYxg==} engines: {node: '>=20.18.1'} + undici@8.12.3: + resolution: {integrity: sha512-+fdndUTwBP86cVjihTp21hZHo7d6oj1c/47XPA3lL8mM0XHs+C4EkcjmgRsFnFk2f/UONGDy9ItBItmXsLOQHw==} + engines: {node: '>=22.19.0'} + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -2901,9 +2799,6 @@ packages: utf8-byte-length@1.0.5: resolution: {integrity: sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==} - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - uuid@13.0.2: resolution: {integrity: sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw==} hasBin: true @@ -2927,8 +2822,8 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - vite@7.3.6: - resolution: {integrity: sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==} + vite@7.3.7: + resolution: {integrity: sha512-AHEzTORMbi7/7aXp7w7KZ5+DCUdSeLsJz0grY8xHpc9DHdYb0vQu6DqJfm2tOw3gDExNgPgnJTXxM6syYFHaCA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -2967,20 +2862,23 @@ packages: yaml: optional: true - vitest@4.0.18: - resolution: {integrity: sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==} + vitest@4.1.12: + resolution: {integrity: sha512-5eWdz2yb3ajxWF3C8C4TjkXl7FGm3n2E/VlazALrQHzK7nYMSGFnCZto0bbPNl77AwkOZVLk0YnBAejUu0NiWA==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.0.18 - '@vitest/browser-preview': 4.0.18 - '@vitest/browser-webdriverio': 4.0.18 - '@vitest/ui': 4.0.18 + '@vitest/browser-playwright': 4.1.12 + '@vitest/browser-preview': 4.1.12 + '@vitest/browser-webdriverio': ^4.1.11 + '@vitest/coverage-istanbul': 4.1.12 + '@vitest/coverage-v8': 4.1.12 + '@vitest/ui': 4.1.12 happy-dom: '*' jsdom: '*' + vite: 7.3.7 peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -2994,6 +2892,10 @@ packages: optional: true '@vitest/browser-webdriverio': optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true '@vitest/ui': optional: true happy-dom: @@ -3001,9 +2903,9 @@ packages: jsdom: optional: true - w3c-xmlserializer@5.0.0: - resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} - engines: {node: '>=18'} + w3c-xmlserializer@6.0.0: + resolution: {integrity: sha512-4Nsy8K5Tr6SPDH9jhKJOHf7ChDrc1zufZTVSF7x72hwuEXBqxqk9G6cK+K2NRUtB3iELRJqjXb4JPDMBjMTl2Q==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} webidl-conversions@8.0.1: resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} @@ -3012,17 +2914,13 @@ packages: webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} - whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} - whatwg-mimetype@5.0.0: resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} engines: {node: '>=20'} - whatwg-url@15.1.0: - resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} - engines: {node: '>=20'} + whatwg-url@17.3.0: + resolution: {integrity: sha512-KwOAJrpf+GTgBvcBQJcP38sMF0DsQKdwtG+TxM2pW44P6E5k0hDbWrDmyuJDIF0Uef0aQq0ZoJs+5oI+k8ddhg==} + engines: {node: ^22.14.0 || >=24.0.0} which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} @@ -3080,61 +2978,60 @@ packages: snapshots: - '@acemir/cssom@0.9.31': {} - '@apidevtools/json-schema-ref-parser@11.9.3': dependencies: '@jsdevtools/ono': 7.1.3 '@types/json-schema': 7.0.15 js-yaml: 4.3.2 - '@asamuzakjp/css-color@4.1.2': + '@asamuzakjp/css-color@7.1.9': dependencies: - '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-color-parser': 4.2.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 - lru-cache: 11.5.2 + '@csstools/css-calc': 3.4.3(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-color-parser': 4.2.7(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-parser-algorithms': 4.0.2(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 + lru-cache: 11.5.3 - '@asamuzakjp/dom-selector@6.8.1': + '@asamuzakjp/dom-selector@10.0.5': dependencies: - '@asamuzakjp/nwsapi': 2.3.9 bidi-js: 1.1.0 css-tree: 3.2.1 is-potential-custom-element-name: 1.0.1 - lru-cache: 11.5.2 - - '@asamuzakjp/nwsapi@2.3.9': {} + lru-cache: 11.5.3 '@borewit/text-codec@0.2.2': {} + '@bramus/specificity@2.4.3': + dependencies: + css-tree: 3.2.1 + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@csstools/color-helpers@6.1.1': {} + '@csstools/color-helpers@6.1.2': {} - '@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-calc@3.4.3(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)': dependencies: - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 + '@csstools/css-parser-algorithms': 4.0.2(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 - '@csstools/css-color-parser@4.2.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-color-parser@4.2.7(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)': dependencies: - '@csstools/color-helpers': 6.1.1 - '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 + '@csstools/color-helpers': 6.1.2 + '@csstools/css-calc': 3.4.3(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-parser-algorithms': 4.0.2(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 - '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2)': dependencies: - '@csstools/css-tokenizer': 4.0.0 + '@csstools/css-tokenizer': 4.0.2 - '@csstools/css-syntax-patches-for-csstree@1.1.12(css-tree@3.2.1)': + '@csstools/css-syntax-patches-for-csstree@1.1.16(css-tree@3.2.1)': optionalDependencies: css-tree: 3.2.1 - '@csstools/css-tokenizer@4.0.0': {} + '@csstools/css-tokenizer@4.0.2': {} '@electric-sql/pglite-socket@0.1.3(@electric-sql/pglite@0.4.3)': dependencies: @@ -3235,7 +3132,7 @@ snapshots: dependencies: '@eslint/object-schema': 2.1.7 debug: 4.4.3(supports-color@7.2.0) - minimatch: 3.1.5 + minimatch: '@topcoder/minimatch-compat@file:tools/minimatch-compat' transitivePeerDependencies: - supports-color @@ -3256,7 +3153,7 @@ snapshots: ignore: 5.3.2 import-fresh: 3.3.1 js-yaml: 4.3.2 - minimatch: 3.1.5 + minimatch: '@topcoder/minimatch-compat@file:tools/minimatch-compat' strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color @@ -3274,21 +3171,9 @@ snapshots: optionalDependencies: '@noble/hashes': 1.8.0 - '@hapi/address@5.1.1': - dependencies: - '@hapi/hoek': 11.0.7 - - '@hapi/formula@3.0.2': {} - - '@hapi/hoek@11.0.7': {} - - '@hapi/pinpoint@2.0.1': {} - - '@hapi/tlds@1.1.7': {} - - '@hapi/topo@6.0.2': - dependencies: - '@hapi/hoek': 11.0.7 + '@exodus/bytes@1.16.0(@noble/hashes@1.8.0)': + optionalDependencies: + '@noble/hashes': 1.8.0 '@humanfs/core@0.19.2': dependencies: @@ -3306,6 +3191,8 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@isaacs/nonrecursive-glob-match@1.0.3': {} + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.6.0 @@ -3348,7 +3235,7 @@ snapshots: '@napi-rs/lzma-linux-x64-gnu@1.5.1': optional: true - '@nestjs/common@11.1.28(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@11.2.8(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: file-type: 21.3.4(supports-color@7.2.0) iterare: 1.2.1 @@ -3363,9 +3250,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@nestjs/core@11.1.28(@nestjs/common@11.1.28(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/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/core@11.2.8(@nestjs/common@11.2.8(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/platform-express@11.2.8)(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.28(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': 11.2.8(class-transformer@0.5.1)(class-validator@0.14.4)(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: 8.4.2 @@ -3374,35 +3261,35 @@ snapshots: tslib: 2.8.1 uid: 2.0.2 optionalDependencies: - '@nestjs/platform-express': 11.1.28(@nestjs/common@11.1.28(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@11.1.28)(supports-color@7.2.0) + '@nestjs/platform-express': 11.2.8(@nestjs/common@11.2.8(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@11.2.8)(supports-color@7.2.0) - '@nestjs/mapped-types@2.1.1(@nestjs/common@11.1.28(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@2.1.1(@nestjs/common@11.2.8(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)': dependencies: - '@nestjs/common': 11.1.28(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': 11.2.8(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 optionalDependencies: class-transformer: 0.5.1 class-validator: 0.14.4 - '@nestjs/platform-express@11.1.28(@nestjs/common@11.1.28(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@11.1.28)(supports-color@7.2.0)': + '@nestjs/platform-express@11.2.8(@nestjs/common@11.2.8(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@11.2.8)(supports-color@7.2.0)': dependencies: - '@nestjs/common': 11.1.28(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': 11.1.28(@nestjs/common@11.1.28(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/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.2.8(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': 11.2.8(@nestjs/common@11.2.8(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/platform-express@11.2.8)(reflect-metadata@0.2.2)(rxjs@7.8.2) cors: 2.8.6 express: 5.2.1(supports-color@7.2.0) - multer: 2.2.0 + multer: 2.5.0 path-to-regexp: 8.4.2 tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@nestjs/swagger@11.4.6(@nestjs/common@11.1.28(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@11.1.28)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)': + '@nestjs/swagger@11.4.6(@nestjs/common@11.2.8(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@11.2.8)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)': dependencies: '@microsoft/tsdoc': 0.16.0 - '@nestjs/common': 11.1.28(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': 11.1.28(@nestjs/common@11.1.28(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/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/mapped-types': 2.1.1(@nestjs/common@11.1.28(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: 5.2.1 + '@nestjs/common': 11.2.8(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': 11.2.8(@nestjs/common@11.2.8(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/platform-express@11.2.8)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/mapped-types': 2.1.1(@nestjs/common@11.2.8(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: 5.5.0 lodash: 4.18.1 path-to-regexp: 8.4.2 reflect-metadata: 0.2.2 @@ -3411,18 +3298,18 @@ snapshots: class-transformer: 0.5.1 class-validator: 0.14.4 - '@nestjs/testing@11.1.28(@nestjs/common@11.1.28(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@11.1.28)(@nestjs/platform-express@11.1.28)': + '@nestjs/testing@11.2.8(@nestjs/common@11.2.8(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@11.2.8)(@nestjs/platform-express@11.2.8)': dependencies: - '@nestjs/common': 11.1.28(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': 11.1.28(@nestjs/common@11.1.28(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/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.2.8(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': 11.2.8(@nestjs/common@11.2.8(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/platform-express@11.2.8)(reflect-metadata@0.2.2)(rxjs@7.8.2) tslib: 2.8.1 optionalDependencies: - '@nestjs/platform-express': 11.1.28(@nestjs/common@11.1.28(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@11.1.28)(supports-color@7.2.0) + '@nestjs/platform-express': 11.2.8(@nestjs/common@11.2.8(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@11.2.8)(supports-color@7.2.0) - '@nestjs/throttler@6.5.0(@nestjs/common@11.1.28(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@11.1.28)(reflect-metadata@0.2.2)': + '@nestjs/throttler@6.5.0(@nestjs/common@11.2.8(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@11.2.8)(reflect-metadata@0.2.2)': dependencies: - '@nestjs/common': 11.1.28(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': 11.1.28(@nestjs/common@11.1.28(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/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.2.8(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': 11.2.8(@nestjs/common@11.2.8(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/platform-express@11.2.8)(reflect-metadata@0.2.2)(rxjs@7.8.2) reflect-metadata: 0.2.2 '@next/env@15.5.25': {} @@ -3442,40 +3329,40 @@ snapshots: dependencies: '@noble/hashes': 1.8.0 - '@payloadcms/translations@3.87.1': + '@payloadcms/translations@3.92.1': dependencies: date-fns: 4.1.0 '@pinojs/redact@0.4.0': {} - '@prisma/adapter-pg@7.10.0': + '@prisma/adapter-pg@7.10.1': dependencies: - '@prisma/driver-adapter-utils': 7.10.0 + '@prisma/driver-adapter-utils': 7.10.1 '@types/pg': 8.23.1 pg: 8.23.0 postgres-array: 3.0.4 transitivePeerDependencies: - pg-native - '@prisma/client-runtime-utils@7.10.0': {} + '@prisma/client-runtime-utils@7.10.1': {} - '@prisma/client@7.10.0(prisma@7.10.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@5.9.3))(typescript@5.9.3)': + '@prisma/client@7.10.1(prisma@7.10.1(@types/node@26.0.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@5.9.3))(typescript@5.9.3)': dependencies: - '@prisma/client-runtime-utils': 7.10.0 + '@prisma/client-runtime-utils': 7.10.1 optionalDependencies: - prisma: 7.10.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@5.9.3) + prisma: 7.10.1(@types/node@26.0.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@5.9.3) typescript: 5.9.3 - '@prisma/config@7.10.0': + '@prisma/config@7.10.1': dependencies: c12: 3.3.4 - deepmerge-ts: 7.1.5 + deepmerge-ts: 8.0.2 effect: 3.20.0 empathic: 2.0.0 transitivePeerDependencies: - magicast - '@prisma/debug@7.10.0': {} + '@prisma/debug@7.10.1': {} '@prisma/debug@7.2.0': {} @@ -3499,28 +3386,28 @@ snapshots: transitivePeerDependencies: - typescript - '@prisma/driver-adapter-utils@7.10.0': + '@prisma/driver-adapter-utils@7.10.1': dependencies: - '@prisma/debug': 7.10.0 + '@prisma/debug': 7.10.1 - '@prisma/engines-version@7.10.0-4.0edf323efd1d98336f3f0a68684b56f689b900d3': {} + '@prisma/engines-version@8.1.0-1.d1b3f377ca835d73fd50954a5e22128b9ebdd6b8': {} - '@prisma/engines@7.10.0': + '@prisma/engines@7.10.1': dependencies: - '@prisma/debug': 7.10.0 - '@prisma/engines-version': 7.10.0-4.0edf323efd1d98336f3f0a68684b56f689b900d3 - '@prisma/fetch-engine': 7.10.0 - '@prisma/get-platform': 7.10.0 + '@prisma/debug': 7.10.1 + '@prisma/engines-version': 8.1.0-1.d1b3f377ca835d73fd50954a5e22128b9ebdd6b8 + '@prisma/fetch-engine': 7.10.1 + '@prisma/get-platform': 7.10.1 - '@prisma/fetch-engine@7.10.0': + '@prisma/fetch-engine@7.10.1': dependencies: - '@prisma/debug': 7.10.0 - '@prisma/engines-version': 7.10.0-4.0edf323efd1d98336f3f0a68684b56f689b900d3 - '@prisma/get-platform': 7.10.0 + '@prisma/debug': 7.10.1 + '@prisma/engines-version': 8.1.0-1.d1b3f377ca835d73fd50954a5e22128b9ebdd6b8 + '@prisma/get-platform': 7.10.1 - '@prisma/get-platform@7.10.0': + '@prisma/get-platform@7.10.1': dependencies: - '@prisma/debug': 7.10.0 + '@prisma/debug': 7.10.1 '@prisma/get-platform@7.2.0': dependencies: @@ -3758,15 +3645,9 @@ snapshots: '@tokenizer/token@0.3.0': {} - '@topcoder-platform/topcoder-bus-api-wrapper@https://codeload.github.com/topcoder-platform/tc-bus-api-wrapper/tar.gz/297a9c0adcdb97661257e7825bee9c3f5578b833(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0)': + '@topcoder/minimatch-compat@file:tools/minimatch-compat': dependencies: - joi: 18.2.9 - lodash: 4.18.1 - superagent: 10.3.0(supports-color@7.2.0) - tc-core-library-js: https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/323567bc50e433ae488b656f9f94e821ebaf3062(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0) - transitivePeerDependencies: - - debug - - supports-color + minimatch: 11.0.1 '@tsconfig/node10@1.0.13': {} @@ -3911,14 +3792,14 @@ snapshots: '@types/validator@13.15.10': {} - '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.72.1(@typescript-eslint/parser@8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.54.0 + '@typescript-eslint/parser': 8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.72.1 + '@typescript-eslint/type-utils': 8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/utils': 8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.72.1 eslint: 9.39.2(jiti@2.7.0)(supports-color@7.2.0) ignore: 7.0.8 natural-compare: 1.4.0 @@ -3927,41 +3808,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': + '@typescript-eslint/parser@8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(supports-color@7.2.0)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.54.0 + '@typescript-eslint/scope-manager': 8.72.1 + '@typescript-eslint/types': 8.72.1 + '@typescript-eslint/typescript-estree': 8.72.1(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.72.1 debug: 4.4.3(supports-color@7.2.0) eslint: 9.39.2(jiti@2.7.0)(supports-color@7.2.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.54.0(supports-color@7.2.0)(typescript@5.9.3)': + '@typescript-eslint/project-service@8.72.1(supports-color@7.2.0)(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) - '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/tsconfig-utils': 8.72.1(typescript@5.9.3) + '@typescript-eslint/types': 8.72.1 debug: 4.4.3(supports-color@7.2.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.54.0': + '@typescript-eslint/scope-manager@8.72.1': dependencies: - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/visitor-keys': 8.54.0 + '@typescript-eslint/types': 8.72.1 + '@typescript-eslint/visitor-keys': 8.72.1 - '@typescript-eslint/tsconfig-utils@8.54.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.72.1(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(supports-color@7.2.0)(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/types': 8.72.1 + '@typescript-eslint/typescript-estree': 8.72.1(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/utils': 8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) debug: 4.4.3(supports-color@7.2.0) eslint: 9.39.2(jiti@2.7.0)(supports-color@7.2.0) ts-api-utils: 2.5.0(typescript@5.9.3) @@ -3969,16 +3850,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.54.0': {} + '@typescript-eslint/types@8.72.1': {} - '@typescript-eslint/typescript-estree@8.54.0(supports-color@7.2.0)(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.72.1(supports-color@7.2.0)(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.54.0(supports-color@7.2.0)(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/visitor-keys': 8.54.0 + '@typescript-eslint/project-service': 8.72.1(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.72.1(typescript@5.9.3) + '@typescript-eslint/types': 8.72.1 + '@typescript-eslint/visitor-keys': 8.72.1 debug: 4.4.3(supports-color@7.2.0) - minimatch: 9.0.9 + minimatch: 11.0.1 semver: 7.8.5 tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@5.9.3) @@ -3986,21 +3867,21 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': + '@typescript-eslint/utils@8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0)) - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.72.1 + '@typescript-eslint/types': 8.72.1 + '@typescript-eslint/typescript-estree': 8.72.1(supports-color@7.2.0)(typescript@5.9.3) eslint: 9.39.2(jiti@2.7.0)(supports-color@7.2.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.54.0': + '@typescript-eslint/visitor-keys@8.72.1': dependencies: - '@typescript-eslint/types': 8.54.0 - eslint-visitor-keys: 4.2.1 + '@typescript-eslint/types': 8.72.1 + eslint-visitor-keys: 5.0.1 '@visx/curve@4.0.1-alpha.0': dependencies: @@ -4079,43 +3960,45 @@ snapshots: d3-time-format: 4.1.0 internmap: 2.0.3 - '@vitest/expect@4.0.18': + '@vitest/expect@4.1.12': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.0.18 - '@vitest/utils': 4.0.18 + '@vitest/spy': 4.1.12 + '@vitest/utils': 4.1.12 chai: 6.2.2 tinyrainbow: 3.1.1 - '@vitest/mocker@4.0.18(vite@7.3.6(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4))': + '@vitest/mocker@4.1.12(vite@7.3.7(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4))': dependencies: - '@vitest/spy': 4.0.18 + '@vitest/spy': 4.1.12 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.6(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4) + vite: 7.3.7(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4) - '@vitest/pretty-format@4.0.18': + '@vitest/pretty-format@4.1.12': dependencies: tinyrainbow: 3.1.1 - '@vitest/runner@4.0.18': + '@vitest/runner@4.1.12': dependencies: - '@vitest/utils': 4.0.18 + '@vitest/utils': 4.1.12 pathe: 2.0.3 - '@vitest/snapshot@4.0.18': + '@vitest/snapshot@4.1.12': dependencies: - '@vitest/pretty-format': 4.0.18 + '@vitest/pretty-format': 4.1.12 + '@vitest/utils': 4.1.12 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.0.18': {} + '@vitest/spy@4.1.12': {} - '@vitest/utils@4.0.18': + '@vitest/utils@4.1.12': dependencies: - '@vitest/pretty-format': 4.0.18 + '@vitest/pretty-format': 4.1.12 + convert-source-map: 2.0.0 tinyrainbow: 3.1.1 accepts@2.0.0: @@ -4133,8 +4016,6 @@ snapshots: acorn@8.18.0: {} - agent-base@7.1.4: {} - ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 @@ -4145,14 +4026,14 @@ snapshots: ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.7 + fast-uri: 3.1.9 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.7 + fast-uri: 3.1.9 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -4166,6 +4047,8 @@ snapshots: argparse@2.0.1: {} + argparse@3.0.4: {} + asap@2.0.6: {} assertion-error@2.0.1: {} @@ -4176,19 +4059,7 @@ snapshots: aws-ssl-profiles@1.1.2: {} - axios@0.30.3(debug@4.4.3(supports-color@7.2.0)): - dependencies: - follow-redirects: 1.16.0(debug@4.4.3(supports-color@7.2.0)) - form-data: 4.0.6 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - - backoff@2.5.0: - dependencies: - precond: 0.2.3 - - balanced-match@1.0.2: {} + balanced-match@4.0.4: {} better-result@2.10.0: {} @@ -4196,7 +4067,7 @@ snapshots: dependencies: require-from-string: 2.0.2 - body-parser@2.3.0(supports-color@7.2.0): + body-parser@2.4.0(supports-color@7.2.0): dependencies: bytes: 3.1.2 content-type: 2.1.0 @@ -4204,34 +4075,20 @@ snapshots: http-errors: 2.0.1 iconv-lite: 0.7.3 on-finished: 2.4.1 - qs: 6.16.0 + qs: 6.16.1 raw-body: 3.0.2 type-is: 2.1.0 transitivePeerDependencies: - supports-color - brace-expansion@1.1.18: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.1.4: + brace-expansion@5.0.12: dependencies: - balanced-match: 1.0.2 + balanced-match: 4.0.4 bson-objectid@2.0.4: {} buffer-equal-constant-time@1.0.1: {} - buffer-from@1.1.2: {} - - bunyan@1.8.15: - optionalDependencies: - dtrace-provider: 0.8.8 - moment: 2.31.0 - mv: 2.1.1 - safe-json-stringify: 1.2.0 - busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -4288,10 +4145,6 @@ snapshots: classnames@2.5.1: {} - codependency@2.1.0: - dependencies: - semver: 5.7.2 - color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -4306,15 +4159,6 @@ snapshots: component-emitter@1.3.1: {} - concat-map@0.0.1: {} - - concat-stream@2.0.0: - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 3.6.2 - typedarray: 0.0.6 - confbox@0.2.4: {} confbox@0.3.1: {} @@ -4329,6 +4173,8 @@ snapshots: content-type@2.1.0: {} + convert-source-map@2.0.0: {} + cookie-signature@1.2.2: {} cookie@0.7.2: {} @@ -4353,14 +4199,7 @@ snapshots: css-tree@3.2.1: dependencies: mdn-data: 2.27.1 - source-map-js: 1.2.1 - - cssstyle@5.3.7: - dependencies: - '@asamuzakjp/css-color': 4.1.2 - '@csstools/css-syntax-patches-for-csstree': 1.1.12(css-tree@3.2.1) - css-tree: 3.2.1 - lru-cache: 11.5.2 + source-map-js: 1.2.2 csstype@3.2.3: {} @@ -4410,10 +4249,12 @@ snapshots: dependencies: d3-array: 3.2.4 - data-urls@6.0.1: + data-urls@8.0.0(@noble/hashes@1.8.0): dependencies: whatwg-mimetype: 5.0.0 - whatwg-url: 15.1.0 + whatwg-url: 17.3.0(@noble/hashes@1.8.0) + transitivePeerDependencies: + - '@noble/hashes' dataloader@2.2.3: {} @@ -4431,7 +4272,7 @@ snapshots: deep-is@0.1.4: {} - deepmerge-ts@7.1.5: {} + deepmerge-ts@8.0.2: {} deepmerge@4.3.1: {} @@ -4460,11 +4301,6 @@ snapshots: dotenv@17.4.2: {} - dtrace-provider@0.8.8: - dependencies: - nan: 2.29.0 - optional: true - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -4500,7 +4336,7 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@1.7.0: {} + es-module-lexer@2.3.2: {} es-object-atoms@1.1.2: dependencies: @@ -4555,6 +4391,8 @@ snapshots: eslint-visitor-keys@4.2.1: {} + eslint-visitor-keys@5.0.1: {} + eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0): dependencies: '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0)) @@ -4588,7 +4426,7 @@ snapshots: is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 lodash.merge: 4.6.2 - minimatch: 3.1.5 + minimatch: '@topcoder/minimatch-compat@file:tools/minimatch-compat' natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: @@ -4627,7 +4465,7 @@ snapshots: express@5.2.1(supports-color@7.2.0): dependencies: accepts: 2.0.0 - body-parser: 2.3.0(supports-color@7.2.0) + body-parser: 2.4.0(supports-color@7.2.0) content-disposition: 1.1.0 content-type: 1.0.5 cookie: 0.7.2 @@ -4645,8 +4483,8 @@ snapshots: on-finished: 2.4.1 once: 1.4.0 parseurl: 1.3.3 - proxy-addr: 2.0.7 - qs: 6.16.0 + proxy-addr: 2.0.8 + qs: 6.16.1 range-parser: 1.3.0 router: 2.2.0(supports-color@7.2.0) send: 1.2.1(supports-color@7.2.0) @@ -4679,7 +4517,7 @@ snapshots: fast-safe-stringify@2.1.1: {} - fast-uri@3.1.7: {} + fast-uri@3.1.9: {} fdir@6.5.0(picomatch@4.0.7): optionalDependencies: @@ -4727,10 +4565,6 @@ snapshots: flatted@3.4.4: {} - follow-redirects@1.16.0(debug@4.4.3(supports-color@7.2.0)): - optionalDependencies: - debug: 4.4.3(supports-color@7.2.0) - foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 @@ -4793,15 +4627,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@6.0.4: - dependencies: - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.5 - once: 1.4.0 - path-is-absolute: 1.0.1 - optional: true - globals@14.0.0: {} globals@16.5.0: {} @@ -4832,7 +4657,7 @@ snapshots: help-me@5.0.0: {} - html-encoding-sniffer@6.0.0(@noble/hashes@1.8.0): + html-encoding-sniffer@7.0.0(@noble/hashes@1.8.0): dependencies: '@exodus/bytes': 1.15.1(@noble/hashes@1.8.0) transitivePeerDependencies: @@ -4846,22 +4671,8 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 - http-proxy-agent@7.0.2(supports-color@7.2.0): - dependencies: - agent-base: 7.1.4 - debug: 4.4.3(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - http-status@2.1.0: {} - https-proxy-agent@7.0.6(supports-color@7.2.0): - dependencies: - agent-base: 7.1.4 - debug: 4.4.3(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - iconv-lite@0.7.3: dependencies: safer-buffer: 2.1.2 @@ -4881,12 +4692,6 @@ snapshots: imurmurhash@0.1.4: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - optional: true - inherits@2.0.4: {} internmap@2.0.3: {} @@ -4915,16 +4720,6 @@ snapshots: jiti@2.7.0: {} - joi@18.2.9: - dependencies: - '@hapi/address': 5.1.1 - '@hapi/formula': 3.0.2 - '@hapi/hoek': 11.0.7 - '@hapi/pinpoint': 2.0.1 - '@hapi/tlds': 1.1.7 - '@hapi/topo': 6.0.2 - '@standard-schema/spec': 1.1.0 - jose@4.15.9: {} jose@5.10.0: {} @@ -4937,37 +4732,34 @@ snapshots: dependencies: argparse: 2.0.1 - js-yaml@5.2.1: + js-yaml@5.5.0: dependencies: - argparse: 2.0.1 + argparse: 3.0.4 - jsdom@27.4.0(@noble/hashes@1.8.0)(supports-color@7.2.0): + jsdom@30.1.3(@noble/hashes@1.8.0): dependencies: - '@acemir/cssom': 0.9.31 - '@asamuzakjp/dom-selector': 6.8.1 - '@exodus/bytes': 1.15.1(@noble/hashes@1.8.0) - cssstyle: 5.3.7 - data-urls: 6.0.1 + '@asamuzakjp/css-color': 7.1.9 + '@asamuzakjp/dom-selector': 10.0.5 + '@bramus/specificity': 2.4.3 + '@csstools/css-syntax-patches-for-csstree': 1.1.16(css-tree@3.2.1) + '@exodus/bytes': 1.16.0(@noble/hashes@1.8.0) + css-tree: 3.2.1 + data-urls: 8.0.0(@noble/hashes@1.8.0) decimal.js: 10.6.0 - html-encoding-sniffer: 6.0.0(@noble/hashes@1.8.0) - http-proxy-agent: 7.0.2(supports-color@7.2.0) - https-proxy-agent: 7.0.6(supports-color@7.2.0) + html-encoding-sniffer: 7.0.0(@noble/hashes@1.8.0) is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.3 parse5: 8.0.1 saxes: 6.0.0 - symbol-tree: 3.2.4 tough-cookie: 6.0.2 - w3c-xmlserializer: 5.0.0 + undici: 8.12.3 + w3c-xmlserializer: 6.0.0 webidl-conversions: 8.0.1 - whatwg-mimetype: 4.0.0 - whatwg-url: 15.1.0 - ws: 8.21.3 + whatwg-mimetype: 5.0.0 + whatwg-url: 17.3.0(@noble/hashes@1.8.0) xml-name-validator: 5.0.0 transitivePeerDependencies: - '@noble/hashes' - - bufferutil - - supports-color - - utf-8-validate json-buffer@3.0.1: {} @@ -5068,7 +4860,7 @@ snapshots: long@5.3.2: {} - lru-cache@11.5.2: {} + lru-cache@11.5.3: {} lru-cache@6.0.0: dependencies: @@ -5099,8 +4891,6 @@ snapshots: methods@1.1.2: {} - millisecond@0.1.2: {} - mime-db@1.52.0: {} mime-db@1.54.0: {} @@ -5115,42 +4905,24 @@ snapshots: mime@2.6.0: {} - minimatch@3.1.5: - dependencies: - brace-expansion: 1.1.18 - - minimatch@9.0.9: + minimatch@11.0.1: dependencies: - brace-expansion: 2.1.4 + '@isaacs/nonrecursive-glob-match': 1.0.3 + brace-expansion: 5.0.12 minimist@1.2.8: {} - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - optional: true - - moment@2.31.0: - optional: true - ms@2.1.3: {} - multer@2.2.0: + multer@2.5.0: dependencies: append-field: 1.0.0 busboy: 1.6.0 - concat-stream: 2.0.0 type-is: 1.6.18 - mv@2.1.1: - dependencies: - mkdirp: 0.5.6 - ncp: 2.0.0 - rimraf: 2.4.5 - optional: true - - mysql2@3.15.3: + mysql2@3.23.1(@types/node@26.0.0): dependencies: + '@types/node': 26.0.0 aws-ssl-profiles: 1.1.2 denque: 2.1.0 generate-function: 2.3.1 @@ -5158,23 +4930,16 @@ snapshots: long: 5.3.2 lru.min: 1.1.5 named-placeholders: 1.1.6 - seq-queue: 0.0.5 - sqlstring: 2.3.3 + sql-escaper: 1.5.2 named-placeholders@1.1.6: dependencies: lru.min: 1.1.5 - nan@2.29.0: - optional: true - nanoid@3.3.18: {} natural-compare@1.4.0: {} - ncp@2.0.0: - optional: true - negotiator@1.1.0: dependencies: content-type: 2.1.0 @@ -5234,9 +4999,6 @@ snapshots: path-exists@4.0.0: {} - path-is-absolute@1.0.1: - optional: true - path-key@3.1.1: {} path-to-regexp@6.3.0: {} @@ -5245,10 +5007,10 @@ snapshots: pathe@2.0.3: {} - payload@3.87.1(graphql@16.14.2)(supports-color@7.2.0)(typescript@5.9.3): + payload@3.92.1(graphql@16.14.2)(supports-color@7.2.0)(typescript@5.9.3): dependencies: '@next/env': 15.5.25 - '@payloadcms/translations': 3.87.1 + '@payloadcms/translations': 3.92.1 '@types/busboy': 1.5.4 ajv: 8.18.0 bson-objectid: 2.0.4 @@ -5274,9 +5036,10 @@ snapshots: qs-esm: 8.0.1 range-parser: 1.2.1 sanitize-filename: 1.6.3 + sax: 1.6.1 ts-essentials: 10.0.3(typescript@5.9.3) - tsx: 4.22.4 - undici: 7.29.0 + tsx: 4.23.15 + undici: 7.30.1 uuid: 13.0.2 ws: 8.21.3 transitivePeerDependencies: @@ -5374,7 +5137,7 @@ snapshots: dependencies: nanoid: 3.3.18 picocolors: 1.1.1 - source-map-js: 1.2.1 + source-map-js: 1.2.2 postgres-array@2.0.0: {} @@ -5390,23 +5153,22 @@ snapshots: postgres@3.4.7: {} - precond@0.2.3: {} - prelude-ls@1.2.1: {} prettier@3.8.1: {} - prisma@7.10.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@5.9.3): + prisma@7.10.1(@types/node@26.0.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@5.9.3): dependencies: - '@prisma/config': 7.10.0 + '@prisma/config': 7.10.1 '@prisma/dev': 0.24.17(typescript@5.9.3) - '@prisma/engines': 7.10.0 + '@prisma/engines': 7.10.1 '@prisma/studio-core': 0.33.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - mysql2: 3.15.3 + mysql2: 3.23.1(@types/node@26.0.0) postgres: 3.4.7 optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: + - '@types/node' - '@types/react' - '@types/react-dom' - magicast @@ -5423,13 +5185,11 @@ snapshots: retry: 0.12.0 signal-exit: 3.0.7 - proxy-addr@2.0.7: + proxy-addr@2.0.8: dependencies: forwarded: 0.2.0 ipaddr.js: 1.9.1 - proxy-from-env@1.1.0: {} - pump@3.0.4: dependencies: end-of-stream: 1.4.5 @@ -5441,20 +5201,13 @@ snapshots: qs-esm@8.0.1: {} - qs@6.16.0: + qs@6.16.1: dependencies: es-define-property: 1.0.1 side-channel: 1.1.1 quick-format-unescaped@4.0.4: {} - r7insight_node@2.1.1: - dependencies: - codependency: 2.1.0 - json-stringify-safe: 5.0.1 - lodash: 4.18.1 - reconnect-core: 1.3.0 - range-parser@1.2.1: {} range-parser@1.3.0: {} @@ -5478,20 +5231,10 @@ snapshots: react@19.2.8: {} - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - readdirp@5.1.1: {} real-require@0.2.0: {} - reconnect-core@1.3.0: - dependencies: - backoff: 2.5.0 - reflect-metadata@0.2.2: {} remeda@2.33.4: {} @@ -5506,11 +5249,6 @@ snapshots: retry@0.12.0: {} - rimraf@2.4.5: - dependencies: - glob: 6.0.4 - optional: true - robust-predicates@3.0.3: {} rollup@4.63.1: @@ -5561,9 +5299,6 @@ snapshots: safe-buffer@5.2.1: {} - safe-json-stringify@1.2.0: - optional: true - safe-regex2@5.1.1: dependencies: ret: 0.5.0 @@ -5576,6 +5311,8 @@ snapshots: dependencies: truncate-utf8-bytes: 1.0.2 + sax@1.6.1: {} + saxes@6.0.0: dependencies: xmlchars: 2.2.0 @@ -5584,8 +5321,6 @@ snapshots: secure-json-parse@4.1.0: {} - semver@5.7.2: {} - semver@7.8.5: {} send@1.2.1(supports-color@7.2.0): @@ -5604,8 +5339,6 @@ snapshots: transitivePeerDependencies: - supports-color - seq-queue@0.0.5: {} - serve-static@2.2.1(supports-color@7.2.0): dependencies: encodeurl: 2.0.0 @@ -5663,11 +5396,11 @@ snapshots: dependencies: atomic-sleep: 1.0.0 - source-map-js@1.2.1: {} + source-map-js@1.2.2: {} split2@4.2.0: {} - sqlstring@2.3.3: {} + sql-escaper@1.5.2: {} stackback@0.0.2: {} @@ -5675,14 +5408,12 @@ snapshots: std-env@3.10.0: {} + std-env@4.3.0: {} + streamsearch@1.1.0: {} strict-event-emitter@0.5.1: {} - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - strip-json-comments@3.1.1: {} strip-json-comments@5.0.3: {} @@ -5701,7 +5432,7 @@ snapshots: formidable: 3.5.4 methods: 1.1.2 mime: 2.6.0 - qs: 6.16.0 + qs: 6.16.1 transitivePeerDependencies: - supports-color @@ -5721,19 +5452,12 @@ snapshots: dependencies: '@scarf/scarf': 1.4.0 - symbol-tree@3.2.4: {} - - tc-core-library-js@https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/323567bc50e433ae488b656f9f94e821ebaf3062(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0): + tc-core-library-js@https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/58de37670180e183e8378c3d203df0112a0414f6(supports-color@7.2.0): dependencies: - axios: 0.30.3(debug@4.4.3(supports-color@7.2.0)) - bunyan: 1.8.15 + '@types/jsonwebtoken': 9.0.10 jsonwebtoken: 9.0.3 jwks-rsa: 3.2.2(supports-color@7.2.0) - lodash: 4.18.1 - millisecond: 0.1.2 - r7insight_node: 2.1.1 transitivePeerDependencies: - - debug - supports-color thread-stream@3.2.0: @@ -5769,7 +5493,7 @@ snapshots: dependencies: tldts: 7.4.12 - tr46@6.0.0: + tr46@7.0.0: dependencies: punycode: 2.3.1 @@ -5813,6 +5537,12 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tsx@4.23.15: + dependencies: + esbuild: 0.28.2 + optionalDependencies: + fsevents: 2.3.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -5828,14 +5558,12 @@ snapshots: media-typer: 1.1.1 mime-types: 3.0.2 - typedarray@0.0.6: {} - - typescript-eslint@8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3): + typescript-eslint@8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.54.0(supports-color@7.2.0)(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.72.1(@typescript-eslint/parser@8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/parser': 8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.72.1(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/utils': 8.72.1(eslint@9.39.2(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) eslint: 9.39.2(jiti@2.7.0)(supports-color@7.2.0) typescript: 5.9.3 transitivePeerDependencies: @@ -5851,7 +5579,9 @@ snapshots: undici-types@8.3.0: {} - undici@7.29.0: {} + undici@7.30.1: {} + + undici@8.12.3: {} unpipe@1.0.0: {} @@ -5877,8 +5607,6 @@ snapshots: utf8-byte-length@1.0.5: {} - util-deprecate@1.0.2: {} - uuid@13.0.2: {} v8-compile-cache-lib@3.0.1: {} @@ -5891,7 +5619,7 @@ snapshots: vary@1.1.2: {} - vite@7.3.6(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4): + vite@7.3.7(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4): dependencies: esbuild: 0.28.2 fdir: 6.5.0(picomatch@4.0.7) @@ -5905,45 +5633,35 @@ snapshots: jiti: 2.7.0 tsx: 4.22.4 - vitest@4.0.18(@types/node@26.0.0)(jiti@2.7.0)(jsdom@27.4.0(@noble/hashes@1.8.0)(supports-color@7.2.0))(tsx@4.22.4): + vitest@4.1.12(@types/node@26.0.0)(jsdom@30.1.3(@noble/hashes@1.8.0))(vite@7.3.7(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4)): dependencies: - '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@7.3.6(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4)) - '@vitest/pretty-format': 4.0.18 - '@vitest/runner': 4.0.18 - '@vitest/snapshot': 4.0.18 - '@vitest/spy': 4.0.18 - '@vitest/utils': 4.0.18 - es-module-lexer: 1.7.0 + '@vitest/expect': 4.1.12 + '@vitest/mocker': 4.1.12(vite@7.3.7(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4)) + '@vitest/pretty-format': 4.1.12 + '@vitest/runner': 4.1.12 + '@vitest/snapshot': 4.1.12 + '@vitest/spy': 4.1.12 + '@vitest/utils': 4.1.12 + es-module-lexer: 2.3.2 expect-type: 1.4.0 magic-string: 0.30.21 obug: 2.1.4 pathe: 2.0.3 picomatch: 4.0.7 - std-env: 3.10.0 + std-env: 4.3.0 tinybench: 2.9.0 tinyexec: 1.3.1 tinyglobby: 0.2.17 tinyrainbow: 3.1.1 - vite: 7.3.6(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4) + vite: 7.3.7(@types/node@26.0.0)(jiti@2.7.0)(tsx@4.22.4) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 26.0.0 - jsdom: 27.4.0(@noble/hashes@1.8.0)(supports-color@7.2.0) + jsdom: 30.1.3(@noble/hashes@1.8.0) transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml - w3c-xmlserializer@5.0.0: + w3c-xmlserializer@6.0.0: dependencies: xml-name-validator: 5.0.0 @@ -5951,14 +5669,15 @@ snapshots: webpack-virtual-modules@0.6.2: {} - whatwg-mimetype@4.0.0: {} - whatwg-mimetype@5.0.0: {} - whatwg-url@15.1.0: + whatwg-url@17.3.0(@noble/hashes@1.8.0): dependencies: - tr46: 6.0.0 + '@exodus/bytes': 1.16.0(@noble/hashes@1.8.0) + tr46: 7.0.0 webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' which@2.0.2: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ef9b100..4507d78 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -7,5 +7,25 @@ allowBuilds: dtrace-provider: false # The shared Bus API wrapper depends on Topcoder's Git-hosted core library. blockExoticSubdeps: false + overrides: - tc-core-library-js: github:topcoder-platform/tc-core-library-js#323567bc50e433ae488b656f9f94e821ebaf3062 + body-parser@^2: 2.4.0 + proxy-addr: 2.0.8 + qs: 6.16.1 + multer: 2.5.0 + deepmerge-ts: 8.0.2 + js-yaml@^3: 3.15.2 + js-yaml@^4: 4.3.2 + js-yaml@^5: 5.5.0 + undici@^7: 7.30.1 + undici@^8: 8.12.3 + fast-uri: 3.1.9 + brace-expansion@^1: 1.1.21 + brace-expansion@^2: 2.1.7 + brace-expansion@>=3: 5.0.12 + source-map-js: 1.2.2 + minimatch@<9: file:tools/minimatch-compat + minimatch@>=9: 11.0.1 + glob@>=9: 14.0.2 + vite: 7.3.7 + mysql2: 3.23.1 diff --git a/prisma/migrations/20261102010000_space_tech_challenge_email/migration.sql b/prisma/migrations/20261102010000_space_tech_challenge_email/migration.sql new file mode 100644 index 0000000..e41820a --- /dev/null +++ b/prisma/migrations/20261102010000_space_tech_challenge_email/migration.sql @@ -0,0 +1,8 @@ +-- Internal notification for SpaceTech landing page challenges (form space_tech_challenge). +-- Every submission goes to a fixed recipient list, with the submitter as reply-to. +-- forms-processor-v6 supplies the settings from SPACE_TECH_CHALLENGE_RECIPIENTS and +-- SPACE_TECH_CHALLENGE_TEMPLATE_ID (SSM); they replace these database settings. +-- Seeded disabled: enable it after both parameters are set and the processor is redeployed. +INSERT INTO forms."ProcessorFlow" (id, "formKey", action, rules) +VALUES ('space-tech-challenge-email', 'space_tech_challenge', 'sendgrid-email', '{"all":[]}') +ON CONFLICT (id) DO NOTHING; diff --git a/scripts/publish-space-tech-challenge.ts b/scripts/publish-space-tech-challenge.ts new file mode 100644 index 0000000..79199c2 --- /dev/null +++ b/scripts/publish-space-tech-challenge.ts @@ -0,0 +1,56 @@ +import { readFile } from 'node:fs/promises'; + +/** + * Idempotently publishes the SpaceTech landing page definition to the selected Forms API (development by default). + * @param No arguments; reads FORMS_API_BASE_URL and FORMS_ADMIN_TOKEN from the environment. + * @returns Completion after registration, immutable version save, and publication; creates no submissions. + * @throws Error for a missing token, unsupported API base, conflicting revision, or failed API request. + */ +async function publishSpaceTechChallenge(): Promise { + const apiBase = ( + process.env.FORMS_API_BASE_URL ?? 'https://api.topcoder-dev.com/v6' + ).replace(/\/+$/, ''); + if ( + ![ + 'https://api.topcoder-dev.com/v6', + 'https://api.topcoder.com/v6', + ].includes(apiBase) + ) + throw new Error( + 'FORMS_API_BASE_URL must select the dev or production Topcoder API.', + ); + const token = process.env.FORMS_ADMIN_TOKEN; + if (!token) + throw new Error( + 'FORMS_ADMIN_TOKEN with manage:forms or Administrator access is required.', + ); + const definition: unknown = JSON.parse( + await readFile('examples/space-tech-challenge.json', 'utf8'), + ); + const base = `${apiBase}/forms`; + for (const [method, path, body] of [ + ['POST', '', { key: 'space_tech_challenge' }], + ['PUT', '/space_tech_challenge/versions/1', definition], + ['POST', '/space_tech_challenge/versions/1/publish', undefined], + ] as const) { + const response = await fetch(`${base}${path}`, { + method, + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + ...(body ? { body: JSON.stringify(body) } : {}), + signal: AbortSignal.timeout(30000), + }); + if (!response.ok) + throw new Error( + `${method} ${path} failed (${response.status}); no credentials or response data logged.`, + ); + } + console.log(`Published space_tech_challenge version 1 to ${apiBase}.`); +} + +void publishSpaceTechChallenge().catch((error: unknown) => { + console.error(error instanceof Error ? error.message : 'Publication failed.'); + process.exitCode = 1; +}); diff --git a/src/auth.ts b/src/auth.ts index 6a528b2..745bac8 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -10,7 +10,7 @@ import { import { Reflector } from '@nestjs/core'; import type { Request } from 'express'; import jwt from 'jsonwebtoken'; -import { middleware, type AuthenticatorRequest } from 'tc-core-library-js'; +import { createJwtAuthenticator, type AuthenticatorRequest } from 'tc-core-library-js'; import { CONFIG, type AppConfig } from './config'; export type Permission = 'public' | 'manage' | 'report'; @@ -35,7 +35,7 @@ export interface ActorRequest extends Request { @Injectable() export class AuthGuard implements CanActivate { private readonly authenticator: ReturnType< - typeof middleware.jwtAuthenticator + typeof createJwtAuthenticator >; /** @@ -47,7 +47,9 @@ export class AuthGuard implements CanActivate { @Inject(CONFIG) private readonly config: AppConfig, private readonly reflector: Reflector, ) { - this.authenticator = middleware.jwtAuthenticator({ + this.authenticator = createJwtAuthenticator({ + AUTH0_AUDIENCE: config.machineAudience, + JWT_AUDIENCE: config.jwtAudience, AUTH_SECRET: config.authSecret, VALID_ISSUERS: JSON.stringify(config.issuers), }); @@ -101,7 +103,7 @@ export class AuthGuard implements CanActivate { * @throws Error for unsupported algorithms, invalid tokens or missing time claims. */ private async authenticate(token: string): Promise> { - // The shared verifier does not call back for unsupported algorithms. + // Reject unsupported algorithms before invoking the shared verifier. const decoded = jwt.decode(token, { complete: true }); if (!decoded || !['HS256', 'RS256'].includes(decoded.header.alg)) throw new Error('Unsupported token algorithm.'); @@ -148,11 +150,7 @@ export function normalizeActor( ',', ).map((r) => r.toLowerCase()); const scopes = stringList(claims.scope ?? claims.scopes, /\s+/); - const machine = - claims.gty === 'client-credentials' || - claims.isMachine === true || - (typeof claims.sub === 'string' && claims.sub.endsWith('@clients')) || - (scopes.length > 0 && roles.length === 0); + const machine = claims.isMachine === true; const userId = claims.userId ?? claims[`${namespace}userId`]; const memberId = !machine && diff --git a/src/config.ts b/src/config.ts index 855c898..bb47058 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,5 @@ import 'dotenv/config'; -import type { BusApiConfiguration } from 'tc-bus-api-wrapper'; +import type { BusApiConfiguration } from 'tc-core-library-js'; /** Runtime configuration validated once before Nest starts serving requests. */ export interface AppConfig { @@ -8,6 +8,8 @@ export interface AppConfig { port: number; origins: string[]; authSecret: string; + jwtAudience?: string; + machineAudience?: string; issuers: string[]; claimNamespace: string; throttleLimit: number; @@ -49,6 +51,8 @@ export function readConfig(env: NodeJS.ProcessEnv = process.env): AppConfig { port: integerSetting(env.PORT ?? '3000', 1, 65535), origins, authSecret, + jwtAudience: env.JWT_AUDIENCE, + machineAudience: env.AUTH0_AUDIENCE, issuers, claimNamespace: env.AUTH_CLAIM_NAMESPACE ?? 'https://topcoder.com/', throttleLimit: integerSetting(env.THROTTLE_LIMIT ?? '30', 1, 10000), diff --git a/src/integrations/event-bus.service.ts b/src/integrations/event-bus.service.ts index 058656d..c8a4d36 100644 --- a/src/integrations/event-bus.service.ts +++ b/src/integrations/event-bus.service.ts @@ -3,7 +3,7 @@ import { Injectable, ServiceUnavailableException, } from '@nestjs/common'; -import createBusApiClient, { type BusApiClient } from 'tc-bus-api-wrapper'; +import { createBusApiClient as createBusApiClient, type BusApiClient } from 'tc-core-library-js'; import { CONFIG, type AppConfig } from '../config'; import type { AnswerValue } from '../forms/validation'; diff --git a/src/types/tc-bus-api-wrapper.d.ts b/src/types/tc-bus-api-wrapper.d.ts deleted file mode 100644 index 612dcd3..0000000 --- a/src/types/tc-bus-api-wrapper.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -declare module 'tc-bus-api-wrapper' { - /** Configuration accepted by the shared Topcoder Bus API wrapper. */ - export interface BusApiConfiguration { - AUTH0_URL: string; - AUTH0_AUDIENCE: string; - AUTH0_CLIENT_ID: string; - AUTH0_CLIENT_SECRET: string; - BUSAPI_URL: string; - KAFKA_ERROR_TOPIC: string; - TOKEN_CACHE_TIME?: number; - AUTH0_PROXY_SERVER_URL?: string; - } - - /** Complete legacy-compatible event envelope published through Bus API. */ - export interface BusApiEvent { - topic: string; - originator: string; - timestamp: string; - 'mime-type': 'application/json'; - payload: T; - key?: string; - } - - /** Subset of the shared wrapper used by Forms API. */ - export interface BusApiClient { - postEvent(event: BusApiEvent): Promise; - } - - /** Creates an authenticated client whose base URL is the Topcoder API v6 base. */ - export default function createBusApiClient( - config: BusApiConfiguration, - ): BusApiClient; -} diff --git a/src/types/tc-core-library-js.d.ts b/src/types/tc-core-library-js.d.ts deleted file mode 100644 index 534e83b..0000000 --- a/src/types/tc-core-library-js.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -declare module 'tc-core-library-js' { - /** Minimal request shape populated by the shared Topcoder authenticator. */ - interface AuthenticatorRequest { - headers: { authorization: string }; - authUser?: Record; - } - - /** Response adapter converts the library's HTTP failures to Nest exceptions. */ - interface AuthenticatorResponse { - status(code: number): AuthenticatorResponse; - json(body?: unknown): void; - send(...args: unknown[]): void; - end(body?: unknown): void; - } - - /** Callback middleware exported by the shared Topcoder library. */ - type JwtAuthenticator = ( - request: AuthenticatorRequest, - response: AuthenticatorResponse, - next: (error?: unknown) => void, - ) => void; - - /** Shared JWT verifier and Topcoder claim-normalization entry point. */ - export const middleware: { - jwtAuthenticator(config: { - AUTH_SECRET: string; - VALID_ISSUERS: string; - }): JwtAuthenticator; - }; -} diff --git a/test/auth-rs256.spec.ts b/test/auth-rs256.spec.ts index 3a35e94..1fa27b0 100644 --- a/test/auth-rs256.spec.ts +++ b/test/auth-rs256.spec.ts @@ -81,6 +81,7 @@ beforeAll(async () => { 'https://api.topcoder-dev.com', ]), // Obsolete deployment settings must not keep rejecting Auth0 browser tokens. + JWT_AUDIENCE: 'BXWXUWnilVUPdN01t2Se29Tw2ZYNGZvH', AUTH_MODE: 'hs256', AUTH_AUDIENCE: 'forms-api', }), diff --git a/test/auth.spec.ts b/test/auth.spec.ts index 3c80ad0..731569f 100644 --- a/test/auth.spec.ts +++ b/test/auth.spec.ts @@ -101,7 +101,6 @@ describe('Topcoder bearer authentication', () => { { sub: 42, aud: 'forms-api' }, { gty: 'client-credentials' }, { isMachine: true }, - { scope: 'read:forms-submissions', roles: [] }, ])('rejects invalid or nonlegacy claims %#', async (claims) => { await expect(authenticate(claims)).rejects.toMatchObject({ status: 401 }); }); @@ -127,18 +126,14 @@ describe('Topcoder bearer authentication', () => { }, ); - it('keeps machine scope authorization separate from administrator roles', async () => { + it('rejects machine claims signed under the legacy audience-free human policy', async () => { const machine = { sub: 'client@clients', aud: 'forms-api', gty: 'client-credentials', + userId: undefined, roles: undefined, }; - await expect(authenticate(machine)).rejects.toMatchObject({ status: 403 }); - expect( - await authenticate({ ...machine, scope: 'read:forms-submissions' }), - ).toMatchObject({ - machine: true, - memberId: undefined, - }); + await expect(authenticate(machine)).rejects.toMatchObject({ status: 401 }); + await expect(authenticate({ ...machine, scope: 'read:forms-submissions' })).rejects.toMatchObject({ status: 401 }); }); }); diff --git a/test/event-bus.spec.ts b/test/event-bus.spec.ts index f0c6f44..8b0ca59 100644 --- a/test/event-bus.spec.ts +++ b/test/event-bus.spec.ts @@ -8,7 +8,7 @@ const { postEvent, createClient } = vi.hoisted(() => { const postEvent = vi.fn(); return { postEvent, createClient: vi.fn(() => ({ postEvent })) }; }); -vi.mock('tc-bus-api-wrapper', () => ({ default: createClient })); +vi.mock('tc-core-library-js', async (importOriginal) => ({ ...await importOriginal(), createBusApiClient: createClient })); const baseEnv = { DATABASE_URL: 'postgresql://localhost/forms', diff --git a/test/forms.integration.spec.ts b/test/forms.integration.spec.ts index e414bb1..59e55de 100644 --- a/test/forms.integration.spec.ts +++ b/test/forms.integration.spec.ts @@ -9,7 +9,9 @@ import { vi, } from 'vitest'; import request from 'supertest'; -import { randomUUID } from 'node:crypto'; +import { generateKeyPairSync, randomUUID, type KeyObject } from 'node:crypto'; +import jwt from 'jsonwebtoken'; +import nock from 'nock'; import letsTalkDefinition from '../examples/lets-talk.json'; import { createApp } from '../src/bootstrap'; import { DbService } from '../src/db.service'; @@ -24,7 +26,7 @@ import { import { syncForm, type ManagedForm } from '../integrations/payload/forms'; const { postEvent } = vi.hoisted(() => ({ postEvent: vi.fn() })); -vi.mock('tc-bus-api-wrapper', () => ({ default: () => ({ postEvent }) })); +vi.mock('tc-core-library-js', async (importOriginal) => ({ ...await importOriginal(), createBusApiClient: () => ({ postEvent }) })); describe('forms API with real PostgreSQL', () => { let app: Awaited>; @@ -33,10 +35,48 @@ describe('forms API with real PostgreSQL', () => { let reporter: string; let member: string; let machine: string; + let machineKey: KeyObject; + const machineKeyId = 'forms-integration-machine'; + + /** + * Signs audience-bound machine credentials for the shared RSA verification policy. + * @param scope Space-separated forms permissions. @returns Signed machine bearer token. + * @throws JWT signing errors for invalid fixture keys or claims. + */ + function machineToken(scope: string) { + return jwt.sign( + { gty: 'client-credentials', azp: 'test-client', scope }, + machineKey, + { + algorithm: 'RS256', + keyid: machineKeyId, + subject: 'test-client@clients', + issuer: 'https://forms.test', + audience: 'forms-api', + expiresIn: '5m', + }, + ); + } beforeAll(async () => { + const keys = generateKeyPairSync('rsa', { modulusLength: 2048 }); + machineKey = keys.privateKey; + // Mock key discovery only; the shared authenticator still verifies RSA signatures. + nock('https://forms.test') + .get('/.well-known/jwks.json') + .reply(200, { + keys: [ + { + ...keys.publicKey.export({ format: 'jwk' }), + kid: machineKeyId, + alg: 'RS256', + use: 'sig', + }, + ], + }); app = await createApp({ ...testConfig(), + machineAudience: 'forms-api', busApi: { BUSAPI_URL: 'https://bus.test/v6', AUTH0_URL: 'https://auth.test', @@ -54,17 +94,14 @@ describe('forms API with real PostgreSQL', () => { 'https://topcoder.com/roles': ['Member'], 'https://topcoder.com/userId': '12345', }); - machine = await token({ - gty: 'client-credentials', - azp: 'test-client', - scope: 'manage:forms read:forms-submissions', - }); + machine = machineToken('manage:forms read:forms-submissions'); }); beforeEach(() => { postEvent.mockReset().mockResolvedValue(undefined); }); afterAll(async () => { if (app) await app.close(); + nock.cleanAll(); }); /** @@ -186,11 +223,7 @@ describe('forms API with real PostgreSQL', () => { key, title: 'Event interest', }); - const readOnly = await token({ - gty: 'client-credentials', - azp: 'test-client', - scope: 'read:forms-submissions', - }); + const readOnly = machineToken('read:forms-submissions'); await request(app.getHttpServer()) .get('/v6/forms/reports/directory') .auth(readOnly, { type: 'bearer' }) @@ -389,6 +422,20 @@ describe('forms API with real PostgreSQL', () => { ); }); + it('seeds the SpaceTech challenge email disabled, with settings left to the processor environment', async () => { + const flows = await db.processorFlow.findMany({ + where: { formKey: 'space_tech_challenge' }, + }); + expect(flows).toHaveLength(1); + expect(flows[0]).toMatchObject({ + id: 'space-tech-challenge-email', + enabled: false, + action: 'sendgrid-email', + rules: { all: [] }, + settings: {}, + }); + }); + it('reports AI classification columns and filters by label only for forms with a classify flow', async () => { const key = await create({ ...definition(), diff --git a/test/policies.spec.ts b/test/policies.spec.ts index 48fd77c..792f162 100644 --- a/test/policies.spec.ts +++ b/test/policies.spec.ts @@ -127,17 +127,26 @@ describe('definition and deployment policies', () => { machine: false, roles: ['member'], }); + // Machine identity is decided by the shared tc-core-library-js verifier (`isMachine`); + // a machine never gets a member identity, even with a userId claim. expect( normalizeActor( { sub: 'client@clients', userId: 'forged', - roles: ['Administrator'], gty: 'client-credentials', + isMachine: true, }, 'https://topcoder.com/', ), ).toMatchObject({ memberId: undefined, machine: true }); + // Without the verifier's flag, machine-looking claims are not trusted as a machine. + expect( + normalizeActor( + { sub: 'client@clients', gty: 'client-credentials' }, + 'https://topcoder.com/', + ), + ).toMatchObject({ machine: false }); }); it('requires signed-token settings and exact CORS origins, defaulting to untrusted proxy headers', () => { diff --git a/tools/minimatch-compat/index.cjs b/tools/minimatch-compat/index.cjs new file mode 100644 index 0000000..21c167f --- /dev/null +++ b/tools/minimatch-compat/index.cjs @@ -0,0 +1,38 @@ +const modern = require('minimatch'); + +// Older build tools expect a callable CommonJS export. glob 7 additionally +// reads _glob and uses String.match on compiled segments. Delegate matching +// to minimatch 11's bounded matcher, without restoring the old regex engine. +function compatible(defaultOptions = {}) { + const options = (value) => ({ ...defaultOptions, ...value }); + const match = (path, pattern, value) => + modern.minimatch(path, pattern, options(value)); + Object.assign(match, modern.minimatch); + match.Minimatch = class extends modern.Minimatch { + constructor(pattern, value) { + super(pattern, options(value)); + for (const row of this.set) { + for (const segment of row) { + if (typeof segment === 'object' && segment !== null) { + segment._glob = segment.pattern; + segment[Symbol.match] = (input) => + segment.test(input) ? [input] : null; + } + } + } + } + + static defaults(value) { + return compatible(options(value)).Minimatch; + } + }; + match.defaults = (value) => compatible(options(value)); + match.filter = (pattern, value) => modern.filter(pattern, options(value)); + match.match = (paths, pattern, value) => + modern.match(paths, pattern, options(value)); + match.braceExpand = (pattern, value) => + modern.braceExpand(pattern, options(value)); + return match; +} + +module.exports = compatible(); diff --git a/tools/minimatch-compat/index.test.cjs b/tools/minimatch-compat/index.test.cjs new file mode 100644 index 0000000..c1d71e8 --- /dev/null +++ b/tools/minimatch-compat/index.test.cjs @@ -0,0 +1,30 @@ +const assert = require('node:assert/strict'); +const { createRequire } = require('node:module'); +const { spawnSync } = require('node:child_process'); +const { test } = require('node:test'); + +const legacyRequire = createRequire(require.resolve('eslint')); +const match = legacyRequire('minimatch'); + +test('legacy consumers retain the callable minimatch API', () => { + assert.equal(typeof match, 'function'); + assert.equal(match('src/main.ts', '**/*.ts'), true); + assert.equal(match('src/main.js', '**/*.ts'), false); + assert.equal(match('.env', '*'), false); + assert.equal(match.defaults({ dot: true })('.env', '*'), true); + assert.deepEqual(match.match(['a.ts', 'b.js'], '*.ts'), ['a.ts']); + assert.deepEqual(['a.ts', 'b.js'].filter(match.filter('*.ts')), ['a.ts']); + assert.deepEqual(match.braceExpand('*.{js,ts}'), ['*.js', '*.ts']); + assert.equal(new match.Minimatch('**/*.ts').match('src/main.ts'), true); + assert.equal(match.Minimatch.defaults({ dot: true }) !== undefined, true); + assert.equal(typeof match.GLOBSTAR, 'symbol'); +}); + +test('amplifying glob patterns terminate within a bounded time', () => { + const result = spawnSync(process.execPath, ['-e', ` + const match = require(${JSON.stringify(legacyRequire.resolve('minimatch'))}); + new match.Minimatch('**/../'.repeat(30) + '*.ts', { optimizationLevel: 2 }); + `], { timeout: 5000, encoding: 'utf8' }); + assert.equal(result.error, undefined); + assert.equal(result.status, 0, result.stderr); +}); diff --git a/tools/minimatch-compat/package.json b/tools/minimatch-compat/package.json new file mode 100644 index 0000000..52aea68 --- /dev/null +++ b/tools/minimatch-compat/package.json @@ -0,0 +1,10 @@ +{ + "name": "@topcoder/minimatch-compat", + "version": "1.0.0", + "private": true, + "description": "Legacy CommonJS entry point backed by patched minimatch", + "main": "index.cjs", + "dependencies": { + "minimatch": "11.0.1" + } +}