diff --git a/.github/actions/install_dependencies/action.yml b/.github/actions/install_dependencies/action.yml new file mode 100644 index 0000000000..b6889575f0 --- /dev/null +++ b/.github/actions/install_dependencies/action.yml @@ -0,0 +1,28 @@ +name: "Install dependencies" +description: "Install dependencies defined in .tool-versions using asdf and npm packages" + +inputs: + npm-required: + description: "Set to true if npm dependencies are already installed" + required: false + default: "true" + GITHUB_TOKEN: + description: "GitHub token to access private npm packages" + required: true + +runs: + using: "composite" + steps: + - name: Setting up .npmrc + shell: bash + env: + NODE_AUTH_TOKEN: ${{ inputs.GITHUB_TOKEN }} + run: | + echo "//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}" >> ~/.npmrc + echo "@nhsdigital:registry=https://npm.pkg.github.com" >> ~/.npmrc + + - name: Run make install + if: inputs.npm-required == 'true' + shell: bash + run: | + make install-node diff --git a/.github/workflows/cdk_package_code.yml b/.github/workflows/cdk_package_code.yml new file mode 100644 index 0000000000..0e41ae4f33 --- /dev/null +++ b/.github/workflows/cdk_package_code.yml @@ -0,0 +1,66 @@ +name: cdk package code + +on: + workflow_call: + inputs: + BRANCH_NAME: + required: true + type: string + VERSION_NUMBER: + required: true + type: string + COMMIT_ID: + required: true + type: string + pinned_image: + required: true + type: string + +permissions: {} + +jobs: + package_code: + runs-on: ubuntu-22.04 + container: + image: ${{ inputs.pinned_image }} + options: --user 1001:1001 --group-add 128 + defaults: + run: + shell: bash + permissions: + id-token: write + contents: read + packages: read + steps: + - name: copy .tool-versions + run: | + cp /home/vscode/.tool-versions "$HOME/.tool-versions" + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + ref: ${{ inputs.BRANCH_NAME }} + persist-credentials: false + + - name: install dependencies + uses: ./.github/actions/install_dependencies + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: make compile + run: make compile + + - name: "Tar files" + run: | + tar -rf artifact.tar \ + .github \ + packages \ + node_modules \ + package.json \ + package-lock.json \ + tsconfig.defaults.json + + - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f + name: upload build artifact + with: + name: build_artifact + path: artifact.tar diff --git a/.github/workflows/cdk_release_code.yml b/.github/workflows/cdk_release_code.yml new file mode 100644 index 0000000000..ccd24991db --- /dev/null +++ b/.github/workflows/cdk_release_code.yml @@ -0,0 +1,128 @@ +name: cdk release code + +on: + workflow_call: + inputs: + BRANCH_NAME: + required: true + type: string + STACK_NAME: + required: true + type: string + AWS_ENVIRONMENT: + required: true + type: string + VERSION_NUMBER: + required: true + type: string + COMMIT_ID: + required: true + type: string + CDK_APP_NAME: + required: true + type: string + LOG_RETENTION_IN_DAYS: + required: true + type: string + LOG_LEVEL: + type: string + IS_PULL_REQUEST: + type: boolean + required: true + TRUSTSTORE_FILE: + type: string + required: true + FORWARD_CSOC_LOGS: + type: boolean + required: true + DEPLOY_CHECK_PRESCRIPTION_STATUS_UPDATE: + type: boolean + required: true + EXPOSE_GET_STATUS_UPDATES: + type: boolean + required: true + SAM_STACK_NAME: + type: string + required: true + ENABLE_POST_DATED_NOTIFICATIONS: + type: boolean + required: true + REQUIRE_APPLICATION_NAME: + type: boolean + required: true + ENABLE_BACKUP: + type: boolean + required: true + pinned_image: + required: true + type: string + secrets: + CLOUD_FORMATION_DEPLOY_ROLE: + required: true +permissions: {} + +jobs: + release_code: + runs-on: ubuntu-22.04 + environment: ${{ inputs.AWS_ENVIRONMENT }} + container: + image: ${{ inputs.pinned_image }} + options: --user 1001:1001 --group-add 128 + defaults: + run: + shell: bash + name: deploy cdk app ${{ inputs.CDK_APP_NAME }} + permissions: + id-token: write + contents: read + + steps: + - name: copy .tool-versions + run: | + cp /home/vscode/.tool-versions "$HOME/.tool-versions" + + - name: build_artifact download + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c + with: + name: build_artifact + + - name: extract build_artifact + run: tar -xf artifact.tar + + - name: install dependencies + uses: ./.github/actions/install_dependencies + with: + npm-required: false + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure AWS Credentials + id: connect-aws-deploy + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 + with: + aws-region: eu-west-2 + role-to-assume: ${{ secrets.CLOUD_FORMATION_DEPLOY_ROLE }} + role-session-name: psu-deployment + + - name: Deploy AWS infrastructure and code + run: npm run cdk-deploy --workspace packages/cdk + shell: bash + env: + CDK_APP_NAME: "${{ inputs.CDK_APP_NAME }}" + CDK_CONFIG_stackName: "${{ inputs.STACK_NAME }}" + CDK_CONFIG_versionNumber: "${{ inputs.VERSION_NUMBER }}" + CDK_CONFIG_commitId: "${{ inputs.COMMIT_ID }}" + CDK_CONFIG_isPullRequest: "${{ inputs.IS_PULL_REQUEST }}" + CDK_CONFIG_environment: "${{ inputs.AWS_ENVIRONMENT }}" + CDK_CONFIG_logRetentionInDays: "${{ inputs.LOG_RETENTION_IN_DAYS }}" + CDK_CONFIG_logLevel: "${{ inputs.LOG_LEVEL }}" + CDK_CONFIG_trustStoreFile: "${{ inputs.TRUSTSTORE_FILE }}" + CDK_CONFIG_forwardCsocLogs: "${{ inputs.FORWARD_CSOC_LOGS }}" + CDK_CONFIG_deployCheckPrescriptionStatusUpdate: "${{ inputs.DEPLOY_CHECK_PRESCRIPTION_STATUS_UPDATE }}" + CDK_CONFIG_exposeGetStatusUpdates: "${{ inputs.EXPOSE_GET_STATUS_UPDATES }}" + CDK_CONFIG_samStackName: "${{ inputs.SAM_STACK_NAME }}" + CDK_CONFIG_enablePostDatedNotifications: "${{ inputs.ENABLE_POST_DATED_NOTIFICATIONS }}" + CDK_CONFIG_requireApplicationName: "${{ inputs.REQUIRE_APPLICATION_NAME }}" + CDK_CONFIG_enableBackup: "${{ inputs.ENABLE_BACKUP }}" + REQUIRE_APPROVAL: "never" + +# later, there will be API deployment steps c.f. https://github.com/NHSDigital/electronic-prescription-service-clinical-prescription-tracker/blob/main/.github/workflows/cdk_release_code.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 527d56b536..7528f64153 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,48 @@ jobs: branch_name: main tag_format: ${{ needs.get_config_values.outputs.tag_format }} - package_code: + cdk_package_code: + needs: [get_commit_id, tag_release, get_config_values] + uses: ./.github/workflows/cdk_package_code.yml + permissions: + contents: read + packages: read + id-token: write + with: + BRANCH_NAME: main + VERSION_NUMBER: ${{ needs.tag_release.outputs.version_tag }} + COMMIT_ID: ${{ needs.get_commit_id.outputs.commit_id }} + pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} + + cdk_release_dev: + needs: [cdk_package_code, get_commit_id, tag_release, get_config_values] + uses: ./.github/workflows/cdk_release_code.yml + permissions: + contents: write + id-token: write + with: + pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} + BRANCH_NAME: main + STACK_NAME: psu-cdk + AWS_ENVIRONMENT: dev + VERSION_NUMBER: ${{ needs.tag_release.outputs.version_tag }} + COMMIT_ID: ${{ needs.get_commit_id.outputs.commit_id }} + CDK_APP_NAME: PsuStatelessApp + LOG_RETENTION_IN_DAYS: "30" + LOG_LEVEL: DEBUG + IS_PULL_REQUEST: false + TRUSTSTORE_FILE: psu-truststore.pem + FORWARD_CSOC_LOGS: false + DEPLOY_CHECK_PRESCRIPTION_STATUS_UPDATE: true + EXPOSE_GET_STATUS_UPDATES: false + SAM_STACK_NAME: psu + ENABLE_POST_DATED_NOTIFICATIONS: true + REQUIRE_APPLICATION_NAME: false + ENABLE_BACKUP: true + secrets: + CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_DEPLOY_ROLE }} + + sam_package_code: needs: [tag_release, get_config_values] uses: ./.github/workflows/run_package_code_and_api.yml permissions: @@ -62,7 +103,7 @@ jobs: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} release_dev: - needs: [tag_release, package_code, get_commit_id, get_config_values] + needs: [tag_release, sam_package_code, get_commit_id, get_config_values] uses: ./.github/workflows/run_release_code_and_api.yml permissions: contents: write @@ -111,7 +152,7 @@ jobs: REGRESSION_TESTS_PEM: ${{ secrets.REGRESSION_TESTS_PEM }} release_sandbox_dev: - needs: [tag_release, package_code, get_commit_id, get_config_values] + needs: [tag_release, sam_package_code, get_commit_id, get_config_values] uses: ./.github/workflows/run_release_code_and_api.yml permissions: contents: write @@ -155,7 +196,13 @@ jobs: release_qa: needs: - [tag_release, release_dev, package_code, get_commit_id, get_config_values] + [ + tag_release, + release_dev, + sam_package_code, + get_commit_id, + get_config_values, + ] uses: ./.github/workflows/run_release_code_and_api.yml permissions: contents: write diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 5dc6e7f020..7fa9f9976c 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -93,7 +93,49 @@ jobs: run: | echo "commit_id=${{ github.sha }}" >> "$GITHUB_OUTPUT" - package_code: + cdk_package_code: + needs: [get_issue_number, get_commit_id, get_config_values] + uses: ./.github/workflows/cdk_package_code.yml + permissions: + contents: read + packages: read + id-token: write + with: + pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} + BRANCH_NAME: ${{ github.event.pull_request.head.ref }} + VERSION_NUMBER: PR-${{ needs.get_issue_number.outputs.issue_number }} + COMMIT_ID: ${{ needs.get_commit_id.outputs.commit_id }} + + cdk_release_code: + needs: + [get_issue_number, cdk_package_code, get_commit_id, get_config_values] + uses: ./.github/workflows/cdk_release_code.yml + permissions: + contents: write + id-token: write + with: + pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} + BRANCH_NAME: ${{ github.event.pull_request.head.ref }} + STACK_NAME: psu-cdk-pr-${{needs.get_issue_number.outputs.issue_number}} + AWS_ENVIRONMENT: dev + VERSION_NUMBER: PR-${{ needs.get_issue_number.outputs.issue_number }} + COMMIT_ID: ${{ needs.get_commit_id.outputs.commit_id }} + CDK_APP_NAME: PsuStatelessApp + LOG_RETENTION_IN_DAYS: "30" + LOG_LEVEL: DEBUG + IS_PULL_REQUEST: true + TRUSTSTORE_FILE: psu-truststore.pem + FORWARD_CSOC_LOGS: false + DEPLOY_CHECK_PRESCRIPTION_STATUS_UPDATE: true + EXPOSE_GET_STATUS_UPDATES: false + SAM_STACK_NAME: psu-pr-${{needs.get_issue_number.outputs.issue_number}} + ENABLE_POST_DATED_NOTIFICATIONS: true + REQUIRE_APPLICATION_NAME: false + ENABLE_BACKUP: false + secrets: + CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_DEPLOY_ROLE }} + + sam_package_code: needs: [get_issue_number, get_config_values] uses: ./.github/workflows/run_package_code_and_api.yml permissions: @@ -103,8 +145,9 @@ jobs: with: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} - release_code: - needs: [get_issue_number, package_code, get_commit_id, get_config_values] + sam_release_code: + needs: + [get_issue_number, sam_package_code, get_commit_id, get_config_values] uses: ./.github/workflows/run_release_code_and_api.yml permissions: contents: write @@ -153,7 +196,8 @@ jobs: REGRESSION_TESTS_PEM: ${{ secrets.REGRESSION_TESTS_PEM }} release_sandbox_code: - needs: [get_issue_number, package_code, get_commit_id, get_config_values] + needs: + [get_issue_number, sam_package_code, get_commit_id, get_config_values] uses: ./.github/workflows/run_release_code_and_api.yml permissions: contents: write diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fb268dc86a..11da192a67 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,7 +53,48 @@ jobs: secrets: EXECUTE_JIRA_LAMBDA_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_EXECUTE_LAMBDA_ROLE }} - package_code: + cdk_package_code: + needs: [get_commit_id, tag_release, get_config_values] + uses: ./.github/workflows/cdk_package_code.yml + permissions: + contents: read + packages: read + id-token: write + with: + BRANCH_NAME: main + VERSION_NUMBER: ${{ needs.tag_release.outputs.version_tag }} + COMMIT_ID: ${{ needs.get_commit_id.outputs.commit_id }} + pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} + + cdk_release_dev: + needs: [cdk_package_code, get_commit_id, tag_release, get_config_values] + uses: ./.github/workflows/cdk_release_code.yml + permissions: + contents: write + id-token: write + with: + pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} + BRANCH_NAME: main + STACK_NAME: psu-cdk + AWS_ENVIRONMENT: dev + VERSION_NUMBER: ${{ needs.tag_release.outputs.version_tag }} + COMMIT_ID: ${{ needs.get_commit_id.outputs.commit_id }} + CDK_APP_NAME: PsuStatelessApp + LOG_RETENTION_IN_DAYS: "30" + LOG_LEVEL: DEBUG + IS_PULL_REQUEST: false + TRUSTSTORE_FILE: psu-truststore.pem + FORWARD_CSOC_LOGS: false + DEPLOY_CHECK_PRESCRIPTION_STATUS_UPDATE: true + EXPOSE_GET_STATUS_UPDATES: false + SAM_STACK_NAME: psu + ENABLE_POST_DATED_NOTIFICATIONS: true + REQUIRE_APPLICATION_NAME: false + ENABLE_BACKUP: true + secrets: + CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_DEPLOY_ROLE }} + + sam_package_code: needs: [tag_release, get_config_values] uses: ./.github/workflows/run_package_code_and_api.yml permissions: @@ -64,7 +105,7 @@ jobs: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} release_dev: - needs: [tag_release, package_code, get_commit_id, get_config_values] + needs: [tag_release, sam_package_code, get_commit_id, get_config_values] uses: ./.github/workflows/run_release_code_and_api.yml permissions: contents: write @@ -117,7 +158,7 @@ jobs: REGRESSION_TESTS_PEM: ${{ secrets.REGRESSION_TESTS_PEM }} release_dev_sandbox: - needs: [tag_release, package_code, get_commit_id, get_config_values] + needs: [tag_release, sam_package_code, get_commit_id, get_config_values] uses: ./.github/workflows/run_release_code_and_api.yml permissions: contents: write @@ -168,7 +209,7 @@ jobs: tag_release, release_dev, release_dev_sandbox, - package_code, + sam_package_code, get_commit_id, get_config_values, ] @@ -224,7 +265,7 @@ jobs: tag_release, release_dev, release_dev_sandbox, - package_code, + sam_package_code, get_commit_id, get_config_values, ] @@ -276,7 +317,13 @@ jobs: release_int: needs: - [tag_release, release_qa, package_code, get_commit_id, get_config_values] + [ + tag_release, + release_qa, + sam_package_code, + get_commit_id, + get_config_values, + ] uses: ./.github/workflows/run_release_code_and_api.yml permissions: contents: write @@ -329,7 +376,13 @@ jobs: release_int_sandbox: needs: - [tag_release, release_qa, package_code, get_commit_id, get_config_values] + [ + tag_release, + release_qa, + sam_package_code, + get_commit_id, + get_config_values, + ] uses: ./.github/workflows/run_release_code_and_api.yml permissions: contents: write @@ -380,7 +433,7 @@ jobs: tag_release, release_int, release_int_sandbox, - package_code, + sam_package_code, get_commit_id, get_config_values, ] diff --git a/.gitignore b/.gitignore index fde104b2ec..67cb59f7ff 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ release_notes /ecs-*.yml .venv .aws-sam +cdk.out lib/ *.tsbuildinfo _site/ @@ -29,3 +30,4 @@ vendor .cfn_guard_out/ .trivy_out/ .sbom/ +.npmrc diff --git a/.grype.yaml b/.grype.yaml index d07cef7c42..fef22bd293 100644 --- a/.grype.yaml +++ b/.grype.yaml @@ -1,3 +1,11 @@ ignore: # path-to-regexp - dependency of aws-sdk-client-mock - vulnerability: GHSA-j3q9-mxjg-w52f + # This is a ReDoS vulnerability that we're not exposed to, since we don't take user regex input + - vulnerability: GHSA-2g4f-4pwh-qvx6 + reason: "We don't take user regex input, so we're not vulnerable to this issue." + # Axios vulnerability in checking NO_PROXY rules, which we don't use + - vulnerability: GHSA-3p68-rc4w-qgx5 + reason: "We don't use NO_PROXY rules, so we're not vulnerable to this issue." + - vulnerability: GHSA-j965-2qgj-vjmq + reason: "We use v3 packages already, so we're not vulnerable to this issue." diff --git a/.vscode/eps-prescription-status-update-api.code-workspace b/.vscode/eps-prescription-status-update-api.code-workspace index f0c1c29f9e..c275205a0e 100644 --- a/.vscode/eps-prescription-status-update-api.code-workspace +++ b/.vscode/eps-prescription-status-update-api.code-workspace @@ -4,6 +4,10 @@ "name": "eps-prescription-status-update-monorepo", "path": ".." }, + { + "name": "packages/cdk", + "path": "../packages/cdk" + }, { "name": "packages/gsul", "path": "../packages/gsul" @@ -151,8 +155,14 @@ "versionable", "whens" ], - "cSpell.dictionaries": ["en-GB"], - "cSpell.ignorePaths": ["package-lock.json", "node_modules", ".vscode"], + "cSpell.dictionaries": [ + "en-GB" + ], + "cSpell.ignorePaths": [ + "package-lock.json", + "node_modules", + ".vscode" + ], "js/ts.tsdk.path": "eps-prescription-status-update-monorepo/node_modules/typescript/lib", "eslint.useFlatConfig": true, "eslint.format.enable": true diff --git a/Makefile b/Makefile index 251be16be8..f06b8951e5 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,28 @@ +SHELL = /bin/bash +.SHELLFLAGS = -o pipefail -c +export CDK_APP_NAME=PsuStatelessApp +export CDK_CONFIG_stackName=${stack_name} +export CDK_CONFIG_samStackName=${stack_name} +export CDK_CONFIG_versionNumber=undefined +export CDK_CONFIG_commitId=undefined +export CDK_CONFIG_isPullRequest=true +export CDK_CONFIG_environment=dev +export CDK_CONFIG_logRetentionInDays=30 +export CDK_CONFIG_logLevel=DEBUG +export CDK_CONFIG_trustStoreFile=psu-truststore.pem +export CDK_CONFIG_forwardCsocLogs=false +export CDK_CONFIG_deployCheckPrescriptionStatusUpdate=true +export CDK_CONFIG_exposeGetStatusUpdates=false +export CDK_CONFIG_enablePostDatedNotifications=false +export CDK_CONFIG_requireApplicationName=false +export CDK_CONFIG_enableBackup=false + +guard-%: + @ if [ "${${*}}" = "" ]; then \ + echo "Environment variable $* not set"; \ + exit 1; \ + fi + .PHONY: install build test publish release clean lint compile install: install-node install-python install-hooks @@ -156,6 +181,7 @@ compile-specification: compile: compile-node compile-specification lint-node: compile-node + npm run lint --workspace packages/cdk npm run lint --workspace packages/updatePrescriptionStatus npm run lint --workspace packages/gsul npm run lint --workspace packages/nhsd-psu-sandbox @@ -217,12 +243,39 @@ clean: rm -rf packages/common/testing/lib rm -rf packages/common/middyErrorHandler/lib rm -rf packages/common/commonTypes/lib + rm -rf packages/cdk/lib rm -rf .aws-sam + rm -rf cdk.out deep-clean: clean rm -rf venv find . -name 'node_modules' -type d -prune -exec rm -rf '{}' + poetry env remove --all +cdk-deploy: + REQUIRE_APPROVAL="$${REQUIRE_APPROVAL:-any-change}" && \ + npm run cdk-deploy --workspace packages/cdk + +cdk-synth: + CDK_CONFIG_stackName=psu-cdk \ + CDK_CONFIG_samStackName=psu \ + CDK_CONFIG_logRetentionInDays=30 \ + CDK_CONFIG_logLevel=DEBUG \ + CDK_CONFIG_environment=dev \ + CDK_CONFIG_forwardCsocLogs=false \ + CDK_CONFIG_deployCheckPrescriptionStatusUpdate=true \ + CDK_CONFIG_exposeGetStatusUpdates=false \ + CDK_CONFIG_enablePostDatedNotifications=false \ + CDK_CONFIG_requireApplicationName=false \ + CDK_CONFIG_enableBackup=false \ + npm run cdk-synth --workspace packages/cdk + +cdk-diff: + npm run cdk-diff --workspace packages/cdk + +cdk-watch: + REQUIRE_APPROVAL="$${REQUIRE_APPROVAL:-any-change}" && \ + npm run cdk-watch --workspace packages/cdk + %: @$(MAKE) -f /usr/local/share/eps/Mk/common.mk $@ diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000000..34f3bd7335 --- /dev/null +++ b/TODO.md @@ -0,0 +1,95 @@ +# FIXME: Delete this file + + +# CDK Migration TODO — Stateless Stack + +This file tracks the migration of stateless components from SAM templates to CDK. +Stateful resources (DynamoDB tables, SSM parameters, Secrets Manager secrets, SQS queues) remain in SAM. + +## Lambda Functions (`SAMtemplates/functions/main.yaml`) + +Each Lambda includes the function itself, a nested `lambda_resources.yaml` stack (IAM role, log group, Splunk subscription filter), and associated IAM policies. + +- [x] **UpdatePrescriptionStatus** — Core function that writes prescription status updates to DynamoDB and sends SQS messages for notifications. Has extensive IAM policies for DynamoDB, SQS, Secrets Manager, and SSM parameters. *(uses `TypescriptLambdaFunction` construct)* +- [x] **ConvertRequestToFhirFormat (CPSU)** — Converts custom format requests to FHIR format. No additional IAM policies beyond basic Lambda execution. *(uses `TypescriptLambdaFunction` construct)* +- [x] **GetStatusUpdates** — Reads prescription status updates from DynamoDB. Needs DynamoDB read and KMS policies. *(uses `TypescriptLambdaFunction` construct)* +- [x] **Status** — Returns `_status` health check info (version, commit ID). Needs Secrets Manager access. *(uses `TypescriptLambdaFunction` construct)* +- [x] **CapabilityStatement** — Returns FHIR CapabilityStatement. No additional IAM policies. *(uses `TypescriptLambdaFunction` construct)* +- [x] **CheckPrescriptionStatusUpdates** — Conditionally deployed (`DeployCheckPrescriptionStatusUpdate`). Reads from DynamoDB. Needs DynamoDB read and KMS policies. *(conditional `TypescriptLambdaFunction` construct)* +- [x] **NotifyProcessor** — Processes NHS Notify messages from SQS on a 1-minute schedule (EventBridge Scheduler). Needs SQS, DynamoDB, Secrets Manager, SSM, and KMS policies. Has a dedicated scheduler IAM role. *(uses `TypescriptLambdaFunction` + `CfnSchedule`)* +- [x] **PostDatedNotifyLambda** — Processes post-dated notifications on a 15-minute schedule (EventBridge Scheduler). Needs SQS and DynamoDB policies. Has a dedicated scheduler IAM role. *(uses `TypescriptLambdaFunction` + `CfnSchedule`)* +- [x] **NHSNotifyUpdateCallback** — Handles NHS Notify delivery status callbacks. Needs DynamoDB and Secrets Manager policies. *(uses `TypescriptLambdaFunction` construct)* +- [x] **PsuRestoreValidation** — Conditionally deployed (`EnableBackup`). Validates DynamoDB backup restores. Has a custom IAM policy for `backup:PutRestoreValidationResult` and an EventBridge rule for restore job state changes. *(conditional `TypescriptLambdaFunction` + `Rule`)* + +### Per-Lambda shared resources (`lambda_resources.yaml`) +Each Lambda above has a nested stack that creates: +- [x] IAM execution role with CloudWatch Logs permissions *(handled by `TypescriptLambdaFunction` construct)* +- [x] CloudWatch Log Group (with configurable retention, optional KMS encryption) *(handled by `TypescriptLambdaFunction` construct)* +- [x] Splunk subscription filter (conditional on `EnableSplunk`) *(handled by `TypescriptLambdaFunction` construct — always enabled)* +- [x] Execute Lambda managed policy (exported for cross-stack references) *(handled by `TypescriptLambdaFunction` construct)* + +## State Machines (`SAMtemplates/state_machines/main.yaml`) + +Each state machine includes the state machine itself and a nested `state_machine_resources.yaml` stack (IAM role, log group, Splunk subscription filter). + +- [x] **UpdatePrescriptionStatusStateMachine** — EXPRESS type. Invokes FHIR Validator (cross-stack import from `fhir-validator` stack) and UpdatePrescriptionStatus Lambda. Uses ASL definition file `UpdatePrescriptionStatusStateMachine.asl.json`. *(uses `ExpressStateMachine` construct + CDK step function definition)* +- [x] **Format1UpdatePrescriptionsStatusStateMachine** — EXPRESS type. Invokes ConvertRequestToFhirFormat and UpdatePrescriptionStatus Lambdas. Uses ASL definition file `Format1UpdatePrescriptionsStatusStateMachine.asl.json`. *(uses `ExpressStateMachine` construct + CDK step function definition)* + +### Per-state-machine shared resources (`state_machine_resources.yaml`) +Each state machine has a nested stack that creates: +- [x] IAM execution role with state machine and Lambda invoke permissions *(handled by `ExpressStateMachine` construct)* +- [x] CloudWatch Log Group (with configurable retention, optional KMS encryption) *(handled by `ExpressStateMachine` construct)* +- [x] Splunk subscription filter (conditional on `EnableSplunk`) *(handled by `ExpressStateMachine` construct — always enabled)* +- [x] Execute state machine managed policy (exported for cross-stack references) *(handled by `ExpressStateMachine` construct)* + +## API Gateway (`SAMtemplates/apis/main.yaml`) + +- [x] **ACM Certificate** (`GenerateCertificate`) — DNS-validated certificate for the custom domain. *(handled by `RestApiGateway` construct)* +- [x] **REST API** (`RestApiGateway`) — Regional REST API with optional execute-api endpoint disabling (when mTLS is enabled). *(handled by `RestApiGateway` construct)* +- [x] **Custom Domain** (`RestApiDomain`) — Regional domain with TLS 1.2, optional mTLS truststore from S3. *(handled by `RestApiGateway` construct)* +- [x] **Route 53 Record** (`RestApiRecordSet`) — Alias A record pointing to the API Gateway domain. *(handled by `RestApiGateway` construct)* +- [x] **API Deployment and Stage** (`RestApiGatewayDeploymentV2h`, `RestApiGatewayStage`) — Deployment with X-Ray tracing and structured access logging. *(handled by `RestApiGateway` construct via `deploy: true`)* +- [x] **Domain Mapping** (`RestApiDomainMapping`) — Base path mapping to the `prod` stage. *(handled by `RestApiGateway` construct)* + +### API Endpoints +- [x] **POST /** — `UpdatePrescriptionStatusMethod` — Step Functions integration (StartSyncExecution) to UpdatePrescriptionStatus state machine. *(root resource method in `Apis` construct)* +- [x] **POST /format-1** — `Format1UpdatePrescriptionStatusMethod` — Step Functions integration to Format1 state machine. *(uses `StateMachineEndpoint` construct)* +- [x] **POST /notification-delivery-status-callback** — `NotificationDeliveryStatusCallbackMethod` — Lambda proxy integration to NHSNotifyUpdateCallback. *(uses `LambdaEndpoint` construct)* +- [x] **GET /_status** — `StatusLambdaMethod` — Lambda proxy integration to Status function. *(uses `LambdaEndpoint` construct)* +- [x] **GET /metadata** — `CapabilityStatementMethod` — Lambda proxy integration to CapabilityStatement function. *(uses `LambdaEndpoint` construct)* +- [x] **GET /checkprescriptionstatusupdates** — `CheckPrescriptionStatusUpdatesMethod` — Conditional. Lambda proxy integration. *(conditional `LambdaEndpoint` in `Apis` construct)* +- [x] **POST /get-status-updates** — `GetStatusUpdatesMethod` — Conditional. Lambda integration (non-proxy) with request/response templates. *(conditional non-proxy `LambdaIntegration` in `Apis` construct)* + +### API shared resources (`api_resources.yaml`) +- [x] API Gateway IAM role with policies to invoke Lambdas and state machines *(handled by `RestApiGateway` construct)* +- [x] API Gateway access log group (with configurable retention, optional KMS encryption) *(handled by `RestApiGateway` construct)* +- [x] Splunk subscription filter (conditional on `EnableSplunk`) *(handled by `RestApiGateway` construct — always enabled)* +- [x] CSOC log forwarding (conditional on `ForwardCsocLogs`) *(handled by `RestApiGateway` construct)* + +## CloudWatch Alarms (`SAMtemplates/alarms/main.yaml`) + +### Log Metric Filters +- [ ] `GetStatusUpdatesErrorsLogsMetricFilter` — Filters ERROR level logs from GetStatusUpdates +- [ ] `PrescriptionStatusUpdateErrorsLogsMetricFilter` — Filters 500 status responses from UpdatePrescriptionStatus +- [ ] `PrescriptionStatusUpdateForcedErrorsLogsMetricFilter` — Filters forced INT test errors +- [ ] `CPSUFhirConverterErrorLogsMetricFilter` — Filters 500 status responses from CPSU converter +- [ ] `NotifyProcessorTimeoutsMetricFilter` — Filters timeout messages from NotifyProcessor + +### Alarms +- [ ] `GetStatusUpdatesErrorsAlarm` — Alerts on GetStatusUpdates errors +- [ ] `GetStatusUpdatesUnhandledErrorsAlarm` — Alerts on GetStatusUpdates unhandled Lambda errors +- [ ] `PrescriptionStatusUpdateErrorsAlarm` — Alerts on true 500 errors (excludes forced INT test errors via math expression) +- [ ] `PrescriptionStatusUpdateUnhandledErrorsAlarm` — Alerts on unhandled Lambda errors +- [ ] `DynamoDBSystemErrorsAlarm` — Alerts on DynamoDB system errors +- [ ] `DynamoDBWriteConsumptionAlarm` — Alerts when DynamoDB write usage nears provisioned capacity threshold +- [ ] `CPSUFhirConverterErrorsAlarm` — Alerts on CPSU FHIR converter errors +- [ ] `NotifyProcessorTimeoutsAlarm` — Alerts on NotifyProcessor timeouts +- [ ] `NHSNotifyPrescriptionsDeadLetterQueueMessagesAlarm` — Alerts on DLQ messages + +## Cross-cutting concerns + +- [ ] **Splunk log forwarding** — Conditionally enabled per log group via subscription filters. Requires `SplunkDeliveryStreamArn` and `SplunkSubscriptionFilterRole` from `lambda-resources` stack. +- [ ] **CSOC log forwarding** — Conditional forwarding of API Gateway access logs to CSOC destination. +- [ ] **KMS encryption** — CloudWatch log groups optionally encrypted with `account-resources:CloudwatchLogsKmsKeyArn`. +- [ ] **Cross-stack imports** — Many resources import values from `account-resources`, `lambda-resources`, `eps-route53-resources`, and `fhir-validator` stacks. These will become `Fn.importValue()` calls in CDK. +- [ ] **Conditional deployments** — `CheckPrescriptionStatusUpdates` and `GetStatusUpdates` endpoints are conditionally deployed. `PsuRestoreValidation` depends on `EnableBackup`. These will need CDK conditions or conditional construct instantiation. diff --git a/package-lock.json b/package-lock.json index b012056b5b..8d6671be92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "MIT", "workspaces": [ + "packages/cdk", "packages/gsul", "packages/nhsd-psu-sandbox", "packages/specification", @@ -55,6 +56,8 @@ }, "node_modules/@ampproject/remapping": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -65,6 +68,113 @@ "node": ">=6.0.0" } }, + "node_modules/@aws-cdk/asset-awscli-v1": { + "version": "2.2.273", + "license": "Apache-2.0" + }, + "node_modules/@aws-cdk/asset-node-proxy-agent-v6": { + "version": "2.1.1", + "license": "Apache-2.0" + }, + "node_modules/@aws-cdk/cloud-assembly-schema": { + "version": "53.14.0", + "bundleDependencies": [ + "jsonschema", + "semver" + ], + "license": "Apache-2.0", + "dependencies": { + "jsonschema": "~1.4.1", + "semver": "^7.7.4" + }, + "engines": { + "node": ">= 18.0.0" + } + }, + "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/jsonschema": { + "version": "1.4.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/semver": { + "version": "7.7.4", + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@aws-crypto/sha256-browser": { "version": "5.2.0", "license": "Apache-2.0", @@ -233,48 +343,46 @@ } }, "node_modules/@aws-sdk/client-backup": { - "version": "3.1025.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-backup/-/client-backup-3.1025.0.tgz", - "integrity": "sha512-Sg52QJU2uU2eE1m9X2yGVIKnV8Yjtqx6u2ityh/Keo/cO8l1TKIIFaHs/IwWSgi8ZYNX1nq3wxOAk1dONBbdyA==", + "version": "3.1019.0", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/credential-provider-node": "^3.972.29", + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/credential-provider-node": "^3.972.27", "@aws-sdk/middleware-host-header": "^3.972.8", "@aws-sdk/middleware-logger": "^3.972.8", "@aws-sdk/middleware-recursion-detection": "^3.972.9", - "@aws-sdk/middleware-user-agent": "^3.972.28", + "@aws-sdk/middleware-user-agent": "^3.972.26", "@aws-sdk/region-config-resolver": "^3.972.10", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.14", + "@aws-sdk/util-user-agent-node": "^3.973.12", "@smithy/config-resolver": "^4.4.13", - "@smithy/core": "^3.23.13", + "@smithy/core": "^3.23.12", "@smithy/fetch-http-handler": "^5.3.15", "@smithy/hash-node": "^4.2.12", "@smithy/invalid-dependency": "^4.2.12", "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.28", - "@smithy/middleware-retry": "^4.4.46", - "@smithy/middleware-serde": "^4.2.16", + "@smithy/middleware-endpoint": "^4.4.27", + "@smithy/middleware-retry": "^4.4.44", + "@smithy/middleware-serde": "^4.2.15", "@smithy/middleware-stack": "^4.2.12", "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.5.1", + "@smithy/node-http-handler": "^4.5.0", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.8", + "@smithy/smithy-client": "^4.12.7", "@smithy/types": "^4.13.1", "@smithy/url-parser": "^4.2.12", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.44", - "@smithy/util-defaults-mode-node": "^4.2.48", + "@smithy/util-defaults-mode-browser": "^4.3.43", + "@smithy/util-defaults-mode-node": "^4.2.47", "@smithy/util-endpoints": "^3.3.3", "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.13", + "@smithy/util-retry": "^4.2.12", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" }, @@ -282,10 +390,57 @@ "node": ">=20.0.0" } }, + "node_modules/@aws-sdk/client-cloudformation": { + "version": "3.1027.0", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/credential-provider-node": "^3.972.30", + "@aws-sdk/middleware-host-header": "^3.972.9", + "@aws-sdk/middleware-logger": "^3.972.9", + "@aws-sdk/middleware-recursion-detection": "^3.972.10", + "@aws-sdk/middleware-user-agent": "^3.972.29", + "@aws-sdk/region-config-resolver": "^3.972.11", + "@aws-sdk/types": "^3.973.7", + "@aws-sdk/util-endpoints": "^3.996.6", + "@aws-sdk/util-user-agent-browser": "^3.972.9", + "@aws-sdk/util-user-agent-node": "^3.973.15", + "@smithy/config-resolver": "^4.4.14", + "@smithy/core": "^3.23.14", + "@smithy/fetch-http-handler": "^5.3.16", + "@smithy/hash-node": "^4.2.13", + "@smithy/invalid-dependency": "^4.2.13", + "@smithy/middleware-content-length": "^4.2.13", + "@smithy/middleware-endpoint": "^4.4.29", + "@smithy/middleware-retry": "^4.5.0", + "@smithy/middleware-serde": "^4.2.17", + "@smithy/middleware-stack": "^4.2.13", + "@smithy/node-config-provider": "^4.3.13", + "@smithy/node-http-handler": "^4.5.2", + "@smithy/protocol-http": "^5.3.13", + "@smithy/smithy-client": "^4.12.9", + "@smithy/types": "^4.14.0", + "@smithy/url-parser": "^4.2.13", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.45", + "@smithy/util-defaults-mode-node": "^4.2.49", + "@smithy/util-endpoints": "^3.3.4", + "@smithy/util-middleware": "^4.2.13", + "@smithy/util-retry": "^4.3.0", + "@smithy/util-utf8": "^4.2.2", + "@smithy/util-waiter": "^4.2.15", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@aws-sdk/client-dynamodb": { - "version": "3.1025.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.1025.0.tgz", - "integrity": "sha512-zDus8uUYmL/ZSEGTWybdAxtcJPwlCUJuAV3d/XuWckKXW1HI78q9Yul1WSn1Z9nDeSFBhCNDuwz1CEAxbIyigA==", + "version": "3.1024.0", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", @@ -335,49 +490,161 @@ "node": ">=20.0.0" } }, + "node_modules/@aws-sdk/client-route-53": { + "version": "3.1027.0", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/credential-provider-node": "^3.972.30", + "@aws-sdk/middleware-host-header": "^3.972.9", + "@aws-sdk/middleware-logger": "^3.972.9", + "@aws-sdk/middleware-recursion-detection": "^3.972.10", + "@aws-sdk/middleware-sdk-route53": "^3.972.11", + "@aws-sdk/middleware-user-agent": "^3.972.29", + "@aws-sdk/region-config-resolver": "^3.972.11", + "@aws-sdk/types": "^3.973.7", + "@aws-sdk/util-endpoints": "^3.996.6", + "@aws-sdk/util-user-agent-browser": "^3.972.9", + "@aws-sdk/util-user-agent-node": "^3.973.15", + "@smithy/config-resolver": "^4.4.14", + "@smithy/core": "^3.23.14", + "@smithy/fetch-http-handler": "^5.3.16", + "@smithy/hash-node": "^4.2.13", + "@smithy/invalid-dependency": "^4.2.13", + "@smithy/middleware-content-length": "^4.2.13", + "@smithy/middleware-endpoint": "^4.4.29", + "@smithy/middleware-retry": "^4.5.0", + "@smithy/middleware-serde": "^4.2.17", + "@smithy/middleware-stack": "^4.2.13", + "@smithy/node-config-provider": "^4.3.13", + "@smithy/node-http-handler": "^4.5.2", + "@smithy/protocol-http": "^5.3.13", + "@smithy/smithy-client": "^4.12.9", + "@smithy/types": "^4.14.0", + "@smithy/url-parser": "^4.2.13", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.45", + "@smithy/util-defaults-mode-node": "^4.2.49", + "@smithy/util-endpoints": "^3.3.4", + "@smithy/util-middleware": "^4.2.13", + "@smithy/util-retry": "^4.3.0", + "@smithy/util-utf8": "^4.2.2", + "@smithy/util-waiter": "^4.2.15", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.1027.0", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/credential-provider-node": "^3.972.30", + "@aws-sdk/middleware-bucket-endpoint": "^3.972.9", + "@aws-sdk/middleware-expect-continue": "^3.972.9", + "@aws-sdk/middleware-flexible-checksums": "^3.974.7", + "@aws-sdk/middleware-host-header": "^3.972.9", + "@aws-sdk/middleware-location-constraint": "^3.972.9", + "@aws-sdk/middleware-logger": "^3.972.9", + "@aws-sdk/middleware-recursion-detection": "^3.972.10", + "@aws-sdk/middleware-sdk-s3": "^3.972.28", + "@aws-sdk/middleware-ssec": "^3.972.9", + "@aws-sdk/middleware-user-agent": "^3.972.29", + "@aws-sdk/region-config-resolver": "^3.972.11", + "@aws-sdk/signature-v4-multi-region": "^3.996.16", + "@aws-sdk/types": "^3.973.7", + "@aws-sdk/util-endpoints": "^3.996.6", + "@aws-sdk/util-user-agent-browser": "^3.972.9", + "@aws-sdk/util-user-agent-node": "^3.973.15", + "@smithy/config-resolver": "^4.4.14", + "@smithy/core": "^3.23.14", + "@smithy/eventstream-serde-browser": "^4.2.13", + "@smithy/eventstream-serde-config-resolver": "^4.3.13", + "@smithy/eventstream-serde-node": "^4.2.13", + "@smithy/fetch-http-handler": "^5.3.16", + "@smithy/hash-blob-browser": "^4.2.14", + "@smithy/hash-node": "^4.2.13", + "@smithy/hash-stream-node": "^4.2.13", + "@smithy/invalid-dependency": "^4.2.13", + "@smithy/md5-js": "^4.2.13", + "@smithy/middleware-content-length": "^4.2.13", + "@smithy/middleware-endpoint": "^4.4.29", + "@smithy/middleware-retry": "^4.5.0", + "@smithy/middleware-serde": "^4.2.17", + "@smithy/middleware-stack": "^4.2.13", + "@smithy/node-config-provider": "^4.3.13", + "@smithy/node-http-handler": "^4.5.2", + "@smithy/protocol-http": "^5.3.13", + "@smithy/smithy-client": "^4.12.9", + "@smithy/types": "^4.14.0", + "@smithy/url-parser": "^4.2.13", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.45", + "@smithy/util-defaults-mode-node": "^4.2.49", + "@smithy/util-endpoints": "^3.3.4", + "@smithy/util-middleware": "^4.2.13", + "@smithy/util-retry": "^4.3.0", + "@smithy/util-stream": "^4.5.22", + "@smithy/util-utf8": "^4.2.2", + "@smithy/util-waiter": "^4.2.15", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.1025.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.1025.0.tgz", - "integrity": "sha512-A08vxPKkRLi9n8o/257w7A52G8ZGvwF5ZHlaWAk7yw+fNHtlUrkQU+pNabI+Lob/3X3AVxTbIb8cfsLD83p47Q==", + "version": "3.1019.0", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/credential-provider-node": "^3.972.29", + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/credential-provider-node": "^3.972.27", "@aws-sdk/middleware-host-header": "^3.972.8", "@aws-sdk/middleware-logger": "^3.972.8", "@aws-sdk/middleware-recursion-detection": "^3.972.9", - "@aws-sdk/middleware-user-agent": "^3.972.28", + "@aws-sdk/middleware-user-agent": "^3.972.26", "@aws-sdk/region-config-resolver": "^3.972.10", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.14", + "@aws-sdk/util-user-agent-node": "^3.973.12", "@smithy/config-resolver": "^4.4.13", - "@smithy/core": "^3.23.13", + "@smithy/core": "^3.23.12", "@smithy/fetch-http-handler": "^5.3.15", "@smithy/hash-node": "^4.2.12", "@smithy/invalid-dependency": "^4.2.12", "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.28", - "@smithy/middleware-retry": "^4.4.46", - "@smithy/middleware-serde": "^4.2.16", + "@smithy/middleware-endpoint": "^4.4.27", + "@smithy/middleware-retry": "^4.4.44", + "@smithy/middleware-serde": "^4.2.15", "@smithy/middleware-stack": "^4.2.12", "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.5.1", + "@smithy/node-http-handler": "^4.5.0", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.8", + "@smithy/smithy-client": "^4.12.7", "@smithy/types": "^4.13.1", "@smithy/url-parser": "^4.2.12", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.44", - "@smithy/util-defaults-mode-node": "^4.2.48", + "@smithy/util-defaults-mode-browser": "^4.3.43", + "@smithy/util-defaults-mode-node": "^4.2.47", "@smithy/util-endpoints": "^3.3.3", "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.13", + "@smithy/util-retry": "^4.2.12", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" }, @@ -386,50 +653,48 @@ } }, "node_modules/@aws-sdk/client-sqs": { - "version": "3.1025.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.1025.0.tgz", - "integrity": "sha512-qXDGLBU7Xmv0cKicDyRFcp47wJ12YMUzTawFZhobdeGJA52nNrAA781hner5O36BOqoXYh1nm0PEybr2KsL1OQ==", + "version": "3.1019.0", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/credential-provider-node": "^3.972.29", + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/credential-provider-node": "^3.972.27", "@aws-sdk/middleware-host-header": "^3.972.8", "@aws-sdk/middleware-logger": "^3.972.8", "@aws-sdk/middleware-recursion-detection": "^3.972.9", - "@aws-sdk/middleware-sdk-sqs": "^3.972.18", - "@aws-sdk/middleware-user-agent": "^3.972.28", + "@aws-sdk/middleware-sdk-sqs": "^3.972.17", + "@aws-sdk/middleware-user-agent": "^3.972.26", "@aws-sdk/region-config-resolver": "^3.972.10", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.14", + "@aws-sdk/util-user-agent-node": "^3.973.12", "@smithy/config-resolver": "^4.4.13", - "@smithy/core": "^3.23.13", + "@smithy/core": "^3.23.12", "@smithy/fetch-http-handler": "^5.3.15", "@smithy/hash-node": "^4.2.12", "@smithy/invalid-dependency": "^4.2.12", "@smithy/md5-js": "^4.2.12", "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.28", - "@smithy/middleware-retry": "^4.4.46", - "@smithy/middleware-serde": "^4.2.16", + "@smithy/middleware-endpoint": "^4.4.27", + "@smithy/middleware-retry": "^4.4.44", + "@smithy/middleware-serde": "^4.2.15", "@smithy/middleware-stack": "^4.2.12", "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.5.1", + "@smithy/node-http-handler": "^4.5.0", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.8", + "@smithy/smithy-client": "^4.12.7", "@smithy/types": "^4.13.1", "@smithy/url-parser": "^4.2.12", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.44", - "@smithy/util-defaults-mode-node": "^4.2.48", + "@smithy/util-defaults-mode-browser": "^4.3.43", + "@smithy/util-defaults-mode-node": "^4.2.47", "@smithy/util-endpoints": "^3.3.3", "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.13", + "@smithy/util-retry": "^4.2.12", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" }, @@ -438,50 +703,48 @@ } }, "node_modules/@aws-sdk/client-ssm": { - "version": "3.1025.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1025.0.tgz", - "integrity": "sha512-sQF0sDvUgJPeSBt4wulaywE/mXkcuxiwo/uNbmUNk4NIoFkDuEdYOK72MBhLF/BSJ4qpNQgherPc5CognefUNg==", + "version": "3.1019.0", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/credential-provider-node": "^3.972.29", + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/credential-provider-node": "^3.972.27", "@aws-sdk/middleware-host-header": "^3.972.8", "@aws-sdk/middleware-logger": "^3.972.8", "@aws-sdk/middleware-recursion-detection": "^3.972.9", - "@aws-sdk/middleware-user-agent": "^3.972.28", + "@aws-sdk/middleware-user-agent": "^3.972.26", "@aws-sdk/region-config-resolver": "^3.972.10", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.14", + "@aws-sdk/util-user-agent-node": "^3.973.12", "@smithy/config-resolver": "^4.4.13", - "@smithy/core": "^3.23.13", + "@smithy/core": "^3.23.12", "@smithy/fetch-http-handler": "^5.3.15", "@smithy/hash-node": "^4.2.12", "@smithy/invalid-dependency": "^4.2.12", "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.28", - "@smithy/middleware-retry": "^4.4.46", - "@smithy/middleware-serde": "^4.2.16", + "@smithy/middleware-endpoint": "^4.4.27", + "@smithy/middleware-retry": "^4.4.44", + "@smithy/middleware-serde": "^4.2.15", "@smithy/middleware-stack": "^4.2.12", "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.5.1", + "@smithy/node-http-handler": "^4.5.0", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.8", + "@smithy/smithy-client": "^4.12.7", "@smithy/types": "^4.13.1", "@smithy/url-parser": "^4.2.12", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.44", - "@smithy/util-defaults-mode-node": "^4.2.48", + "@smithy/util-defaults-mode-browser": "^4.3.43", + "@smithy/util-defaults-mode-node": "^4.2.47", "@smithy/util-endpoints": "^3.3.3", "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.13", + "@smithy/util-retry": "^4.2.12", "@smithy/util-utf8": "^4.2.2", - "@smithy/util-waiter": "^4.2.14", + "@smithy/util-waiter": "^4.2.13", "tslib": "^2.6.2" }, "engines": { @@ -489,22 +752,20 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.973.26", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.26.tgz", - "integrity": "sha512-A/E6n2W42ruU+sfWk+mMUOyVXbsSgGrY3MJ9/0Az5qUdG67y8I6HYzzoAa+e/lzxxl1uCYmEL6BTMi9ZiZnplQ==", + "version": "3.973.27", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@aws-sdk/xml-builder": "^3.972.16", - "@smithy/core": "^3.23.13", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/property-provider": "^4.2.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/signature-v4": "^5.3.12", - "@smithy/smithy-client": "^4.12.8", - "@smithy/types": "^4.13.1", + "@aws-sdk/types": "^3.973.7", + "@aws-sdk/xml-builder": "^3.972.17", + "@smithy/core": "^3.23.14", + "@smithy/node-config-provider": "^4.3.13", + "@smithy/property-provider": "^4.2.13", + "@smithy/protocol-http": "^5.3.13", + "@smithy/signature-v4": "^5.3.13", + "@smithy/smithy-client": "^4.12.9", + "@smithy/types": "^4.14.0", "@smithy/util-base64": "^4.3.2", - "@smithy/util-middleware": "^4.2.12", + "@smithy/util-middleware": "^4.2.13", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" }, @@ -512,62 +773,67 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.24.tgz", - "integrity": "sha512-FWg8uFmT6vQM7VuzELzwVo5bzExGaKHdubn0StjgrcU5FvuLExUe+k06kn/40uKv59rYzhez8eFNM4yYE/Yb/w==", + "node_modules/@aws-sdk/crc64-nvme": { + "version": "3.972.6", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/types": "^4.13.1", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.26", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.26.tgz", - "integrity": "sha512-CY4ppZ+qHYqcXqBVi//sdHST1QK3KzOEiLtpLsc9W2k2vfZPKExGaQIsOwcyvjpjUEolotitmd3mUNY56IwDEA==", + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.25", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/types": "^3.973.6", - "@smithy/fetch-http-handler": "^5.3.15", - "@smithy/node-http-handler": "^4.5.1", - "@smithy/property-provider": "^4.2.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.8", - "@smithy/types": "^4.13.1", - "@smithy/util-stream": "^4.5.21", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/types": "^3.973.7", + "@smithy/property-provider": "^4.2.13", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.972.28", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.28.tgz", - "integrity": "sha512-wXYvq3+uQcZV7k+bE4yDXCTBdzWTU9x/nMiKBfzInmv6yYK1veMK0AKvRfRBd72nGWYKcL6AxwiPg9z/pYlgpw==", + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.27", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/credential-provider-env": "^3.972.24", - "@aws-sdk/credential-provider-http": "^3.972.26", - "@aws-sdk/credential-provider-login": "^3.972.28", - "@aws-sdk/credential-provider-process": "^3.972.24", - "@aws-sdk/credential-provider-sso": "^3.972.28", - "@aws-sdk/credential-provider-web-identity": "^3.972.28", - "@aws-sdk/nested-clients": "^3.996.18", - "@aws-sdk/types": "^3.973.6", - "@smithy/credential-provider-imds": "^4.2.12", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/types": "^3.973.7", + "@smithy/fetch-http-handler": "^5.3.16", + "@smithy/node-http-handler": "^4.5.2", + "@smithy/property-provider": "^4.2.13", + "@smithy/protocol-http": "^5.3.13", + "@smithy/smithy-client": "^4.12.9", + "@smithy/types": "^4.14.0", + "@smithy/util-stream": "^4.5.22", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.972.29", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/credential-provider-env": "^3.972.25", + "@aws-sdk/credential-provider-http": "^3.972.27", + "@aws-sdk/credential-provider-login": "^3.972.29", + "@aws-sdk/credential-provider-process": "^3.972.25", + "@aws-sdk/credential-provider-sso": "^3.972.29", + "@aws-sdk/credential-provider-web-identity": "^3.972.29", + "@aws-sdk/nested-clients": "^3.996.19", + "@aws-sdk/types": "^3.973.7", + "@smithy/credential-provider-imds": "^4.2.13", + "@smithy/property-provider": "^4.2.13", + "@smithy/shared-ini-file-loader": "^4.4.8", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { @@ -575,18 +841,16 @@ } }, "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.28", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.28.tgz", - "integrity": "sha512-ZSTfO6jqUTCysbdBPtEX5OUR//3rbD0lN7jO3sQeS2Gjr/Y+DT6SbIJ0oT2cemNw3UzKu97sNONd1CwNMthuZQ==", + "version": "3.972.29", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/nested-clients": "^3.996.18", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/nested-clients": "^3.996.19", + "@aws-sdk/types": "^3.973.7", + "@smithy/property-provider": "^4.2.13", + "@smithy/protocol-http": "^5.3.13", + "@smithy/shared-ini-file-loader": "^4.4.8", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { @@ -594,22 +858,20 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.29", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.29.tgz", - "integrity": "sha512-clSzDcvndpFJAggLDnDb36sPdlZYyEs5Zm6zgZjjUhwsJgSWiWKwFIXUVBcbruidNyBdbpOv2tNDL9sX8y3/0g==", + "version": "3.972.30", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.24", - "@aws-sdk/credential-provider-http": "^3.972.26", - "@aws-sdk/credential-provider-ini": "^3.972.28", - "@aws-sdk/credential-provider-process": "^3.972.24", - "@aws-sdk/credential-provider-sso": "^3.972.28", - "@aws-sdk/credential-provider-web-identity": "^3.972.28", - "@aws-sdk/types": "^3.973.6", - "@smithy/credential-provider-imds": "^4.2.12", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", + "@aws-sdk/credential-provider-env": "^3.972.25", + "@aws-sdk/credential-provider-http": "^3.972.27", + "@aws-sdk/credential-provider-ini": "^3.972.29", + "@aws-sdk/credential-provider-process": "^3.972.25", + "@aws-sdk/credential-provider-sso": "^3.972.29", + "@aws-sdk/credential-provider-web-identity": "^3.972.29", + "@aws-sdk/types": "^3.973.7", + "@smithy/credential-provider-imds": "^4.2.13", + "@smithy/property-provider": "^4.2.13", + "@smithy/shared-ini-file-loader": "^4.4.8", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { @@ -617,16 +879,14 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.24.tgz", - "integrity": "sha512-Q2k/XLrFXhEztPHqj4SLCNID3hEPdlhh1CDLBpNnM+1L8fq7P+yON9/9M1IGN/dA5W45v44ylERfXtDAlmMNmw==", + "version": "3.972.25", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/types": "^3.973.7", + "@smithy/property-provider": "^4.2.13", + "@smithy/shared-ini-file-loader": "^4.4.8", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { @@ -634,18 +894,16 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.972.28", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.28.tgz", - "integrity": "sha512-IoUlmKMLEITFn1SiCTjPfR6KrE799FBo5baWyk/5Ppar2yXZoUdaRqZzJzK6TcJxx450M8m8DbpddRVYlp5R/A==", + "version": "3.972.29", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/nested-clients": "^3.996.18", - "@aws-sdk/token-providers": "3.1021.0", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/nested-clients": "^3.996.19", + "@aws-sdk/token-providers": "3.1026.0", + "@aws-sdk/types": "^3.973.7", + "@smithy/property-provider": "^4.2.13", + "@smithy/shared-ini-file-loader": "^4.4.8", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { @@ -653,17 +911,15 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.28", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.28.tgz", - "integrity": "sha512-d+6h0SD8GGERzKe27v5rOzNGKOl0D+l0bWJdqrxH8WSQzHzjsQFIAPgIeOTUwBHVsKKwtSxc91K/SWax6XgswQ==", + "version": "3.972.29", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/nested-clients": "^3.996.18", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/nested-clients": "^3.996.19", + "@aws-sdk/types": "^3.973.7", + "@smithy/property-provider": "^4.2.13", + "@smithy/shared-ini-file-loader": "^4.4.8", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { @@ -672,8 +928,6 @@ }, "node_modules/@aws-sdk/dynamodb-codec": { "version": "3.972.27", - "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.972.27.tgz", - "integrity": "sha512-S7IWE0K+aqbvjP8PHnOyDJK1fzrazAismH5XutJtS3YBvRvmfLb8Ac7Z1ZC4LBWvO8Gx1t/szFe46K51FqZn/A==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/core": "^3.973.26", @@ -689,8 +943,6 @@ }, "node_modules/@aws-sdk/endpoint-cache": { "version": "3.972.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.972.5.tgz", - "integrity": "sha512-itVdge0NozgtgmtbZ25FVwWU3vGlE7x7feE/aOEJNkQfEpbkrF8Rj1QmnK+2blFfYE1xWt/iU+6/jUp/pv1+MA==", "license": "Apache-2.0", "dependencies": { "mnemonist": "0.38.3", @@ -701,15 +953,13 @@ } }, "node_modules/@aws-sdk/lib-dynamodb": { - "version": "3.1025.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.1025.0.tgz", - "integrity": "sha512-5MFISrm/BRwD6sjz5wba4SGXnFjkiZNMSMyeKkmm8RmpGkGw/FVe9yboKM4GVfU9derOB3icMGxovlABhnU1qw==", + "version": "3.1019.0", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.26", + "@aws-sdk/core": "^3.973.25", "@aws-sdk/util-dynamodb": "^3.996.2", - "@smithy/core": "^3.23.13", - "@smithy/smithy-client": "^4.12.8", + "@smithy/core": "^3.23.12", + "@smithy/smithy-client": "^4.12.7", "@smithy/types": "^4.13.1", "tslib": "^2.6.2" }, @@ -717,31 +967,32 @@ "node": ">=20.0.0" }, "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.1025.0" + "@aws-sdk/client-dynamodb": "^3.1019.0" } }, - "node_modules/@aws-sdk/middleware-endpoint-discovery": { + "node_modules/@aws-sdk/middleware-bucket-endpoint": { "version": "3.972.9", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.972.9.tgz", - "integrity": "sha512-1503Y5Xk14SdXY0ucXwc08CY+aVuoY1tmQxsR/apwAVAwcLT7FFzqjYJYLq8JOkKJyzIB8M6J27e1ZcagGK+Fg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/endpoint-cache": "^3.972.5", - "@aws-sdk/types": "^3.973.6", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", + "@aws-sdk/types": "^3.973.7", + "@aws-sdk/util-arn-parser": "^3.972.3", + "@smithy/node-config-provider": "^4.3.13", + "@smithy/protocol-http": "^5.3.13", + "@smithy/types": "^4.14.0", + "@smithy/util-config-provider": "^4.2.2", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.972.8", + "node_modules/@aws-sdk/middleware-endpoint-discovery": { + "version": "3.972.9", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/endpoint-cache": "^3.972.5", "@aws-sdk/types": "^3.973.6", + "@smithy/node-config-provider": "^4.3.12", "@smithy/protocol-http": "^5.3.12", "@smithy/types": "^4.13.1", "tslib": "^2.6.2" @@ -750,222 +1001,341 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.972.8", + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.972.9", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/types": "^4.13.1", + "@aws-sdk/types": "^3.973.7", + "@smithy/protocol-http": "^5.3.13", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.972.9", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.9.tgz", - "integrity": "sha512-/Wt5+CT8dpTFQxEJ9iGy/UGrXr7p2wlIOEHvIr/YcHYByzoLjrqkYqXdJjd9UIgWjv7eqV2HnFJen93UTuwfTQ==", + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.974.7", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@aws/lambda-invoke-store": "^0.2.2", - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/crc64-nvme": "^3.972.6", + "@aws-sdk/types": "^3.973.7", + "@smithy/is-array-buffer": "^4.2.2", + "@smithy/node-config-provider": "^4.3.13", + "@smithy/protocol-http": "^5.3.13", + "@smithy/types": "^4.14.0", + "@smithy/util-middleware": "^4.2.13", + "@smithy/util-stream": "^4.5.22", + "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/middleware-sdk-sqs": { - "version": "3.972.18", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.972.18.tgz", - "integrity": "sha512-BdsGFuBJUX5PnuZkEV6JRB5g/6ts7iGmN3pXwyoiGCCM2HHXrlFqjkBs+iPX7yO884WqYeQJpme7nwn4DzU5xw==", + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.972.9", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/smithy-client": "^4.12.8", - "@smithy/types": "^4.13.1", - "@smithy/util-hex-encoding": "^4.2.2", - "@smithy/util-utf8": "^4.2.2", + "@aws-sdk/types": "^3.973.7", + "@smithy/protocol-http": "^5.3.13", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.972.28", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.28.tgz", - "integrity": "sha512-cfWZFlVh7Va9lRay4PN2A9ARFzaBYcA097InT5M2CdRS05ECF5yaz86jET8Wsl2WcyKYEvVr/QNmKtYtafUHtQ==", + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.972.9", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/types": "^3.973.6", - "@aws-sdk/util-endpoints": "^3.996.5", - "@smithy/core": "^3.23.13", - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", - "@smithy/util-retry": "^4.2.13", + "@aws-sdk/types": "^3.973.7", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/nested-clients": { - "version": "3.996.18", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.18.tgz", - "integrity": "sha512-c7ZSIXrESxHKx2Mcopgd8AlzZgoXMr20fkx5ViPWPOLBvmyhw9VwJx/Govg8Ef/IhEon5R9l53Z8fdYSEmp6VA==", + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.972.9", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/middleware-host-header": "^3.972.8", - "@aws-sdk/middleware-logger": "^3.972.8", - "@aws-sdk/middleware-recursion-detection": "^3.972.9", - "@aws-sdk/middleware-user-agent": "^3.972.28", - "@aws-sdk/region-config-resolver": "^3.972.10", - "@aws-sdk/types": "^3.973.6", - "@aws-sdk/util-endpoints": "^3.996.5", - "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.14", - "@smithy/config-resolver": "^4.4.13", - "@smithy/core": "^3.23.13", - "@smithy/fetch-http-handler": "^5.3.15", - "@smithy/hash-node": "^4.2.12", - "@smithy/invalid-dependency": "^4.2.12", - "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.28", - "@smithy/middleware-retry": "^4.4.46", - "@smithy/middleware-serde": "^4.2.16", - "@smithy/middleware-stack": "^4.2.12", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.5.1", - "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.8", - "@smithy/types": "^4.13.1", - "@smithy/url-parser": "^4.2.12", - "@smithy/util-base64": "^4.3.2", - "@smithy/util-body-length-browser": "^4.2.2", - "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.44", - "@smithy/util-defaults-mode-node": "^4.2.48", - "@smithy/util-endpoints": "^3.3.3", - "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.13", - "@smithy/util-utf8": "^4.2.2", + "@aws-sdk/types": "^3.973.7", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/region-config-resolver": { + "node_modules/@aws-sdk/middleware-recursion-detection": { "version": "3.972.10", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.10.tgz", - "integrity": "sha512-1dq9ToC6e070QvnVhhbAs3bb5r6cQ10gTVc6cyRV5uvQe7P138TV2uG2i6+Yok4bAkVAcx5AqkTEBUvWEtBlsQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/config-resolver": "^4.4.13", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/types": "^4.13.1", + "@aws-sdk/types": "^3.973.7", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.13", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.1021.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1021.0.tgz", - "integrity": "sha512-TKY6h9spUk3OLs5v1oAgW9mAeBE3LAGNBwJokLy96wwmd4W2v/tYlXseProyed9ValDj2u1jK/4Rg1T+1NXyJA==", + "node_modules/@aws-sdk/middleware-sdk-route53": { + "version": "3.972.11", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.26", - "@aws-sdk/nested-clients": "^3.996.18", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", + "@aws-sdk/types": "^3.973.7", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/types": { - "version": "3.973.6", + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.972.28", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.13.1", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/types": "^3.973.7", + "@aws-sdk/util-arn-parser": "^3.972.3", + "@smithy/core": "^3.23.14", + "@smithy/node-config-provider": "^4.3.13", + "@smithy/protocol-http": "^5.3.13", + "@smithy/signature-v4": "^5.3.13", + "@smithy/smithy-client": "^4.12.9", + "@smithy/types": "^4.14.0", + "@smithy/util-config-provider": "^4.2.2", + "@smithy/util-middleware": "^4.2.13", + "@smithy/util-stream": "^4.5.22", + "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/util-dynamodb": { - "version": "3.996.2", + "node_modules/@aws-sdk/middleware-sdk-sqs": { + "version": "3.972.17", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@smithy/smithy-client": "^4.12.7", + "@smithy/types": "^4.13.1", + "@smithy/util-hex-encoding": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.1003.0" } }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.996.5", + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.972.9", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/types": "^4.13.1", - "@smithy/url-parser": "^4.2.12", - "@smithy/util-endpoints": "^3.3.3", + "@aws-sdk/types": "^3.973.7", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.893.0", + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.972.29", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/types": "^3.973.7", + "@aws-sdk/util-endpoints": "^3.996.6", + "@smithy/core": "^3.23.14", + "@smithy/protocol-http": "^5.3.13", + "@smithy/types": "^4.14.0", + "@smithy/util-retry": "^4.3.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.972.8", + "node_modules/@aws-sdk/nested-clients": { + "version": "3.996.19", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/types": "^4.13.1", - "bowser": "^2.11.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/middleware-host-header": "^3.972.9", + "@aws-sdk/middleware-logger": "^3.972.9", + "@aws-sdk/middleware-recursion-detection": "^3.972.10", + "@aws-sdk/middleware-user-agent": "^3.972.29", + "@aws-sdk/region-config-resolver": "^3.972.11", + "@aws-sdk/types": "^3.973.7", + "@aws-sdk/util-endpoints": "^3.996.6", + "@aws-sdk/util-user-agent-browser": "^3.972.9", + "@aws-sdk/util-user-agent-node": "^3.973.15", + "@smithy/config-resolver": "^4.4.14", + "@smithy/core": "^3.23.14", + "@smithy/fetch-http-handler": "^5.3.16", + "@smithy/hash-node": "^4.2.13", + "@smithy/invalid-dependency": "^4.2.13", + "@smithy/middleware-content-length": "^4.2.13", + "@smithy/middleware-endpoint": "^4.4.29", + "@smithy/middleware-retry": "^4.5.0", + "@smithy/middleware-serde": "^4.2.17", + "@smithy/middleware-stack": "^4.2.13", + "@smithy/node-config-provider": "^4.3.13", + "@smithy/node-http-handler": "^4.5.2", + "@smithy/protocol-http": "^5.3.13", + "@smithy/smithy-client": "^4.12.9", + "@smithy/types": "^4.14.0", + "@smithy/url-parser": "^4.2.13", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.45", + "@smithy/util-defaults-mode-node": "^4.2.49", + "@smithy/util-endpoints": "^3.3.4", + "@smithy/util-middleware": "^4.2.13", + "@smithy/util-retry": "^4.3.0", + "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.973.14", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.14.tgz", - "integrity": "sha512-vNSB/DYaPOyujVZBg/zUznH9QC142MaTHVmaFlF7uzzfg3CgT9f/l4C0Yi+vU/tbBhxVcXVB90Oohk5+o+ZbWw==", + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.972.11", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "^3.972.28", - "@aws-sdk/types": "^3.973.6", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/types": "^4.13.1", - "@smithy/util-config-provider": "^4.2.2", + "@aws-sdk/types": "^3.973.7", + "@smithy/config-resolver": "^4.4.14", + "@smithy/node-config-provider": "^4.3.13", + "@smithy/types": "^4.14.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.16", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "^3.972.28", + "@aws-sdk/types": "^3.973.7", + "@smithy/protocol-http": "^5.3.13", + "@smithy/signature-v4": "^5.3.13", + "@smithy/types": "^4.14.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.1026.0", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.27", + "@aws-sdk/nested-clients": "^3.996.19", + "@aws-sdk/types": "^3.973.7", + "@smithy/property-provider": "^4.2.13", + "@smithy/shared-ini-file-loader": "^4.4.8", + "@smithy/types": "^4.14.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.973.7", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.14.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.972.3", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-dynamodb": { + "version": "3.996.2", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.1003.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.996.6", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.7", + "@smithy/types": "^4.14.0", + "@smithy/url-parser": "^4.2.13", + "@smithy/util-endpoints": "^3.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.893.0", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.972.9", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.7", + "@smithy/types": "^4.14.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.973.15", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "^3.972.29", + "@aws-sdk/types": "^3.973.7", + "@smithy/node-config-provider": "^4.3.13", + "@smithy/types": "^4.14.0", + "@smithy/util-config-provider": "^4.2.2", "tslib": "^2.6.2" }, "engines": { @@ -981,12 +1351,10 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.16", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.16.tgz", - "integrity": "sha512-iu2pyvaqmeatIJLURLqx9D+4jKAdTH20ntzB6BFwjyN7V960r4jK32mx0Zf7YbtOYAbmbtQfDNuL60ONinyw7A==", + "version": "3.972.17", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.13.1", + "@smithy/types": "^4.14.0", "fast-xml-parser": "5.5.8", "tslib": "^2.6.2" }, @@ -1557,7 +1925,7 @@ } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "5.0.5", + "version": "5.0.4", "dev": true, "license": "MIT", "dependencies": { @@ -1648,8 +2016,6 @@ }, "node_modules/@faker-js/faker": { "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-10.4.0.tgz", - "integrity": "sha512-sDBWI3yLy8EcDzgobvJTWq1MJYzAkQdpjXuPukga9wXonhpMRvd1Izuo2Qgwey2OiEoRIBr35RMU9HJRoOHzpw==", "dev": true, "funding": [ { @@ -1705,8 +2071,6 @@ }, "node_modules/@humanwhocodes/momoa": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-2.0.4.tgz", - "integrity": "sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==", "license": "Apache-2.0", "engines": { "node": ">=10.10.0" @@ -1924,10 +2288,21 @@ "uninstall": "^0.0.0" } }, + "node_modules/@nhsdigital/eps-cdk-constructs": { + "version": "1.6.1", + "license": "MIT", + "dependencies": { + "@aws-sdk/client-cloudformation": "^3.1018.0", + "@aws-sdk/client-route-53": "^3.1018.0", + "@aws-sdk/client-s3": "^3.1018.0", + "aws-cdk": "^2.1114.1", + "aws-cdk-lib": "^2.244.0", + "cdk-nag": "^2.37.52", + "constructs": "^10.6.0" + } + }, "node_modules/@noble/hashes": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", "license": "MIT", "engines": { "node": "^14.21.3 || >=16" @@ -2221,9 +2596,7 @@ "license": "MIT" }, "node_modules/@redocly/cli": { - "version": "2.25.4", - "resolved": "https://registry.npmjs.org/@redocly/cli/-/cli-2.25.4.tgz", - "integrity": "sha512-ypBv8ZhckTzcOfsFH2VILsLqk00bJ1tI0POtlaEf8z0rDsnmD8auUETkMzw8wlUB+aQM7+VSzpSsmcmqeSgzWQ==", + "version": "2.25.2", "license": "MIT", "dependencies": { "@opentelemetry/exporter-trace-otlp-http": "0.202.0", @@ -2231,8 +2604,8 @@ "@opentelemetry/sdk-trace-node": "2.0.1", "@opentelemetry/semantic-conventions": "1.34.0", "@redocly/cli-otel": "0.1.2", - "@redocly/openapi-core": "2.25.4", - "@redocly/respect-core": "2.25.4", + "@redocly/openapi-core": "2.25.2", + "@redocly/respect-core": "2.25.2", "abort-controller": "^3.0.0", "ajv": "npm:@redocly/ajv@8.18.0", "ajv-formats": "^3.0.1", @@ -2240,7 +2613,7 @@ "cookie": "^0.7.2", "dotenv": "16.4.7", "glob": "^13.0.5", - "handlebars": "^4.7.9", + "handlebars": "^4.7.6", "https-proxy-agent": "^7.0.5", "mobx": "^6.0.4", "picomatch": "^4.0.4", @@ -2267,8 +2640,6 @@ }, "node_modules/@redocly/cli-otel": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@redocly/cli-otel/-/cli-otel-0.1.2.tgz", - "integrity": "sha512-Bg7BoO5t1x3lVK+KhA5aGPmeXpQmdf6WtTYHhelKJCsQ+tRMiJoFAQoKHoBHAoNxXrhlS3K9lKFLHGmtxsFQfA==", "license": "MIT", "dependencies": { "ulid": "^2.3.0" @@ -2276,8 +2647,6 @@ }, "node_modules/@redocly/cli-otel/node_modules/ulid": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.4.0.tgz", - "integrity": "sha512-fIRiVTJNcSRmXKPZtGzFQv9WRrZ3M9eoptl/teFJvjOzmpU+/K/JH6HZ8deBfb5vMEpicJcLn7JmvdknlMq7Zg==", "license": "MIT", "bin": { "ulid": "bin/cli.js" @@ -2313,7 +2682,7 @@ } }, "node_modules/@redocly/cli/node_modules/brace-expansion": { - "version": "5.0.5", + "version": "5.0.4", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -2388,6 +2757,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@redocly/cli/node_modules/picomatch": { + "version": "4.0.4", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@redocly/cli/node_modules/string-width": { "version": "4.2.3", "license": "MIT", @@ -2449,9 +2828,7 @@ } }, "node_modules/@redocly/config": { - "version": "0.46.1", - "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.46.1.tgz", - "integrity": "sha512-dSdkB2wRLtvl3f7ayRu9vqVhUMjjRaxZlHgRbgOtPPXxn4uI/ciDO87h4CJb7Iet+OVpevpAU6gU8bo5qVbQxg==", + "version": "0.45.0", "license": "MIT", "dependencies": { "json-schema-to-ts": "2.7.2" @@ -2459,8 +2836,6 @@ }, "node_modules/@redocly/config/node_modules/json-schema-to-ts": { "version": "2.7.2", - "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-2.7.2.tgz", - "integrity": "sha512-R1JfqKqbBR4qE8UyBR56Ms30LL62/nlhoz+1UkfI/VE7p54Awu919FZ6ZUPG8zIa3XB65usPJgr1ONVncUGSaQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.18.3", @@ -2473,18 +2848,14 @@ }, "node_modules/@redocly/config/node_modules/ts-algebra": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.2.2.tgz", - "integrity": "sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==", "license": "MIT" }, "node_modules/@redocly/openapi-core": { - "version": "2.25.4", - "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-2.25.4.tgz", - "integrity": "sha512-zYdKQEsowPNtkTixrfbn5DySWBLQpTsISthVBBEPAa3OZC75UI76CbHXEamJ8Kmlead9IkD5RbgeJvxqJ5/H6Q==", + "version": "2.25.2", "license": "MIT", "dependencies": { "@redocly/ajv": "^8.18.0", - "@redocly/config": "^0.46.0", + "@redocly/config": "^0.45.0", "ajv": "npm:@redocly/ajv@8.18.0", "ajv-formats": "^3.0.1", "colorette": "^1.2.0", @@ -2502,8 +2873,6 @@ "node_modules/@redocly/openapi-core/node_modules/ajv": { "name": "@redocly/ajv", "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-F+LMD2IDIXuHxgpLJh3nkLj9+tSaEzoUWd+7fONGq5pe2169FUDjpEkOfEpoGLz1sbZni/69p07OsecNfAOpqA==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -2518,14 +2887,10 @@ }, "node_modules/@redocly/openapi-core/node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, "node_modules/@redocly/openapi-core/node_modules/js-yaml": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -2536,20 +2901,26 @@ }, "node_modules/@redocly/openapi-core/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, + "node_modules/@redocly/openapi-core/node_modules/picomatch": { + "version": "4.0.4", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@redocly/respect-core": { - "version": "2.25.4", - "resolved": "https://registry.npmjs.org/@redocly/respect-core/-/respect-core-2.25.4.tgz", - "integrity": "sha512-0xMbcSft+9Q2sO1wSJMxo510Aqc/kGF/AmUK3OaLQvGvKUgOqq2Op/0aorNQJk6s8WBEH4UN4eFt7fUzUeXs8g==", + "version": "2.25.2", "license": "MIT", "dependencies": { "@faker-js/faker": "^7.6.0", "@noble/hashes": "^1.8.0", "@redocly/ajv": "^8.18.0", - "@redocly/openapi-core": "2.25.4", + "@redocly/openapi-core": "2.25.2", "ajv": "npm:@redocly/ajv@8.18.0", "better-ajv-errors": "^1.2.0", "colorette": "^2.0.20", @@ -2566,8 +2937,6 @@ }, "node_modules/@redocly/respect-core/node_modules/@faker-js/faker": { "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz", - "integrity": "sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==", "license": "MIT", "engines": { "node": ">=14.0.0", @@ -2577,8 +2946,6 @@ "node_modules/@redocly/respect-core/node_modules/ajv": { "name": "@redocly/ajv", "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-F+LMD2IDIXuHxgpLJh3nkLj9+tSaEzoUWd+7fONGq5pe2169FUDjpEkOfEpoGLz1sbZni/69p07OsecNfAOpqA==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -2593,20 +2960,26 @@ }, "node_modules/@redocly/respect-core/node_modules/colorette": { "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "license": "MIT" }, "node_modules/@redocly/respect-core/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, + "node_modules/@redocly/respect-core/node_modules/picomatch": { + "version": "4.0.4", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.0.tgz", - "integrity": "sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", "cpu": [ "arm" ], @@ -2618,9 +2991,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.0.tgz", - "integrity": "sha512-u6JHLll5QKRvjciE78bQXDmqRqNs5M/3GVqZeMwvmjaNODJih/WIrJlFVEihvV0MiYFmd+ZyPr9wxOVbPAG2Iw==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", "cpu": [ "arm64" ], @@ -2632,9 +3005,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.0.tgz", - "integrity": "sha512-qEF7CsKKzSRc20Ciu2Zw1wRrBz4g56F7r/vRwY430UPp/nt1x21Q/fpJ9N5l47WWvJlkNCPJz3QRVw008fi7yA==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", "cpu": [ "arm64" ], @@ -2646,9 +3019,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.0.tgz", - "integrity": "sha512-WADYozJ4QCnXCH4wPB+3FuGmDPoFseVCUrANmA5LWwGmC6FL14BWC7pcq+FstOZv3baGX65tZ378uT6WG8ynTw==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", "cpu": [ "x64" ], @@ -2660,9 +3033,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.0.tgz", - "integrity": "sha512-6b8wGHJlDrGeSE3aH5mGNHBjA0TTkxdoNHik5EkvPHCt351XnigA4pS7Wsj/Eo9Y8RBU6f35cjN9SYmCFBtzxw==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", "cpu": [ "arm64" ], @@ -2674,9 +3047,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.0.tgz", - "integrity": "sha512-h25Ga0t4jaylMB8M/JKAyrvvfxGRjnPQIR8lnCayyzEjEOx2EJIlIiMbhpWxDRKGKF8jbNH01NnN663dH638mA==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", "cpu": [ "x64" ], @@ -2688,9 +3061,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.0.tgz", - "integrity": "sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", "cpu": [ "arm" ], @@ -2702,9 +3075,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.0.tgz", - "integrity": "sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", "cpu": [ "arm" ], @@ -2716,9 +3089,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.0.tgz", - "integrity": "sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", "cpu": [ "arm64" ], @@ -2730,9 +3103,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.0.tgz", - "integrity": "sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", "cpu": [ "arm64" ], @@ -2744,9 +3117,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.0.tgz", - "integrity": "sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", "cpu": [ "loong64" ], @@ -2758,9 +3131,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.0.tgz", - "integrity": "sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", "cpu": [ "loong64" ], @@ -2772,9 +3145,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.0.tgz", - "integrity": "sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", "cpu": [ "ppc64" ], @@ -2786,9 +3159,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.0.tgz", - "integrity": "sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", "cpu": [ "ppc64" ], @@ -2800,9 +3173,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.0.tgz", - "integrity": "sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", "cpu": [ "riscv64" ], @@ -2814,9 +3187,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.0.tgz", - "integrity": "sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", "cpu": [ "riscv64" ], @@ -2828,9 +3201,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.0.tgz", - "integrity": "sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", "cpu": [ "s390x" ], @@ -2842,7 +3215,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.0", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", "cpu": [ "x64" ], @@ -2854,7 +3229,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.0", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", "cpu": [ "x64" ], @@ -2866,9 +3243,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.0.tgz", - "integrity": "sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", "cpu": [ "x64" ], @@ -2880,9 +3257,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.0.tgz", - "integrity": "sha512-pESDkos/PDzYwtyzB5p/UoNU/8fJo68vcXM9ZW2V0kjYayj1KaaUfi1NmTUTUpMn4UhU4gTuK8gIaFO4UGuMbA==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", "cpu": [ "arm64" ], @@ -2894,9 +3271,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.0.tgz", - "integrity": "sha512-hj1wFStD7B1YBeYmvY+lWXZ7ey73YGPcViMShYikqKT1GtstIKQAtfUI6yrzPjAy/O7pO0VLXGmUVWXQMaYgTQ==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", "cpu": [ "arm64" ], @@ -2908,9 +3285,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.0.tgz", - "integrity": "sha512-SyaIPFoxmUPlNDq5EHkTbiKzmSEmq/gOYFI/3HHJ8iS/v1mbugVa7dXUzcJGQfoytp9DJFLhHH4U3/eTy2Bq4w==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", "cpu": [ "ia32" ], @@ -2922,9 +3299,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.0.tgz", - "integrity": "sha512-RdcryEfzZr+lAr5kRm2ucN9aVlCCa2QNq4hXelZxb8GG0NJSazq44Z3PCCc8wISRuCVnGs0lQJVX5Vp6fKA+IA==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", "cpu": [ "x64" ], @@ -2936,9 +3313,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.0.tgz", - "integrity": "sha512-PrsWNQ8BuE00O3Xsx3ALh2Df8fAj9+cvvX9AIA6o4KpATR98c9mud4XtDWVvsEuyia5U4tVSTKygawyJkjm60w==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", "cpu": [ "x64" ], @@ -2987,10 +3364,29 @@ "dev": true, "license": "(Unlicense OR Apache-2.0)" }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "5.2.2", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "4.2.3", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-base64": "^4.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@smithy/config-resolver": { "version": "4.4.14", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.14.tgz", - "integrity": "sha512-N55f8mPEccpzKetUagdvmAy8oohf0J5cuj9jLI1TaSceRlq0pJsIZepY3kmAXAhyxqXPV6hDerDQhqQPKWgAoQ==", "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.3.13", @@ -3006,8 +3402,6 @@ }, "node_modules/@smithy/core": { "version": "3.23.14", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.14.tgz", - "integrity": "sha512-vJ0IhpZxZAkFYOegMKSrxw7ujhhT2pass/1UEcZ4kfl5srTAqtPU5I7MdYQoreVas3204ykCiNhY1o7Xlz6Yyg==", "license": "Apache-2.0", "dependencies": { "@smithy/protocol-http": "^5.3.13", @@ -3027,8 +3421,6 @@ }, "node_modules/@smithy/credential-provider-imds": { "version": "4.2.13", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.13.tgz", - "integrity": "sha512-wboCPijzf6RJKLOvnjDAiBxGSmSnGXj35o5ZAWKDaHa/cvQ5U3ZJ13D4tMCE8JG4dxVAZFy/P0x/V9CwwdfULQ==", "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.3.13", @@ -3041,10 +3433,68 @@ "node": ">=18.0.0" } }, + "node_modules/@smithy/eventstream-codec": { + "version": "4.2.13", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.14.0", + "@smithy/util-hex-encoding": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "4.2.13", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.13", + "@smithy/types": "^4.14.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "4.3.13", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.14.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "4.2.13", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.13", + "@smithy/types": "^4.14.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "4.2.13", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-codec": "^4.2.13", + "@smithy/types": "^4.14.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@smithy/fetch-http-handler": { "version": "5.3.16", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.16.tgz", - "integrity": "sha512-nYDRUIvNd4mFmuXraRWt6w5UsZTNqtj4hXJA/iiOD4tuseIdLP9Lq38teH/SZTcIFCa2f+27o7hYpIsWktJKEQ==", "license": "Apache-2.0", "dependencies": { "@smithy/protocol-http": "^5.3.13", @@ -3057,11 +3507,24 @@ "node": ">=18.0.0" } }, + "node_modules/@smithy/hash-blob-browser": { + "version": "4.2.14", + "license": "Apache-2.0", + "dependencies": { + "@smithy/chunked-blob-reader": "^5.2.2", + "@smithy/chunked-blob-reader-native": "^4.2.3", + "@smithy/types": "^4.14.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@smithy/hash-node": { - "version": "4.2.12", + "version": "4.2.13", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.13.1", + "@smithy/types": "^4.14.0", "@smithy/util-buffer-from": "^4.2.2", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" @@ -3070,11 +3533,23 @@ "node": ">=18.0.0" } }, + "node_modules/@smithy/hash-stream-node": { + "version": "4.2.13", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.14.0", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@smithy/invalid-dependency": { - "version": "4.2.12", + "version": "4.2.13", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.13.1", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { @@ -3092,10 +3567,10 @@ } }, "node_modules/@smithy/md5-js": { - "version": "4.2.12", + "version": "4.2.13", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.13.1", + "@smithy/types": "^4.14.0", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" }, @@ -3104,11 +3579,11 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "4.2.12", + "version": "4.2.13", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", + "@smithy/protocol-http": "^5.3.13", + "@smithy/types": "^4.14.0", "tslib": "^2.6.2" }, "engines": { @@ -3117,8 +3592,6 @@ }, "node_modules/@smithy/middleware-endpoint": { "version": "4.4.29", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.29.tgz", - "integrity": "sha512-R9Q/58U+qBiSARGWbAbFLczECg/RmysRksX6Q8BaQEpt75I7LI6WGDZnjuC9GXSGKljEbA7N118LhGaMbfrTXw==", "license": "Apache-2.0", "dependencies": { "@smithy/core": "^3.23.14", @@ -3136,8 +3609,6 @@ }, "node_modules/@smithy/middleware-retry": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.5.0.tgz", - "integrity": "sha512-/NzISn4grj/BRFVua/xnQwF+7fakYZgimpw2dfmlPgcqecBMKxpB9g5mLYRrmBD5OrPoODokw4Vi1hrSR4zRyw==", "license": "Apache-2.0", "dependencies": { "@smithy/core": "^3.23.14", @@ -3157,8 +3628,6 @@ }, "node_modules/@smithy/middleware-serde": { "version": "4.2.17", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.17.tgz", - "integrity": "sha512-0T2mcaM6v9W1xku86Dk0bEW7aEseG6KenFkPK98XNw0ZhOqOiD1MrMsdnQw9QsL3/Oa85T53iSMlm0SZdSuIEQ==", "license": "Apache-2.0", "dependencies": { "@smithy/core": "^3.23.14", @@ -3172,8 +3641,6 @@ }, "node_modules/@smithy/middleware-stack": { "version": "4.2.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.13.tgz", - "integrity": "sha512-g72jN/sGDLyTanrCLH9fhg3oysO3f7tQa6eWWsMyn2BiYNCgjF24n4/I9wff/5XidFvjj9ilipAoQrurTUrLvw==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.14.0", @@ -3185,8 +3652,6 @@ }, "node_modules/@smithy/node-config-provider": { "version": "4.3.13", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.13.tgz", - "integrity": "sha512-iGxQ04DsKXLckbgnX4ipElrOTk+IHgTyu0q0WssZfYhDm9CQWHmu6cOeI5wmWRxpXbBDhIIfXMWz5tPEtcVqbw==", "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.2.13", @@ -3200,8 +3665,6 @@ }, "node_modules/@smithy/node-http-handler": { "version": "4.5.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.5.2.tgz", - "integrity": "sha512-/oD7u8M0oj2ZTFw7GkuuHWpIxtWdLlnyNkbrWcyVYhd5RJNDuczdkb0wfnQICyNFrVPlr8YHOhamjNy3zidhmA==", "license": "Apache-2.0", "dependencies": { "@smithy/protocol-http": "^5.3.13", @@ -3215,8 +3678,6 @@ }, "node_modules/@smithy/property-provider": { "version": "4.2.13", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.13.tgz", - "integrity": "sha512-bGzUCthxRmezuxkbu9wD33wWg9KX3hJpCXpQ93vVkPrHn9ZW6KNNdY5xAUWNuRCwQ+VyboFuWirG1lZhhkcyRQ==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.14.0", @@ -3228,8 +3689,6 @@ }, "node_modules/@smithy/protocol-http": { "version": "5.3.13", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.13.tgz", - "integrity": "sha512-+HsmuJUF4u8POo6s8/a2Yb/AQ5t/YgLovCuHF9oxbocqv+SZ6gd8lC2duBFiCA/vFHoHQhoq7QjqJqZC6xOxxg==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.14.0", @@ -3241,8 +3700,6 @@ }, "node_modules/@smithy/querystring-builder": { "version": "4.2.13", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.13.tgz", - "integrity": "sha512-tG4aOYFCZdPMjbgfhnIQ322H//ojujldp1SrHPHpBSb3NqgUp3dwiUGRJzie87hS1DYwWGqDuPaowoDF+rYCbQ==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.14.0", @@ -3255,8 +3712,6 @@ }, "node_modules/@smithy/querystring-parser": { "version": "4.2.13", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.13.tgz", - "integrity": "sha512-hqW3Q4P+CDzUyQ87GrboGMeD7XYNMOF+CuTwu936UQRB/zeYn3jys8C3w+wMkDfY7CyyyVwZQ5cNFoG0x1pYmA==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.14.0", @@ -3268,8 +3723,6 @@ }, "node_modules/@smithy/service-error-classification": { "version": "4.2.13", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.13.tgz", - "integrity": "sha512-a0s8XZMfOC/qpqq7RCPvJlk93rWFrElH6O++8WJKz0FqnA4Y7fkNi/0mnGgSH1C4x6MFsuBA8VKu4zxFrMe5Vw==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.14.0" @@ -3280,8 +3733,6 @@ }, "node_modules/@smithy/shared-ini-file-loader": { "version": "4.4.8", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.8.tgz", - "integrity": "sha512-VZCZx2bZasxdqxVgEAhREvDSlkatTPnkdWy1+Kiy8w7kYPBosW0V5IeDwzDUMvWBt56zpK658rx1cOBFOYaPaw==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.14.0", @@ -3292,14 +3743,14 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.3.12", + "version": "5.3.13", "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^4.2.2", - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", + "@smithy/protocol-http": "^5.3.13", + "@smithy/types": "^4.14.0", "@smithy/util-hex-encoding": "^4.2.2", - "@smithy/util-middleware": "^4.2.12", + "@smithy/util-middleware": "^4.2.13", "@smithy/util-uri-escape": "^4.2.2", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" @@ -3310,8 +3761,6 @@ }, "node_modules/@smithy/smithy-client": { "version": "4.12.9", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.12.9.tgz", - "integrity": "sha512-ovaLEcTU5olSeHcRXcxV6viaKtpkHZumn6Ps0yn7dRf2rRSfy794vpjOtrWDO0d1auDSvAqxO+lyhERSXQ03EQ==", "license": "Apache-2.0", "dependencies": { "@smithy/core": "^3.23.14", @@ -3328,8 +3777,6 @@ }, "node_modules/@smithy/types": { "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.0.tgz", - "integrity": "sha512-OWgntFLW88kx2qvf/c/67Vno1yuXm/f9M7QFAtVkkO29IJXGBIg0ycEaBTH0kvCtwmvZxRujrgP5a86RvsXJAQ==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -3340,8 +3787,6 @@ }, "node_modules/@smithy/url-parser": { "version": "4.2.13", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.13.tgz", - "integrity": "sha512-2G03yoboIRZlZze2+PT4GZEjgwQsJjUgn6iTsvxA02bVceHR6vp4Cuk7TUnPFWKF+ffNUk3kj4COwkENS2K3vw==", "license": "Apache-2.0", "dependencies": { "@smithy/querystring-parser": "^4.2.13", @@ -3407,8 +3852,6 @@ }, "node_modules/@smithy/util-defaults-mode-browser": { "version": "4.3.45", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.45.tgz", - "integrity": "sha512-ag9sWc6/nWZAuK3Wm9KlFJUnRkXLrXn33RFjIAmCTFThqLHY+7wCst10BGq56FxslsDrjhSie46c8OULS+BiIw==", "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.2.13", @@ -3422,8 +3865,6 @@ }, "node_modules/@smithy/util-defaults-mode-node": { "version": "4.2.49", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.49.tgz", - "integrity": "sha512-jlN6vHwE8gY5AfiFBavtD3QtCX2f7lM3BKkz7nFKSNfFR5nXLXLg6sqXTJEEyDwtxbztIDBQCfjsGVXlIru2lQ==", "license": "Apache-2.0", "dependencies": { "@smithy/config-resolver": "^4.4.14", @@ -3440,8 +3881,6 @@ }, "node_modules/@smithy/util-endpoints": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.3.4.tgz", - "integrity": "sha512-BKoR/ubPp9KNKFxPpg1J28N1+bgu8NGAtJblBP7yHy8yQPBWhIAv9+l92SlQLpolGm71CVO+btB60gTgzT0wog==", "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.3.13", @@ -3464,8 +3903,6 @@ }, "node_modules/@smithy/util-middleware": { "version": "4.2.13", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.13.tgz", - "integrity": "sha512-GTooyrlmRTqvUen4eK7/K1p6kryF7bnDfq6XsAbIsf2mo51B/utaH+XThY6dKgNCWzMAaH/+OLmqaBuLhLWRow==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.14.0", @@ -3477,8 +3914,6 @@ }, "node_modules/@smithy/util-retry": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.3.0.tgz", - "integrity": "sha512-tSOPQNT/4KfbvqeMovWC3g23KSYy8czHd3tlN+tOYVNIDLSfxIsrPJihYi5TpNcoV789KWtgChUVedh2y6dDPg==", "license": "Apache-2.0", "dependencies": { "@smithy/service-error-classification": "^4.2.13", @@ -3491,8 +3926,6 @@ }, "node_modules/@smithy/util-stream": { "version": "4.5.22", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.22.tgz", - "integrity": "sha512-3H8iq/0BfQjUs2/4fbHZ9aG9yNzcuZs24LPkcX1Q7Z+qpqaGM8+qbGmE8zo9m2nCRgamyvS98cHdcWvR6YUsew==", "license": "Apache-2.0", "dependencies": { "@smithy/fetch-http-handler": "^5.3.16", @@ -3531,8 +3964,6 @@ }, "node_modules/@smithy/util-waiter": { "version": "4.2.15", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.15.tgz", - "integrity": "sha512-oUt9o7n8hBv3BL56sLSneL0XeigZSuem0Hr78JaoK33D9oKieyCvVP8eTSe3j7g2mm/S1DvzxKieG7JEWNJUNg==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.14.0", @@ -3579,6 +4010,8 @@ }, "node_modules/@types/chai": { "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { @@ -3588,6 +4021,8 @@ }, "node_modules/@types/deep-eql": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, @@ -3640,20 +4075,18 @@ "optional": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.0.tgz", - "integrity": "sha512-RLkVSiNuUP1C2ROIWfqX+YcUfLaSnxGE/8M+Y57lopVwg9VTYYfhuz15Yf1IzCKgZj6/rIbYTmJCUSqr76r0Wg==", + "version": "8.57.2", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.58.0", - "@typescript-eslint/type-utils": "8.58.0", - "@typescript-eslint/utils": "8.58.0", - "@typescript-eslint/visitor-keys": "8.58.0", + "@typescript-eslint/scope-manager": "8.57.2", + "@typescript-eslint/type-utils": "8.57.2", + "@typescript-eslint/utils": "8.57.2", + "@typescript-eslint/visitor-keys": "8.57.2", "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3663,22 +4096,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.58.0", + "@typescript-eslint/parser": "^8.57.2", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.0.tgz", - "integrity": "sha512-rLoGZIf9afaRBYsPUMtvkDWykwXwUPL60HebR4JgTI8mxfFe2cQTu3AGitANp4b9B2QlVru6WzjgB2IzJKiCSA==", + "version": "8.57.2", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.58.0", - "@typescript-eslint/types": "8.58.0", - "@typescript-eslint/typescript-estree": "8.58.0", - "@typescript-eslint/visitor-keys": "8.58.0", + "@typescript-eslint/scope-manager": "8.57.2", + "@typescript-eslint/types": "8.57.2", + "@typescript-eslint/typescript-estree": "8.57.2", + "@typescript-eslint/visitor-keys": "8.57.2", "debug": "^4.4.3" }, "engines": { @@ -3690,18 +4121,16 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.0.tgz", - "integrity": "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg==", + "version": "8.57.2", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.58.0", - "@typescript-eslint/types": "^8.58.0", + "@typescript-eslint/tsconfig-utils": "^8.57.2", + "@typescript-eslint/types": "^8.57.2", "debug": "^4.4.3" }, "engines": { @@ -3712,18 +4141,16 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.0.tgz", - "integrity": "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ==", + "version": "8.57.2", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.0", - "@typescript-eslint/visitor-keys": "8.58.0" + "@typescript-eslint/types": "8.57.2", + "@typescript-eslint/visitor-keys": "8.57.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3734,9 +4161,7 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.0.tgz", - "integrity": "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A==", + "version": "8.57.2", "dev": true, "license": "MIT", "engines": { @@ -3747,21 +4172,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.0.tgz", - "integrity": "sha512-aGsCQImkDIqMyx1u4PrVlbi/krmDsQUs4zAcCV6M7yPcPev+RqVlndsJy9kJ8TLihW9TZ0kbDAzctpLn5o+lOg==", + "version": "8.57.2", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.0", - "@typescript-eslint/typescript-estree": "8.58.0", - "@typescript-eslint/utils": "8.58.0", + "@typescript-eslint/types": "8.57.2", + "@typescript-eslint/typescript-estree": "8.57.2", + "@typescript-eslint/utils": "8.57.2", "debug": "^4.4.3", - "ts-api-utils": "^2.5.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3772,13 +4195,11 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.0.tgz", - "integrity": "sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==", + "version": "8.57.2", "dev": true, "license": "MIT", "engines": { @@ -3790,21 +4211,19 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.0.tgz", - "integrity": "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA==", + "version": "8.57.2", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.58.0", - "@typescript-eslint/tsconfig-utils": "8.58.0", - "@typescript-eslint/types": "8.58.0", - "@typescript-eslint/visitor-keys": "8.58.0", + "@typescript-eslint/project-service": "8.57.2", + "@typescript-eslint/tsconfig-utils": "8.57.2", + "@typescript-eslint/types": "8.57.2", + "@typescript-eslint/visitor-keys": "8.57.2", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3814,13 +4233,11 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", "engines": { @@ -3829,8 +4246,6 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3841,13 +4256,11 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "version": "10.2.4", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^5.0.5" + "brace-expansion": "^5.0.2" }, "engines": { "node": "18 || 20 || >=22" @@ -3857,16 +4270,14 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.0.tgz", - "integrity": "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA==", + "version": "8.57.2", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.58.0", - "@typescript-eslint/types": "8.58.0", - "@typescript-eslint/typescript-estree": "8.58.0" + "@typescript-eslint/scope-manager": "8.57.2", + "@typescript-eslint/types": "8.57.2", + "@typescript-eslint/typescript-estree": "8.57.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3877,17 +4288,15 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.0.tgz", - "integrity": "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ==", + "version": "8.57.2", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/types": "8.57.2", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3900,8 +4309,6 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3913,6 +4320,8 @@ }, "node_modules/@vitest/coverage-v8": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz", + "integrity": "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3945,6 +4354,8 @@ }, "node_modules/@vitest/coverage-v8/node_modules/@bcoe/v8-coverage": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", "dev": true, "license": "MIT", "engines": { @@ -3953,6 +4364,8 @@ }, "node_modules/@vitest/coverage-v8/node_modules/balanced-match": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", "engines": { @@ -3961,7 +4374,9 @@ }, "node_modules/@vitest/coverage-v8/node_modules/brace-expansion": { "version": "5.0.5", - "dev": true, + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -3971,11 +4386,13 @@ } }, "node_modules/@vitest/coverage-v8/node_modules/minimatch": { - "version": "10.2.4", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -3986,6 +4403,8 @@ }, "node_modules/@vitest/coverage-v8/node_modules/test-exclude": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.2.tgz", + "integrity": "sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==", "dev": true, "license": "ISC", "dependencies": { @@ -3999,6 +4418,8 @@ }, "node_modules/@vitest/expect": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", "dependencies": { @@ -4012,33 +4433,10 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/mocker": { - "version": "3.2.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "3.2.4", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, "node_modules/@vitest/pretty-format": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { @@ -4050,6 +4448,8 @@ }, "node_modules/@vitest/runner": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4063,6 +4463,8 @@ }, "node_modules/@vitest/snapshot": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4076,6 +4478,8 @@ }, "node_modules/@vitest/spy": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, "license": "MIT", "dependencies": { @@ -4087,6 +4491,8 @@ }, "node_modules/@vitest/utils": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, "license": "MIT", "dependencies": { @@ -4224,87 +4630,494 @@ "version": "10.0.0", "license": "MIT", "engines": { - "node": ">=14" + "node": ">=14" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/apim-spec": { + "resolved": "packages/specification", + "link": true + }, + "node_modules/arg": { + "version": "4.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.12.tgz", + "integrity": "sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-cdk": { + "version": "2.1118.0", + "license": "Apache-2.0", + "bin": { + "cdk": "bin/cdk" + }, + "engines": { + "node": ">= 18.0.0" + } + }, + "node_modules/aws-cdk-lib": { + "version": "2.248.0", + "bundleDependencies": [ + "@balena/dockerignore", + "@aws-cdk/cloud-assembly-api", + "case", + "fs-extra", + "ignore", + "jsonschema", + "minimatch", + "punycode", + "semver", + "table", + "yaml", + "mime-types" + ], + "license": "Apache-2.0", + "dependencies": { + "@aws-cdk/asset-awscli-v1": "2.2.273", + "@aws-cdk/asset-node-proxy-agent-v6": "^2.1.1", + "@aws-cdk/cloud-assembly-api": "^2.2.0", + "@aws-cdk/cloud-assembly-schema": "^53.0.0", + "@balena/dockerignore": "^1.0.2", + "case": "1.6.3", + "fs-extra": "^11.3.3", + "ignore": "^5.3.2", + "jsonschema": "^1.5.0", + "mime-types": "^2.1.35", + "minimatch": "^10.2.3", + "punycode": "^2.3.1", + "semver": "^7.7.4", + "table": "^6.9.0", + "yaml": "1.10.3" + }, + "engines": { + "node": ">= 20.0.0" + }, + "peerDependencies": { + "constructs": "^10.5.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/@aws-cdk/cloud-assembly-api": { + "version": "2.2.0", + "bundleDependencies": [ + "jsonschema", + "semver" + ], + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "jsonschema": "~1.4.1", + "semver": "^7.7.4" + }, + "engines": { + "node": ">= 18.0.0" + }, + "peerDependencies": { + "@aws-cdk/cloud-assembly-schema": ">=53.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/@aws-cdk/cloud-assembly-api/node_modules/jsonschema": { + "version": "1.4.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/aws-cdk-lib/node_modules/@aws-cdk/cloud-assembly-api/node_modules/semver": { + "version": "7.7.4", + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": { + "version": "1.0.2", + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/aws-cdk-lib/node_modules/ajv": { + "version": "8.18.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/aws-cdk-lib/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aws-cdk-lib/node_modules/astral-regex": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/balanced-match": { + "version": "4.0.4", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/aws-cdk-lib/node_modules/brace-expansion": { + "version": "5.0.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/aws-cdk-lib/node_modules/case": { + "version": "1.6.3", + "inBundle": true, + "license": "(MIT OR GPL-3.0-or-later)", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/color-convert": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/color-name": { + "version": "1.1.4", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/emoji-regex": { + "version": "8.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/fast-deep-equal": { + "version": "3.1.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/fast-uri": { + "version": "3.1.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/aws-cdk-lib/node_modules/fs-extra": { + "version": "11.3.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/aws-cdk-lib/node_modules/graceful-fs": { + "version": "4.2.11", + "inBundle": true, + "license": "ISC" + }, + "node_modules/aws-cdk-lib/node_modules/ignore": { + "version": "5.3.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/aws-cdk-lib/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/json-schema-traverse": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/jsonfile": { + "version": "6.2.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/jsonschema": { + "version": "1.5.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/aws-cdk-lib/node_modules/lodash.truncate": { + "version": "4.4.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/mime-db": { + "version": "1.52.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/mime-types": { + "version": "2.1.35", + "inBundle": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/minimatch": { + "version": "10.2.5", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/aws-cdk-lib/node_modules/punycode": { + "version": "2.3.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/aws-cdk-lib/node_modules/require-from-string": { + "version": "2.0.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/semver": { + "version": "7.7.4", + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "dev": true, + "node_modules/aws-cdk-lib/node_modules/slice-ansi": { + "version": "4.0.0", + "inBundle": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/aws-cdk-lib/node_modules/string-width": { + "version": "4.2.3", + "inBundle": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/apim-spec": { - "resolved": "packages/specification", - "link": true - }, - "node_modules/arg": { - "version": "4.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "1.0.10", + "node_modules/aws-cdk-lib/node_modules/strip-ansi": { + "version": "6.0.1", + "inBundle": true, "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/assertion-error": { - "version": "2.0.1", - "dev": true, - "license": "MIT", + "node_modules/aws-cdk-lib/node_modules/table": { + "version": "6.9.0", + "inBundle": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=12" + "node": ">=10.0.0" } }, - "node_modules/ast-v8-to-istanbul": { - "version": "0.3.12", - "dev": true, + "node_modules/aws-cdk-lib/node_modules/universalify": { + "version": "2.0.1", + "inBundle": true, "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.31", - "estree-walker": "^3.0.3", - "js-tokens": "^10.0.0" + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { - "version": "10.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "license": "MIT" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, + "node_modules/aws-cdk-lib/node_modules/yaml": { + "version": "1.10.3", + "inBundle": true, + "license": "ISC", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 6" } }, "node_modules/aws-lambda": { @@ -4321,7 +5134,7 @@ } }, "node_modules/aws-sdk": { - "version": "2.1693.0", + "version": "2.1692.0", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -4407,8 +5220,6 @@ }, "node_modules/better-ajv-errors": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/better-ajv-errors/-/better-ajv-errors-1.2.0.tgz", - "integrity": "sha512-UW+IsFycygIo7bclP9h5ugkNH8EjCSgqyFB/yQ4Hqqa1OEYDtb0uFIkYE0b6+CjkgJYVM5UKI/pJPxjYe9EZlA==", "license": "Apache-2.0", "dependencies": { "@babel/code-frame": "^7.16.0", @@ -4429,7 +5240,7 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "2.0.3", + "version": "2.0.2", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -4446,6 +5257,8 @@ }, "node_modules/cac": { "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, "license": "MIT", "engines": { @@ -4525,8 +5338,22 @@ "upper-case-first": "^2.0.2" } }, + "node_modules/cdk": { + "resolved": "packages/cdk", + "link": true + }, + "node_modules/cdk-nag": { + "version": "2.37.55", + "license": "Apache-2.0", + "peerDependencies": { + "aws-cdk-lib": "^2.176.0", + "constructs": "^10.0.5" + } + }, "node_modules/chai": { "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", "dev": true, "license": "MIT", "dependencies": { @@ -4574,6 +5401,8 @@ }, "node_modules/check-error": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", "dev": true, "license": "MIT", "engines": { @@ -4696,6 +5525,10 @@ "upper-case": "^2.0.2" } }, + "node_modules/constructs": { + "version": "10.6.0", + "license": "Apache-2.0" + }, "node_modules/cookie": { "version": "0.7.2", "license": "MIT", @@ -4703,16 +5536,6 @@ "node": ">= 0.6" } }, - "node_modules/core-js": { - "version": "3.49.0", - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/cpsuLambda": { "resolved": "packages/cpsuLambda", "link": true @@ -4775,6 +5598,8 @@ }, "node_modules/deep-eql": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, "license": "MIT", "engines": { @@ -4809,7 +5634,7 @@ } }, "node_modules/diff": { - "version": "4.0.4", + "version": "4.0.2", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -4821,7 +5646,7 @@ "license": "MIT" }, "node_modules/dompurify": { - "version": "3.3.3", + "version": "3.2.7", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -4883,6 +5708,8 @@ }, "node_modules/es-module-lexer": { "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, @@ -5118,14 +5945,14 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "5.0.5", + "version": "5.0.2", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { @@ -5231,6 +6058,8 @@ }, "node_modules/estree-walker": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { @@ -5265,6 +6094,8 @@ }, "node_modules/expect-type": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5342,22 +6173,6 @@ "fxparser": "src/cli/cli.js" } }, - "node_modules/fdir": { - "version": "6.5.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "dev": true, @@ -5488,7 +6303,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5546,6 +6360,16 @@ "node": ">= 0.4" } }, + "node_modules/get-tsconfig": { + "version": "4.13.7", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "10.5.0", "dev": true, @@ -5593,6 +6417,8 @@ }, "node_modules/globrex": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "dev": true, "license": "MIT" }, @@ -6009,8 +6835,6 @@ }, "node_modules/jsonpath-rfc9535": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsonpath-rfc9535/-/jsonpath-rfc9535-1.3.0.tgz", - "integrity": "sha512-3jFHya7oZ45aDxIIdx+/zQARahHXxFSMWBkcBUldfXpLS9VCXDJyTKt35kQfEXLqh0K3Ixw/9xFnvcDStaxh7Q==", "license": "Apache-2.0", "engines": { "node": ">=20" @@ -6018,8 +6842,6 @@ }, "node_modules/jsonpointer": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6087,6 +6909,8 @@ }, "node_modules/loupe": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", "dev": true, "license": "MIT" }, @@ -6103,6 +6927,8 @@ }, "node_modules/magic-string": { "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6111,6 +6937,8 @@ }, "node_modules/magicast": { "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6196,8 +7024,6 @@ }, "node_modules/mnemonist": { "version": "0.38.3", - "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", - "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", "license": "MIT", "dependencies": { "obliterator": "^1.6.1" @@ -6412,13 +7238,6 @@ "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/oas-linter/node_modules/yaml": { - "version": "1.10.3", - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, "node_modules/oas-resolver": { "version": "2.5.6", "license": "BSD-3-Clause", @@ -6436,13 +7255,6 @@ "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/oas-resolver/node_modules/yaml": { - "version": "1.10.3", - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, "node_modules/oas-schema-walker": { "version": "1.1.5", "license": "BSD-3-Clause", @@ -6467,13 +7279,6 @@ "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/oas-validator/node_modules/yaml": { - "version": "1.10.3", - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, "node_modules/object-assign": { "version": "4.1.1", "license": "MIT", @@ -6483,8 +7288,6 @@ }, "node_modules/obliterator": { "version": "1.6.1", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", - "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", "license": "MIT" }, "node_modules/openapi-sampler": { @@ -6514,8 +7317,6 @@ }, "node_modules/outdent": { "version": "0.8.0", - "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz", - "integrity": "sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==", "license": "MIT" }, "node_modules/outvariant": { @@ -6633,7 +7434,7 @@ "license": "ISC" }, "node_modules/path-to-regexp": { - "version": "8.4.1", + "version": "8.3.0", "dev": true, "license": "MIT", "funding": { @@ -6643,11 +7444,15 @@ }, "node_modules/pathe": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/pathval": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, "license": "MIT", "engines": { @@ -6662,16 +7467,6 @@ "version": "1.1.1", "license": "ISC" }, - "node_modules/picomatch": { - "version": "4.0.4", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/pluralize": { "version": "8.0.0", "license": "MIT", @@ -6819,8 +7614,6 @@ }, "node_modules/proxy-from-env": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", - "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", "license": "MIT", "engines": { "node": ">=10" @@ -7027,6 +7820,13 @@ "node": ">=0.10.0" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/ret": { "version": "0.1.15", "license": "MIT", @@ -7035,7 +7835,9 @@ } }, "node_modules/rollup": { - "version": "4.60.0", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", "dev": true, "license": "MIT", "dependencies": { @@ -7049,31 +7851,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.0", - "@rollup/rollup-android-arm64": "4.60.0", - "@rollup/rollup-darwin-arm64": "4.60.0", - "@rollup/rollup-darwin-x64": "4.60.0", - "@rollup/rollup-freebsd-arm64": "4.60.0", - "@rollup/rollup-freebsd-x64": "4.60.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.0", - "@rollup/rollup-linux-arm-musleabihf": "4.60.0", - "@rollup/rollup-linux-arm64-gnu": "4.60.0", - "@rollup/rollup-linux-arm64-musl": "4.60.0", - "@rollup/rollup-linux-loong64-gnu": "4.60.0", - "@rollup/rollup-linux-loong64-musl": "4.60.0", - "@rollup/rollup-linux-ppc64-gnu": "4.60.0", - "@rollup/rollup-linux-ppc64-musl": "4.60.0", - "@rollup/rollup-linux-riscv64-gnu": "4.60.0", - "@rollup/rollup-linux-riscv64-musl": "4.60.0", - "@rollup/rollup-linux-s390x-gnu": "4.60.0", - "@rollup/rollup-linux-x64-gnu": "4.60.0", - "@rollup/rollup-linux-x64-musl": "4.60.0", - "@rollup/rollup-openbsd-x64": "4.60.0", - "@rollup/rollup-openharmony-arm64": "4.60.0", - "@rollup/rollup-win32-arm64-msvc": "4.60.0", - "@rollup/rollup-win32-ia32-msvc": "4.60.0", - "@rollup/rollup-win32-x64-gnu": "4.60.0", - "@rollup/rollup-win32-x64-msvc": "4.60.0", + "@rollup/rollup-android-arm-eabi": "4.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", "fsevents": "~2.3.2" } }, @@ -7216,6 +8018,8 @@ }, "node_modules/siginfo": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, @@ -7293,7 +8097,7 @@ } }, "node_modules/sinon/node_modules/diff": { - "version": "5.2.2", + "version": "5.2.0", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -7345,6 +8149,8 @@ }, "node_modules/stackback": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, @@ -7354,6 +8160,8 @@ }, "node_modules/std-env": { "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, "license": "MIT" }, @@ -7461,6 +8269,8 @@ }, "node_modules/strip-literal": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", "dev": true, "license": "MIT", "dependencies": { @@ -7472,6 +8282,8 @@ }, "node_modules/strip-literal/node_modules/js-tokens": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", "dev": true, "license": "MIT" }, @@ -7555,13 +8367,6 @@ "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/swagger2openapi/node_modules/yaml": { - "version": "1.10.3", - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, "node_modules/synckit": { "version": "0.11.12", "dev": true, @@ -7578,11 +8383,15 @@ }, "node_modules/tinybench": { "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, "license": "MIT" }, "node_modules/tinyexec": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", "dev": true, "license": "MIT" }, @@ -7601,8 +8410,37 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinypool": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "dev": true, "license": "MIT", "engines": { @@ -7611,6 +8449,8 @@ }, "node_modules/tinyrainbow": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, "license": "MIT", "engines": { @@ -7619,6 +8459,8 @@ }, "node_modules/tinyspy": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", "dev": true, "license": "MIT", "engines": { @@ -7634,9 +8476,7 @@ "license": "MIT" }, "node_modules/ts-api-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", - "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "version": "2.4.0", "dev": true, "license": "MIT", "engines": { @@ -7697,6 +8537,8 @@ }, "node_modules/tsconfck": { "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", "dev": true, "license": "MIT", "bin": { @@ -7718,6 +8560,23 @@ "version": "2.8.1", "license": "0BSD" }, + "node_modules/tsx": { + "version": "4.21.0", + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/type-check": { "version": "0.4.0", "dev": true, @@ -7750,16 +8609,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.58.0.tgz", - "integrity": "sha512-e2TQzKfaI85fO+F3QywtX+tCTsu/D3WW5LVU6nz8hTFKFZ8yBJ6mSYRpXqdR3mFjPWmO0eWsTa5f+UpAOe/FMA==", + "version": "8.57.2", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.58.0", - "@typescript-eslint/parser": "8.58.0", - "@typescript-eslint/typescript-estree": "8.58.0", - "@typescript-eslint/utils": "8.58.0" + "@typescript-eslint/eslint-plugin": "8.57.2", + "@typescript-eslint/parser": "8.57.2", + "@typescript-eslint/typescript-estree": "8.57.2", + "@typescript-eslint/utils": "8.57.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7770,7 +8627,7 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/uglify-js": { @@ -7872,16 +8729,99 @@ "node_modules/uuid": { "version": "8.0.0", "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-node/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite-node/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", + "node_modules/vite-node/node_modules/postcss": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", + "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", "dev": true, - "license": "MIT" + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } }, - "node_modules/vite": { + "node_modules/vite-node/node_modules/vite": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", @@ -7956,29 +8896,10 @@ } } }, - "node_modules/vite-node": { - "version": "3.2.4", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.4.1", - "es-module-lexer": "^1.7.0", - "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, "node_modules/vite-tsconfig-paths": { "version": "5.1.4", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", + "integrity": "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==", "dev": true, "license": "MIT", "dependencies": { @@ -7995,35 +8916,10 @@ } } }, - "node_modules/vite/node_modules/postcss": { - "version": "8.5.8", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, "node_modules/vitest": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", "dependencies": { @@ -8093,6 +8989,168 @@ } } }, + "node_modules/vitest/node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest/node_modules/postcss": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", + "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/vitest/node_modules/vite": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", + "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, "node_modules/watchpack": { "version": "2.4.4", "license": "MIT", @@ -8151,6 +9209,8 @@ }, "node_modules/why-is-node-running": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "license": "MIT", "dependencies": { @@ -8302,17 +9362,10 @@ } }, "node_modules/yaml": { - "version": "2.8.3", - "dev": true, + "version": "1.10.2", "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" + "node": ">= 6" } }, "node_modules/yaml-ast-parser": { @@ -8408,6 +9461,17 @@ "@psu-common/testing": "^1.0.0" } }, + "packages/cdk": { + "version": "0.1.0", + "dependencies": { + "@nhsdigital/eps-cdk-constructs": "^1.6.1", + "aws-cdk": "^2.1114.1", + "aws-cdk-lib": "^2.245.0", + "cdk-nag": "^2.37.55", + "constructs": "^10.6.0", + "tsx": "^4.21.0" + } + }, "packages/checkPrescriptionStatusUpdates": { "version": "1.0.0", "license": "MIT", @@ -8603,6 +9667,22 @@ "npm": "11.6.x" } }, + "packages/specification/node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "packages/statusLambda": { "version": "1.0.0", "license": "MIT", diff --git a/package.json b/package.json index f666d31f7f..a3fe5c2231 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "author": "NHS Digital", "license": "MIT", "workspaces": [ + "packages/cdk", "packages/gsul", "packages/nhsd-psu-sandbox", "packages/specification", diff --git a/packages/cdk/bin/PsuStatelessApp.ts b/packages/cdk/bin/PsuStatelessApp.ts new file mode 100644 index 0000000000..7116cc73c0 --- /dev/null +++ b/packages/cdk/bin/PsuStatelessApp.ts @@ -0,0 +1,39 @@ +import { + calculateVersionedStackName, + createApp, + getBooleanConfigFromEnvVar, + getConfigFromEnvVar, + getNumberConfigFromEnvVar +} from "@nhsdigital/eps-cdk-constructs" +import {PsuStatelessStack} from "../stacks/PsuStatelessStack" + +async function main() { + const {app, props} = createApp({ + productName: "Prescription Status Update API", + appName: "PsuStatelessApp", + repoName: "eps-prescription-status-update-api", + driftDetectionGroup: "psu-api" + }) + + new PsuStatelessStack(app, "PsuStatelessStack", { + ...props, + stackName: calculateVersionedStackName(getConfigFromEnvVar("stackName"), props), + samStackName: getConfigFromEnvVar("samStackName"), // TODO: REMOVE THE NEED FOR THIS + logRetentionInDays: getNumberConfigFromEnvVar("logRetentionInDays"), + logLevel: getConfigFromEnvVar("logLevel"), + environment: getConfigFromEnvVar("environment"), + mutualTlsTrustStoreKey: props.isPullRequest ? undefined : getConfigFromEnvVar("trustStoreFile"), + csocApiGatewayDestination: "arn:aws:logs:eu-west-2:693466633220:destination:api_gateway_log_destination", + forwardCsocLogs: getBooleanConfigFromEnvVar("forwardCsocLogs"), + deployCheckPrescriptionStatusUpdate: getBooleanConfigFromEnvVar("deployCheckPrescriptionStatusUpdate"), + exposeGetStatusUpdates: getBooleanConfigFromEnvVar("exposeGetStatusUpdates"), + enablePostDatedNotifications: getConfigFromEnvVar("enablePostDatedNotifications", undefined, "false"), + requireApplicationName: getConfigFromEnvVar("requireApplicationName", undefined, "false"), + enableBackup: getBooleanConfigFromEnvVar("enableBackup", undefined, "false") + }) +} + +main().catch((error) => { + console.error(error) + process.exit(1) +}) diff --git a/packages/cdk/nagSuppressions.ts b/packages/cdk/nagSuppressions.ts new file mode 100644 index 0000000000..d03ec56507 --- /dev/null +++ b/packages/cdk/nagSuppressions.ts @@ -0,0 +1,80 @@ +/* eslint-disable max-len */ +import {Stack} from "aws-cdk-lib" +import {safeAddNagSuppression, safeAddNagSuppressionGroup} from "@nhsdigital/eps-cdk-constructs" + +export const nagSuppressions = (stack: Stack) => { + // State machine log policies require wildcard for log streams and log delivery actions + safeAddNagSuppressionGroup( + stack, + [ + "/PsuStatelessStack/StateMachines/UpdatePrescriptionStatusStateMachine/StateMachinePutLogsManagedPolicy/Resource", + "/PsuStatelessStack/StateMachines/Format1UpdatePrescriptionsStatusStateMachine/StateMachinePutLogsManagedPolicy/Resource" + ], + [ + { + id: "AwsSolutions-IAM5", + reason: "Wildcard on log-stream is required to write to any log stream under the log group. Wildcard on Resource::* is required for log delivery management actions (DescribeLogGroups, ListLogDeliveries, etc.) which do not support resource-level permissions." + } + ] + ) + + // API Gateway does not use request validation — validation is handled by service logic + safeAddNagSuppression( + stack, + "/PsuStatelessStack/Apis/RestApiGateway/ApiGateway/Resource", + [ + { + id: "AwsSolutions-APIG2", + reason: "Request validation is handled by the backend service logic and FHIR validation state machine, not at the API Gateway level." + } + ] + ) + + // API Gateway CloudWatch role uses AWS managed policy + safeAddNagSuppression( + stack, + "/PsuStatelessStack/Apis/RestApiGateway/ApiGateway/CloudWatchRole/Resource", + [ + { + id: "AwsSolutions-IAM4", + reason: "AWS managed policy AmazonAPIGatewayPushToCloudWatchLogs is the standard approach for API Gateway logging and is maintained by AWS.", + appliesTo: ["Policy::arn::iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"] + } + ] + ) + + // API Gateway stage is not associated with WAFv2 — WAF is managed externally via Apigee + safeAddNagSuppression( + stack, + "/PsuStatelessStack/Apis/RestApiGateway/ApiGateway/DeploymentStage.prod/Resource", + [ + { + id: "AwsSolutions-APIG3", + reason: "WAF is managed externally via the Apigee proxy layer, not at the API Gateway level." + } + ] + ) + + // API methods do not use authorization — mTLS and Apigee handle auth externally + safeAddNagSuppressionGroup( + stack, + [ + "/PsuStatelessStack/Apis/RestApiGateway/ApiGateway/Default/POST/Resource", + "/PsuStatelessStack/Apis/RestApiGateway/ApiGateway/Default/format-1/POST/Resource", + "/PsuStatelessStack/Apis/RestApiGateway/ApiGateway/Default/notification-delivery-status-callback/POST/Resource", + "/PsuStatelessStack/Apis/RestApiGateway/ApiGateway/Default/_status/GET/Resource", + "/PsuStatelessStack/Apis/RestApiGateway/ApiGateway/Default/metadata/GET/Resource", + "/PsuStatelessStack/Apis/RestApiGateway/ApiGateway/Default/checkprescriptionstatusupdates/GET/Resource" + ], + [ + { + id: "AwsSolutions-APIG4", + reason: "Authorization is handled externally via mutual TLS and the Apigee API gateway proxy. API Gateway methods do not require an additional authorizer." + }, + { + id: "AwsSolutions-COG4", + reason: "This API does not use Cognito for authentication. Auth is handled via mutual TLS and the Apigee API gateway proxy." + } + ] + ) +} diff --git a/packages/cdk/package.json b/packages/cdk/package.json new file mode 100644 index 0000000000..c6988a51c4 --- /dev/null +++ b/packages/cdk/package.json @@ -0,0 +1,20 @@ +{ + "name": "cdk", + "version": "0.1.0", + "scripts": { + "cdk-synth": "cdk synth --output ../../cdk.out --quiet --app \"npm run tsx -- bin/${CDK_APP_NAME}.ts\"", + "cdk-diff": "cdk diff --app \"npm run tsx -- bin/${CDK_APP_NAME}.ts\"", + "cdk-deploy": "cdk deploy --app \"npm run tsx -- bin/${CDK_APP_NAME}.ts\" --all --ci true --require-approval ${REQUIRE_APPROVAL}", + "cdk-watch": "cdk deploy --app \"npm run tsx -- bin/${CDK_APP_NAME}.ts\" --watch --all --ci true --require-approval ${REQUIRE_APPROVAL}", + "lint": "eslint --max-warnings 0 --fix --config ../../eslint.config.mjs .", + "tsx": "tsx" + }, + "dependencies": { + "@nhsdigital/eps-cdk-constructs": "^1.6.1", + "aws-cdk": "^2.1114.1", + "aws-cdk-lib": "^2.245.0", + "cdk-nag": "^2.37.55", + "constructs": "^10.6.0", + "tsx": "^4.21.0" + } +} diff --git a/packages/cdk/resources/Apis.ts b/packages/cdk/resources/Apis.ts new file mode 100644 index 0000000000..a7ddc3ad1f --- /dev/null +++ b/packages/cdk/resources/Apis.ts @@ -0,0 +1,151 @@ +import {LambdaIntegration, PassthroughBehavior, StepFunctionsIntegration} from "aws-cdk-lib/aws-apigateway" +import {IManagedPolicy} from "aws-cdk-lib/aws-iam" +import {HttpMethod} from "aws-cdk-lib/aws-lambda" +import {Construct} from "constructs" +import { + ExpressStateMachine, + LambdaEndpoint, + RestApiGateway, + StateMachineEndpoint, + TypescriptLambdaFunction +} from "@nhsdigital/eps-cdk-constructs" + +export interface ApisProps { + readonly stackName: string + readonly logRetentionInDays: number + readonly mutualTlsTrustStoreKey: string | undefined + readonly forwardCsocLogs: boolean + readonly csocApiGatewayDestination: string + readonly deployCheckPrescriptionStatusUpdate: boolean + readonly exposeGetStatusUpdates: boolean + functions: {[key: string]: TypescriptLambdaFunction} + stateMachines: {[key: string]: ExpressStateMachine} +} + +export class Apis extends Construct { + public constructor(scope: Construct, id: string, props: ApisProps) { + super(scope, id) + + // Collect execution policies for all resources that need API Gateway access + const executionPolicies: Array = [ + props.stateMachines.updatePrescriptionStatus.executionPolicy, + props.stateMachines.format1UpdatePrescriptionsStatus.executionPolicy, + props.functions.status.executionPolicy, + props.functions.capabilityStatement.executionPolicy, + props.functions.nhsNotifyUpdateCallback.executionPolicy + ] + + if (props.exposeGetStatusUpdates) { + executionPolicies.push(props.functions.getStatusUpdates.executionPolicy) + } + + if (props.deployCheckPrescriptionStatusUpdate) { + executionPolicies.push(props.functions.checkPrescriptionStatusUpdates.executionPolicy) + } + + const apiGateway = new RestApiGateway(this, "RestApiGateway", { + stackName: props.stackName, + logRetentionInDays: props.logRetentionInDays, + mutualTlsTrustStoreKey: props.mutualTlsTrustStoreKey, + forwardCsocLogs: props.forwardCsocLogs, + csocApiGatewayDestination: props.csocApiGatewayDestination, + executionPolicies + }) + + const rootResource = apiGateway.api.root + + // POST / — UpdatePrescriptionStatus state machine integration (root resource) + rootResource.addMethod( + HttpMethod.POST, + StepFunctionsIntegration.startExecution( + props.stateMachines.updatePrescriptionStatus.stateMachine, + { + credentialsRole: apiGateway.role, + passthroughBehavior: PassthroughBehavior.WHEN_NO_MATCH + } + ), + { + methodResponses: [ + {statusCode: "200"}, + {statusCode: "400"}, + {statusCode: "500"} + ] + } + ) + + // POST /format-1 — Format1 state machine integration + new StateMachineEndpoint(this, "Format1UpdatePrescriptionStatusEndpoint", { + parentResource: rootResource, + resourceName: "format-1", + method: HttpMethod.POST, + restApiGatewayRole: apiGateway.role, + stateMachine: props.stateMachines.format1UpdatePrescriptionsStatus + }) + + // POST /notification-delivery-status-callback — Lambda proxy integration + new LambdaEndpoint(this, "NotificationDeliveryStatusCallbackEndpoint", { + parentResource: rootResource, + resourceName: "notification-delivery-status-callback", + method: HttpMethod.POST, + restApiGatewayRole: apiGateway.role, + lambdaFunction: props.functions.nhsNotifyUpdateCallback + }) + + // GET /_status — Lambda proxy integration + new LambdaEndpoint(this, "StatusEndpoint", { + parentResource: rootResource, + resourceName: "_status", + method: HttpMethod.GET, + restApiGatewayRole: apiGateway.role, + lambdaFunction: props.functions.status + }) + + // GET /metadata — Lambda proxy integration + new LambdaEndpoint(this, "CapabilityStatementEndpoint", { + parentResource: rootResource, + resourceName: "metadata", + method: HttpMethod.GET, + restApiGatewayRole: apiGateway.role, + lambdaFunction: props.functions.capabilityStatement + }) + + // GET /checkprescriptionstatusupdates — conditional Lambda proxy integration + if (props.deployCheckPrescriptionStatusUpdate) { + new LambdaEndpoint(this, "CheckPrescriptionStatusUpdatesEndpoint", { + parentResource: rootResource, + resourceName: "checkprescriptionstatusupdates", + method: HttpMethod.GET, + restApiGatewayRole: apiGateway.role, + lambdaFunction: props.functions.checkPrescriptionStatusUpdates + }) + } + + // POST /get-status-updates — conditional Lambda integration (non-proxy) + if (props.exposeGetStatusUpdates) { + const getStatusUpdatesResource = rootResource.addResource("get-status-updates") + getStatusUpdatesResource.addMethod( + HttpMethod.POST, + new LambdaIntegration(props.functions.getStatusUpdates.function, { + credentialsRole: apiGateway.role, + proxy: false, + requestTemplates: { + "application/json": "$input.json('$')" + }, + integrationResponses: [ + { + statusCode: "200", + responseTemplates: { + "application/json": "$input.body" + } + } + ] + }), + { + methodResponses: [ + {statusCode: "200"} + ] + } + ) + } + } +} diff --git a/packages/cdk/resources/Functions.ts b/packages/cdk/resources/Functions.ts new file mode 100644 index 0000000000..1c73242a6b --- /dev/null +++ b/packages/cdk/resources/Functions.ts @@ -0,0 +1,480 @@ +import {Fn} from "aws-cdk-lib" +import {CfnSchedule} from "aws-cdk-lib/aws-scheduler" +import { + ManagedPolicy, + PolicyStatement, + Role, + ServicePrincipal +} from "aws-cdk-lib/aws-iam" +import {Rule} from "aws-cdk-lib/aws-events" +import {LambdaFunction as LambdaFunctionTarget} from "aws-cdk-lib/aws-events-targets" +import {IFunction} from "aws-cdk-lib/aws-lambda" +import {Construct} from "constructs" +import {TypescriptLambdaFunction} from "@nhsdigital/eps-cdk-constructs" +import {NagSuppressions} from "cdk-nag" +import {resolve} from "node:path" + +export interface FunctionsProps { + readonly stackName: string + readonly samStackName: string + readonly version: string + readonly commitId: string + readonly logRetentionInDays: number + readonly logLevel: string + readonly environment: string + readonly enablePostDatedNotifications: string + readonly requireApplicationName: string + readonly deployCheckPrescriptionStatusUpdate: boolean + readonly enableBackup: boolean +} + +const baseDir = resolve(__dirname, "../../..") + +export class Functions extends Construct { + functions: {[key: string]: TypescriptLambdaFunction} + + public constructor(scope: Construct, id: string, props: FunctionsProps) { + super(scope, id) + + const sam = props.samStackName + + // Table names derived from SAM stack naming convention (not exported) + const prescriptionStatusUpdatesTableName = `${sam}-PrescriptionStatusUpdates` + const prescriptionNotificationStatesTableName = `${sam}-PrescriptionNotificationStatesV1` + + // Cross-stack imports from SAM stateful stack — tables + const tableWritePolicy = ManagedPolicy.fromManagedPolicyArn( + this, "TableWritePolicy", + Fn.importValue(`${sam}:tables:${prescriptionStatusUpdatesTableName}:TableWritePolicyArn`) + ) + const tableReadPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "TableReadPolicy", + Fn.importValue(`${sam}:tables:${prescriptionStatusUpdatesTableName}:TableReadPolicyArn`) + ) + const tableKmsPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "TableKmsPolicy", + Fn.importValue(`${sam}:tables:UsePrescriptionStatusUpdatesKMSKeyPolicyArn`) + ) + const notificationStatesReadPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "NotificationStatesTableReadPolicy", + Fn.importValue( + `${sam}:tables:${prescriptionNotificationStatesTableName}:TableReadPolicyArn` + ) + ) + const notificationStatesWritePolicy = ManagedPolicy.fromManagedPolicyArn( + this, "NotificationStatesTableWritePolicy", + Fn.importValue( + `${sam}:tables:${prescriptionNotificationStatesTableName}:TableWritePolicyArn` + ) + ) + const notificationStatesKmsPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "NotificationStatesKmsPolicy", + Fn.importValue(`${sam}:tables:UsePrescriptionNotificationStatesKMSKeyPolicyArn`) + ) + + // Cross-stack imports from SAM stateful stack — messaging + const notificationSqsKmsPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "NotificationSqsKmsPolicy", + Fn.importValue(`${sam}-UseNotificationSQSQueueKMSKeyPolicyArn`) + ) + const writeNotifySqsPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "WriteNotifySqsPolicy", + Fn.importValue(`${sam}-WriteNHSNotifyPrescriptionsSQSQueuePolicyArn`) + ) + const readNotifySqsPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "ReadNotifySqsPolicy", + Fn.importValue(`${sam}-ReadNHSNotifyPrescriptionsSQSQueuePolicyArn`) + ) + const writePostDatedSqsPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "WritePostDatedSqsPolicy", + Fn.importValue(`${sam}-WritePostDatedNotificationsSQSQueuePolicyArn`) + ) + const readPostDatedSqsPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "ReadPostDatedSqsPolicy", + Fn.importValue(`${sam}-ReadPostDatedNotificationsSQSQueuePolicyArn`) + ) + const nhsNotifyPrescriptionsSqsQueueUrl = Fn.importValue(`${sam}-NHSNotifyPrescriptionsSQSQueueUrl`) + const postDatedNotificationsSqsQueueUrl = Fn.importValue(`${sam}-PostDatedNotificationsSQSQueueUrl`) + + // Cross-stack imports from SAM stateful stack — secrets + const sqsSaltSecret = Fn.importValue(`${sam}-SQSSaltSecret`) + const getSqsSaltSecretPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "GetSqsSaltSecretPolicy", + Fn.importValue(`${sam}-GetSQSSaltSecretPolicy`) + ) + const notifyApiKeySecret = Fn.importValue(`${sam}-PSU-Notify-API-Key`) + const notifyPrivateKeySecret = Fn.importValue(`${sam}-PSU-Notify-PrivateKey`) + const notifyKidSecret = Fn.importValue(`${sam}-PSU-Notify-KID`) + const notifyAppIdSecret = Fn.importValue(`${sam}-PSU-Notify-Application-ID`) + const getPsuSecretPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "GetPsuSecretPolicy", + Fn.importValue(`${sam}-GetPSUSecretPolicy`) + ) + const usePsuSecretsKmsPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "UsePsuSecretsKmsPolicy", + Fn.importValue(`${sam}-UsePSUSecretsKMSKeyPolicyArn`) + ) + + // Cross-stack imports from SAM stateful stack — parameters + const getNotificationsParamPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "GetNotificationsParamPolicy", + Fn.importValue(`${sam}-GetNotificationsParameterPolicy`) + ) + const enabledSiteOdsCodesParam = Fn.importValue(`${sam}-PSUNotifyEnabledSiteODSCodesParam`) + const enabledSystemsParam = Fn.importValue(`${sam}-PSUNotifyEnabledSystemsParam`) + const enabledSupplierAppIdsParam = Fn.importValue(`${sam}-PSUNotifyEnabledSupplierApplicationIDsParam`) + const blockedSiteOdsCodesParam = Fn.importValue(`${sam}-PSUNotifyBlockedSiteODSCodesParam`) + const notifyRoutingPlanIdParam = Fn.importValue(`${sam}-PSUNotifyRoutingPlanIDParam`) + const notifyApiBaseUrlParam = Fn.importValue(`${sam}-PSUNotifyApiBaseUrlParam`) + const enableNotificationsExternalParam = Fn.importValue(`${sam}-EnableNotificationsExternalName`) + const enableNotificationsInternalParam = Fn.importValue(`${sam}-EnableNotificationsInternalName`) + const testPrescriptionsParamName1 = Fn.importValue(`${sam}-TestPrescriptionsParameterName1`) + const testPrescriptionsParamName2 = Fn.importValue(`${sam}-TestPrescriptionsParameterName2`) + const testPrescriptionsParamName3 = Fn.importValue(`${sam}-TestPrescriptionsParameterName3`) + const testPrescriptionsParamName4 = Fn.importValue(`${sam}-TestPrescriptionsParameterName4`) + + // Account-level imports + const lambdaAccessSecretsPolicy = ManagedPolicy.fromManagedPolicyArn( + this, "LambdaAccessSecretsPolicy", + Fn.importValue("account-resources:LambdaAccessSecretsPolicy") + ) + + // Lambda Functions + + const updatePrescriptionStatus = new TypescriptLambdaFunction( + this, "UpdatePrescriptionStatus", { + functionName: `${props.stackName}-UpdatePrescriptionStatus`, + projectBaseDir: baseDir, + packageBasePath: "packages/updatePrescriptionStatus", + entryPoint: "src/updatePrescriptionStatus.ts", + environmentVariables: { + TABLE_NAME: prescriptionStatusUpdatesTableName, + NHS_NOTIFY_PRESCRIPTIONS_SQS_QUEUE_URL: nhsNotifyPrescriptionsSqsQueueUrl, + POST_DATED_PRESCRIPTIONS_SQS_QUEUE_URL: postDatedNotificationsSqsQueueUrl, + ENABLE_POST_DATED_NOTIFICATIONS: props.enablePostDatedNotifications, + SQS_SALT: sqsSaltSecret, + USE_APP_ID_FOR_NOTIFICATIONS_FILTERING: "false", + ENABLED_SYSTEMS_PARAM: enabledSystemsParam, + ENABLED_APPLICATION_IDS_PARAM: enabledSupplierAppIdsParam, + ENABLED_SITE_ODS_CODES_PARAM: enabledSiteOdsCodesParam, + BLOCKED_SITE_ODS_CODES_PARAM: blockedSiteOdsCodesParam, + ENABLE_NOTIFICATIONS_PARAM: enableNotificationsInternalParam, + ENVIRONMENT: props.environment, + REQUIRE_APPLICATION_NAME: props.requireApplicationName, + TEST_PRESCRIPTIONS_PARAM_NAME_1: testPrescriptionsParamName1, + TEST_PRESCRIPTIONS_PARAM_NAME_2: testPrescriptionsParamName2, + TEST_PRESCRIPTIONS_PARAM_NAME_3: testPrescriptionsParamName3, + TEST_PRESCRIPTIONS_PARAM_NAME_4: testPrescriptionsParamName4 + }, + additionalPolicies: [ + tableWritePolicy, + tableReadPolicy, + tableKmsPolicy, + notificationSqsKmsPolicy, + writeNotifySqsPolicy, + writePostDatedSqsPolicy, + getSqsSaltSecretPolicy, + getNotificationsParamPolicy + ], + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + version: props.version, + commitId: props.commitId + }) + + const convertRequestToFhirFormat = new TypescriptLambdaFunction( + this, "ConvertRequestToFhirFormat", { + functionName: `${props.stackName}-ConvertRequestToFhirFormat`, + projectBaseDir: baseDir, + packageBasePath: "packages/cpsuLambda", + entryPoint: "src/cpsu.ts", + environmentVariables: {}, + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + version: props.version, + commitId: props.commitId + }) + + const getStatusUpdates = new TypescriptLambdaFunction(this, "GetStatusUpdates", { + functionName: `${props.stackName}-GetStatusUpdates`, + projectBaseDir: baseDir, + packageBasePath: "packages/gsul", + entryPoint: "src/getStatusUpdates.ts", + environmentVariables: { + TABLE_NAME: prescriptionStatusUpdatesTableName + }, + additionalPolicies: [tableReadPolicy, tableKmsPolicy], + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + version: props.version, + commitId: props.commitId + }) + + const status = new TypescriptLambdaFunction(this, "Status", { + functionName: `${props.stackName}-status`, + projectBaseDir: baseDir, + packageBasePath: "packages/statusLambda", + entryPoint: "src/statusLambda.ts", + environmentVariables: {}, + additionalPolicies: [lambdaAccessSecretsPolicy], + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + version: props.version, + commitId: props.commitId + }) + + const capabilityStatement = new TypescriptLambdaFunction(this, "CapabilityStatement", { + functionName: `${props.stackName}-CapabilityStatement`, + projectBaseDir: baseDir, + packageBasePath: "packages/capabilityStatement", + entryPoint: "src/capabilityStatement.ts", + environmentVariables: {}, + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + version: props.version, + commitId: props.commitId + }) + + const nhsNotifyUpdateCallback = new TypescriptLambdaFunction( + this, "NHSNotifyUpdateCallback", { + functionName: `${props.stackName}-NHSNotifyUpdateCallback`, + projectBaseDir: baseDir, + packageBasePath: "packages/nhsNotifyUpdateCallback", + entryPoint: "src/lambdaHandler.ts", + environmentVariables: { + TABLE_NAME: prescriptionNotificationStatesTableName, + APP_ID_SECRET: notifyAppIdSecret, + API_KEY_SECRET: notifyApiKeySecret + }, + additionalPolicies: [ + notificationStatesReadPolicy, + notificationStatesWritePolicy, + notificationStatesKmsPolicy, + getPsuSecretPolicy, + usePsuSecretsKmsPolicy + ], + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + version: props.version, + commitId: props.commitId + }) + + const notifyProcessor = new TypescriptLambdaFunction(this, "NotifyProcessor", { + functionName: `${props.stackName}-NotifyProcessor`, + projectBaseDir: baseDir, + packageBasePath: "packages/nhsNotifyLambda", + entryPoint: "src/nhsNotifyLambda.ts", + environmentVariables: { + NHS_NOTIFY_PRESCRIPTIONS_SQS_QUEUE_URL: nhsNotifyPrescriptionsSqsQueueUrl, + TABLE_NAME: prescriptionNotificationStatesTableName, + API_KEY_SECRET: notifyApiKeySecret, + PRIVATE_KEY_SECRET: notifyPrivateKeySecret, + KID_SECRET: notifyKidSecret, + NHS_NOTIFY_ROUTING_ID_PARAM: notifyRoutingPlanIdParam, + NOTIFY_API_BASE_URL_PARAM: notifyApiBaseUrlParam, + MAKE_REAL_NOTIFY_REQUESTS_PARAM: enableNotificationsExternalParam + }, + additionalPolicies: [ + writeNotifySqsPolicy, + readNotifySqsPolicy, + notificationSqsKmsPolicy, + notificationStatesReadPolicy, + notificationStatesWritePolicy, + notificationStatesKmsPolicy, + getNotificationsParamPolicy, + getPsuSecretPolicy, + usePsuSecretsKmsPolicy + ], + timeoutInSeconds: 900, + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + version: props.version, + commitId: props.commitId + }) + + this.createSchedule( + "NotifyProcessorSchedule", + `${props.stackName}-NotifySchedule`, + "rate(1 minute)", + notifyProcessor.function + ) + + const postDatedNotifyLambda = new TypescriptLambdaFunction( + this, "PostDatedNotifyLambda", { + functionName: `${props.stackName}-postDatedNotifyLambda`, + projectBaseDir: baseDir, + packageBasePath: "packages/postDatedLambda", + entryPoint: "src/main.ts", + environmentVariables: { + NHS_NOTIFY_PRESCRIPTIONS_SQS_QUEUE_URL: nhsNotifyPrescriptionsSqsQueueUrl, + POST_DATED_PRESCRIPTIONS_SQS_QUEUE_URL: postDatedNotificationsSqsQueueUrl, + TABLE_NAME: prescriptionStatusUpdatesTableName + }, + additionalPolicies: [ + writeNotifySqsPolicy, + readNotifySqsPolicy, + notificationSqsKmsPolicy, + writePostDatedSqsPolicy, + readPostDatedSqsPolicy, + tableWritePolicy, + tableReadPolicy, + tableKmsPolicy + ], + timeoutInSeconds: 900, + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + version: props.version, + commitId: props.commitId + }) + + this.createSchedule( + "PostDatedNotifySchedule", + `${props.stackName}-PostDatedNotifySchedule`, + "rate(15 minutes)", + postDatedNotifyLambda.function + ) + + // Conditional: CheckPrescriptionStatusUpdates + let checkPrescriptionStatusUpdates: TypescriptLambdaFunction | undefined + if (props.deployCheckPrescriptionStatusUpdate) { + checkPrescriptionStatusUpdates = new TypescriptLambdaFunction( + this, "CheckPrescriptionStatusUpdates", { + functionName: `${props.stackName}-CheckPrescriptionStatusUpdates`, + projectBaseDir: baseDir, + packageBasePath: "packages/checkPrescriptionStatusUpdates", + entryPoint: "src/checkPrescriptionStatusUpdates.ts", + environmentVariables: { + TABLE_NAME: prescriptionStatusUpdatesTableName, + MIN_RESULTS_RETURNED: "5", + MAX_RESULTS_RETURNED: "15" + }, + additionalPolicies: [tableReadPolicy, tableKmsPolicy], + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + version: props.version, + commitId: props.commitId + } + ) + } + + // Conditional: PsuRestoreValidation + if (props.enableBackup) { + const psuRestoreValidationPolicy = new ManagedPolicy(this, "PsuRestoreValidationPolicy", { + managedPolicyName: `${props.stackName}-PsuRestoreValidationPolicy`, + statements: [ + new PolicyStatement({ + actions: ["backup:PutRestoreValidationResult"], + resources: ["*"] + }), + new PolicyStatement({ + actions: [ + "dynamodb:GetItem", + "dynamodb:BatchGetItem", + "dynamodb:Scan", + "dynamodb:Query", + "dynamodb:ConditionCheckItem", + "dynamodb:DescribeTable" + ], + resources: [ + Fn.sub( + "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/awsbackup-restore-test-*" + ) + ] + }) + ] + }) + + NagSuppressions.addResourceSuppressions(psuRestoreValidationPolicy, [ + { + id: "AwsSolutions-IAM5", + reason: "Wildcard needed for backup:PutRestoreValidationResult on any restore job" + } + ]) + + const psuRestoreValidation = new TypescriptLambdaFunction(this, "PsuRestoreValidation", { + functionName: `${props.stackName}-PsuRestoreValidation`, + projectBaseDir: baseDir, + packageBasePath: "packages/psuRestoreValidationLambda", + entryPoint: "src/handler.ts", + environmentVariables: {}, + additionalPolicies: [ + psuRestoreValidationPolicy, + tableReadPolicy, + tableKmsPolicy + ], + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + version: props.version, + commitId: props.commitId + }) + + const restoreRule = new Rule(this, "PsuBackupRestoreJobStateChangeRule", { + eventPattern: { + source: ["aws.backup"], + detailType: ["Restore Job State Change"], + detail: { + resourceType: ["DynamoDB.FullyManaged"], + status: ["COMPLETED"], + sourceResourceArn: [ + Fn.sub( + + `arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${prescriptionStatusUpdatesTableName}` + ) + ] + } + } + }) + restoreRule.addTarget(new LambdaFunctionTarget(psuRestoreValidation.function)) + } + + this.functions = { + updatePrescriptionStatus, + convertRequestToFhirFormat, + getStatusUpdates, + status, + capabilityStatement, + nhsNotifyUpdateCallback, + notifyProcessor, + postDatedNotifyLambda, + ...(checkPrescriptionStatusUpdates ? {checkPrescriptionStatusUpdates} : {}) + } + } + + private createSchedule( + id: string, + scheduleName: string, + scheduleExpression: string, + lambdaFunction: IFunction + ): void { + const scheduleRole = new Role(this, `${id}Role`, { + assumedBy: new ServicePrincipal("scheduler.amazonaws.com") + }) + + const schedulePolicy = new ManagedPolicy(this, `${id}Policy`, { + statements: [ + new PolicyStatement({ + actions: ["lambda:InvokeFunction"], + resources: [lambdaFunction.functionArn] + }) + ] + }) + scheduleRole.addManagedPolicy(schedulePolicy) + + NagSuppressions.addResourceSuppressions(scheduleRole, [ + { + id: "AwsSolutions-IAM5", + reason: "Role only grants InvokeFunction on a specific Lambda" + } + ]) + + new CfnSchedule(this, id, { + name: scheduleName, + scheduleExpression: scheduleExpression, + flexibleTimeWindow: {mode: "OFF"}, + target: { + arn: lambdaFunction.functionArn, + roleArn: scheduleRole.roleArn + } + }) + } +} diff --git a/packages/cdk/resources/StateMachineDefinitions/Format1UpdatePrescriptionsStatus.ts b/packages/cdk/resources/StateMachineDefinitions/Format1UpdatePrescriptionsStatus.ts new file mode 100644 index 0000000000..7e3192549e --- /dev/null +++ b/packages/cdk/resources/StateMachineDefinitions/Format1UpdatePrescriptionsStatus.ts @@ -0,0 +1,127 @@ +import {IFunction} from "aws-cdk-lib/aws-lambda" +import {LambdaInvoke} from "aws-cdk-lib/aws-stepfunctions-tasks" +import {Construct} from "constructs" +import { + Chain, + Choice, + Condition, + IChainable, + Pass, + TaskInput +} from "aws-cdk-lib/aws-stepfunctions" + +export interface Format1UpdatePrescriptionsStatusDefinitionProps { + readonly convertRequestToFhirFormatFunction: IFunction + readonly updatePrescriptionStatusFunction: IFunction +} + +export class Format1UpdatePrescriptionsStatusDefinition extends Construct { + public readonly definition: IChainable + + public constructor( + scope: Construct, id: string, props: Format1UpdatePrescriptionsStatusDefinitionProps + ) { + super(scope, id) + + const catchAllError = new Pass(this, "CatchAllError", { + result: { + value: { + Payload: { + statusCode: 500, + headers: { + "Content-Type": "application/fhir+json", + "Cache-Control": "no-cache" + }, + body: JSON.stringify({ + resourceType: "OperationOutcome", + issue: [{severity: "error", code: "processing", diagnostics: "System error"}] + }) + } + } + } + }) + + const callConvertRequestToFhirFormat = new LambdaInvoke( + this, "Call Convert Request To Fhir Format", { + lambdaFunction: props.convertRequestToFhirFormatFunction, + assign: { + convertStatusCode: "{% $states.result.Payload.statusCode %}", + convertHeaders: "{% $states.result.Payload.headers %}", + convertBody: "{% $parse($states.result.Payload.body) %}" + } + } + ) + callConvertRequestToFhirFormat.addCatch(catchAllError) + + const failedConvertRequestToFhir = new Pass(this, "Failed Convert Request to FHIR", { + outputs: { + Payload: { + statusCode: "{% $convertStatusCode %}", + headers: "{% $convertHeaders %}", + body: "{% $string($convertBody) %}" + } + } + }) + + const callUpdatePrescriptionStatus = new LambdaInvoke( + this, "Call Update Prescription Status", { + lambdaFunction: props.updatePrescriptionStatusFunction, + payload: TaskInput.fromObject({ + body: "{% $string($convertBody) %}", + headers: "{% $convertHeaders %}" + }), + assign: { + updateStatusCode: "{% $states.result.Payload.statusCode %}", + updatePayload: "{% $states.result.Payload %}" + } + } + ) + callUpdatePrescriptionStatus.addCatch(catchAllError) + + const translate409To202 = new Pass(this, "Translate 409 to 202", { + result: { + value: { + Payload: { + statusCode: 202, + headers: { + "Content-Type": "application/fhir+json", + "Cache-Control": "no-cache" + }, + body: JSON.stringify({ + resourceType: "OperationOutcome", + issue: [{ + severity: "information", + code: "informational", + diagnostics: + "Duplicate update detected. The message was valid but did not result in an update." + }] + }) + } + } + } + }) + + const endState = new Pass(this, "End State") + + const checkConvertResult = new Choice(this, "Convert Request to FHIR result") + const convertNotOk = Condition.jsonata("{% $convertStatusCode != 200 %}") + + const checkUpdateResult = new Choice(this, "Check Update Prescription Status Result") + const updateIs409 = Condition.jsonata("{% $updateStatusCode = 409 %}") + + this.definition = Chain + .start(callConvertRequestToFhirFormat) + .next( + checkConvertResult + .when(convertNotOk, failedConvertRequestToFhir) + .otherwise( + callUpdatePrescriptionStatus + .next( + checkUpdateResult + .when(updateIs409, translate409To202) + .otherwise(endState) + ) + ) + ) + } +} diff --git a/packages/cdk/resources/StateMachineDefinitions/UpdatePrescriptionStatus.ts b/packages/cdk/resources/StateMachineDefinitions/UpdatePrescriptionStatus.ts new file mode 100644 index 0000000000..11847d5284 --- /dev/null +++ b/packages/cdk/resources/StateMachineDefinitions/UpdatePrescriptionStatus.ts @@ -0,0 +1,84 @@ +import {IFunction} from "aws-cdk-lib/aws-lambda" +import {LambdaInvoke} from "aws-cdk-lib/aws-stepfunctions-tasks" +import {Construct} from "constructs" +import { + Chain, + Choice, + Condition, + IChainable, + Pass +} from "aws-cdk-lib/aws-stepfunctions" + +export interface UpdatePrescriptionStatusDefinitionProps { + readonly fhirValidationFunction: IFunction + readonly updatePrescriptionStatusFunction: IFunction +} + +export class UpdatePrescriptionStatusDefinition extends Construct { + public readonly definition: IChainable + + public constructor( + scope: Construct, id: string, props: UpdatePrescriptionStatusDefinitionProps + ) { + super(scope, id) + + const catchAllError = new Pass(this, "CatchAllError", { + result: { + value: { + Payload: { + statusCode: 500, + headers: { + "Content-Type": "application/fhir+json", + "Cache-Control": "no-cache" + }, + body: JSON.stringify({ + resourceType: "OperationOutcome", + issue: [{severity: "error", code: "processing", diagnostics: "System error"}] + }) + } + } + } + }) + + const callFhirValidation = new LambdaInvoke(this, "Call FHIR Validation", { + lambdaFunction: props.fhirValidationFunction, + assign: { + fhirValidationResponse: "{% $states.result.Payload %}", + fhirValidationErrorCount: + "{% $count($states.result.Payload.issue[severity = 'error']) %}" + } + }) + callFhirValidation.addCatch(catchAllError) + + const returnFailedFhirValidationErrors = new Pass(this, "Return Failed FHIR Validation Errors", { + outputs: { + Payload: { + statusCode: 400, + headers: { + "Content-Type": "application/fhir+json", + "Cache-Control": "no-cache" + }, + body: "{% $string($fhirValidationResponse) %}" + } + } + }) + + const callUpdatePrescriptionStatus = new LambdaInvoke( + this, "Call Update Prescription Status", { + lambdaFunction: props.updatePrescriptionStatusFunction + } + ) + callUpdatePrescriptionStatus.addCatch(catchAllError) + + const doFhirValidationErrorsExist = new Choice(this, "Do FHIR Validation Errors Exist") + const hasErrors = Condition.jsonata("{% $fhirValidationErrorCount > 0 %}") + + this.definition = Chain + .start(callFhirValidation) + .next( + doFhirValidationErrorsExist + .when(hasErrors, returnFailedFhirValidationErrors) + .otherwise(callUpdatePrescriptionStatus) + ) + } +} diff --git a/packages/cdk/resources/StateMachines.ts b/packages/cdk/resources/StateMachines.ts new file mode 100644 index 0000000000..4fabb92215 --- /dev/null +++ b/packages/cdk/resources/StateMachines.ts @@ -0,0 +1,92 @@ +import {Fn} from "aws-cdk-lib" +import {Function} from "aws-cdk-lib/aws-lambda" +import {ManagedPolicy, PolicyStatement} from "aws-cdk-lib/aws-iam" +import {Construct} from "constructs" +import {ExpressStateMachine, TypescriptLambdaFunction} from "@nhsdigital/eps-cdk-constructs" +import {UpdatePrescriptionStatusDefinition} from "./StateMachineDefinitions/UpdatePrescriptionStatus" +import {Format1UpdatePrescriptionsStatusDefinition} from "./StateMachineDefinitions/Format1UpdatePrescriptionsStatus" + +export interface StateMachinesProps { + readonly stackName: string + readonly logRetentionInDays: number + readonly functions: {[key: string]: TypescriptLambdaFunction} +} + +export class StateMachines extends Construct { + stateMachines: {[key: string]: ExpressStateMachine} + + public constructor(scope: Construct, id: string, props: StateMachinesProps) { + super(scope, id) + + // Import the FHIR Validator function from the fhir-validator stack + const fhirValidatorFunctionArn = `${Fn.importValue("fhir-validator:FHIRValidatorUKCoreLambdaArn")}:$LATEST` + const fhirValidatorFunction = Function.fromFunctionArn( + this, "FhirValidatorFunction", fhirValidatorFunctionArn + ) + const fhirValidatorExecutePolicy = ManagedPolicy.fromManagedPolicyArn( + this, "FhirValidatorExecutePolicy", + Fn.importValue("fhir-validator:FHIRValidatorUKCoreExecuteLambdaPolicyArn") + ) + + // Policy to invoke the FHIR validator function (needed because the import + // uses a qualified ARN with :$LATEST suffix which may not be covered by + // the execute policy from the fhir-validator stack) + const callFhirValidatorPolicy = new ManagedPolicy(this, "CallFhirValidatorPolicy", { + description: "Invoke FHIR validator lambda from state machine", + statements: [ + new PolicyStatement({ + actions: ["lambda:InvokeFunction"], + resources: [fhirValidatorFunctionArn] + }) + ] + }) + + // UpdatePrescriptionStatus state machine definition + const updatePrescriptionStatusDefinition = new UpdatePrescriptionStatusDefinition( + this, "UpdatePrescriptionStatusDefinition", { + fhirValidationFunction: fhirValidatorFunction, + updatePrescriptionStatusFunction: props.functions.updatePrescriptionStatus.function + } + ) + + const updatePrescriptionStatusStateMachine = new ExpressStateMachine( + this, "UpdatePrescriptionStatusStateMachine", { + stackName: props.stackName, + stateMachineName: `${props.stackName}-UpdatePrescriptionStatus`, + definition: updatePrescriptionStatusDefinition.definition, + logRetentionInDays: props.logRetentionInDays, + additionalPolicies: [ + props.functions.updatePrescriptionStatus.executionPolicy, + fhirValidatorExecutePolicy, + callFhirValidatorPolicy + ] + } + ) + + // Format1UpdatePrescriptionsStatus state machine definition + const format1Definition = new Format1UpdatePrescriptionsStatusDefinition( + this, "Format1UpdatePrescriptionsStatusDefinition", { + convertRequestToFhirFormatFunction: props.functions.convertRequestToFhirFormat.function, + updatePrescriptionStatusFunction: props.functions.updatePrescriptionStatus.function + } + ) + + const format1UpdatePrescriptionsStatusStateMachine = new ExpressStateMachine( + this, "Format1UpdatePrescriptionsStatusStateMachine", { + stackName: props.stackName, + stateMachineName: `${props.stackName}-Format1UpdatePrescriptionsStatus`, + definition: format1Definition.definition, + logRetentionInDays: props.logRetentionInDays, + additionalPolicies: [ + props.functions.convertRequestToFhirFormat.executionPolicy, + props.functions.updatePrescriptionStatus.executionPolicy + ] + } + ) + + this.stateMachines = { + updatePrescriptionStatus: updatePrescriptionStatusStateMachine, + format1UpdatePrescriptionsStatus: format1UpdatePrescriptionsStatusStateMachine + } + } +} diff --git a/packages/cdk/stacks/PsuStatelessStack.ts b/packages/cdk/stacks/PsuStatelessStack.ts new file mode 100644 index 0000000000..c1a681484a --- /dev/null +++ b/packages/cdk/stacks/PsuStatelessStack.ts @@ -0,0 +1,62 @@ +import {App, Stack} from "aws-cdk-lib" +import {nagSuppressions} from "../nagSuppressions" +import {StandardStackProps} from "@nhsdigital/eps-cdk-constructs" +import {Functions} from "../resources/Functions" +import {StateMachines} from "../resources/StateMachines" +import {Apis} from "../resources/Apis" + +export interface PsuStatelessStackProps extends StandardStackProps { + readonly stackName: string + readonly samStackName: string + readonly logRetentionInDays: number + readonly logLevel: string + readonly environment: string + readonly mutualTlsTrustStoreKey: string | undefined + readonly forwardCsocLogs: boolean + readonly csocApiGatewayDestination: string + readonly deployCheckPrescriptionStatusUpdate: boolean + readonly exposeGetStatusUpdates: boolean + readonly enablePostDatedNotifications: string + readonly requireApplicationName: string + readonly enableBackup: boolean +} + +export class PsuStatelessStack extends Stack { + public constructor(scope: App, id: string, props: PsuStatelessStackProps) { + super(scope, id, props) + + const functions = new Functions(this, "Functions", { + stackName: props.stackName, + samStackName: props.samStackName, + version: props.version, + commitId: props.commitId, + logRetentionInDays: props.logRetentionInDays, + logLevel: props.logLevel, + environment: props.environment, + enablePostDatedNotifications: props.enablePostDatedNotifications, + requireApplicationName: props.requireApplicationName, + deployCheckPrescriptionStatusUpdate: props.deployCheckPrescriptionStatusUpdate, + enableBackup: props.enableBackup + }) + + const stateMachines = new StateMachines(this, "StateMachines", { + stackName: props.stackName, + logRetentionInDays: props.logRetentionInDays, + functions: functions.functions + }) + + new Apis(this, "Apis", { + stackName: props.stackName, + logRetentionInDays: props.logRetentionInDays, + mutualTlsTrustStoreKey: props.mutualTlsTrustStoreKey, + forwardCsocLogs: props.forwardCsocLogs, + csocApiGatewayDestination: props.csocApiGatewayDestination, + deployCheckPrescriptionStatusUpdate: props.deployCheckPrescriptionStatusUpdate, + exposeGetStatusUpdates: props.exposeGetStatusUpdates, + functions: functions.functions, + stateMachines: stateMachines.stateMachines + }) + + nagSuppressions(this) + } +} diff --git a/packages/cdk/tsconfig.json b/packages/cdk/tsconfig.json new file mode 100644 index 0000000000..280f62c4ca --- /dev/null +++ b/packages/cdk/tsconfig.json @@ -0,0 +1,38 @@ +{ + "extends": "../../tsconfig.defaults.json", + "compilerOptions": { + "module": "commonjs", + "rootDir": ".", + "outDir": "lib", + "allowImportingTsExtensions": true, + "noEmit": true, + "strict": false, + "lib": [ + "es2020" + ], + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": false, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization": false, + "typeRoots": [ + "../../node_modules/@types" + ] + }, + "include": [ + "stacks/**/*", + "bin/**/*", + "resources/**/*", + "nagSuppressions.ts" + ], + "exclude": [ + "node_modules", + "cdk.out" + ] +} diff --git a/zizmor.yml b/zizmor.yml index 6659946d6b..728f741a11 100644 --- a/zizmor.yml +++ b/zizmor.yml @@ -5,6 +5,10 @@ rules: - run_release_code_and_api.yml:146:7 - run_regression_tests.yml:26:7 - run_package_code_and_api.yml:16:7 + - cdk_package_code.yml:25:7 + - cdk_release_code.yml:45:7 + - cdk_release_code.yml:57:7 + - cdk_release_code.yml:69:7 secrets-outside-env: # these are ignored because they are using known secrets ignore: