From 712b86422e874b845fa212d34d69f54b09356c8c Mon Sep 17 00:00:00 2001 From: Tim Stephenson <231503406+tstephen-nhs@users.noreply.github.com> Date: Mon, 3 Nov 2025 12:47:00 +0000 Subject: [PATCH 01/45] Chore: devcontainer fail fast, posix equality, force docker gid --- .devcontainer/Dockerfile | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index f25502096..3cd09f31b 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,11 +1,16 @@ FROM mcr.microsoft.com/devcontainers/base:ubuntu +# provide DOCKER_GID via build args if you need to force group id to match host +ARG DOCKER_GID ARG TARGETARCH ENV TARGETARCH=${TARGETARCH} ARG ASDF_VERSION COPY .tool-versions.asdf /tmp/.tool-versions.asdf +# Anticipate and resolve potential permission issues with apt +RUN mkdir -p /tmp && chmod 1777 /tmp + RUN apt-get update \ && export DEBIAN_FRONTEND=noninteractive \ && apt-get -y dist-upgrade \ @@ -18,7 +23,7 @@ RUN apt-get update \ xz-utils tk-dev liblzma-dev netcat-traditional libyaml-dev # Download correct AWS CLI for arch -RUN if [ "$TARGETARCH" = "arm64" ] || [ "$TARGETARCH" == "aarch64" ]; then \ +RUN if [ "$TARGETARCH" = "arm64" ] || [ "$TARGETARCH" = "aarch64" ]; then \ wget -O /tmp/awscliv2.zip "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip"; \ else \ wget -O /tmp/awscliv2.zip "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"; \ @@ -28,7 +33,7 @@ RUN if [ "$TARGETARCH" = "arm64" ] || [ "$TARGETARCH" == "aarch64" ]; then \ rm /tmp/awscliv2.zip && rm -rf /tmp/aws-cli # Download correct SAM CLI for arch -RUN if [ "$TARGETARCH" = "arm64" ] || [ "$TARGETARCH" == "aarch64" ]; then \ +RUN if [ "$TARGETARCH" = "arm64" ] || [ "$TARGETARCH" = "aarch64" ]; then \ wget -O /tmp/aws-sam-cli.zip "https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-arm64.zip"; \ else \ wget -O /tmp/aws-sam-cli.zip "https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip"; \ @@ -43,6 +48,16 @@ RUN ASDF_VERSION=$(awk '!/^#/ && NF {print $1; exit}' /tmp/.tool-versions.asdf) tar -xvzf /tmp/asdf.tar.gz; \ mv asdf /usr/bin +# specify DOCKER_GID to force container docker group id to match host +RUN if [ -n "${DOCKER_GID}" ]; then \ + if ! getent group docker; then \ + groupadd -g ${DOCKER_GID} docker; \ + else \ + groupmod -g ${DOCKER_GID} docker; \ + fi && \ + usermod -aG docker vscode; \ + fi + USER vscode ENV PATH="/home/vscode/.asdf/shims/:$PATH" @@ -54,15 +69,15 @@ RUN \ echo 'export PATH="$HOME/gems/bin:$PATH"' >> ~/.bashrc; # Install ASDF plugins -RUN asdf plugin add python; \ - asdf plugin add poetry https://github.com/asdf-community/asdf-poetry.git; \ - asdf plugin add shellcheck https://github.com/luizm/asdf-shellcheck.git; \ - asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git; \ - asdf plugin add java; \ - asdf plugin add direnv; \ - asdf plugin add golang https://github.com/kennyp/asdf-golang.git; \ - asdf plugin add golangci-lint https://github.com/hypnoglow/asdf-golangci-lint.git; \ - asdf plugin add actionlint; \ +RUN asdf plugin add python && \ + asdf plugin add poetry https://github.com/asdf-community/asdf-poetry.git && \ + asdf plugin add shellcheck https://github.com/luizm/asdf-shellcheck.git && \ + asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git && \ + asdf plugin add java && \ + asdf plugin add direnv && \ + asdf plugin add golang https://github.com/kennyp/asdf-golang.git && \ + asdf plugin add golangci-lint https://github.com/hypnoglow/asdf-golangci-lint.git && \ + asdf plugin add actionlint && \ asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git @@ -71,5 +86,5 @@ ADD .tool-versions /workspaces/prescriptionsforpatients/.tool-versions ADD .tool-versions /home/vscode/.tool-versions # install python before poetry to ensure correct python version is used -RUN asdf install python; \ +RUN asdf install python && \ asdf install From b2ebc80f9946ae6e3a7f364ae4e9981f1025f85c Mon Sep 17 00:00:00 2001 From: Tim Stephenson <231503406+tstephen-nhs@users.noreply.github.com> Date: Tue, 4 Nov 2025 12:42:04 +0000 Subject: [PATCH 02/45] chore: provide docker gid from env --- .devcontainer/devcontainer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6d0da5506..f13304475 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,7 +3,9 @@ "build": { "dockerfile": "Dockerfile", "context": "..", - "args": {} + "args": { + "DOCKER_GID": "${env:DOCKER_GID:}" + } }, "mounts": [ "source=${env:HOME}${env:USERPROFILE}/.aws,target=/home/vscode/.aws,type=bind", From 2ffc014a3dd163a088566d6d1b872ec211eb8b25 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Thu, 11 Dec 2025 09:37:53 +0000 Subject: [PATCH 03/45] WIP - Modify pipeline & include full spec Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/scripts/deploy_api.sh | 195 ++ .github/workflows/ci.yml | 6 + .github/workflows/pull_request.yml | 10 +- .github/workflows/release.yml | 18 +- .github/workflows/sam_release_code.yml | 52 + package-lock.json | 2628 +++++++++++++++-- package.json | 3 +- .../Bundle/error/error-401.json | 19 + .../Bundle/error/error-500.json | 19 + .../success/success-distance-selling.json | 232 ++ .../Bundle/success/success-empty.json | 10 + .../success/success-multiple-cancelled.json | 686 +++++ .../success/success-multiple-exclusion.json | 260 ++ .../Bundle/success/success-multiple.json | 686 +++++ .../success/success-ready-dispatch.json | 414 +++ .../success/success-single-exclusion.json | 232 ++ ...cess-tracking-temporarily-unavailable.json | 232 ++ .../Bundle/success/success.json | 414 +++ packages/specification/jest.config.ts | 9 + packages/specification/jest.debug.config.ts | 9 + packages/specification/package.json | 23 + .../prescriptions-for-patients.yaml | 433 +++ packages/specification/redocly.yaml | 3 + .../schemas/fragments/address.yaml | 47 + .../schemas/fragments/codes.yaml | 54 + .../schemas/fragments/groupIdentifier.yaml | 14 + .../schemas/fragments/identifiers.yaml | 29 + .../fragments/medicationRequest/status.yaml | 50 + .../medicationRequest/statusDate.yaml | 14 + .../schemas/fragments/structuredName.yaml | 25 + .../schemas/fragments/telecom.yaml | 19 + .../schemas/resources/MedicationRequest.yaml | 128 + .../schemas/resources/OperationOutcome.yaml | 83 + .../schemas/resources/Organisation.yaml | 30 + .../schemas/resources/Practitioner.yaml | 21 + .../schemas/resources/PractitionerRole.yaml | 26 + packages/specification/tsconfig.json | 9 + tsconfig.build.json | 3 +- 38 files changed, 6925 insertions(+), 220 deletions(-) create mode 100755 .github/scripts/deploy_api.sh create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/error/error-401.json create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/error/error-500.json create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/success/success-distance-selling.json create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/success/success-empty.json create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple-cancelled.json create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple-exclusion.json create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple.json create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/success/success-ready-dispatch.json create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/success/success-single-exclusion.json create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/success/success-tracking-temporarily-unavailable.json create mode 100644 packages/specification/examples/GetMyPrescriptions/Bundle/success/success.json create mode 100644 packages/specification/jest.config.ts create mode 100644 packages/specification/jest.debug.config.ts create mode 100644 packages/specification/package.json create mode 100644 packages/specification/prescriptions-for-patients.yaml create mode 100644 packages/specification/redocly.yaml create mode 100644 packages/specification/schemas/fragments/address.yaml create mode 100644 packages/specification/schemas/fragments/codes.yaml create mode 100644 packages/specification/schemas/fragments/groupIdentifier.yaml create mode 100644 packages/specification/schemas/fragments/identifiers.yaml create mode 100644 packages/specification/schemas/fragments/medicationRequest/status.yaml create mode 100644 packages/specification/schemas/fragments/medicationRequest/statusDate.yaml create mode 100644 packages/specification/schemas/fragments/structuredName.yaml create mode 100644 packages/specification/schemas/fragments/telecom.yaml create mode 100644 packages/specification/schemas/resources/MedicationRequest.yaml create mode 100644 packages/specification/schemas/resources/OperationOutcome.yaml create mode 100644 packages/specification/schemas/resources/Organisation.yaml create mode 100644 packages/specification/schemas/resources/Practitioner.yaml create mode 100644 packages/specification/schemas/resources/PractitionerRole.yaml create mode 100644 packages/specification/tsconfig.json diff --git a/.github/scripts/deploy_api.sh b/.github/scripts/deploy_api.sh new file mode 100755 index 000000000..ccb1a36b3 --- /dev/null +++ b/.github/scripts/deploy_api.sh @@ -0,0 +1,195 @@ +#!/usr/bin/env bash +set -eu pipefail + +echo "Specification path: ${SPEC_PATH}" +echo "Specification version: ${VERSION_NUMBER}" +echo "Stack name: ${STACK_NAME}" +echo "AWS environment: ${AWS_ENVIRONMENT}" +echo "Apigee environment: ${APIGEE_ENVIRONMENT}" +echo "Proxygen private key name: ${PROXYGEN_PRIVATE_KEY_NAME}" +echo "Proxygen KID: ${PROXYGEN_KID}" +echo "Dry run: ${DRY_RUN}" +echo "ENABLE_MUTUAL_TLS: ${ENABLE_MUTUAL_TLS}" +echo "is_pull_request: ${IS_PULL_REQUEST}" + +client_private_key=$(cat ~/.proxygen/tmp/client_private_key) +client_cert=$(cat ~/.proxygen/tmp/client_cert) + +if [ -z "${client_private_key}" ]; then + echo "client_private_key is unset or set to the empty string" + exit 1 +fi +if [ -z "${client_cert}" ]; then + echo "client_cert is unset or set to the empty string" + exit 1 +fi + +put_secret_lambda=lambda-resources-ProxygenPTLMTLSSecretPut +instance_put_lambda=lambda-resources-ProxygenPTLInstancePut +spec_publish_lambda=lambda-resources-ProxygenPTLSpecPublish + +if [[ "$APIGEE_ENVIRONMENT" =~ ^(int|sandbox|prod)$ ]]; then + put_secret_lambda=lambda-resources-ProxygenProdMTLSSecretPut + instance_put_lambda=lambda-resources-ProxygenProdInstancePut + spec_publish_lambda=lambda-resources-ProxygenProdSpecPublish +fi + +instance_suffix="" +if [[ "${IS_PULL_REQUEST}" == "true" ]]; then + # Extracting the PR ID from $STACK_NAME + pr_id=$(echo "$STACK_NAME" | awk -F'-' '{print $NF}') + instance_suffix=-"pr-${pr_id}" +fi + +# Determine the proxy instance based on the provided $STACK_NAME +apigee_api=pfp-proxygen +instance="pfp-proxygen${instance_suffix}" + +echo "Proxy instance: ${instance}" +echo "Apigee api: ${apigee_api}" + +echo + +echo "Fixing the spec" +# Find and replace the title +title=$(jq -r '.info.title' "${SPEC_PATH}") +if [[ "${IS_PULL_REQUEST}" == "true" ]]; then + jq --arg title "[PR-${pr_id}] $title" '.info.title = $title' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" + echo "disabling monitoring for pull request deployment" + jq '."x-nhsd-apim".monitoring = false' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" +fi + +# Find and replace the specification version number +jq --arg version "${VERSION_NUMBER}" '.info.version = $version' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" + +# Find and replace the x-nhsd-apim.target.url value +jq --arg stack_name "${STACK_NAME}" --arg aws_env "${AWS_ENVIRONMENT}" '.["x-nhsd-apim"].target.url = "https://\($stack_name).\($aws_env).eps.national.nhs.uk"' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" + +# Find and replace the servers object +if [[ "${APIGEE_ENVIRONMENT}" == "prod" ]]; then + jq --arg inst "${instance}" '.servers = [ { "url": "https://api.service.nhs.uk/\($inst)" } ]' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" +else + jq --arg env "${APIGEE_ENVIRONMENT}" --arg inst "${instance}" '.servers = [ { "url": "https://\($env).api.service.nhs.uk/\($inst)" } ]' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" +fi + +# Find and replace securitySchemes +if [[ "${APIGEE_ENVIRONMENT}" == "prod" ]]; then + jq '.components.securitySchemes."nhs-cis2-aal3" = {"$ref": "https://proxygen.prod.api.platform.nhs.uk/components/securitySchemes/nhs-cis2-aal3"}' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" +else + jq '.components.securitySchemes."nhs-cis2-aal3" = {"$ref": "https://proxygen.ptl.api.platform.nhs.uk/components/securitySchemes/nhs-cis2-aal3"}' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" +fi + +# Find and replace the x-nhsd-apim.target.secret value +jq --arg mtls_key "${MTLS_KEY}" '.["x-nhsd-apim"].target.security.secret = "\($mtls_key)"' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" + +# Remove target attributes if the environment is sandbox +if [[ "${APIGEE_ENVIRONMENT}" == *"sandbox"* ]]; then + echo "Removing target attributes for sandbox environment" + jq 'del(."x-nhsd-apim"."target-attributes")' "$SPEC_PATH" > temp.json && mv temp.json "${SPEC_PATH}" +fi + +echo + +echo "Retrieving proxygen credentials" + +# Retrieve the proxygen private key and client private key and cert from AWS Secrets Manager +proxygen_private_key_arn=$(aws cloudformation list-exports --query "Exports[?Name=='account-resources:${PROXYGEN_PRIVATE_KEY_NAME}'].Value" --output text) + +if [[ "${ENABLE_MUTUAL_TLS}" == "true" ]]; then + echo + echo "Store the secret used for mutual TLS to AWS using Proxygen proxy lambda" + if [[ "${DRY_RUN}" == "false" ]]; then + jq -n --arg apiName "${apigee_api}" \ + --arg environment "${APIGEE_ENVIRONMENT}" \ + --arg secretName "${MTLS_KEY}" \ + --arg secretKey "${client_private_key}" \ + --arg secretCert "${client_cert}" \ + --arg kid "${PROXYGEN_KID}" \ + --arg proxygenSecretName "${proxygen_private_key_arn}" \ + '{apiName: $apiName, environment: $environment, secretName: $secretName, secretKey: $secretKey, secretCert: $secretCert, kid, $kid, proxygenSecretName: $proxygenSecretName}' > payload.json + + aws lambda invoke --function-name "${put_secret_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json + if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then + echo 'Error calling lambda' + cat out.txt + exit 1 + fi + echo "Secret stored successfully" + else + echo "Would call ${put_secret_lambda}" + fi +fi + +echo +echo "Deploy the API instance using Proxygen proxy lambda" +if [[ "${DRY_RUN}" == "false" ]]; then + + jq -n --argfile spec "${SPEC_PATH}" \ + --arg apiName "${apigee_api}" \ + --arg environment "${APIGEE_ENVIRONMENT}" \ + --arg instance "${instance}" \ + --arg kid "${PROXYGEN_KID}" \ + --arg proxygenSecretName "${proxygen_private_key_arn}" \ + '{apiName: $apiName, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json + + aws lambda invoke --function-name "${instance_put_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json + + if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then + echo 'Error calling lambda' + cat out.txt + exit 1 + fi + echo "Instance deployed" +else + echo "Would call ${instance_put_lambda}" +fi + +# if [[ "${APIGEE_ENVIRONMENT}" == "int" ]]; then +# echo +# echo "Deploy the API spec to prod catalogue as it is int environment" +# if [[ "${DRY_RUN}" == "false" ]]; then +# jq -n --argfile spec "${SPEC_PATH}" \ +# --arg apiName "${apigee_api}" \ +# --arg environment "prod" \ +# --arg instance "${instance}" \ +# --arg kid "${PROXYGEN_KID}" \ +# --arg proxygenSecretName "${proxygen_private_key_arn}" \ +# '{apiName: $apiName, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json + +# aws lambda invoke --function-name "${spec_publish_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json + +# if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then +# echo 'Error calling lambda' +# cat out.txt +# exit 1 +# fi +# echo "Spec deployed" +# else +# echo "Would call ${spec_publish_lambda}" +# fi +# fi + +if [[ "${APIGEE_ENVIRONMENT}" == "internal-dev" && "${IS_PULL_REQUEST}" == "false" ]]; then + echo + echo "Deploy the API spec to uat catalogue as it is internal-dev environment" + if [[ "${DRY_RUN}" == "false" ]]; then + jq -n --argfile spec "${SPEC_PATH}" \ + --arg apiName "${apigee_api}" \ + --arg environment "uat" \ + --arg instance "${instance}" \ + --arg kid "${PROXYGEN_KID}" \ + --arg proxygenSecretName "${proxygen_private_key_arn}" \ + '{apiName: $apiName, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json + + aws lambda invoke --function-name "${spec_publish_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json + + if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then + echo 'Error calling lambda' + cat out.txt + exit 1 + fi + echo "Spec deployed" + else + echo "Would call ${spec_publish_lambda}" + fi +fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f93cd02ef..f759dcf34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,6 +67,7 @@ jobs: TARGET_ENVIRONMENT: dev APIGEE_ENVIRONMENT: internal-dev ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code TRUSTSTORE_FILE: pfp-truststore.pem VERSION_NUMBER: ${{needs.tag_release.outputs.version_tag}} @@ -90,6 +91,7 @@ jobs: INT_CLOUD_FORMATION_CHECK_VERSION_ROLE: ${{ secrets.INT_CLOUD_FORMATION_CHECK_VERSION_ROLE }} PROD_CLOUD_FORMATION_CHECK_VERSION_ROLE: ${{ secrets.PROD_CLOUD_FORMATION_CHECK_VERSION_ROLE }} DEV_CLOUD_FORMATION_EXECUTE_LAMBDA_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_EXECUTE_LAMBDA_ROLE }} + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} release_dev_sandbox: needs: [tag_release, package_code, get_commit_id] @@ -100,6 +102,7 @@ jobs: TARGET_ENVIRONMENT: dev APIGEE_ENVIRONMENT: internal-dev-sandbox ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_sandbox_code TRUSTSTORE_FILE: pfp-sandbox-truststore.pem VERSION_NUMBER: ${{needs.tag_release.outputs.version_tag}} @@ -114,6 +117,7 @@ jobs: CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_DEPLOY_ROLE }} TARGET_SPINE_SERVER: sandbox TARGET_SERVICE_SEARCH_SERVER: sandbox + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} release_qa: needs: @@ -131,6 +135,7 @@ jobs: TARGET_ENVIRONMENT: qa APIGEE_ENVIRONMENT: internal-qa ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code TRUSTSTORE_FILE: pfp-truststore.pem VERSION_NUMBER: ${{needs.tag_release.outputs.version_tag}} @@ -148,3 +153,4 @@ jobs: CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.QA_CLOUD_FORMATION_DEPLOY_ROLE }} TARGET_SPINE_SERVER: ${{ secrets.QA_TARGET_SPINE_SERVER }} TARGET_SERVICE_SEARCH_SERVER: ${{ secrets.QA_TARGET_SERVICE_SEARCH_SERVER }} + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 185f0d676..c353e58dd 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -100,13 +100,15 @@ jobs: needs: [get_issue_number, package_code, get_commit_id] uses: ./.github/workflows/sam_release_code.yml with: + IS_PULL_REQUEST: true STACK_NAME: pfp-pr-${{needs.get_issue_number.outputs.issue_number}} ARTIFACT_BUCKET_PREFIX: PR-${{needs.get_issue_number.outputs.issue_number}} TARGET_ENVIRONMENT: dev-pr APIGEE_ENVIRONMENT: internal-dev - ENABLE_MUTUAL_TLS: false + ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code - TRUSTSTORE_FILE: pfp-truststore.pem + TRUSTSTORE_FILE: pfp-truststore-pr.pem # temporary VERSION_NUMBER: PR-${{ needs.get_issue_number.outputs.issue_number }} COMMIT_ID: ${{ needs.get_commit_id.outputs.commit_id }} LOG_LEVEL: DEBUG @@ -117,11 +119,13 @@ jobs: RUN_REGRESSION_TESTS: true REGRESSION_TEST_PRODUCT: PFP-AWS FORWARD_CSOC_LOGS: false + DEPLOY_APIGEE: true # temporary secrets: REGRESSION_TESTS_PEM: ${{ secrets.REGRESSION_TESTS_PEM }} CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_DEPLOY_ROLE }} TARGET_SPINE_SERVER: ${{ secrets.DEV_TARGET_SPINE_SERVER }} TARGET_SERVICE_SEARCH_SERVER: ${{ secrets.DEV_TARGET_SERVICE_SEARCH_SERVER }} + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} release_sandbox_code: needs: [get_issue_number, package_code, get_commit_id] @@ -132,6 +136,7 @@ jobs: TARGET_ENVIRONMENT: dev-pr APIGEE_ENVIRONMENT: internal-dev-sandbox ENABLE_MUTUAL_TLS: false + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_sandbox_code TRUSTSTORE_FILE: pfp-sandbox-truststore.pem VERSION_NUMBER: PR-${{ needs.get_issue_number.outputs.issue_number }} @@ -146,3 +151,4 @@ jobs: CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_DEPLOY_ROLE }} TARGET_SPINE_SERVER: sandbox TARGET_SERVICE_SEARCH_SERVER: sandbox + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c7238c927..ea14eb04f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -64,6 +64,7 @@ jobs: TARGET_ENVIRONMENT: dev APIGEE_ENVIRONMENT: internal-dev ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code TRUSTSTORE_FILE: pfp-truststore.pem VERSION_NUMBER: ${{needs.tag_release.outputs.version_tag}} @@ -90,7 +91,7 @@ jobs: INT_CLOUD_FORMATION_CHECK_VERSION_ROLE: ${{ secrets.INT_CLOUD_FORMATION_CHECK_VERSION_ROLE }} PROD_CLOUD_FORMATION_CHECK_VERSION_ROLE: ${{ secrets.PROD_CLOUD_FORMATION_CHECK_VERSION_ROLE }} DEV_CLOUD_FORMATION_EXECUTE_LAMBDA_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_EXECUTE_LAMBDA_ROLE }} - + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} release_dev_sandbox: needs: [tag_release, package_code, get_commit_id] uses: ./.github/workflows/sam_release_code.yml @@ -100,6 +101,7 @@ jobs: TARGET_ENVIRONMENT: dev APIGEE_ENVIRONMENT: internal-dev-sandbox ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_sandbox_code TRUSTSTORE_FILE: pfp-sandbox-truststore.pem VERSION_NUMBER: ${{needs.tag_release.outputs.version_tag}} @@ -117,6 +119,7 @@ jobs: CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_DEPLOY_ROLE }} TARGET_SPINE_SERVER: sandbox TARGET_SERVICE_SEARCH_SERVER: sandbox + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} release_ref: needs: @@ -134,6 +137,7 @@ jobs: TARGET_ENVIRONMENT: ref APIGEE_ENVIRONMENT: ref ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code TRUSTSTORE_FILE: pfp-truststore.pem VERSION_NUMBER: ${{needs.tag_release.outputs.version_tag}} @@ -153,7 +157,7 @@ jobs: CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.REF_CLOUD_FORMATION_DEPLOY_ROLE }} TARGET_SPINE_SERVER: ${{ secrets.REF_TARGET_SPINE_SERVER }} TARGET_SERVICE_SEARCH_SERVER: ${{ secrets.REF_TARGET_SERVICE_SEARCH_SERVER }} - + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} release_qa: needs: [ @@ -170,6 +174,7 @@ jobs: TARGET_ENVIRONMENT: qa APIGEE_ENVIRONMENT: internal-qa ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code TRUSTSTORE_FILE: pfp-truststore.pem VERSION_NUMBER: ${{needs.tag_release.outputs.version_tag}} @@ -190,7 +195,7 @@ jobs: CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.QA_CLOUD_FORMATION_DEPLOY_ROLE }} TARGET_SPINE_SERVER: ${{ secrets.QA_TARGET_SPINE_SERVER }} TARGET_SERVICE_SEARCH_SERVER: ${{ secrets.QA_TARGET_SERVICE_SEARCH_SERVER }} - + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} release_int: needs: [tag_release, release_qa, package_code, get_commit_id] uses: ./.github/workflows/sam_release_code.yml @@ -200,6 +205,7 @@ jobs: TARGET_ENVIRONMENT: int APIGEE_ENVIRONMENT: int ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code TRUSTSTORE_FILE: pfp-truststore.pem VERSION_NUMBER: ${{needs.tag_release.outputs.version_tag}} @@ -226,7 +232,7 @@ jobs: INT_CLOUD_FORMATION_CHECK_VERSION_ROLE: ${{ secrets.INT_CLOUD_FORMATION_CHECK_VERSION_ROLE }} PROD_CLOUD_FORMATION_CHECK_VERSION_ROLE: ${{ secrets.PROD_CLOUD_FORMATION_CHECK_VERSION_ROLE }} DEV_CLOUD_FORMATION_EXECUTE_LAMBDA_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_EXECUTE_LAMBDA_ROLE }} - + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} release_sandbox: needs: [tag_release, release_qa, package_code, get_commit_id] uses: ./.github/workflows/sam_release_code.yml @@ -236,6 +242,7 @@ jobs: TARGET_ENVIRONMENT: int APIGEE_ENVIRONMENT: int-sandbox ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_sandbox_code TRUSTSTORE_FILE: pfp-sandbox-truststore.pem VERSION_NUMBER: ${{needs.tag_release.outputs.version_tag}} @@ -250,6 +257,7 @@ jobs: CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.INT_CLOUD_FORMATION_DEPLOY_ROLE }} TARGET_SPINE_SERVER: sandbox TARGET_SERVICE_SEARCH_SERVER: sandbox + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} release_prod: needs: @@ -261,6 +269,7 @@ jobs: TARGET_ENVIRONMENT: prod APIGEE_ENVIRONMENT: prod ENABLE_MUTUAL_TLS: true + MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code TRUSTSTORE_FILE: pfp-truststore.pem VERSION_NUMBER: ${{needs.tag_release.outputs.version_tag}} @@ -283,3 +292,4 @@ jobs: INT_CLOUD_FORMATION_CHECK_VERSION_ROLE: ${{ secrets.INT_CLOUD_FORMATION_CHECK_VERSION_ROLE }} PROD_CLOUD_FORMATION_CHECK_VERSION_ROLE: ${{ secrets.PROD_CLOUD_FORMATION_CHECK_VERSION_ROLE }} DEV_CLOUD_FORMATION_EXECUTE_LAMBDA_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_EXECUTE_LAMBDA_ROLE }} + PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PROD_ROLE }} diff --git a/.github/workflows/sam_release_code.yml b/.github/workflows/sam_release_code.yml index 3e087af3e..c6247a57d 100644 --- a/.github/workflows/sam_release_code.yml +++ b/.github/workflows/sam_release_code.yml @@ -3,6 +3,9 @@ name: sam release code on: workflow_call: inputs: + IS_PULL_REQUEST: + type: boolean + default: false STACK_NAME: required: true type: string @@ -75,6 +78,12 @@ on: TC009_NHS_NUMBERS: required: false type: string + DEPLOY_APIGEE: + type: boolean + default: true + MTLS_KEY: + type: string + required: true secrets: CLOUD_FORMATION_DEPLOY_ROLE: required: true @@ -92,6 +101,8 @@ on: required: false REGRESSION_TESTS_PEM: required: true + PROXYGEN_ROLE: + required: true jobs: sam_release_code: @@ -160,6 +171,47 @@ jobs: TC009_NHS_NUMBERS: ${{ inputs.TC009_NHS_NUMBERS || '9992387920' }} run: ./release_code.sh + - name: get mtls secrets + shell: bash + run: | + mkdir -p ~/.proxygen/tmp + client_private_key_arn=$(aws cloudformation list-exports --query "Exports[?Name=='account-resources:PfpClientKeySecret'].Value" --output text) + client_cert_arn=$(aws cloudformation list-exports --query "Exports[?Name=='account-resources:PfpClientCertSecret'].Value" --output text) + aws secretsmanager get-secret-value --secret-id "${client_private_key_arn}" --query SecretString --output text > ~/.proxygen/tmp/client_private_key + aws secretsmanager get-secret-value --secret-id "${client_cert_arn}" --query SecretString --output text > ~/.proxygen/tmp/client_cert + + - name: Configure AWS Credentials for api release + uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 + with: + aws-region: eu-west-2 + role-to-assume: ${{ secrets.PROXYGEN_ROLE }} + role-session-name: pfp-api-proxygen + + - name: Deploy PFP API to Apigee + shell: bash + if: ${{ inputs.DEPLOY_APIGEE == true && always() && !failure() && !cancelled() }} + env: + API_TYPE: standard + VERSION_NUMBER: ${{ inputs.VERSION_NUMBER }} + SPEC_PATH: ./.build/packages/specification/dist/prescriptions-for-patients.resolved.json + STACK_NAME: ${{ inputs.STACK_NAME }} + AWS_ENVIRONMENT: ${{ inputs.TARGET_ENVIRONMENT }} + APIGEE_ENVIRONMENT: ${{ inputs.APIGEE_ENVIRONMENT }} + PROXYGEN_PRIVATE_KEY_NAME: PrescriptonsForPatientsProxygenPrivateKey + PROXYGEN_KID: prescriptions-for-patients + DRY_RUN: false + ENABLE_MUTUAL_TLS: ${{ inputs.ENABLE_MUTUAL_TLS }} + MTLS_KEY: ${{ inputs.MTLS_KEY }} + IS_PULL_REQUEST: ${{ inputs.IS_PULL_REQUEST }} + run: ./.github/scripts/deploy_api.sh + + - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 + name: Upload specs + with: + name: ${{ inputs.APIGEE_ENVIRONMENT }}-specs + path: | + ./.build/packages/specification/dist/prescriptions-for-patients.resolved.json + - name: create_int_release_notes uses: ./.github/actions/update_confluence_jira if: ${{ inputs.CREATE_INT_RELEASE_NOTES == true && always() && !failure() && !cancelled() }} diff --git a/package-lock.json b/package-lock.json index f5fa3c3b9..82032a0aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,8 @@ "packages/serviceSearchClient", "packages/common/utilities", "packages/common/testing", - "packages/distanceSelling" + "packages/distanceSelling", + "packages/specification" ], "dependencies": { "esbuild": "^0.27.1" @@ -642,7 +643,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.946.0.tgz", "integrity": "sha512-pXBHu9mq8WJzny3vgtjKUmo2OXsQLlaDjFuBQCapijZrtOq5Bu2fx2EEtTMAR3/TMBCIeqNAPEr5udlOiTdoRw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -1197,7 +1197,6 @@ "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -1628,6 +1627,16 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", @@ -1741,6 +1750,30 @@ "tslib": "^2.4.0" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.1", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.1.tgz", @@ -2366,6 +2399,24 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@exodus/schemasafe": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", + "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -2418,6 +2469,16 @@ "url": "https://github.com/sponsors/nzakas" } }, + "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==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.10.0" + } + }, "node_modules/@humanwhocodes/retry": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", @@ -2432,6 +2493,29 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -3000,238 +3084,884 @@ "mustache": "^4.2.0" } }, - "node_modules/@pfp-common/testing": { - "resolved": "packages/common/testing", - "link": true - }, - "node_modules/@pfp-common/utilities": { - "resolved": "packages/common/utilities", - "link": true - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "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==", "dev": true, "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://opencollective.com/pkgr" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@prescriptionsforpatients/distanceSelling": { - "resolved": "packages/distanceSelling", - "link": true - }, - "node_modules/@prescriptionsforpatients/serviceSearchClient": { - "resolved": "packages/serviceSearchClient", - "link": true - }, - "node_modules/@sinclair/typebox": { - "version": "0.34.40", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.40.tgz", - "integrity": "sha512-gwBNIP8ZAYev/ORDWW0QvxdwPXwxBtLsdsJgSc7eDIRt8ubP+rxUBzPsrwnu16fgEF8Bx4lh/+mvQvJzcTM6Kw==", + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/@opentelemetry/api-logs": { + "version": "0.202.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.202.0.tgz", + "integrity": "sha512-fTBjMqKCfotFWfLzaKyhjLvyEyq5vDKTTFfBmx21btv3gvy8Lq6N5Dh2OzqeuN4DjtpSvNT1uNVfg08eD2Rfxw==", "dev": true, - "license": "BSD-3-Clause", + "license": "Apache-2.0", "dependencies": { - "type-detect": "4.0.8" + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "node_modules/@opentelemetry/context-async-hooks": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.1.tgz", + "integrity": "sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@smithy/abort-controller": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz", - "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==", + "node_modules/@opentelemetry/core": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz", + "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" + "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { - "node": ">=18.0.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@smithy/config-resolver": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz", - "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==", + "node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.202.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.202.0.tgz", + "integrity": "sha512-/hKE8DaFCJuaQqE1IxpgkcjOolUIwgi3TgHElPVKGdGRBSmJMTmN/cr6vWa55pCJIXPyhKvcMrbrya7DZ3VmzA==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/types": "^4.9.0", - "@smithy/util-config-provider": "^4.2.0", - "@smithy/util-endpoints": "^3.2.5", - "@smithy/util-middleware": "^4.2.5", - "tslib": "^2.6.2" + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.202.0", + "@opentelemetry/otlp-transformer": "0.202.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1" }, "engines": { - "node": ">=18.0.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@smithy/core": { - "version": "3.18.7", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.7.tgz", - "integrity": "sha512-axG9MvKhMWOhFbvf5y2DuyTxQueO0dkedY9QC3mAfndLosRI/9LJv8WaL0mw7ubNhsO4IuXX9/9dYGPFvHrqlw==", + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.202.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.202.0.tgz", + "integrity": "sha512-nMEOzel+pUFYuBJg2znGmHJWbmvMbdX5/RhoKNKowguMbURhz0fwik5tUKplLcUtl8wKPL1y9zPnPxeBn65N0Q==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^4.2.6", - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-middleware": "^4.2.5", - "@smithy/util-stream": "^4.5.6", - "@smithy/util-utf8": "^4.2.0", - "@smithy/uuid": "^1.1.0", - "tslib": "^2.6.2" + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-transformer": "0.202.0" }, "engines": { - "node": ">=18.0.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz", - "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==", + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.202.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.202.0.tgz", + "integrity": "sha512-5XO77QFzs9WkexvJQL9ksxL8oVFb/dfi9NWQSq7Sv0Efr9x3N+nb1iklP1TeVgxqJ7m1xWiC/Uv3wupiQGevMw==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/property-provider": "^4.2.5", - "@smithy/types": "^4.9.0", - "@smithy/url-parser": "^4.2.5", - "tslib": "^2.6.2" + "@opentelemetry/api-logs": "0.202.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-logs": "0.202.0", + "@opentelemetry/sdk-metrics": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1", + "protobufjs": "^7.3.0" }, "engines": { - "node": ">=18.0.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz", - "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==", + "node_modules/@opentelemetry/resources": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz", + "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.5", - "@smithy/querystring-builder": "^4.2.5", - "@smithy/types": "^4.9.0", - "@smithy/util-base64": "^4.3.0", - "tslib": "^2.6.2" + "@opentelemetry/core": "2.0.1", + "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { - "node": ">=18.0.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, - "node_modules/@smithy/hash-node": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz", - "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==", + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.202.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.202.0.tgz", + "integrity": "sha512-pv8QiQLQzk4X909YKm0lnW4hpuQg4zHwJ4XBd5bZiXcd9urvrJNoNVKnxGHPiDVX/GiLFvr5DMYsDBQbZCypRQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", - "@smithy/util-buffer-from": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" + "@opentelemetry/api-logs": "0.202.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1" }, "engines": { - "node": ">=18.0.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, - "node_modules/@smithy/invalid-dependency": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz", - "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==", + "node_modules/@opentelemetry/sdk-metrics": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz", + "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1" }, "engines": { - "node": ">=18.0.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, - "node_modules/@smithy/is-array-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", - "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz", + "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "tslib": "^2.6.2" + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { - "node": ">=18.0.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, - "node_modules/@smithy/middleware-content-length": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz", - "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==", + "node_modules/@opentelemetry/sdk-trace-node": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.0.1.tgz", + "integrity": "sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" + "@opentelemetry/context-async-hooks": "2.0.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1" }, "engines": { - "node": ">=18.0.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@smithy/middleware-endpoint": { - "version": "4.3.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.14.tgz", - "integrity": "sha512-v0q4uTKgBM8dsqGjqsabZQyH85nFaTnFcgpWU1uydKFsdyyMzfvOkNum9G7VK+dOP01vUnoZxIeRiJ6uD0kjIg==", + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.34.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.34.0.tgz", + "integrity": "sha512-aKcOkyrorBGlajjRdVoJWHTxfxO1vCNHLJVlSDaRHDIdjU+pX8IYQPvPDkYiujKLbRnWU+1TBwEt0QRgSm4SGA==", + "dev": true, "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.18.7", - "@smithy/middleware-serde": "^4.2.6", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "@smithy/url-parser": "^4.2.5", - "@smithy/util-middleware": "^4.2.5", - "tslib": "^2.6.2" - }, "engines": { - "node": ">=18.0.0" + "node": ">=14" } }, - "node_modules/@smithy/middleware-retry": { - "version": "4.4.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.14.tgz", - "integrity": "sha512-Z2DG8Ej7FyWG1UA+7HceINtSLzswUgs2np3sZX0YBBxCt+CXG4QUxv88ZDS3+2/1ldW7LqtSY1UO/6VQ1pND8Q==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/service-error-classification": "^4.2.5", + "node_modules/@pfp-common/testing": { + "resolved": "packages/common/testing", + "link": true + }, + "node_modules/@pfp-common/utilities": { + "resolved": "packages/common/utilities", + "link": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@prescriptionsforpatients/distanceSelling": { + "resolved": "packages/distanceSelling", + "link": true + }, + "node_modules/@prescriptionsforpatients/serviceSearchClient": { + "resolved": "packages/serviceSearchClient", + "link": true + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@redocly/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-EDtsGZS964mf9zAUXAl9Ew16eYbeyAFWhsPr0fX6oaJxgd8rApYlPBf0joyhnUHz88WxrigyFtTaqqzXNzPgqw==", + "dev": 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/@redocly/ajv/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==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/cli": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/@redocly/cli/-/cli-2.12.6.tgz", + "integrity": "sha512-GAg0JzSxK5ZXAHQAAGNwXpDCl82VuJssV+kN0PFVb4IzZDq4tXtkZeS7v8YrD7h7sP2TzMEpxxQWumRAFVb3Lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@opentelemetry/exporter-trace-otlp-http": "0.202.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-node": "2.0.1", + "@opentelemetry/semantic-conventions": "1.34.0", + "@redocly/openapi-core": "2.12.6", + "@redocly/respect-core": "2.12.6", + "abort-controller": "^3.0.0", + "chokidar": "^3.5.1", + "colorette": "^1.2.0", + "cookie": "^0.7.2", + "dotenv": "16.4.7", + "form-data": "^4.0.4", + "glob": "^11.0.1", + "handlebars": "^4.7.6", + "https-proxy-agent": "^7.0.5", + "mobx": "^6.0.4", + "pluralize": "^8.0.0", + "react": "^17.0.0 || ^18.2.0 || ^19.2.1", + "react-dom": "^17.0.0 || ^18.2.0 || ^19.2.1", + "redoc": "2.5.1", + "semver": "^7.5.2", + "set-cookie-parser": "^2.3.5", + "simple-websocket": "^9.0.0", + "styled-components": "^6.0.7", + "ulid": "^3.0.1", + "undici": "^6.21.3", + "yargs": "17.0.1" + }, + "bin": { + "openapi": "bin/cli.js", + "redocly": "bin/cli.js" + }, + "engines": { + "node": ">=22.12.0 || >=20.19.0 <21.0.0", + "npm": ">=10" + } + }, + "node_modules/@redocly/cli/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@redocly/cli/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/@redocly/cli/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/cli/node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@redocly/cli/node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@redocly/cli/node_modules/lru-cache": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@redocly/cli/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@redocly/cli/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@redocly/cli/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@redocly/cli/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@redocly/cli/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@redocly/cli/node_modules/yargs": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.0.1.tgz", + "integrity": "sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@redocly/cli/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/@redocly/config": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.41.0.tgz", + "integrity": "sha512-8yJ2e+ex8KVF25zijdpDbAEjyubk7NLfHsLI8h0MUnLEo2iEg6rTCDT9Qw71XDqd5UlXvfJb0Z0h6dd+Y6pWLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-schema-to-ts": "2.7.2" + } + }, + "node_modules/@redocly/openapi-core": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-2.12.6.tgz", + "integrity": "sha512-X4NK5wW0lr1Cdd5CB/St6hABU7OLw3kaI9gxVODENuxcMCIWa27v8AZwUJom5arp3f9kY0KJwNNqBghrWDQC+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/ajv": "^8.17.1", + "@redocly/config": "^0.41.0", + "ajv-formats": "^3.0.1", + "colorette": "^1.2.0", + "js-levenshtein": "^1.1.6", + "js-yaml": "^4.1.0", + "picomatch": "^4.0.3", + "pluralize": "^8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=22.12.0 || >=20.19.0 <21.0.0", + "npm": ">=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==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@redocly/openapi-core/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@redocly/respect-core": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/@redocly/respect-core/-/respect-core-2.12.6.tgz", + "integrity": "sha512-F9Zla4M9wGZGfgavWddC4AObHkfPzsTCNAmyBOAj/ub8ycjfI719MqnEZvurIMYxmVDoTv4maHnuich5IGVzlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@faker-js/faker": "^7.6.0", + "@noble/hashes": "^1.8.0", + "@redocly/ajv": "8.17.1", + "@redocly/openapi-core": "2.12.6", + "better-ajv-errors": "^1.2.0", + "colorette": "^2.0.20", + "json-pointer": "^0.6.2", + "jsonpath-rfc9535": "1.3.0", + "openapi-sampler": "^1.6.1", + "outdent": "^0.8.0" + }, + "engines": { + "node": ">=22.12.0 || >=20.19.0 <21.0.0", + "npm": ">=10" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.40", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.40.tgz", + "integrity": "sha512-gwBNIP8ZAYev/ORDWW0QvxdwPXwxBtLsdsJgSc7eDIRt8ubP+rxUBzPsrwnu16fgEF8Bx4lh/+mvQvJzcTM6Kw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz", + "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz", + "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "3.18.7", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.7.tgz", + "integrity": "sha512-axG9MvKhMWOhFbvf5y2DuyTxQueO0dkedY9QC3mAfndLosRI/9LJv8WaL0mw7ubNhsO4IuXX9/9dYGPFvHrqlw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/middleware-serde": "^4.2.6", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz", + "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz", + "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz", + "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz", + "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", + "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz", + "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.3.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.14.tgz", + "integrity": "sha512-v0q4uTKgBM8dsqGjqsabZQyH85nFaTnFcgpWU1uydKFsdyyMzfvOkNum9G7VK+dOP01vUnoZxIeRiJ6uD0kjIg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.18.7", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-middleware": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.4.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.14.tgz", + "integrity": "sha512-Z2DG8Ej7FyWG1UA+7HceINtSLzswUgs2np3sZX0YBBxCt+CXG4QUxv88ZDS3+2/1ldW7LqtSY1UO/6VQ1pND8Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/service-error-classification": "^4.2.5", "@smithy/smithy-client": "^4.9.10", "@smithy/types": "^4.9.0", "@smithy/util-middleware": "^4.2.5", @@ -3822,7 +4552,6 @@ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -3834,6 +4563,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/stylis": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", + "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -3887,7 +4631,6 @@ "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.48.1", "@typescript-eslint/types": "8.48.1", @@ -4369,13 +5112,25 @@ "dev": true, "license": "ISC" }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4406,6 +5161,16 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4423,6 +5188,48 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": 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/ajv-formats/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==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -4482,6 +5289,10 @@ "node": ">= 8" } }, + "node_modules/apim-spec": { + "resolved": "packages/specification", + "link": true + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -4578,7 +5389,6 @@ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "license": "MIT", - "peer": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", @@ -4737,6 +5547,39 @@ ], "license": "MIT" }, + "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==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "@humanwhocodes/momoa": "^2.0.2", + "chalk": "^4.1.2", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0 < 4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "peerDependencies": { + "ajv": "4.11.8 - 8" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bowser": { "version": "2.12.1", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.1.tgz", @@ -4786,7 +5629,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001735", "electron-to-chromium": "^1.5.204", @@ -4888,6 +5730,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true, + "license": "MIT" + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -4908,6 +5757,16 @@ "node": ">=6" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001735", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz", @@ -4960,6 +5819,44 @@ "node": ">=10" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/ci-info": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", @@ -4983,6 +5880,13 @@ "dev": true, "license": "MIT" }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "dev": true, + "license": "MIT" + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -5061,6 +5965,16 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -5099,6 +6013,13 @@ "dev": true, "license": "MIT" }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true, + "license": "MIT" + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -5131,6 +6052,29 @@ "dev": true, "license": "MIT" }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/core-js": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz", + "integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -5153,6 +6097,35 @@ "node": ">= 8" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", @@ -5182,6 +6155,12 @@ "node": "*" } }, + "node_modules/decko": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decko/-/decko-1.2.0.tgz", + "integrity": "sha512-m8FnyHXV1QX+S1cl+KPFDIl6NMkxtKsy6+U/aYyjrOqWMuwAwYWu7ePqrsUHtDR5Y8Yk2pi/KIDSgF+vT4cPOQ==", + "dev": true + }, "node_modules/dedent": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", @@ -5271,6 +6250,29 @@ "node": ">=0.3.1" } }, + "node_modules/dompurify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "dev": true, + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -5378,6 +6380,13 @@ "node": ">= 0.4" } }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", + "dev": true, + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.27.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", @@ -5448,7 +6457,6 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -5686,6 +6694,23 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" + }, "node_modules/events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", @@ -5788,6 +6813,30 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fast-xml-parser": { "version": "5.2.5", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", @@ -5915,6 +6964,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/foreach": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", + "integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==", + "dev": true, + "license": "MIT" + }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", @@ -6046,6 +7102,19 @@ "node": ">= 0.4" } }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/getMyPrescriptions": { "resolved": "packages/getMyPrescriptions", "link": true @@ -6225,6 +7294,27 @@ "dev": true, "license": "MIT" }, + "node_modules/http2-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", + "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -6339,6 +7429,19 @@ "dev": true, "license": "MIT" }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-buffer": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", @@ -6626,7 +7729,6 @@ "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "30.2.0", "@jest/types": "30.2.0", @@ -7272,6 +8374,16 @@ "node": ">= 0.6.0" } }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7319,6 +8431,31 @@ "dev": true, "license": "MIT" }, + "node_modules/json-pointer": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.2.tgz", + "integrity": "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "foreach": "^2.0.4" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@types/json-schema": "^7.0.9", + "ts-algebra": "^1.2.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -7346,6 +8483,26 @@ "node": ">=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==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -7549,6 +8706,26 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "license": "MIT" }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -7559,6 +8736,13 @@ "yallist": "^3.0.2" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true, + "license": "MIT" + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -7592,6 +8776,26 @@ "tmpl": "1.0.5" } }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -7702,6 +8906,69 @@ "node": ">=10" } }, + "node_modules/mobx": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.15.0.tgz", + "integrity": "sha512-UczzB+0nnwGotYSgllfARAqWCJ5e/skuV2K/l+Zyck/H6pJIhLXuBnz+6vn2i211o7DtbE78HQtsYEKICHGI+g==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mobx" + } + }, + "node_modules/mobx-react": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-9.2.0.tgz", + "integrity": "sha512-dkGWCx+S0/1mfiuFfHRH8D9cplmwhxOV5CkXMp38u6rQGG2Pv3FWYztS0M7ncR6TyPRQKaTG/pnitInoYE9Vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mobx-react-lite": "^4.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mobx" + }, + "peerDependencies": { + "mobx": "^6.9.0", + "react": "^16.8.0 || ^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/mobx-react-lite": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-4.1.1.tgz", + "integrity": "sha512-iUxiMpsvNraCKXU+yPotsOncNNmyeS2B5DKL+TL6Tar/xm+wwNJAubJmtRSeAoYawdZqwv8Z/+5nPRHeQxTiXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.4.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mobx" + }, + "peerDependencies": { + "mobx": "^6.9.0", + "react": "^16.8.0 || ^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -7727,6 +8994,25 @@ "mustache": "bin/mustache" } }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/napi-postinstall": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", @@ -7761,6 +9047,40 @@ "resolved": "packages/nhsd-pfp-sandbox", "link": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-h2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", + "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "http2-client": "^1.2.5" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -7768,6 +9088,16 @@ "dev": true, "license": "MIT" }, + "node_modules/node-readfiles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", + "integrity": "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es6-promise": "^3.2.1" + } + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -7807,39 +9137,124 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "license": "ISC", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true, + "license": "ISC" + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/oas-kit-common": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", + "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/oas-linter": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", + "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@exodus/schemasafe": "^1.0.0-rc.2", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-resolver": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", + "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, "bin": { - "semver": "bin/semver" + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/oas-schema-walker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", + "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "license": "BSD-3-Clause", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "node_modules/oas-validator": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", + "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", "dev": true, - "license": "ISC" + "license": "BSD-3-Clause", + "dependencies": { + "call-me-maybe": "^1.0.1", + "oas-kit-common": "^1.0.8", + "oas-linter": "^3.2.2", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "reftools": "^1.1.9", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/once": { @@ -7868,6 +9283,50 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openapi-sampler": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.6.2.tgz", + "integrity": "sha512-NyKGiFKfSWAZr4srD/5WDhInOWDhfml32h/FKUqLpEwKJt0kG0LGUU0MdyNkKrVGuJnw6DuPWq/sHCwAMpiRxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.7", + "fast-xml-parser": "^4.5.0", + "json-pointer": "0.6.2" + } + }, + "node_modules/openapi-sampler/node_modules/fast-xml-parser": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", + "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.1.1" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/openapi-sampler/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -7918,6 +9377,13 @@ "os-tmpdir": "^1.0.0" } }, + "node_modules/outdent": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz", + "integrity": "sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==", + "dev": true, + "license": "MIT" + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -7999,6 +9465,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8060,6 +9533,13 @@ "dev": true, "license": "ISC" }, + "node_modules/perfect-scrollbar": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.6.tgz", + "integrity": "sha512-rixgxw3SxyJbCaSpo1n35A/fwI1r2rdwMKOTCg/AcG+xOEyZcE8UHVjpZMFCVImzsFoCZeJTT+M/rdEIQYO2nw==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -8159,6 +9639,29 @@ "node": ">=8" } }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/polished": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -8168,6 +9671,42 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "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.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -8206,6 +9745,60 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -8248,6 +9841,60 @@ "node": ">=0.4.x" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", + "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", + "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.1" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -8255,6 +9902,20 @@ "dev": true, "license": "MIT" }, + "node_modules/react-tabs": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-6.1.0.tgz", + "integrity": "sha512-6QtbTRDKM+jA/MZTTefvigNxo0zz+gnBTVFw2CFVvq+f2BuH0nF0vDLNClL045nuTAdOoK/IL1vTP0ZLX0DAyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "prop-types": "^15.5.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0" + } + }, "node_modules/read-installed": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz", @@ -8327,35 +9988,176 @@ "engines": { "node": "*" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/read-package-json/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-scoped-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "license": "ISC", + "dependencies": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redoc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.5.1.tgz", + "integrity": "sha512-LmqA+4A3CmhTllGG197F0arUpmChukAj9klfSdxNRemT9Hr07xXr7OGKu4PHzBs359sgrJ+4JwmOlM7nxLPGMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/openapi-core": "^1.4.0", + "classnames": "^2.3.2", + "decko": "^1.2.0", + "dompurify": "^3.2.4", + "eventemitter3": "^5.0.1", + "json-pointer": "^0.6.2", + "lunr": "^2.3.9", + "mark.js": "^8.11.1", + "marked": "^4.3.0", + "mobx-react": "9.2.0", + "openapi-sampler": "^1.5.0", + "path-browserify": "^1.0.1", + "perfect-scrollbar": "^1.5.5", + "polished": "^4.2.2", + "prismjs": "^1.29.0", + "prop-types": "^15.8.1", + "react-tabs": "^6.0.2", + "slugify": "~1.4.7", + "stickyfill": "^1.1.1", + "swagger2openapi": "^7.0.8", + "url-template": "^2.0.8" + }, + "engines": { + "node": ">=6.9", + "npm": ">=3.0.0" + }, + "peerDependencies": { + "core-js": "^3.1.4", + "mobx": "^6.0.4", + "react": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "styled-components": "^4.1.1 || ^5.1.1 || ^6.0.5" + } + }, + "node_modules/redoc/node_modules/@redocly/config": { + "version": "0.22.2", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.22.2.tgz", + "integrity": "sha512-roRDai8/zr2S9YfmzUfNhKjOF0NdcOIqF7bhf4MVC5UxpjIysDjyudvlAiVbpPHp3eDRWbdzUgtkK1a7YiDNyQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/redoc/node_modules/@redocly/openapi-core": { + "version": "1.34.6", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.34.6.tgz", + "integrity": "sha512-2+O+riuIUgVSuLl3Lyh5AplWZyVMNuG2F98/o6NrutKJfW4/GTZdPpZlIphS0HGgcOHgmWcCSHj+dWFlZaGSHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/ajv": "^8.11.2", + "@redocly/config": "^0.22.0", + "colorette": "^1.2.0", + "https-proxy-agent": "^7.0.5", + "js-levenshtein": "^1.1.6", + "js-yaml": "^4.1.0", + "minimatch": "^5.0.1", + "pluralize": "^8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=18.17.0", + "npm": ">=9.5.0" + } + }, + "node_modules/redoc/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==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/redoc/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/read-package-json/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/redoc/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=10" } }, - "node_modules/readdir-scoped-modules": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", - "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", - "deprecated": "This functionality has been moved to @npmcli/fs", + "node_modules/reftools": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", + "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", "dev": true, - "license": "ISC", - "dependencies": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" + "license": "BSD-3-Clause", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, "node_modules/require-directory": { @@ -8368,6 +10170,16 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -8422,6 +10234,37 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", @@ -8445,6 +10288,13 @@ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", "license": "ISC" }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -8458,6 +10308,13 @@ "node": ">=10" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "dev": true, + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -8475,6 +10332,13 @@ "node": ">= 0.4" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "dev": true, + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -8498,6 +10362,66 @@ "node": ">=8" } }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true, + "license": "MIT" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -8511,6 +10435,34 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-websocket": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/simple-websocket/-/simple-websocket-9.1.0.tgz", + "integrity": "sha512-8MJPnjRN6A8UCp1I+H/dSFyjwJhp6wta4hsVRhjf8w9qBHRzxYt14RaOcjvQnhD1N4yKOddEjflwMnQM4VtXjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "debug": "^4.3.1", + "queue-microtask": "^1.2.2", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0", + "ws": "^7.4.2" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -8531,6 +10483,16 @@ "node": "*" } }, + "node_modules/slugify": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.7.tgz", + "integrity": "sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -8541,6 +10503,16 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", @@ -8652,6 +10624,22 @@ "resolved": "packages/statusLambda", "link": true }, + "node_modules/stickyfill": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stickyfill/-/stickyfill-1.1.1.tgz", + "integrity": "sha512-GCp7vHAfpao+Qh/3Flh9DXEJ/qSi0KJwJw6zYlZOtRYXWUIpMM6mC2rIep/dK8RQqwW0KxGJIllmjPIBOGN8AA==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -8838,6 +10826,49 @@ ], "license": "MIT" }, + "node_modules/styled-components": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.19.tgz", + "integrity": "sha512-1v/e3Dl1BknC37cXMhwGomhO8AkYmN41CqyX9xhUDxry1ns3BFQy2lLDRQXJRdVVWB9OHemv/53xaStimvWyuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emotion/is-prop-valid": "1.2.2", + "@emotion/unitless": "0.8.1", + "@types/stylis": "4.2.5", + "css-to-react-native": "3.2.0", + "csstype": "3.1.3", + "postcss": "8.4.49", + "shallowequal": "1.1.0", + "stylis": "4.3.2", + "tslib": "2.6.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true, + "license": "0BSD" + }, + "node_modules/stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==", + "dev": true, + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -8864,6 +10895,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger2openapi": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", + "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "call-me-maybe": "^1.0.1", + "node-fetch": "^2.6.1", + "node-fetch-h2": "^2.3.0", + "node-readfiles": "^0.2.0", + "oas-kit-common": "^1.0.8", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "oas-validator": "^5.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "boast": "boast.js", + "oas-validate": "oas-validate.js", + "swagger2openapi": "swagger2openapi.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, "node_modules/synckit": { "version": "0.11.11", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", @@ -8982,7 +11041,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -9010,6 +11068,13 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, "node_modules/treeify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", @@ -9020,6 +11085,13 @@ "node": ">=0.6" } }, + "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==", + "dev": true, + "license": "MIT" + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -9105,7 +11177,6 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -9150,6 +11221,26 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "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", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -9192,7 +11283,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9215,6 +11305,26 @@ "node": ">=0.8.0" } }, + "node_modules/ulid": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/ulid/-/ulid-3.0.2.tgz", + "integrity": "sha512-yu26mwteFYzBAot7KVMqFGCVpsF6g8wXfJzQUHvu1no3+rRRSFcSV2nKeYvNPLD2J4b08jYBDhHUjeH0ygIl9w==", + "dev": true, + "license": "MIT", + "bin": { + "ulid": "dist/cli.js" + } + }, + "node_modules/undici": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.22.0.tgz", + "integrity": "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/undici-types": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", @@ -9308,12 +11418,29 @@ "querystring": "0.2.0" } }, + "node_modules/url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==", + "dev": true, + "license": "BSD" + }, "node_modules/url/node_modules/punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", "license": "MIT" }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -9327,6 +11454,13 @@ "which-typed-array": "^1.1.2" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, "node_modules/util-extend": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", @@ -9399,6 +11533,24 @@ "node": ">=10.13.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -9569,6 +11721,28 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xml": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", @@ -9615,6 +11789,23 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -9840,6 +12031,19 @@ "axios-mock-adapter": "^2.1.0" } }, + "packages/specification": { + "name": "apim-spec", + "version": "0.0.1", + "license": "MIT", + "devDependencies": { + "@redocly/cli": "^2.12.3", + "tsx": "4.21.0" + }, + "engines": { + "node": "20.10.x", + "npm": "10.2.x" + } + }, "packages/statusLambda": { "version": "1.0.0", "license": "MIT", diff --git a/package.json b/package.json index 1cad6b91f..85924728c 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "packages/serviceSearchClient", "packages/common/utilities", "packages/common/testing", - "packages/distanceSelling" + "packages/distanceSelling", + "packages/specification" ], "devDependencies": { "@types/aws-lambda": "^8.10.159", diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/error/error-401.json b/packages/specification/examples/GetMyPrescriptions/Bundle/error/error-401.json new file mode 100644 index 000000000..ae3500f44 --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/error/error-401.json @@ -0,0 +1,19 @@ +{ + "resourceType": "OperationOutcome", + "issue": [ + { + "severity": "error", + "code": "forbidden", + "details": { + "coding": [ + { + "system": "https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode", + "version": "1", + "code": "ACCESS_DENIED", + "display": "Invalid access token" + } + ] + } + } + ] +} diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/error/error-500.json b/packages/specification/examples/GetMyPrescriptions/Bundle/error/error-500.json new file mode 100644 index 000000000..480c58be7 --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/error/error-500.json @@ -0,0 +1,19 @@ +{ + "resourceType": "OperationOutcome", + "issue": [ + { + "code": "security", + "severity": "fatal", + "details": { + "coding": [ + { + "system": "https://fhir.nhs.uk/CodeSystem/http-error-codes", + "code": "SERVER_ERROR", + "display": "500: The Server has encountered an error processing the request." + } + ] + }, + "diagnostics": "Spine certificate is not configured" + } + ] +} diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-distance-selling.json b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-distance-selling.json new file mode 100644 index 000000000..a5946fa23 --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-distance-selling.json @@ -0,0 +1,232 @@ +{ + "resourceType": "Bundle", + "id": "155e1102-9e71-4f19-9453-b905c0bbc494", + "meta": { + "lastUpdated": "2022-11-21T14:00:00+00:00" + }, + "type": "searchset", + "link": [ + { + "relation": "self", + "url": "https://sandbox.api.service.nhs.uk/electronic-prescriptions/Bundle" + } + ], + "total": 1, + "entry": [ + { + "fullUrl": "urn:uuid:0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:a54219b8-f741-4c47-b662-e4f8dfa49ab6", + "resource": { + "resourceType": "MedicationRequest", + "status": "completed", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "39732311000001104", + "display": "Amoxicillin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-01-16" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-01-18T08:13:24Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Collected" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666", + "resource": { + "resourceType": "PractitionerRole", + "id": "56166769-c1c4-4d07-afa8-132b5dfca666", + "practitioner": { + "reference": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a" + }, + "organization": { + "reference": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8" + } + } + }, + { + "fullUrl": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "resource": { + "resourceType": "Practitioner", + "id": "a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "name": [ + { + "family": "BOIN", + "given": [ + "C" + ], + "prefix": [ + "DR" + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "resource": { + "resourceType": "Organization", + "id": "3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "A83008" + } + ], + "name": "HALLGARTH SURGERY", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9737320" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "HALLGARTH SURGERY", + "CHEAPSIDE" + ], + "city": "SHILDON", + "district": "COUNTY DURHAM", + "postalCode": "DL4 2HP" + } + ] + } + }, + { + "fullUrl": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "resource": { + "resourceType": "Organization", + "id": "afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "FLM49" + } + ], + "name": "PHARMACY2U", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9999999" + }, + { + "system": "url", + "use": "work", + "value": "www.pharmacy2u.co.uk" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "text": "Unit 4B, Victoria Road", + "postalCode": "TR1 3FF" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:1a388581-dbbe-43e3-9054-f5976c0245e5", + "search": { + "mode": "outcome" + }, + "resource": { + "resourceType": "OperationOutcome", + "id": "1a388581-dbbe-43e3-9054-f5976c0245e5", + "meta": { + "lastUpdated": "2023-09-29T10:52:00+00:00" + }, + "issue": [ + { + "code": "business-rule", + "severity": "warning", + "details": { + "coding": [ + { + "system": "https://fhir.nhs.uk/CodeSystem/Spine-ErrorOrWarningCode", + "code": "INVALIDATED_RESOURCE", + "display": "Invalidated resource" + } + ] + }, + "diagnostics": "Some prescriptions have been invalidated so could not be returned." + } + ] + } + } + ] +} diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-empty.json b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-empty.json new file mode 100644 index 000000000..2bf4a3ade --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-empty.json @@ -0,0 +1,10 @@ +{ + "resourceType": "Bundle", + "id": "155e1102-9e71-4f19-9453-b905c0bbc494", + "meta": { + "lastUpdated": "2022-11-21T14:00:00+00:00" + }, + "type": "searchset", + "total": 0, + "entry": [] +} diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple-cancelled.json b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple-cancelled.json new file mode 100644 index 000000000..b41304c3e --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple-cancelled.json @@ -0,0 +1,686 @@ +{ + "resourceType": "Bundle", + "id": "155e1102-9e71-4f19-9453-b905c0bbc494", + "meta": { + "lastUpdated": "2022-11-21T14:00:00+00:00" + }, + "type": "searchset", + "total": 3, + "entry": [ + { + "fullUrl": "urn:uuid:0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:a54219b8-f741-4c47-b662-e4f8dfa49ab6", + "resource": { + "resourceType": "MedicationRequest", + "status": "cancelled", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "39732311000001104", + "display": "Amoxicillin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-02-27" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-03-02T14:04:36Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Prescriber Cancelled" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:6989b7bd-8db6-428c-a593-4022e3044c00", + "resource": { + "resourceType": "MedicationRequest", + "status": "stopped", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "322341003", + "display": "Co-codamol 30mg/500mg tablets" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-02-27" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-03-02T14:04:36Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Not Dispensed" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:2868554c-5565-4d31-b92a-c5b8dab8b90a", + "resource": { + "resourceType": "MedicationRequest", + "status": "cancelled", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "321080004", + "display": "Pseudoephedrine hydrochloride 60mg tablets" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-02-27" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-03-02T14:04:36Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Prescriber Cancelled" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:5cb17f5a-11ac-4e18-825f-6470467238b3", + "resource": { + "resourceType": "MedicationRequest", + "status": "stopped", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "324252006", + "display": "Azithromycin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-02-27" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-03-02T14:04:36Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Not Dispensed" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666", + "resource": { + "resourceType": "PractitionerRole", + "id": "56166769-c1c4-4d07-afa8-132b5dfca666", + "practitioner": { + "reference": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a" + }, + "organization": { + "reference": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8" + } + } + }, + { + "fullUrl": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "resource": { + "resourceType": "Practitioner", + "id": "a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "name": [ + { + "family": "BOIN", + "given": ["C"], + "prefix": ["DR"] + } + ] + } + }, + { + "fullUrl": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "resource": { + "resourceType": "Organization", + "id": "3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "A83008" + } + ], + "name": "HALLGARTH SURGERY", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9737320" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "HALLGARTH SURGERY", + "CHEAPSIDE", + "SHILDON", + "COUNTY DURHAM" + ], + "postalCode": "DL4 2HP" + } + ] + } + }, + { + "fullUrl": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "resource": { + "resourceType": "Organization", + "id": "afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "VNE51" + } + ], + "name": "Social Care Site - HEALTH AND CARE AT HOME", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9999999" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "text": "THE HEALTH AND WELLBEING INNOVATION C, TRELISKE, TRURO, CORNWALL", + "postalCode": "TR1 3FF" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:5b77c3fa-8dc1-40eb-bd08-230c34f593f7", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "5b77c3fa-8dc1-40eb-bd08-230c34f593f7", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:ee035711-7aac-48c4-951a-62c07891d37d", + "resource": { + "resourceType": "MedicationRequest", + "status": "cancelled", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "324252006", + "display": "Azithromycin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:815c6eb3-41f8-4f48-9e0d-2983624d4f90" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "566946-B86044-FEFEFN" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-02-11" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-02-19T16:37:14Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Prescriber Cancelled" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:815c6eb3-41f8-4f48-9e0d-2983624d4f90", + "resource": { + "resourceType": "PractitionerRole", + "id": "815c6eb3-41f8-4f48-9e0d-2983624d4f90", + "practitioner": { + "reference": "urn:uuid:acd5b009-c78f-40f2-a48b-b38ac72de992" + }, + "organization": { + "reference": "urn:uuid:9683c147-ddad-41d9-9858-6e585c3f04df" + } + } + }, + { + "fullUrl": "urn:uuid:acd5b009-c78f-40f2-a48b-b38ac72de992", + "resource": { + "resourceType": "Practitioner", + "id": "acd5b009-c78f-40f2-a48b-b38ac72de992", + "name": [ + { + "family": "ROBINSON", + "given": ["C"], + "prefix": ["DR"] + } + ] + } + }, + { + "fullUrl": "urn:uuid:9683c147-ddad-41d9-9858-6e585c3f04df", + "resource": { + "resourceType": "Organization", + "id": "9683c147-ddad-41d9-9858-6e585c3f04df", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "B86044" + } + ], + "name": "IRELAND WOOD SURGERY", + "telecom": [ + { + "system": "phone", + "value": "0113 2303470" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "text": "IVESON APPROACH, LEEDS, WEST YORKSHIRE, ENGLAND, LS16 6FR" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:37017443-4c6f-4c22-a46c-4362972e2008", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "37017443-4c6f-4c22-a46c-4362972e2008", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:5cb4600c-d758-42db-8091-16b030f6c00e", + "resource": { + "resourceType": "MedicationRequest", + "status": "stopped", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "324252006", + "display": "Azithromycin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:86affa2e-f6e9-4d39-831e-b9b132874cda" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "29AE98-C153C8-31BC6A" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2023-10-17" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2023-10-15T11:12:32Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Not Dispensed" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:86affa2e-f6e9-4d39-831e-b9b132874cda", + "resource": { + "resourceType": "PractitionerRole", + "id": "86affa2e-f6e9-4d39-831e-b9b132874cda", + "practitioner": { + "reference": "urn:uuid:01eca5b5-bf93-4c9e-ad70-abcfc39fc19e" + }, + "organization": { + "reference": "urn:uuid:0ef7bc64-5a55-4f96-9c5c-3b56c64819d5" + } + } + }, + { + "fullUrl": "urn:uuid:01eca5b5-bf93-4c9e-ad70-abcfc39fc19e", + "resource": { + "resourceType": "Practitioner", + "id": "01eca5b5-bf93-4c9e-ad70-abcfc39fc19e", + "name": [ + { + "family": "ROBINSON", + "given": ["C"], + "prefix": ["DR"] + } + ] + } + }, + { + "fullUrl": "urn:uuid:0ef7bc64-5a55-4f96-9c5c-3b56c64819d5", + "resource": { + "resourceType": "Organization", + "id": "0ef7bc64-5a55-4f96-9c5c-3b56c64819d5", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "B86044" + } + ], + "name": "IRELAND WOOD SURGERY", + "telecom": [ + { + "system": "phone", + "value": "0113 2303470" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "text": "IVESON APPROACH, LEEDS, WEST YORKSHIRE, ENGLAND, LS16 6FR" + } + ] + } + } + ] + } + } + ] +} diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple-exclusion.json b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple-exclusion.json new file mode 100644 index 000000000..ccebc5638 --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple-exclusion.json @@ -0,0 +1,260 @@ +{ + "resourceType": "Bundle", + "id": "155e1102-9e71-4f19-9453-b905c0bbc494", + "meta": { + "lastUpdated": "2022-11-21T14:00:00+00:00" + }, + "type": "searchset", + "total": 1, + "entry": [ + { + "fullUrl": "urn:uuid:0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:a54219b8-f741-4c47-b662-e4f8dfa49ab6", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "39732311000001104", + "display": "Amoxicillin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-01-25" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-01-30T12:01:24Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Ready to Collect" + } + } + ] + } + ], + "note": [ + { + "text": "Located in Collection Locker 3. Access code '124564'" + } + ] + } + }, + { + "fullUrl": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666", + "resource": { + "resourceType": "PractitionerRole", + "id": "56166769-c1c4-4d07-afa8-132b5dfca666", + "practitioner": { + "reference": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a" + }, + "organization": { + "reference": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8" + } + } + }, + { + "fullUrl": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "resource": { + "resourceType": "Practitioner", + "id": "a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "name": [ + { + "family": "BOIN", + "given": [ + "C" + ], + "prefix": [ + "DR" + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "resource": { + "resourceType": "Organization", + "id": "3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "A83008" + } + ], + "name": "HALLGARTH SURGERY", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9737320" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "HALLGARTH SURGERY", + "CHEAPSIDE" + ], + "city": "SHILDON", + "district": "COUNTY DURHAM", + "postalCode": "DL4 2HP" + } + ] + } + }, + { + "fullUrl": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "resource": { + "resourceType": "Organization", + "id": "afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "VNE51" + } + ], + "name": "Social Care Site - HEALTH AND CARE AT HOME", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9999999" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "THE HEALTH AND WELLBEING INNOVATION C", + "TRELISKE" + ], + "city": "TRURO", + "district": "CORNWALL", + "postalCode": "TR1 3FF" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:1a388581-dbbe-43e3-9054-f5976c0245e5", + "search": { + "mode": "outcome" + }, + "resource": { + "resourceType": "OperationOutcome", + "id": "1a388581-dbbe-43e3-9054-f5976c0245e5", + "meta": { + "lastUpdated": "2023-09-29T10:52:00+00:00" + }, + "issue": [ + { + "code": "business-rule", + "severity": "warning", + "details": { + "coding": [ + { + "system": "https://fhir.nhs.uk/CodeSystem/Spine-ErrorOrWarningCode", + "code": "INVALIDATED_RESOURCE", + "display": "Invalidated resource" + } + ] + }, + "diagnostics": "Prescription with short form ID D7AC09-A99968-4BA59C has been invalidated so could not be returned." + } + ] + } + }, + { + "fullUrl": "urn:uuid:fedef61e-bc62-452e-91c0-6f44ad2d5c0c", + "search": { + "mode": "outcome" + }, + "resource": { + "resourceType": "OperationOutcome", + "id": "fedef61e-bc62-452e-91c0-6f44ad2d5c0c", + "meta": { + "lastUpdated": "2023-09-29T10:52:00+00:00" + }, + "issue": [ + { + "code": "business-rule", + "severity": "warning", + "details": { + "coding": [ + { + "system": "https://fhir.nhs.uk/CodeSystem/Spine-ErrorOrWarningCode", + "code": "INVALIDATED_RESOURCE", + "display": "Invalidated resource" + } + ] + }, + "diagnostics": "Prescription with short form ID CDF34E-A99968-4FF3BQ has been invalidated so could not be returned." + } + ] + } + } + ] +} diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple.json b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple.json new file mode 100644 index 000000000..53b3693a2 --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-multiple.json @@ -0,0 +1,686 @@ +{ + "resourceType": "Bundle", + "id": "155e1102-9e71-4f19-9453-b905c0bbc494", + "meta": { + "lastUpdated": "2022-11-21T14:00:00+00:00" + }, + "type": "searchset", + "total": 3, + "entry": [ + { + "fullUrl": "urn:uuid:0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:a54219b8-f741-4c47-b662-e4f8dfa49ab6", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "39732311000001104", + "display": "Amoxicillin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-02-27" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-03-02T14:04:36Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "With Pharmacy - Preparing Remainder" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:6989b7bd-8db6-428c-a593-4022e3044c00", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "322341003", + "display": "Co-codamol 30mg/500mg tablets" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-02-27" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-03-02T14:04:36Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Ready to Collect - Partial" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:2868554c-5565-4d31-b92a-c5b8dab8b90a", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "321080004", + "display": "Pseudoephedrine hydrochloride 60mg tablets" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-02-27" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-03-02T14:04:36Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "With Pharmacy" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:5cb17f5a-11ac-4e18-825f-6470467238b3", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "324252006", + "display": "Azithromycin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-02-27" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-03-02T14:04:36Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Ready to Collect" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666", + "resource": { + "resourceType": "PractitionerRole", + "id": "56166769-c1c4-4d07-afa8-132b5dfca666", + "practitioner": { + "reference": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a" + }, + "organization": { + "reference": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8" + } + } + }, + { + "fullUrl": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "resource": { + "resourceType": "Practitioner", + "id": "a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "name": [ + { + "family": "BOIN", + "given": ["C"], + "prefix": ["DR"] + } + ] + } + }, + { + "fullUrl": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "resource": { + "resourceType": "Organization", + "id": "3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "A83008" + } + ], + "name": "HALLGARTH SURGERY", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9737320" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "HALLGARTH SURGERY", + "CHEAPSIDE", + "SHILDON", + "COUNTY DURHAM" + ], + "postalCode": "DL4 2HP" + } + ] + } + }, + { + "fullUrl": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "resource": { + "resourceType": "Organization", + "id": "afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "VNE51" + } + ], + "name": "Social Care Site - HEALTH AND CARE AT HOME", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9999999" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "text": "THE HEALTH AND WELLBEING INNOVATION C, TRELISKE, TRURO, CORNWALL", + "postalCode": "TR1 3FF" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:5b77c3fa-8dc1-40eb-bd08-230c34f593f7", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "5b77c3fa-8dc1-40eb-bd08-230c34f593f7", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:ee035711-7aac-48c4-951a-62c07891d37d", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "324252006", + "display": "Azithromycin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:815c6eb3-41f8-4f48-9e0d-2983624d4f90" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "566946-B86044-FEFEFN" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-02-11" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-02-19T16:37:14Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Prescriber Approved" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:815c6eb3-41f8-4f48-9e0d-2983624d4f90", + "resource": { + "resourceType": "PractitionerRole", + "id": "815c6eb3-41f8-4f48-9e0d-2983624d4f90", + "practitioner": { + "reference": "urn:uuid:acd5b009-c78f-40f2-a48b-b38ac72de992" + }, + "organization": { + "reference": "urn:uuid:9683c147-ddad-41d9-9858-6e585c3f04df" + } + } + }, + { + "fullUrl": "urn:uuid:acd5b009-c78f-40f2-a48b-b38ac72de992", + "resource": { + "resourceType": "Practitioner", + "id": "acd5b009-c78f-40f2-a48b-b38ac72de992", + "name": [ + { + "family": "ROBINSON", + "given": ["C"], + "prefix": ["DR"] + } + ] + } + }, + { + "fullUrl": "urn:uuid:9683c147-ddad-41d9-9858-6e585c3f04df", + "resource": { + "resourceType": "Organization", + "id": "9683c147-ddad-41d9-9858-6e585c3f04df", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "B86044" + } + ], + "name": "IRELAND WOOD SURGERY", + "telecom": [ + { + "system": "phone", + "value": "0113 2303470" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "text": "IVESON APPROACH, LEEDS, WEST YORKSHIRE, ENGLAND, LS16 6FR" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:37017443-4c6f-4c22-a46c-4362972e2008", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "37017443-4c6f-4c22-a46c-4362972e2008", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:5cb4600c-d758-42db-8091-16b030f6c00e", + "resource": { + "resourceType": "MedicationRequest", + "status": "completed", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "324252006", + "display": "Azithromycin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:86affa2e-f6e9-4d39-831e-b9b132874cda" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "29AE98-C153C8-31BC6A" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2023-10-17" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2023-10-15T11:12:32Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Dispatched" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:86affa2e-f6e9-4d39-831e-b9b132874cda", + "resource": { + "resourceType": "PractitionerRole", + "id": "86affa2e-f6e9-4d39-831e-b9b132874cda", + "practitioner": { + "reference": "urn:uuid:01eca5b5-bf93-4c9e-ad70-abcfc39fc19e" + }, + "organization": { + "reference": "urn:uuid:0ef7bc64-5a55-4f96-9c5c-3b56c64819d5" + } + } + }, + { + "fullUrl": "urn:uuid:01eca5b5-bf93-4c9e-ad70-abcfc39fc19e", + "resource": { + "resourceType": "Practitioner", + "id": "01eca5b5-bf93-4c9e-ad70-abcfc39fc19e", + "name": [ + { + "family": "ROBINSON", + "given": ["C"], + "prefix": ["DR"] + } + ] + } + }, + { + "fullUrl": "urn:uuid:0ef7bc64-5a55-4f96-9c5c-3b56c64819d5", + "resource": { + "resourceType": "Organization", + "id": "0ef7bc64-5a55-4f96-9c5c-3b56c64819d5", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "B86044" + } + ], + "name": "IRELAND WOOD SURGERY", + "telecom": [ + { + "system": "phone", + "value": "0113 2303470" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "text": "IVESON APPROACH, LEEDS, WEST YORKSHIRE, ENGLAND, LS16 6FR" + } + ] + } + } + ] + } + } + ] +} diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-ready-dispatch.json b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-ready-dispatch.json new file mode 100644 index 000000000..cb2e8c367 --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-ready-dispatch.json @@ -0,0 +1,414 @@ +{ + "resourceType": "Bundle", + "id": "155e1102-9e71-4f19-9453-b905c0bbc494", + "meta": { + "lastUpdated": "2022-11-21T14:00:00+00:00" + }, + "type": "searchset", + "total": 1, + "entry": [ + { + "fullUrl": "urn:uuid:0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:a54219b8-f741-4c47-b662-e4f8dfa49ab6", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "39732311000001104", + "display": "Amoxicillin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-01-17" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-02-01T11:14:21Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Ready to Dispatch" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:6989b7bd-8db6-428c-a593-4022e3044c00", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "322341003", + "display": "Co-codamol 30mg/500mg tablets" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-01-17" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-02-01T11:14:21Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Ready to Dispatch - Partial" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:2868554c-5565-4d31-b92a-c5b8dab8b90a", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "321080004", + "display": "Pseudoephedrine hydrochloride 60mg tablets" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-01-17" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-02-01T11:14:21Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Ready to Dispatch" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:5cb17f5a-11ac-4e18-825f-6470467238b3", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "324252006", + "display": "Azithromycin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-01-17" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-02-01T11:14:21Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Ready to Dispatch - Partial" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666", + "resource": { + "resourceType": "PractitionerRole", + "id": "56166769-c1c4-4d07-afa8-132b5dfca666", + "practitioner": { + "reference": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a" + }, + "organization": { + "reference": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8" + } + } + }, + { + "fullUrl": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "resource": { + "resourceType": "Practitioner", + "id": "a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "name": [ + { + "family": "BOIN", + "given": [ + "C" + ], + "prefix": [ + "DR" + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "resource": { + "resourceType": "Organization", + "id": "3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "A83008" + } + ], + "name": "HALLGARTH SURGERY", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9737320" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "HALLGARTH SURGERY", + "CHEAPSIDE", + "SHILDON", + "COUNTY DURHAM" + ], + "postalCode": "DL4 2HP" + } + ] + } + }, + { + "fullUrl": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "resource": { + "resourceType": "Organization", + "id": "afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "VNE51" + } + ], + "name": "Social Care Site - HEALTH AND CARE AT HOME", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9999999" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "text": "THE HEALTH AND WELLBEING INNOVATION C, TRELISKE, TRURO, CORNWALL", + "postalCode": "TR1 3FF" + } + ] + } + } + ] + } + } + ] +} diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-single-exclusion.json b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-single-exclusion.json new file mode 100644 index 000000000..31d0770af --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-single-exclusion.json @@ -0,0 +1,232 @@ +{ + "resourceType": "Bundle", + "id": "155e1102-9e71-4f19-9453-b905c0bbc494", + "meta": { + "lastUpdated": "2022-11-21T14:00:00+00:00" + }, + "type": "searchset", + "link": [ + { + "relation": "self", + "url": "https://sandbox.api.service.nhs.uk/electronic-prescriptions/Bundle" + } + ], + "total": 1, + "entry": [ + { + "fullUrl": "urn:uuid:0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:a54219b8-f741-4c47-b662-e4f8dfa49ab6", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "39732311000001104", + "display": "Amoxicillin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2023-11-14" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2023-12-02T15:27:53Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "With Pharmacy but Tracking not Supported" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666", + "resource": { + "resourceType": "PractitionerRole", + "id": "56166769-c1c4-4d07-afa8-132b5dfca666", + "practitioner": { + "reference": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a" + }, + "organization": { + "reference": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8" + } + } + }, + { + "fullUrl": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "resource": { + "resourceType": "Practitioner", + "id": "a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "name": [ + { + "family": "BOIN", + "given": [ + "C" + ], + "prefix": [ + "DR" + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "resource": { + "resourceType": "Organization", + "id": "3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "A83008" + } + ], + "name": "HALLGARTH SURGERY", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9737320" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "HALLGARTH SURGERY", + "CHEAPSIDE" + ], + "city": "SHILDON", + "district": "COUNTY DURHAM", + "postalCode": "DL4 2HP" + } + ] + } + }, + { + "fullUrl": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "resource": { + "resourceType": "Organization", + "id": "afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "VNE51" + } + ], + "name": "Social Care Site - HEALTH AND CARE AT HOME", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9999999" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "THE HEALTH AND WELLBEING INNOVATION C", + "TRELISKE" + ], + "city": "TRURO", + "district": "CORNWALL", + "postalCode": "TR1 3FF" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:fedef61e-bc62-452e-91c0-6f44ad2d5c0c", + "search": { + "mode": "outcome" + }, + "resource": { + "resourceType": "OperationOutcome", + "id": "fedef61e-bc62-452e-91c0-6f44ad2d5c0c", + "meta": { + "lastUpdated": "2023-09-29T10:52:00+00:00" + }, + "issue": [ + { + "code": "business-rule", + "severity": "warning", + "details": { + "coding": [ + { + "system": "https://fhir.nhs.uk/CodeSystem/Spine-ErrorOrWarningCode", + "code": "INVALIDATED_RESOURCE", + "display": "Invalidated resource" + } + ] + }, + "diagnostics": "Prescription with short form ID CDF34E-A99968-4FF3BQ has been invalidated so could not be returned." + } + ] + } + } + ] +} diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-tracking-temporarily-unavailable.json b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-tracking-temporarily-unavailable.json new file mode 100644 index 000000000..1184e7248 --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success-tracking-temporarily-unavailable.json @@ -0,0 +1,232 @@ +{ + "resourceType": "Bundle", + "id": "155e1102-9e71-4f19-9453-b905c0bbc494", + "meta": { + "lastUpdated": "2022-11-21T14:00:00+00:00" + }, + "type": "searchset", + "link": [ + { + "relation": "self", + "url": "https://sandbox.api.service.nhs.uk/electronic-prescriptions/Bundle" + } + ], + "total": 1, + "entry": [ + { + "fullUrl": "urn:uuid:0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:a54219b8-f741-4c47-b662-e4f8dfa49ab6", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "39732311000001104", + "display": "Amoxicillin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2023-11-14" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2023-12-02T15:27:53Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "Tracking Temporarily Unavailable" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666", + "resource": { + "resourceType": "PractitionerRole", + "id": "56166769-c1c4-4d07-afa8-132b5dfca666", + "practitioner": { + "reference": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a" + }, + "organization": { + "reference": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8" + } + } + }, + { + "fullUrl": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "resource": { + "resourceType": "Practitioner", + "id": "a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "name": [ + { + "family": "BOIN", + "given": [ + "C" + ], + "prefix": [ + "DR" + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "resource": { + "resourceType": "Organization", + "id": "3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "A83008" + } + ], + "name": "HALLGARTH SURGERY", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9737320" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "HALLGARTH SURGERY", + "CHEAPSIDE" + ], + "city": "SHILDON", + "district": "COUNTY DURHAM", + "postalCode": "DL4 2HP" + } + ] + } + }, + { + "fullUrl": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "resource": { + "resourceType": "Organization", + "id": "afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "VNE51" + } + ], + "name": "Social Care Site - HEALTH AND CARE AT HOME", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9999999" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "THE HEALTH AND WELLBEING INNOVATION C", + "TRELISKE" + ], + "city": "TRURO", + "district": "CORNWALL", + "postalCode": "TR1 3FF" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:fedef61e-bc62-452e-91c0-6f44ad2d5c0c", + "search": { + "mode": "outcome" + }, + "resource": { + "resourceType": "OperationOutcome", + "id": "fedef61e-bc62-452e-91c0-6f44ad2d5c0c", + "meta": { + "lastUpdated": "2023-09-29T10:52:00+00:00" + }, + "issue": [ + { + "code": "business-rule", + "severity": "warning", + "details": { + "coding": [ + { + "system": "https://fhir.nhs.uk/CodeSystem/Spine-ErrorOrWarningCode", + "code": "INVALIDATED_RESOURCE", + "display": "Invalidated resource" + } + ] + }, + "diagnostics": "Prescription with short form ID CDF34E-A99968-4FF3BQ has been invalidated so could not be returned." + } + ] + } + } + ] +} diff --git a/packages/specification/examples/GetMyPrescriptions/Bundle/success/success.json b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success.json new file mode 100644 index 000000000..383f0060c --- /dev/null +++ b/packages/specification/examples/GetMyPrescriptions/Bundle/success/success.json @@ -0,0 +1,414 @@ +{ + "resourceType": "Bundle", + "id": "155e1102-9e71-4f19-9453-b905c0bbc494", + "meta": { + "lastUpdated": "2022-11-21T14:00:00+00:00" + }, + "type": "searchset", + "total": 1, + "entry": [ + { + "fullUrl": "urn:uuid:0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "search": { + "mode": "match" + }, + "resource": { + "resourceType": "Bundle", + "id": "0cb82cfa-76c8-4fb2-a08e-bf0e326e5487", + "type": "collection", + "entry": [ + { + "fullUrl": "urn:uuid:a54219b8-f741-4c47-b662-e4f8dfa49ab6", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "39732311000001104", + "display": "Amoxicillin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-01-17" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-02-01T11:14:21Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "With Pharmacy" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:6989b7bd-8db6-428c-a593-4022e3044c00", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "322341003", + "display": "Co-codamol 30mg/500mg tablets" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-01-17" + }, + "quantity": { + "value": 20, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-02-01T11:14:21Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "With Pharmacy" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:2868554c-5565-4d31-b92a-c5b8dab8b90a", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "321080004", + "display": "Pseudoephedrine hydrochloride 60mg tablets" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-01-17" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-02-01T11:14:21Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "With Pharmacy" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:5cb17f5a-11ac-4e18-825f-6470467238b3", + "resource": { + "resourceType": "MedicationRequest", + "status": "active", + "intent": "order", + "medicationCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "324252006", + "display": "Azithromycin 250mg capsules" + } + ] + }, + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9449304130" + } + }, + "requester": { + "reference": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666" + }, + "groupIdentifier": { + "system": "https://fhir.nhs.uk/Id/prescription-order-number", + "value": "24F5DA-A83008-7EFE6Z" + }, + "courseOfTherapyType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy", + "code": "acute", + "display": "Short course (acute) therapy" + } + ] + }, + "dispenseRequest": { + "validityPeriod": { + "start": "2024-01-17" + }, + "quantity": { + "value": 30, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "performer": { + "reference": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1" + } + }, + "substitution": { + "allowedBoolean": false + }, + "extension": [ + { + "url": "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory", + "extension": [ + { + "url": "statusDate", + "valueDateTime": "2024-02-01T11:14:21Z" + }, + { + "url": "status", + "valueCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt", + "code": "With Pharmacy" + } + } + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666", + "resource": { + "resourceType": "PractitionerRole", + "id": "56166769-c1c4-4d07-afa8-132b5dfca666", + "practitioner": { + "reference": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a" + }, + "organization": { + "reference": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8" + } + } + }, + { + "fullUrl": "urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "resource": { + "resourceType": "Practitioner", + "id": "a8c85454-f8cb-498d-9629-78e2cb5fa47a", + "name": [ + { + "family": "BOIN", + "given": [ + "C" + ], + "prefix": [ + "DR" + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "resource": { + "resourceType": "Organization", + "id": "3b4b03a5-52ba-4ba6-9b82-70350aa109d8", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "A83008" + } + ], + "name": "HALLGARTH SURGERY", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9737320" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "line": [ + "HALLGARTH SURGERY", + "CHEAPSIDE", + "SHILDON", + "COUNTY DURHAM" + ], + "postalCode": "DL4 2HP" + } + ] + } + }, + { + "fullUrl": "urn:uuid:afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "resource": { + "resourceType": "Organization", + "id": "afb07f8b-e8d7-4cad-895d-494e6b35b2a1", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "VNE51" + } + ], + "name": "Social Care Site - HEALTH AND CARE AT HOME", + "telecom": [ + { + "system": "phone", + "use": "work", + "value": "0115 9999999" + } + ], + "address": [ + { + "use": "work", + "type": "both", + "text": "THE HEALTH AND WELLBEING INNOVATION C, TRELISKE, TRURO, CORNWALL", + "postalCode": "TR1 3FF" + } + ] + } + } + ] + } + } + ] +} diff --git a/packages/specification/jest.config.ts b/packages/specification/jest.config.ts new file mode 100644 index 000000000..1ddbc83f6 --- /dev/null +++ b/packages/specification/jest.config.ts @@ -0,0 +1,9 @@ +import defaultConfig from "../../jest.default.config" +import type {JestConfigWithTsJest} from "ts-jest" + +const jestConfig: JestConfigWithTsJest = { + ...defaultConfig, + "rootDir": "./" +} + +export default jestConfig diff --git a/packages/specification/jest.debug.config.ts b/packages/specification/jest.debug.config.ts new file mode 100644 index 000000000..a30627383 --- /dev/null +++ b/packages/specification/jest.debug.config.ts @@ -0,0 +1,9 @@ +import config from "./jest.config" +import type {JestConfigWithTsJest} from "ts-jest" + +const debugConfig: JestConfigWithTsJest = { + ...config, + "preset": "ts-jest" +} + +export default debugConfig diff --git a/packages/specification/package.json b/packages/specification/package.json new file mode 100644 index 000000000..96f0acd7f --- /dev/null +++ b/packages/specification/package.json @@ -0,0 +1,23 @@ +{ + "name": "apim-spec", + "version": "0.0.1", + "description": "OAS (Swagger v3) API Definition for Prescriptions-For-Patients", + "homepage": "https://github.com/NHSDigital/prescriptionsforpatients", + "author": "NHS Digital", + "license": "MIT", + "type": "module", + "engines": { + "node": "20.10.x", + "npm": "10.2.x" + }, + "scripts": { + "lint": "redocly lint --extends=recommended --config ./redocly.yaml", + "resolve": "redocly bundle prescriptions-for-patients.yaml -d -o dist/prescriptions-for-patients.resolved.json", + "clean": "rm -rf lib coverage", + "check-licenses": "license-checker --failOn GPL --failOn LGPL --start ../.." + }, + "devDependencies": { + "@redocly/cli": "^2.12.3", + "tsx": "4.21.0" + } +} diff --git a/packages/specification/prescriptions-for-patients.yaml b/packages/specification/prescriptions-for-patients.yaml new file mode 100644 index 000000000..38232cf20 --- /dev/null +++ b/packages/specification/prescriptions-for-patients.yaml @@ -0,0 +1,433 @@ +# This is an OpenAPI Specification (https://swagger.io/specification/) +# for the Prescriptions API +# owned by NHS Digital (https://digital.nhs.uk/) + +openapi: 3.0.0 +x-nhs-api-spec-guid: 816f3e79-1d81-4ae7-af54-dcd4a739d01a +info: + title: Prescriptions for Patients API + version: "0.0.1" + contact: + name: Prescriptions for Patients API Support + url: https://digital.nhs.uk/developer/help-and-support + email: api.management@nhs.net + description: | + ## Overview + Use this API to retrieve prescriptions data for individual patients from the [Electronic Prescription Service (EPS)](https://digital.nhs.uk/developer/api-catalogue/electronic-prescription-service-fhir). + + For use in patient-facing applications such as NHS App, to allow patients to view their digital prescriptions. + + Patients can use their digital prescriptions to collect their medication at any pharmacy in England. + Patients will be able to view: + * repeat and acute prescriptions created using the [Electronic Prescription Service](https://digital.nhs.uk/developer/api-catalogue/electronic-prescription-service-fhir) + * information about the pharmacy their prescriptions can be collected from or will be delivered by + * limited information about the status of their prescriptions + + ## Who can use this API + Currently, this API is for [internal use only](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#statuses) - the only API consumer is the NHS App. + + It is not currently available for integration by external third parties. + + ## Related APIs + The following APIs are related to this API: + * [Electronic Prescriptions Service](https://digital.nhs.uk/developer/api-catalogue/electronic-prescription-service-fhir): The national service for creating and dispensing prescriptions across health and social care. + * [Personal Demographics Service](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir): the national service for storing and retrieving NHS patient details such as name, address, date of birth, related people, registered GP and NHS number. + + ## API status and roadmap + This API is in an [internal private beta](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#statuses), meaning the API is not currently available for integration by external third parties. + + If you want to use this API when it becomes available for external use, contact us at epsonboarding@nhs.net to register your interest. + + ## Service Level + This API is a silver service, meaning it is operational and supported between 8am and 6pm, Monday to Friday, but not bank holidays. + For more details, see [service levels](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#service-levels) + + ## Technology + This API is [RESTful](https://digital.nhs.uk/developer/guides-and-documentation/our-api-technologies#basic-rest). + + It conforms to the [FHIR](https://digital.nhs.uk/developer/guides-and-documentation/our-api-technologies#fhir) global standard for health care data exchange, specifically to [FHIR UK Core](https://digital.nhs.uk/services/fhir-uk-core). + + It includes some country-specific FHIR extensions, which are built against [FHIR UK Core, specifically [UKcore.stu1 0.5.1](https://simplifier.net/packages/fhir.r4.ukcore.stu1/0.5.1). + + You do not need to know much about FHIR to use this API. The API only supports GET requests and the responses will be FHIR. + + FHIR APIs are just RESTful APIs that follow specific rules. In particular: + * resource names are capitalised and singular, for example `/Bundle` not `/bundle` + * array names are singular, for example `line` not `lines` for address lines + * data items that are country-specific and thus not included in the FHIR global base resources are usually wrapped in an `extension` object + + There are [libraries and software development kits available](https://digital.nhs.uk/developer/guides-and-documentation/api-technologies-at-nhs-digital#fhir-libraries-and-sdks) to help with FHIR API integration. + + ## Network access + This API is available on the internet. + + For more details see [Network access for APIs](https://digital.nhs.uk/developer/guides-and-documentation/network-access-for-apis). + + ## Security and authorisation + This API is [user-restricted](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis), meaning an end user must be present, authenticated and authorised. + + The end user must be: + * a patient who receives health and social care or makes use of NHS services + * strongly authenticated to a P9 level, using [NHS login - separate authentication and authorisation](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-login-separate-authentication-and-authorisation) + + To use this API, use the following security pattern: + + | Security pattern | Technical details | Advantages | Disadvantages | + |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ----------------------------------------------------| ------------------------------------------------------------|---------------------------------------------------------| + |[NHS login - separate authentication and authorisation](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-login-separate-authentication-and-authorisation) |OAuth 2.0 token exchange with signed JWT |Gives access to user information. |Need to integrate and onboard separately with NHS login. | + + ## Environment and testing + | Environment | Base URL | + | --------------------- | ---------------------------------------------------------------------------- | + | Integration | `https://int.api.service.nhs.uk/prescriptions-for-patients` | + | Production | Not yet available | + | Sandbox | `https://sandbox.api.service.nhs.uk/prescriptions-for-patients` | + + ## Onboarding + This API is not currently available to external third parties for onboarding. + + ## Errors + We use standard HTTP status codes to show whether an API request succeeded or not. They are usually in the range: + + * 200 to 299 if it succeeded, including code 202 if it was accepted by an API that needs to wait for further action + * 400 to 499 if it failed because of a client error by your application + * 500 to 599 if it failed because of an error on our server + + Errors specific to each API are shown in the Endpoints section, under Response. See our [reference guide](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#http-status-codes) for more on errors. + +x-spec-publication: + operation-order: + - operations: + - method: GET + path: /Bundle + +servers: + - url: "https://sandbox.api.service.nhs.uk/prescriptions-for-patients" + description: Sandbox + - url: "https://int.api.service.nhs.uk/prescriptions-for-patients" + description: Integration + - url: "https://api.service.nhs.uk/prescriptions-for-patients" + description: Production + +paths: + /Bundle: + get: + operationId: prescriptions-for-patients-bundle + summary: Get prescriptions + description: | + ## Overview + Use this endpoint to get a list of a patient's prescriptions, expressed as a FHIR Bundle. + parameters: + - $ref: "#/components/parameters/BearerAuthorisation" + - $ref: "#/components/parameters/RequestID" + - $ref: "#/components/parameters/CorrelationID" + responses: + "200": + description: Successful retrieval. + content: + application/fhir+json: + schema: + $ref: "#/components/schemas/bundle-response" + examples: + prescriptions-present: + description: A successful response to a GetMyPrescriptions/Bundle request, containing one prescription. + value: + $ref: "examples/GetMyPrescriptions/Bundle/success/success.json" + prescriptions-present-multiple: + description: A successful response to a GetMyPrescriptions/Bundle request, containing multiple prescriptions. + value: + $ref: "examples/GetMyPrescriptions/Bundle/success/success-multiple.json" + prescriptions-not-present: + description: A successful response to a GetMyPrescriptions/Bundle request, where no prescriptions were found. + value: + $ref: "examples/GetMyPrescriptions/Bundle/success/success-empty.json" + prescriptions-ready-to-dispatch: + description: A successful response to a GetMyPrescriptions/Bundle request, where prescriptions are ready to be dispatched. + value: + $ref: "examples/GetMyPrescriptions/Bundle/success/success-ready-dispatch.json" + prescriptions-cancelled-not-dispensed: + description: A successful response to a GetMyPrescriptions/Bundle request, where prescriptions have been cancelled or not dispensed. + value: + $ref: "examples/GetMyPrescriptions/Bundle/success/success-multiple-cancelled.json" + prescription-excluded: + description: A successful response to a GetMyPrescriptions/Bundle request, with a single prescription excluded. + value: + $ref: "examples/GetMyPrescriptions/Bundle/success/success-single-exclusion.json" + prescriptions-excluded: + description: A successful response to a GetMyPrescriptions/Bundle request, with multiple prescriptions excluded. + value: + $ref: "examples/GetMyPrescriptions/Bundle/success/success-multiple-exclusion.json" + distance-selling-pharmacy: + description: A successful response to a GetMyPrescriptions/Bundle request, where the performer organisation is a distance selling pharmacy. + value: + $ref: "examples/GetMyPrescriptions/Bundle/success/success-distance-selling.json" + tracking-temporarily-unavailable: + description: A successful response to a GetMyPrescriptions/Bundle request, when tracking is temporarily unavailable. + value: + $ref: "examples/GetMyPrescriptions/Bundle/success/success-tracking-temporarily-unavailable.json" + + "4XX": + description: | + An error occurred as follows: + + | HTTP status | Error code | Description | + | ----------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | + | 401 | `ACCESS_DENIED` | Missing or invalid OAuth 2.0 bearer token in request | + | 408 | `timeout` | Request timed out | + | 429 | `throttled` | You have exceeded your application's [rate limit](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#rate-limits). | + + The error code will be included in the returned OperationOutcome (below). + content: + application/fhir+json: + schema: + $ref: "#/components/schemas/operation-outcome" + examples: + example: + description: | + An error response to a GetMyPrescriptions/Bundle request that invalidates the request. + value: + $ref: examples/GetMyPrescriptions/Bundle/error/error-401.json + "500": + description: | + An error occurred as follows: + + | HTTP status | Error code | Description | + | ----------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | + | 500 | `SERVER_ERROR` | An internal error has occurred when processing the request. | + + The error code will be included in the returned OperationOutcome (below). + content: + application/fhir+json: + schema: + $ref: "#/components/schemas/operation-outcome" + examples: + example: + description: | + An error response to a GetMyPrescriptions/Bundle request that invalidates the request. + value: + $ref: examples/GetMyPrescriptions/Bundle/error/error-500.json +components: + parameters: + BearerAuthorisation: + in: header + name: Authorization + description: | + An [OAuth 2.0 bearer token](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis). + required: true + schema: + type: string + format: '^Bearer\ [[:ascii:]]+$' + example: "Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM" + RequestID: + in: header + name: X-Request-ID + required: true + description: | + A globally unique identifier (GUID) for the request, which we use to correlate logs through different components. + Must be a universally unique identifier (UUID) (ideally version 4). + Mirrored back in a response header. + schema: + type: string + pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" + example: 60E0B220-8136-4CA5-AE46-1D97EF59D068 + CorrelationID: + in: header + name: X-Correlation-ID + required: false + description: | + An optional ID which you can use to track transactions across multiple systems. If included, its value must be a valid GUID. + Mirrored back in a response header. + schema: + type: string + pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" + example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA + schemas: + bundle-response: + type: object + required: + - resourceType + - id + - meta + - type + - total + - entry + description: A FHIR searchset Bundle. + properties: + resourceType: + type: string + description: FHIR resource type. + default: Bundle + id: + type: string + description: Object ID for the Bundle. + example: 164996aa-29eb-4f14-a5ac-4b556a7baf6e + meta: + type: object + description: Metadata about the bundle + properties: + lastUpdated: + type: string + description: Datetime of the bundle's creation + example: "2022-11-21T14:00:00+00:00" + type: + type: string + description: Denotes that the bundle is a list of resources returned as a result of a search. + enum: [searchset] + total: + type: number + description: | + The number of prescription bundles contained within the searchset + + Note that this excludes OperationOutcomes. + entry: + type: array + description: | + A collection of resources contained within the Bundle. + + Note that the presence of an OperationOutcome resource as part of the bundle implies that one + of a patient's prescriptions have been excluded from the response due to a processing error. + An OperationOutcome resource will be included for each prescription that cannot be processed. + items: + oneOf: + - $ref: "#/components/schemas/PrescriptionBundle" + - $ref: "#/components/schemas/OperationOutcome-Resource" + PrescriptionBundle: + type: object + required: + - fullUrl + - search + - resource + properties: + fullUrl: + type: string + example: urn:uuid:fedef61e-bc62-452e-91c0-6f44ad2d5c0c + description: The FHIR urn of the contained Bundle + search: + type: object + properties: + mode: + type: string + example: match + resource: + $ref: "#/components/schemas/CollectionBundle" + CollectionBundle: + type: object + required: + - resourceType + - identifier + - type + - entry + description: A FHIR collection Bundle. + properties: + resourceType: + type: string + description: FHIR resource type. + default: Bundle + id: + type: string + description: Object ID for the Bundle. + example: 164996aa-29eb-4f14-a5ac-4b556a7baf6e + type: + type: string + description: Denotes that the bundle is a collection of resources. Representing a Prescription, in this case. + enum: [collection] + entry: + type: array + description: | + A collection of resources contained within the Bundle. + + Note that the presence of an OperationOutcome resource as part of the bundle implies that one + of a patient's prescriptions have been excluded from the response due to a processing error. + An OperationOutcome resource will be included for each prescription that cannot be processed. + items: + oneOf: + - $ref: "#/components/schemas/MedicationRequest-Resource" + - $ref: "#/components/schemas/OrganisationDispensing-Resource" + - $ref: "#/components/schemas/Practitioner-Resource" + - $ref: "#/components/schemas/PractitionerRole-Resource" + MedicationRequest-Resource: + type: object + description: MedicationRequest + properties: + fullUrl: + type: string + example: urn:uuid:fedef61e-bc62-452e-91c0-6f44ad2d5c0c + description: The FHIR urn of the contained resource + resource: + $ref: schemas/resources/MedicationRequest.yaml + OrganisationDispensing-Resource: + type: object + description: Dispensing Organisation + properties: + fullUrl: + type: string + example: urn:uuid:fedef61e-bc62-452e-91c0-6f44ad2d5c0c + description: The FHIR urn of the contained resource + resource: + $ref: schemas/resources/Organisation.yaml + OrganisationPrescribing-Resource: + type: object + description: Prescribing Organisation + properties: + fullUrl: + type: string + example: urn:uuid:fedef61e-bc62-452e-91c0-6f44ad2d5c0c + description: The FHIR urn of the contained resource + resource: + $ref: schemas/resources/Organisation.yaml + Practitioner-Resource: + type: object + description: Practitioner + properties: + fullUrl: + type: string + example: urn:uuid:fedef61e-bc62-452e-91c0-6f44ad2d5c0c + description: The FHIR urn of the contained resource + resource: + $ref: schemas/resources/Practitioner.yaml + PractitionerRole-Resource: + type: object + description: PractitionerRole + properties: + fullUrl: + type: string + example: urn:uuid:fedef61e-bc62-452e-91c0-6f44ad2d5c0c + description: The FHIR urn of the contained resource + resource: + $ref: schemas/resources/PractitionerRole.yaml + OperationOutcome-Resource: + type: object + description: OperationOutcome + properties: + fullUrl: + type: string + example: urn:uuid:fedef61e-bc62-452e-91c0-6f44ad2d5c0c + description: The FHIR urn of the contained resource + resource: + $ref: schemas/resources/OperationOutcome.yaml + operation-outcome: + $ref: schemas/resources/OperationOutcome.yaml +x-nhsd-apim: + temporary: false + monitoring: true + access: + - title: User Restricted + grants: + nhs-login-p9: [] + target: + type: external + healthcheck: /_status + url: https://internal-dev.api.service.nhs.uk/ + security: + type: mtls + secret: prescriptions-for-patients-mtls-1 + target-identity: + - name: nhs-login-nhs-number + header: "nhs-login-nhs-number" + ratelimiting: + proxy: + limit: 20000 + timeunit: minute + app-default: + limit: 20000 + timeunit: minute diff --git a/packages/specification/redocly.yaml b/packages/specification/redocly.yaml new file mode 100644 index 000000000..2bfa4b078 --- /dev/null +++ b/packages/specification/redocly.yaml @@ -0,0 +1,3 @@ +apis: + pfp: + root: ./dist/prescriptions-for-patients.resolved.json diff --git a/packages/specification/schemas/fragments/address.yaml b/packages/specification/schemas/fragments/address.yaml new file mode 100644 index 000000000..41c4af9fd --- /dev/null +++ b/packages/specification/schemas/fragments/address.yaml @@ -0,0 +1,47 @@ +type: object +properties: + use: + type: string + description: The purpose of the address. + default: work + enum: [home, work, billing, temp] + type: + type: string + description: The type of address. + default: both + enum: [postal, physical, both] + line: + type: array + description: | + All lines of the address, and optionally postal code. + Systems will apply the following formatting convention when adding or replacing addresses lines: + If any of the lines are blank, they are not returned due to FHIR conformance constraints. + items: + type: string + example: + - 1 Trevelyan Square + - Boar Lane + - City Centre + text: + type: string + description: | + A plain text string address, optionally including the postal code. + example: IVESON APPROACH, LEEDS, WEST YORKSHIRE, ENGLAND, LS16 6FR + city: + type: string + description: | + The city of the address. + Note: This will not be populated by existing prescriptions. + example: Leeds + district: + type: string + description: | + The district of the address. + Note: This will not be populated by existing prescriptions. + example: West Yorkshire + postalCode: + type: string + description: | + The postal code of the address. + Note: This is an optionally populated field. Postal code may be included in line or text if absent. + example: LS1 6AE diff --git a/packages/specification/schemas/fragments/codes.yaml b/packages/specification/schemas/fragments/codes.yaml new file mode 100644 index 000000000..d4d408512 --- /dev/null +++ b/packages/specification/schemas/fragments/codes.yaml @@ -0,0 +1,54 @@ +MedicationRequestCourseOfTherapy: + type: object + required: [system, code] + properties: + system: + type: string + description: Codesystem URL for the prescription treatment type. + enum: + - http://terminology.hl7.org/CodeSystem/medicationrequest-course-of-therapy + code: + type: string + description: | + Code identifying the prescription treatment type. + * acute: one-off prescriptions + * continuous: repeat prescriptions + enum: [acute, continuous] + display: + type: string + description: Display value for the prescription treatment type. + enum: + - Short course (acute) therapy + - Continuous long term therapy +SnomedSctMedication: + type: object + required: [system, code] + properties: + system: + type: string + description: SNOMED codesystem URL. + enum: [http://snomed.info/sct] + code: + type: string + description: SNOMED code for the medication, as defined in the Dictionary of Medicines and Devices (DM+D). + example: "321196004" + display: + type: string + description: Human readable name for the medication. + example: Diazepam 2mg tablets +SpineErrorOrWarningCode: + type: object + required: [system, code] + properties: + system: + type: string + description: URI of the coding system specification. + enum: [https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode] + code: + type: string + description: Symbol in syntax defined by the system. + example: INVALID_VALUE + display: + type: string + description: Representation defined by the system. + example: Provided value is invalid diff --git a/packages/specification/schemas/fragments/groupIdentifier.yaml b/packages/specification/schemas/fragments/groupIdentifier.yaml new file mode 100644 index 000000000..dbdb8c222 --- /dev/null +++ b/packages/specification/schemas/fragments/groupIdentifier.yaml @@ -0,0 +1,14 @@ +type: object +required: [value] +description: | + Prescription ID to be used by the client to generate a prescription barcode. + Can be used directly to facilitate accessing a prescription, in the event that a barcode scanner was inoperable. +properties: + system: + type: string + description: Codesystem URL for the short-form Prescription ID. + enum: [https://fhir.nhs.uk/Id/prescription-order-number] + value: + type: string + description: The short-form Prescription ID. + example: 04F4C2-A99968-7F717P diff --git a/packages/specification/schemas/fragments/identifiers.yaml b/packages/specification/schemas/fragments/identifiers.yaml new file mode 100644 index 000000000..8f42af27c --- /dev/null +++ b/packages/specification/schemas/fragments/identifiers.yaml @@ -0,0 +1,29 @@ +OdsOrganisationCode: + type: object + description: The Organisation Data Service (ODS) code. + required: [system, value] + properties: + system: + type: string + description: Codesystem URL for the ODS code. + enum: [https://fhir.nhs.uk/Id/ods-organization-code] + value: + type: string + description: ODS code. + example: A83008 +NhsNumber: + type: object + required: [system, value] + properties: + system: + type: string + format: url + description: Codesystem URL for the NHS number. + enum: [https://fhir.nhs.uk/Id/nhs-number] + value: + description: | + The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. + Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html). + type: string + pattern: "^\\d{10}$" + example: "9000000009" diff --git a/packages/specification/schemas/fragments/medicationRequest/status.yaml b/packages/specification/schemas/fragments/medicationRequest/status.yaml new file mode 100644 index 000000000..4aee20b30 --- /dev/null +++ b/packages/specification/schemas/fragments/medicationRequest/status.yaml @@ -0,0 +1,50 @@ +type: object +description: | + The status of the line item within the prescription. + * 'Prescriber Approved' means the item has been approved by a prescriber and is waiting to be released from Spine by the pharmacy. + * 'Prescriber Cancelled' means the item has been cancelled by the prescriber. A cancelled item can be included in a prescription where other items have not been cancelled. The patient should be advised to contact their prescriber to find out the reason for cancellation. + * 'With Pharmacy' means the item has been downloaded by the pharmacy and is being prepared but is not ready to collect. + * 'With Pharmacy but Tracking not Supported' means that there is no prescription tracking data for the prescription item. This is because the pharmacy is not yet using a dispensing system which is onboarded to the National Patient Prescription Tracking Service. + * 'With Pharmacy - Preparing Remainder' means the prescription item has been partially dispensed, but the remaining part of the item is still with the pharmacy to prepare and dispense. + * 'Ready to Collect' means the pharmacy has prepared the prescription + item and it's ready to collect. + * 'Ready to Collect - Partial' means the prescription item has been partially dispensed and is ready to collect, but the remaining part of the item is still with the pharmacy to prepare and dispense. + * 'Ready to Dispatch' means the prescription item is in a holding area ready for collection by a delivery courier. This status will be set based on activity triggered by the pharmacy dispensing process. This might be the scanning of the prescription package barcode, or another action performed only against the item/s when they are placed in a holding area. + * 'Ready to Dispatch - Partial' means part of the prescription item is in a holding area ready for collection by a delivery courier. This status will be set based on activity triggered by the pharmacy dispensing process. This might be the scanning of the prescription package barcode, or another action performed only against the item/s when they are placed in a holding area. This status reflects the full medication item dosage isn't in stock. + * 'Not Dispensed' means the prescription item has not been dispensed, which may be for several reasons including the pharmacist deciding it's clinically unsuitable or the patient has reported side effects. The patient should be advised that the dispenser set the 'not dispensed' status so they know to contact their pharmacy should they have any questions. + * 'Dispatched' means the pharmacy has prepared the prescription item and it has been dispatched for delivery by a courier service. + * 'Collected' means that the patient or patient proxy has collected the prescription item. + * 'Tracking Temporarily Unavailable' means that the system was temporarily unable to obtain the status update for the item. This would happen in the event of the service going down. +required: + - url + - valueCoding +properties: + url: + type: string + enum: ["status"] + valueCoding: + type: object + required: + - code + - system + properties: + code: + type: string + enum: + - Prescriber Approved + - Prescriber Cancelled + - With Pharmacy + - With Pharmacy but Tracking not Supported + - With Pharmacy - Preparing Remainder + - Ready to Collect + - Ready to Collect - Partial + - Ready to Dispatch + - Ready to Dispatch - Partial + - Not Dispensed + - Dispatched + - Collected + - Tracking Temporarily Unavailable + + system: + type: string + enum: ["https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt"] diff --git a/packages/specification/schemas/fragments/medicationRequest/statusDate.yaml b/packages/specification/schemas/fragments/medicationRequest/statusDate.yaml new file mode 100644 index 000000000..c0d510029 --- /dev/null +++ b/packages/specification/schemas/fragments/medicationRequest/statusDate.yaml @@ -0,0 +1,14 @@ +type: object +description: | + Date and time at which the item status was updated +required: + - url + - valueDateTime +properties: + url: + type: string + enum: ["statusDate"] + valueDateTime: + type: string + format: date-time + example: "2024-03-01T08:27:14Z" diff --git a/packages/specification/schemas/fragments/structuredName.yaml b/packages/specification/schemas/fragments/structuredName.yaml new file mode 100644 index 000000000..db8a9d2ed --- /dev/null +++ b/packages/specification/schemas/fragments/structuredName.yaml @@ -0,0 +1,25 @@ +type: object +description: A structured name +properties: + family: + type: string + description: Family name (often called Surname). + example: Smith + given: + type: array + description: Given names, including any middle names. + items: + type: string + example: John + prefix: + type: array + description: Name prefixes, titles, and prenominals. + items: + type: string + example: Dr + suffix: + type: array + description: Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the end of the name. + items: + type: string + example: MD diff --git a/packages/specification/schemas/fragments/telecom.yaml b/packages/specification/schemas/fragments/telecom.yaml new file mode 100644 index 000000000..063dd5e49 --- /dev/null +++ b/packages/specification/schemas/fragments/telecom.yaml @@ -0,0 +1,19 @@ +type: object +required: + - use + - value +properties: + system: + description: Means of communication, such as phone or URL. + type: string + enum: [phone, URL, other] + default: phone + use: + type: string + description: Location associated with the contact details provided. + enum: [home, work, temp, mobile] + default: work + value: + description: Phone number, URL. + type: string + example: "01234567890" diff --git a/packages/specification/schemas/resources/MedicationRequest.yaml b/packages/specification/schemas/resources/MedicationRequest.yaml new file mode 100644 index 000000000..365d7b80b --- /dev/null +++ b/packages/specification/schemas/resources/MedicationRequest.yaml @@ -0,0 +1,128 @@ +type: object +required: + - resourceType + - identifier + - status + - intent + - medicationCodeableConcept + - subject + - requester + - groupIdentifier + - courseOfTherapyType + - dispenseRequest + - substitution +description: Information about a specific line item within a prescription. +properties: + resourceType: + type: string + description: FHIR resource type. + enum: [MedicationRequest] + status: + type: string + description: | + Indicator to identify prescription items that are in a terminal state, + such as collected or dispatched + enum: [completed, active] + intent: + type: string + description: The intent of a MedicationRequest object. Required by the FHIR standard but offers no patient value and can be ignored. + enum: [order, original-order, instance-order] + medicationCodeableConcept: + type: object + description: The medication prescribed to a patient. + properties: + coding: + type: array + items: + $ref: ../fragments/codes.yaml#/SnomedSctMedication + subject: + type: object + description: The NHS number of the patient the prescription is for. + properties: + identifier: + $ref: ../fragments/identifiers.yaml#/NhsNumber + requester: + type: object + description: | + The prescriber who created the prescription. + Useful if the patient or dispenser has a query about the prescription. + properties: + reference: + type: string + description: A reference to a PractitionerRole resource within the Bundle. + example: urn:uuid:56166769-c1c4-4d07-afa8-132b5dfca666 + groupIdentifier: + $ref: ../fragments/groupIdentifier.yaml + courseOfTherapyType: + type: object + description: Whether this prescription is an acute or a repeat. + properties: + coding: + type: array + items: + $ref: ../fragments/codes.yaml#/MedicationRequestCourseOfTherapy + dispenseRequest: + type: object + required: [quantity] + properties: + validityPeriod: + type: object + properties: + start: + type: string + description: The prescription's start date, could be after the prescription is created for a post dated prescription. + format: date + example: "2024-02-27" + performer: + type: object + description: A reference to either the nominated dispensing organisation or the organisation currently processing the prescription if it has already been downloaded. + properties: + reference: + type: string + description: A reference to an Organisation resource within the Bundle. + example: urn:uuid:d16fe9ef-665a-4039-9e21-70bca37f8a4a + quantity: + type: object + description: The quantity of medication prescribed. + properties: + value: + type: integer + description: The numeric value of the quantity. + format: int32 + example: 20 + unit: + type: string + description: The units in which the quantity was prescribed, defined using Dictionary of Medicines and Devices (DM+D) units of measure. + example: tablet + system: + type: string + description: SNOMED codesystem URL. + enum: [http://snomed.info/sct] + code: + type: integer + description: The DM+D code associated with a given unit of measure. + example: 428673006 + substitution: + type: object + description: This is a boolean value that should always default to false because EPS does not support substitutions. + required: [allowedBoolean] + properties: + allowedBoolean: + type: boolean + enum: [false] + extension: + type: array + items: + type: object + description: Will contain the most recent status update for the prescription item provided in the prescription status update API. + required: [url, extension] + properties: + url: + type: string + enum: ["https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory"] + extension: + type: array + items: + anyOf: + - $ref: ../fragments/medicationRequest/statusDate.yaml + - $ref: ../fragments/medicationRequest/status.yaml diff --git a/packages/specification/schemas/resources/OperationOutcome.yaml b/packages/specification/schemas/resources/OperationOutcome.yaml new file mode 100644 index 000000000..cc8b0db37 --- /dev/null +++ b/packages/specification/schemas/resources/OperationOutcome.yaml @@ -0,0 +1,83 @@ +type: object +description: | + Outcome of an operation that does not result in a resource or bundle being returned. + For example - error, async/batch submission. +properties: + resourceType: + type: string + description: FHIR Resource Type. + enum: [OperationOutcome] + id: + type: string + description: ID to link the request and response (Lambda request ID) + meta: + type: object + required: [lastUpdated] + description: Metadata regarding the request + properties: + lastUpdated: + type: string + description: Timestamp at which the response was generated + issue: + type: array + description: List of issues that have occurred. + minItems: 1 + items: + type: object + required: [severity, code] + properties: + severity: + type: string + enum: [fatal, error, warning, information] + description: Severity of the error. + code: + type: string + description: FHIR error code. + enum: + - business-rule + - code-invalid + - conflict + - deleted + - duplicate + - exception + - expired + - extension + - forbidden + - incomplete + - informational + - invalid + - invariant + - lock-error + - login + - multiple-matches + - no-store + - not-supported + - not-found + - processing + - required + - structure + - security + - suppressed + - throttled + - timeout + - too-costly + - too-long + - transient + - unknown + - value + details: + type: object + description: Internal error code. + properties: + coding: + type: array + items: + $ref: ../fragments/codes.yaml#/SpineErrorOrWarningCode + expression: + type: string + description: FHIR Path of element(s) related to the error. + example: Patient.name.given + diagnostics: + type: string + description: A description of the reasoning for including an OperationOutcome + example: Some prescriptions have been invalidated so could not be returned. diff --git a/packages/specification/schemas/resources/Organisation.yaml b/packages/specification/schemas/resources/Organisation.yaml new file mode 100644 index 000000000..eeb3ede13 --- /dev/null +++ b/packages/specification/schemas/resources/Organisation.yaml @@ -0,0 +1,30 @@ +type: object +description: Details of the organisation. +properties: + resourceType: + type: string + description: FHIR resource type. + default: Organization + identifier: + type: array + description: An array containing the ODS code of the organisation. + items: + $ref: ../fragments/identifiers.yaml#/OdsOrganisationCode + name: + type: string + description: Organisation name. + address: + type: array + description: | + Organisation address. + One of line or text, and optionally postalCode, will be populated. + If postalCode is not populated, the organization's postalCode may be included in line or text, if they are populated. + So address will contain use and type, along with one of: line, line and postalCode, text, text and postalCode, postalCode. + Note: city and district will not be populated by existing prescriptions. + items: + $ref: ../fragments/address.yaml + telecom: + type: array + description: The telephone number or Website URL associated with the organisation. + items: + $ref: ../fragments/telecom.yaml diff --git a/packages/specification/schemas/resources/Practitioner.yaml b/packages/specification/schemas/resources/Practitioner.yaml new file mode 100644 index 000000000..9be319973 --- /dev/null +++ b/packages/specification/schemas/resources/Practitioner.yaml @@ -0,0 +1,21 @@ +type: object +required: [resourceType, name] +description: Details of the prescriber of a prescription. +properties: + resourceType: + type: string + description: FHIR resource type. + enum: [Practitioner] + name: + type: array + description: The prescriber's name. + items: + oneOf: + - $ref: ../fragments/structuredName.yaml + - type: object + description: An unstructured name + properties: + text: + type: string + description: Text representation of the full name + example: Dr John Paul Smith MD diff --git a/packages/specification/schemas/resources/PractitionerRole.yaml b/packages/specification/schemas/resources/PractitionerRole.yaml new file mode 100644 index 000000000..2c1aa559f --- /dev/null +++ b/packages/specification/schemas/resources/PractitionerRole.yaml @@ -0,0 +1,26 @@ +type: object +required: + - practitioner + - organization +description: Role-specific details of the prescriber of a prescription. +properties: + resourceType: + type: string + description: FHIR resource type. + enum: [PractitionerRole] + practitioner: + type: object + description: A reference to a Practitioner resource for a given prescriber. + properties: + reference: + type: string + description: A FHIR reference object. + example: urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa47a + organization: + type: object + description: A reference to an Organization resource. + properties: + reference: + type: string + description: A FHIR reference object. + example: urn:uuid:a8c85454-f8cb-498d-9629-78e2cb5fa38b diff --git a/packages/specification/tsconfig.json b/packages/specification/tsconfig.json new file mode 100644 index 000000000..8a13686fe --- /dev/null +++ b/packages/specification/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.defaults.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "lib" + }, + "include": ["scripts/**/*", "tests/**/*"], + "exclude": ["node_modules"] +} diff --git a/tsconfig.build.json b/tsconfig.build.json index 85939df41..879f030e1 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -12,6 +12,7 @@ { "path": "packages/enrichPrescriptions" }, { "path": "packages/nhsd-pfp-sandbox" }, { "path": "packages/statusLambda" }, - { "path": "packages/distanceSelling" } + { "path": "packages/distanceSelling" }, + { "path": "packages/specification" } ] } From 4c10f797ead3b3d1567c0ccf0b4715bafc0e2878 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:27:16 +0000 Subject: [PATCH 04/45] Remove specification as TS package Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- packages/common/testing/src/index.ts | 3 ++- .../tests/testStatusUpdate.test.ts | 3 ++- .../tests/statusUpdate.test.ts | 3 ++- .../tests/test-handler.test.ts | 3 ++- packages/specification/jest.config.ts | 9 -------- packages/specification/jest.debug.config.ts | 9 -------- packages/specification/package.json | 23 ------------------- packages/specification/tsconfig.json | 9 -------- tsconfig.build.json | 3 +-- 9 files changed, 9 insertions(+), 56 deletions(-) delete mode 100644 packages/specification/jest.config.ts delete mode 100644 packages/specification/jest.debug.config.ts delete mode 100644 packages/specification/package.json delete mode 100644 packages/specification/tsconfig.json diff --git a/packages/common/testing/src/index.ts b/packages/common/testing/src/index.ts index 587f4819c..3fe760f9d 100644 --- a/packages/common/testing/src/index.ts +++ b/packages/common/testing/src/index.ts @@ -23,6 +23,7 @@ import _mockAPIResponseBody from "./mockAPIResponseBody.json" const mockAPIResponseBody = _mockAPIResponseBody import {createMockedPfPConfig, setupTestEnvironment} from "./test_fixtures" +import type {MockedPfPConfig} from "./test_fixtures" export { mockAPIGatewayProxyEvent, @@ -39,4 +40,4 @@ export { } // Type-only exports -export type {MockedPfPConfig} from "./test_fixtures" +export type {MockedPfPConfig} diff --git a/packages/enrichPrescriptions/tests/testStatusUpdate.test.ts b/packages/enrichPrescriptions/tests/testStatusUpdate.test.ts index ad94f1331..db8d3bd75 100644 --- a/packages/enrichPrescriptions/tests/testStatusUpdate.test.ts +++ b/packages/enrichPrescriptions/tests/testStatusUpdate.test.ts @@ -38,7 +38,8 @@ import { import {Bundle, MedicationRequest} from "fhir/r4" import {Logger} from "@aws-lambda-powertools/logger" import {isolateMedicationRequests, isolatePrescriptions} from "../src/fhirUtils" -import {createMockedPfPConfig, MockedPfPConfig, setupTestEnvironment} from "@pfp-common/testing" +import {createMockedPfPConfig, setupTestEnvironment} from "@pfp-common/testing" +import type {MockedPfPConfig} from "@pfp-common/testing" const TC007_NHS_NUMBER = "9992032499" diff --git a/packages/getMyPrescriptions/tests/statusUpdate.test.ts b/packages/getMyPrescriptions/tests/statusUpdate.test.ts index 9bf72f8b6..6d7365f93 100644 --- a/packages/getMyPrescriptions/tests/statusUpdate.test.ts +++ b/packages/getMyPrescriptions/tests/statusUpdate.test.ts @@ -30,7 +30,8 @@ import { stateMachineEventHandler } from "../src/getMyPrescriptions" import {EXPECTED_TRACE_IDS, SERVICE_SEARCH_PARAMS} from "./utils" -import {createMockedPfPConfig, MockedPfPConfig, setupTestEnvironment} from "@pfp-common/testing" +import {createMockedPfPConfig, setupTestEnvironment} from "@pfp-common/testing" +import type {MockedPfPConfig} from "@pfp-common/testing" import {LogLevel} from "@aws-lambda-powertools/logger/types" import {Logger} from "@aws-lambda-powertools/logger" import {createSpineClient} from "@NHSDigital/eps-spine-client" diff --git a/packages/getMyPrescriptions/tests/test-handler.test.ts b/packages/getMyPrescriptions/tests/test-handler.test.ts index dcca05001..728e6aa7a 100644 --- a/packages/getMyPrescriptions/tests/test-handler.test.ts +++ b/packages/getMyPrescriptions/tests/test-handler.test.ts @@ -31,7 +31,8 @@ import {EXPECTED_TRACE_IDS} from "./utils" import {LogLevel} from "@aws-lambda-powertools/logger/types" import {createSpineClient} from "@NHSDigital/eps-spine-client" import {MiddyfiedHandler} from "@middy/core" -import {createMockedPfPConfig, MockedPfPConfig, setupTestEnvironment} from "@pfp-common/testing" +import {createMockedPfPConfig, setupTestEnvironment} from "@pfp-common/testing" +import type {MockedPfPConfig} from "@pfp-common/testing" const TC008_NHS_NUMBER = "9992387920" diff --git a/packages/specification/jest.config.ts b/packages/specification/jest.config.ts deleted file mode 100644 index 1ddbc83f6..000000000 --- a/packages/specification/jest.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import defaultConfig from "../../jest.default.config" -import type {JestConfigWithTsJest} from "ts-jest" - -const jestConfig: JestConfigWithTsJest = { - ...defaultConfig, - "rootDir": "./" -} - -export default jestConfig diff --git a/packages/specification/jest.debug.config.ts b/packages/specification/jest.debug.config.ts deleted file mode 100644 index a30627383..000000000 --- a/packages/specification/jest.debug.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import config from "./jest.config" -import type {JestConfigWithTsJest} from "ts-jest" - -const debugConfig: JestConfigWithTsJest = { - ...config, - "preset": "ts-jest" -} - -export default debugConfig diff --git a/packages/specification/package.json b/packages/specification/package.json deleted file mode 100644 index 96f0acd7f..000000000 --- a/packages/specification/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "apim-spec", - "version": "0.0.1", - "description": "OAS (Swagger v3) API Definition for Prescriptions-For-Patients", - "homepage": "https://github.com/NHSDigital/prescriptionsforpatients", - "author": "NHS Digital", - "license": "MIT", - "type": "module", - "engines": { - "node": "20.10.x", - "npm": "10.2.x" - }, - "scripts": { - "lint": "redocly lint --extends=recommended --config ./redocly.yaml", - "resolve": "redocly bundle prescriptions-for-patients.yaml -d -o dist/prescriptions-for-patients.resolved.json", - "clean": "rm -rf lib coverage", - "check-licenses": "license-checker --failOn GPL --failOn LGPL --start ../.." - }, - "devDependencies": { - "@redocly/cli": "^2.12.3", - "tsx": "4.21.0" - } -} diff --git a/packages/specification/tsconfig.json b/packages/specification/tsconfig.json deleted file mode 100644 index 8a13686fe..000000000 --- a/packages/specification/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.defaults.json", - "compilerOptions": { - "rootDir": ".", - "outDir": "lib" - }, - "include": ["scripts/**/*", "tests/**/*"], - "exclude": ["node_modules"] -} diff --git a/tsconfig.build.json b/tsconfig.build.json index 879f030e1..85939df41 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -12,7 +12,6 @@ { "path": "packages/enrichPrescriptions" }, { "path": "packages/nhsd-pfp-sandbox" }, { "path": "packages/statusLambda" }, - { "path": "packages/distanceSelling" }, - { "path": "packages/specification" } + { "path": "packages/distanceSelling" } ] } From 398771cfbc214e01ba186bc4c38d6c1ab1bb02c2 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 11:19:37 +0000 Subject: [PATCH 05/45] Pipeline kickoff From 519d0c5aacd5d36daac6485cc5db867fd6660086 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 11:37:55 +0000 Subject: [PATCH 06/45] Pipeline kickoff From 0382173dae64507b59914ad326387cfa5142dbb6 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 11:38:04 +0000 Subject: [PATCH 07/45] Pipeline kickoff From ad0dbf465494a3b5fcf699a0782c7d0e4b479247 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 11:38:26 +0000 Subject: [PATCH 08/45] Pipeline kickoff2 From 8af4e503263df5cf668b273e6e6232ee38f2c68d Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 12:09:46 +0000 Subject: [PATCH 09/45] NPM run redocly #skip-qc Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- packages/specification/package.json | 26 ++++++++++++++++++++++++++ packages/specification/tsconfig.json | 9 +++++++++ tsconfig.build.json | 3 ++- 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 packages/specification/package.json create mode 100644 packages/specification/tsconfig.json diff --git a/packages/specification/package.json b/packages/specification/package.json new file mode 100644 index 000000000..ceff63249 --- /dev/null +++ b/packages/specification/package.json @@ -0,0 +1,26 @@ +{ + "name": "apim-spec", + "version": "0.0.1", + "description": "OAS (Swagger v3) API Definition for Prescriptions for Patients", + "homepage": "https://github.com/NHSDigital/prescriptionsforpatients", + "author": "NHS Digital", + "license": "MIT", + "type": "module", + "engines": { + "node": "20.10.x", + "npm": "10.2.x" + }, + "scripts": { + "lint": "redocly lint --extends=recommended --config ./redocly.yaml", + "resolve": "redocly bundle prescriptions-for-patients.yaml -d -o dist/prescriptions-for-patients.resolved.json", + "clean": "rm -rf lib coverage", + "check-licenses": "license-checker --failOn GPL --failOn LGPL --start ../.." + }, + "devDependencies": { + "@redocly/cli": "^2.12.6", + "clinicalView": "^1.0.0", + "prescriptionSearch": "^1.0.0", + "@cpt-common/common-types": "^1.0.0", + "tsx": "4.21.0" + } +} diff --git a/packages/specification/tsconfig.json b/packages/specification/tsconfig.json new file mode 100644 index 000000000..81eae7c5d --- /dev/null +++ b/packages/specification/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.defaults.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "lib" + }, + "files": [], + "exclude": ["node_modules"] +} diff --git a/tsconfig.build.json b/tsconfig.build.json index 85939df41..879f030e1 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -12,6 +12,7 @@ { "path": "packages/enrichPrescriptions" }, { "path": "packages/nhsd-pfp-sandbox" }, { "path": "packages/statusLambda" }, - { "path": "packages/distanceSelling" } + { "path": "packages/distanceSelling" }, + { "path": "packages/specification" } ] } From 08e1e78f94361c0ad5bcb9e3195f979924f57f4f Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 12:15:25 +0000 Subject: [PATCH 10/45] Remove unneccessary dependencies Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- packages/specification/package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/specification/package.json b/packages/specification/package.json index ceff63249..02624efdb 100644 --- a/packages/specification/package.json +++ b/packages/specification/package.json @@ -18,9 +18,6 @@ }, "devDependencies": { "@redocly/cli": "^2.12.6", - "clinicalView": "^1.0.0", - "prescriptionSearch": "^1.0.0", - "@cpt-common/common-types": "^1.0.0", "tsx": "4.21.0" } } From 09df7a01e95100440127f7cec71bc25f83cd6999 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 12:38:30 +0000 Subject: [PATCH 11/45] Fix build #skip-qc Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/sam_package_code.yml | 1 + packages/specification/package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sam_package_code.yml b/.github/workflows/sam_package_code.yml index c623ffea8..0d02c9b7e 100644 --- a/.github/workflows/sam_package_code.yml +++ b/.github/workflows/sam_package_code.yml @@ -71,6 +71,7 @@ jobs: path: | .aws-sam/build packages/getSecretLayer/lib/get-secrets-layer.zip + packages/specification/dist/prescriptions-for-patients.resolved.json SAMtemplates/state_machines/GetMyPrescriptionsStateMachine.asl.json - shell: bash diff --git a/packages/specification/package.json b/packages/specification/package.json index 02624efdb..e3f6f9005 100644 --- a/packages/specification/package.json +++ b/packages/specification/package.json @@ -12,7 +12,7 @@ }, "scripts": { "lint": "redocly lint --extends=recommended --config ./redocly.yaml", - "resolve": "redocly bundle prescriptions-for-patients.yaml -d -o dist/prescriptions-for-patients.resolved.json", + "compile": "redocly bundle prescriptions-for-patients.yaml -d -o dist/prescriptions-for-patients.resolved.json", "clean": "rm -rf lib coverage", "check-licenses": "license-checker --failOn GPL --failOn LGPL --start ../.." }, From b4b34618bb478e2af47ac4ebc06ad7a12c702704 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 14:04:37 +0000 Subject: [PATCH 12/45] Modify path Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/sam_release_code.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sam_release_code.yml b/.github/workflows/sam_release_code.yml index c6247a57d..ef675139b 100644 --- a/.github/workflows/sam_release_code.yml +++ b/.github/workflows/sam_release_code.yml @@ -193,7 +193,7 @@ jobs: env: API_TYPE: standard VERSION_NUMBER: ${{ inputs.VERSION_NUMBER }} - SPEC_PATH: ./.build/packages/specification/dist/prescriptions-for-patients.resolved.json + SPEC_PATH: ./packages/specification/dist/prescriptions-for-patients.resolved.json STACK_NAME: ${{ inputs.STACK_NAME }} AWS_ENVIRONMENT: ${{ inputs.TARGET_ENVIRONMENT }} APIGEE_ENVIRONMENT: ${{ inputs.APIGEE_ENVIRONMENT }} From ccbbf0ce131f8e615f1833ff925993a6fb33b461 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 14:27:13 +0000 Subject: [PATCH 13/45] Compile then upload Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/sam_package_code.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/sam_package_code.yml b/.github/workflows/sam_package_code.yml index 0d02c9b7e..e466c66c8 100644 --- a/.github/workflows/sam_package_code.yml +++ b/.github/workflows/sam_package_code.yml @@ -53,6 +53,7 @@ jobs: - name: make install run: | make install + make compile - shell: bash name: package code @@ -91,3 +92,4 @@ jobs: path: | .aws-sam/build packages/getSecretLayer/lib/get-secrets-layer.zip + packages/specification/dist/prescriptions-for-patients.resolved.json From 5fa4728d52790288c166fa6e1b5fffc5fe983ba9 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 14:40:23 +0000 Subject: [PATCH 14/45] Add in compile stage on makefile Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f3800ca4d..b4de239a5 100644 --- a/Makefile +++ b/Makefile @@ -112,7 +112,10 @@ sam-deploy-package: guard-artifact_bucket guard-artifact_bucket_prefix guard-sta compile-node: npx tsc --build tsconfig.build.json -compile: compile-node +compile: compile-node compile-specification + +compile-specification: + npm run compile --workspace packages/specification download-get-secrets-layer: mkdir -p packages/getSecretLayer/lib From a95ac8c1e0408b038bdbbd4c23906fbd032ee4e9 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:19:52 +0000 Subject: [PATCH 15/45] Correct proxygen secret name Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/scripts/deploy_api.sh | 2 +- .github/workflows/sam_release_code.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/scripts/deploy_api.sh b/.github/scripts/deploy_api.sh index ccb1a36b3..f38a75bfe 100755 --- a/.github/scripts/deploy_api.sh +++ b/.github/scripts/deploy_api.sh @@ -93,7 +93,7 @@ echo echo "Retrieving proxygen credentials" # Retrieve the proxygen private key and client private key and cert from AWS Secrets Manager -proxygen_private_key_arn=$(aws cloudformation list-exports --query "Exports[?Name=='account-resources:${PROXYGEN_PRIVATE_KEY_NAME}'].Value" --output text) +proxygen_private_key_arn=$(aws cloudformation list-exports --query "Exports[?Name=='secrets:${PROXYGEN_PRIVATE_KEY_NAME}'].Value" --output text) if [[ "${ENABLE_MUTUAL_TLS}" == "true" ]]; then echo diff --git a/.github/workflows/sam_release_code.yml b/.github/workflows/sam_release_code.yml index ef675139b..79fbc99af 100644 --- a/.github/workflows/sam_release_code.yml +++ b/.github/workflows/sam_release_code.yml @@ -197,7 +197,7 @@ jobs: STACK_NAME: ${{ inputs.STACK_NAME }} AWS_ENVIRONMENT: ${{ inputs.TARGET_ENVIRONMENT }} APIGEE_ENVIRONMENT: ${{ inputs.APIGEE_ENVIRONMENT }} - PROXYGEN_PRIVATE_KEY_NAME: PrescriptonsForPatientsProxygenPrivateKey + PROXYGEN_PRIVATE_KEY_NAME: PrescriptionsForPatientsProxygenPrivateKey PROXYGEN_KID: prescriptions-for-patients DRY_RUN: false ENABLE_MUTUAL_TLS: ${{ inputs.ENABLE_MUTUAL_TLS }} From e1af0edc0eb993bbaec293007d3e4a29295ed948 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 09:38:52 +0000 Subject: [PATCH 16/45] Modify apigee client Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/scripts/deploy_api.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/scripts/deploy_api.sh b/.github/scripts/deploy_api.sh index f38a75bfe..0d3327f92 100755 --- a/.github/scripts/deploy_api.sh +++ b/.github/scripts/deploy_api.sh @@ -43,10 +43,12 @@ fi # Determine the proxy instance based on the provided $STACK_NAME apigee_api=pfp-proxygen +apigee_client=prescriptions-for-patients instance="pfp-proxygen${instance_suffix}" echo "Proxy instance: ${instance}" echo "Apigee api: ${apigee_api}" +echo "Apigee client: ${apigee_client}" echo @@ -100,6 +102,7 @@ if [[ "${ENABLE_MUTUAL_TLS}" == "true" ]]; then echo "Store the secret used for mutual TLS to AWS using Proxygen proxy lambda" if [[ "${DRY_RUN}" == "false" ]]; then jq -n --arg apiName "${apigee_api}" \ + --arg apiClient "${apigee_client}" \ --arg environment "${APIGEE_ENVIRONMENT}" \ --arg secretName "${MTLS_KEY}" \ --arg secretKey "${client_private_key}" \ @@ -126,6 +129,7 @@ if [[ "${DRY_RUN}" == "false" ]]; then jq -n --argfile spec "${SPEC_PATH}" \ --arg apiName "${apigee_api}" \ + --arg apiClient "${apigee_client}" \ --arg environment "${APIGEE_ENVIRONMENT}" \ --arg instance "${instance}" \ --arg kid "${PROXYGEN_KID}" \ @@ -150,6 +154,7 @@ fi # if [[ "${DRY_RUN}" == "false" ]]; then # jq -n --argfile spec "${SPEC_PATH}" \ # --arg apiName "${apigee_api}" \ +# --arg apiClient "${apigee_client}" \ # --arg environment "prod" \ # --arg instance "${instance}" \ # --arg kid "${PROXYGEN_KID}" \ @@ -175,6 +180,7 @@ if [[ "${APIGEE_ENVIRONMENT}" == "internal-dev" && "${IS_PULL_REQUEST}" == "fals if [[ "${DRY_RUN}" == "false" ]]; then jq -n --argfile spec "${SPEC_PATH}" \ --arg apiName "${apigee_api}" \ + --arg apiClient "${apigee_client}" \ --arg environment "uat" \ --arg instance "${instance}" \ --arg kid "${PROXYGEN_KID}" \ From fea4c425f6500405a171cbec28bf5a37d963caff Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 11:04:50 +0000 Subject: [PATCH 17/45] Kick off pipelines From aa755bbcbab483cf3b6b758aa436d87d8a7ce578 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 11:20:00 +0000 Subject: [PATCH 18/45] Include apiclient in payload JSON #skip-qc Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/scripts/deploy_api.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/scripts/deploy_api.sh b/.github/scripts/deploy_api.sh index 0d3327f92..cdac7e68c 100755 --- a/.github/scripts/deploy_api.sh +++ b/.github/scripts/deploy_api.sh @@ -109,7 +109,7 @@ if [[ "${ENABLE_MUTUAL_TLS}" == "true" ]]; then --arg secretCert "${client_cert}" \ --arg kid "${PROXYGEN_KID}" \ --arg proxygenSecretName "${proxygen_private_key_arn}" \ - '{apiName: $apiName, environment: $environment, secretName: $secretName, secretKey: $secretKey, secretCert: $secretCert, kid, $kid, proxygenSecretName: $proxygenSecretName}' > payload.json + '{apiName: $apiName, apiClient: $apiClient, environment: $environment, secretName: $secretName, secretKey: $secretKey, secretCert: $secretCert, kid, $kid, proxygenSecretName: $proxygenSecretName}' > payload.json aws lambda invoke --function-name "${put_secret_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then @@ -134,7 +134,7 @@ if [[ "${DRY_RUN}" == "false" ]]; then --arg instance "${instance}" \ --arg kid "${PROXYGEN_KID}" \ --arg proxygenSecretName "${proxygen_private_key_arn}" \ - '{apiName: $apiName, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json + '{apiName: $apiName, apiClient: $apiClient, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json aws lambda invoke --function-name "${instance_put_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json @@ -159,7 +159,7 @@ fi # --arg instance "${instance}" \ # --arg kid "${PROXYGEN_KID}" \ # --arg proxygenSecretName "${proxygen_private_key_arn}" \ -# '{apiName: $apiName, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json +# '{apiName: $apiName, apiClient: $apiClient, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json # aws lambda invoke --function-name "${spec_publish_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json @@ -185,7 +185,7 @@ if [[ "${APIGEE_ENVIRONMENT}" == "internal-dev" && "${IS_PULL_REQUEST}" == "fals --arg instance "${instance}" \ --arg kid "${PROXYGEN_KID}" \ --arg proxygenSecretName "${proxygen_private_key_arn}" \ - '{apiName: $apiName, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json + '{apiName: $apiName, apiClient: $apiClient, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json aws lambda invoke --function-name "${spec_publish_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json From ed0307e99d05f7ae3378204f78593598cea383bf Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 11:44:35 +0000 Subject: [PATCH 19/45] Set internal dev server & modify when mtls is set Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/scripts/deploy_api.sh | 50 +++++++++---------- .../prescriptions-for-patients.yaml | 2 + 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/.github/scripts/deploy_api.sh b/.github/scripts/deploy_api.sh index cdac7e68c..4151eaef7 100755 --- a/.github/scripts/deploy_api.sh +++ b/.github/scripts/deploy_api.sh @@ -97,6 +97,31 @@ echo "Retrieving proxygen credentials" # Retrieve the proxygen private key and client private key and cert from AWS Secrets Manager proxygen_private_key_arn=$(aws cloudformation list-exports --query "Exports[?Name=='secrets:${PROXYGEN_PRIVATE_KEY_NAME}'].Value" --output text) +echo +echo "Deploy the API instance using Proxygen proxy lambda" +if [[ "${DRY_RUN}" == "false" ]]; then + + jq -n --argfile spec "${SPEC_PATH}" \ + --arg apiName "${apigee_api}" \ + --arg apiClient "${apigee_client}" \ + --arg environment "${APIGEE_ENVIRONMENT}" \ + --arg instance "${instance}" \ + --arg kid "${PROXYGEN_KID}" \ + --arg proxygenSecretName "${proxygen_private_key_arn}" \ + '{apiName: $apiName, apiClient: $apiClient, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json + + aws lambda invoke --function-name "${instance_put_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json + + if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then + echo 'Error calling lambda' + cat out.txt + exit 1 + fi + echo "Instance deployed" +else + echo "Would call ${instance_put_lambda}" +fi + if [[ "${ENABLE_MUTUAL_TLS}" == "true" ]]; then echo echo "Store the secret used for mutual TLS to AWS using Proxygen proxy lambda" @@ -123,31 +148,6 @@ if [[ "${ENABLE_MUTUAL_TLS}" == "true" ]]; then fi fi -echo -echo "Deploy the API instance using Proxygen proxy lambda" -if [[ "${DRY_RUN}" == "false" ]]; then - - jq -n --argfile spec "${SPEC_PATH}" \ - --arg apiName "${apigee_api}" \ - --arg apiClient "${apigee_client}" \ - --arg environment "${APIGEE_ENVIRONMENT}" \ - --arg instance "${instance}" \ - --arg kid "${PROXYGEN_KID}" \ - --arg proxygenSecretName "${proxygen_private_key_arn}" \ - '{apiName: $apiName, apiClient: $apiClient, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json - - aws lambda invoke --function-name "${instance_put_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json - - if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then - echo 'Error calling lambda' - cat out.txt - exit 1 - fi - echo "Instance deployed" -else - echo "Would call ${instance_put_lambda}" -fi - # if [[ "${APIGEE_ENVIRONMENT}" == "int" ]]; then # echo # echo "Deploy the API spec to prod catalogue as it is int environment" diff --git a/packages/specification/prescriptions-for-patients.yaml b/packages/specification/prescriptions-for-patients.yaml index 38232cf20..2422631db 100644 --- a/packages/specification/prescriptions-for-patients.yaml +++ b/packages/specification/prescriptions-for-patients.yaml @@ -102,6 +102,8 @@ x-spec-publication: path: /Bundle servers: + - url: https://internal-dev.api.service.nhs.uk/prescriptions-for-patients + description: Internal Dev - url: "https://sandbox.api.service.nhs.uk/prescriptions-for-patients" description: Sandbox - url: "https://int.api.service.nhs.uk/prescriptions-for-patients" From d3715c2d42877b2cc5200b6456aae542751363e1 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 12:09:11 +0000 Subject: [PATCH 20/45] Adjust API to be p-f-p Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/scripts/deploy_api.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/deploy_api.sh b/.github/scripts/deploy_api.sh index 4151eaef7..57843a9f8 100755 --- a/.github/scripts/deploy_api.sh +++ b/.github/scripts/deploy_api.sh @@ -42,7 +42,7 @@ if [[ "${IS_PULL_REQUEST}" == "true" ]]; then fi # Determine the proxy instance based on the provided $STACK_NAME -apigee_api=pfp-proxygen +apigee_api=prescriptions-for-patients apigee_client=prescriptions-for-patients instance="pfp-proxygen${instance_suffix}" From d4e6dab191a48928d6a6144fff46354d53af300a Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 12:11:21 +0000 Subject: [PATCH 21/45] Set MTLS first Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/scripts/deploy_api.sh | 50 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/scripts/deploy_api.sh b/.github/scripts/deploy_api.sh index 57843a9f8..d37dff5b3 100755 --- a/.github/scripts/deploy_api.sh +++ b/.github/scripts/deploy_api.sh @@ -97,31 +97,6 @@ echo "Retrieving proxygen credentials" # Retrieve the proxygen private key and client private key and cert from AWS Secrets Manager proxygen_private_key_arn=$(aws cloudformation list-exports --query "Exports[?Name=='secrets:${PROXYGEN_PRIVATE_KEY_NAME}'].Value" --output text) -echo -echo "Deploy the API instance using Proxygen proxy lambda" -if [[ "${DRY_RUN}" == "false" ]]; then - - jq -n --argfile spec "${SPEC_PATH}" \ - --arg apiName "${apigee_api}" \ - --arg apiClient "${apigee_client}" \ - --arg environment "${APIGEE_ENVIRONMENT}" \ - --arg instance "${instance}" \ - --arg kid "${PROXYGEN_KID}" \ - --arg proxygenSecretName "${proxygen_private_key_arn}" \ - '{apiName: $apiName, apiClient: $apiClient, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json - - aws lambda invoke --function-name "${instance_put_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json - - if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then - echo 'Error calling lambda' - cat out.txt - exit 1 - fi - echo "Instance deployed" -else - echo "Would call ${instance_put_lambda}" -fi - if [[ "${ENABLE_MUTUAL_TLS}" == "true" ]]; then echo echo "Store the secret used for mutual TLS to AWS using Proxygen proxy lambda" @@ -148,6 +123,31 @@ if [[ "${ENABLE_MUTUAL_TLS}" == "true" ]]; then fi fi +echo +echo "Deploy the API instance using Proxygen proxy lambda" +if [[ "${DRY_RUN}" == "false" ]]; then + + jq -n --argfile spec "${SPEC_PATH}" \ + --arg apiName "${apigee_api}" \ + --arg apiClient "${apigee_client}" \ + --arg environment "${APIGEE_ENVIRONMENT}" \ + --arg instance "${instance}" \ + --arg kid "${PROXYGEN_KID}" \ + --arg proxygenSecretName "${proxygen_private_key_arn}" \ + '{apiName: $apiName, apiClient: $apiClient, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json + + aws lambda invoke --function-name "${instance_put_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json + + if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then + echo 'Error calling lambda' + cat out.txt + exit 1 + fi + echo "Instance deployed" +else + echo "Would call ${instance_put_lambda}" +fi + # if [[ "${APIGEE_ENVIRONMENT}" == "int" ]]; then # echo # echo "Deploy the API spec to prod catalogue as it is int environment" From 4890c369522e63c206a8119bd85fbcdecc87aa7c Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 12:35:39 +0000 Subject: [PATCH 22/45] Kick off pipeline From 7f13f217f9d9b1cd3428074c317cdcccd4003f90 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 14:53:56 +0000 Subject: [PATCH 23/45] Switch naming to pfp-proxygen Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/scripts/deploy_api.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/scripts/deploy_api.sh b/.github/scripts/deploy_api.sh index d37dff5b3..13e5a5d73 100755 --- a/.github/scripts/deploy_api.sh +++ b/.github/scripts/deploy_api.sh @@ -42,8 +42,8 @@ if [[ "${IS_PULL_REQUEST}" == "true" ]]; then fi # Determine the proxy instance based on the provided $STACK_NAME -apigee_api=prescriptions-for-patients -apigee_client=prescriptions-for-patients +apigee_api=prescriptions-for-patients-proxygen +apigee_client=prescriptions-for-patients-proxygen instance="pfp-proxygen${instance_suffix}" echo "Proxy instance: ${instance}" From 9800d9a9c6829716707a0447428c04c03e719ae6 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 15:22:25 +0000 Subject: [PATCH 24/45] Set security schemas Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/scripts/deploy_api.sh | 2 ++ packages/specification/prescriptions-for-patients.yaml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/.github/scripts/deploy_api.sh b/.github/scripts/deploy_api.sh index 13e5a5d73..456592f89 100755 --- a/.github/scripts/deploy_api.sh +++ b/.github/scripts/deploy_api.sh @@ -77,8 +77,10 @@ fi # Find and replace securitySchemes if [[ "${APIGEE_ENVIRONMENT}" == "prod" ]]; then jq '.components.securitySchemes."nhs-cis2-aal3" = {"$ref": "https://proxygen.prod.api.platform.nhs.uk/components/securitySchemes/nhs-cis2-aal3"}' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" + jq '.components.securitySchemes."nhs-login-p9" = {"$ref": "https://proxygen.prod.api.platform.nhs.uk/components/securitySchemes/nhs-login-p9"}' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" else jq '.components.securitySchemes."nhs-cis2-aal3" = {"$ref": "https://proxygen.ptl.api.platform.nhs.uk/components/securitySchemes/nhs-cis2-aal3"}' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" + jq '.components.securitySchemes."nhs-login-p9" = {"$ref": "https://proxygen.ptl.api.platform.nhs.uk/components/securitySchemes/nhs-login-p9"}' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}" fi # Find and replace the x-nhsd-apim.target.secret value diff --git a/packages/specification/prescriptions-for-patients.yaml b/packages/specification/prescriptions-for-patients.yaml index 2422631db..fb85b4728 100644 --- a/packages/specification/prescriptions-for-patients.yaml +++ b/packages/specification/prescriptions-for-patients.yaml @@ -209,6 +209,9 @@ paths: value: $ref: examples/GetMyPrescriptions/Bundle/error/error-500.json components: + securitySchemes: + nhs-login-p9: + $ref: https://proxygen.prod.api.platform.nhs.uk/components/securitySchemes/nhs-login-p9 parameters: BearerAuthorisation: in: header From eb591e26fcd0574453d07694efe08f0a7ee41cff Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 16:11:05 +0000 Subject: [PATCH 25/45] Spec adjustments - Output spec always Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/sam_release_code.yml | 1 + packages/specification/prescriptions-for-patients.yaml | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sam_release_code.yml b/.github/workflows/sam_release_code.yml index 79fbc99af..5633b5676 100644 --- a/.github/workflows/sam_release_code.yml +++ b/.github/workflows/sam_release_code.yml @@ -206,6 +206,7 @@ jobs: run: ./.github/scripts/deploy_api.sh - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 + if: always() && !cancelled() name: Upload specs with: name: ${{ inputs.APIGEE_ENVIRONMENT }}-specs diff --git a/packages/specification/prescriptions-for-patients.yaml b/packages/specification/prescriptions-for-patients.yaml index fb85b4728..5ec5d91a7 100644 --- a/packages/specification/prescriptions-for-patients.yaml +++ b/packages/specification/prescriptions-for-patients.yaml @@ -2,8 +2,7 @@ # for the Prescriptions API # owned by NHS Digital (https://digital.nhs.uk/) -openapi: 3.0.0 -x-nhs-api-spec-guid: 816f3e79-1d81-4ae7-af54-dcd4a739d01a +openapi: 3.0.3 info: title: Prescriptions for Patients API version: "0.0.1" @@ -123,6 +122,8 @@ paths: - $ref: "#/components/parameters/BearerAuthorisation" - $ref: "#/components/parameters/RequestID" - $ref: "#/components/parameters/CorrelationID" + security: + - nhs-login-p9: [] responses: "200": description: Successful retrieval. From 052c4abe8629f97978c9e27551e34151d1ff3cf3 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Tue, 16 Dec 2025 17:29:56 +0000 Subject: [PATCH 26/45] temp disable enablement of mtls Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index ead607e8b..f93849adc 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -105,7 +105,7 @@ jobs: ARTIFACT_BUCKET_PREFIX: PR-${{needs.get_issue_number.outputs.issue_number}} TARGET_ENVIRONMENT: dev-pr APIGEE_ENVIRONMENT: internal-dev - ENABLE_MUTUAL_TLS: true + ENABLE_MUTUAL_TLS: false MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code TRUSTSTORE_FILE: pfp-truststore-pr.pem # temporary From db692f9e3b2b356b6c18141f77850e31a2474296 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:08:41 +0000 Subject: [PATCH 27/45] Modify target environment Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index f93849adc..e78351aff 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -103,7 +103,7 @@ jobs: IS_PULL_REQUEST: true STACK_NAME: pfp-pr-${{needs.get_issue_number.outputs.issue_number}} ARTIFACT_BUCKET_PREFIX: PR-${{needs.get_issue_number.outputs.issue_number}} - TARGET_ENVIRONMENT: dev-pr + TARGET_ENVIRONMENT: dev APIGEE_ENVIRONMENT: internal-dev ENABLE_MUTUAL_TLS: false MTLS_KEY: prescriptions-for-patients-mtls-1 From 98383c15c418450d6727f4372ed0b0ad1d493031 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:14:57 +0000 Subject: [PATCH 28/45] Stop release tag update from PRs Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/sam_release_code.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sam_release_code.yml b/.github/workflows/sam_release_code.yml index 5633b5676..e145fe35c 100644 --- a/.github/workflows/sam_release_code.yml +++ b/.github/workflows/sam_release_code.yml @@ -249,7 +249,7 @@ jobs: path: gh-pages - name: update release tag in github pages - if: ${{ inputs.TARGET_ENVIRONMENT != 'dev-pr' }} + if: ${{ inputs.IS_PULL_REQUEST == false }} run: | cd gh-pages NOW=$(date +'%Y-%m-%dT%H:%M:%S') From f8077b9cdb097b3e3b5faeaee1fc646d76668bda Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:37:48 +0000 Subject: [PATCH 29/45] enable tls Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index e78351aff..45a24205d 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -105,7 +105,7 @@ jobs: ARTIFACT_BUCKET_PREFIX: PR-${{needs.get_issue_number.outputs.issue_number}} TARGET_ENVIRONMENT: dev APIGEE_ENVIRONMENT: internal-dev - ENABLE_MUTUAL_TLS: false + ENABLE_MUTUAL_TLS: true MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code TRUSTSTORE_FILE: pfp-truststore-pr.pem # temporary From bd9ccdb8266e9cac938ed9a35f0334685b38e5f8 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Wed, 17 Dec 2025 10:59:46 +0000 Subject: [PATCH 30/45] Kick off pipeline From 633e4e62e4c426e2ddef72105ef53ddc75e7d594 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Thu, 18 Dec 2025 10:17:43 +0000 Subject: [PATCH 31/45] Modify header given to pfp Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- packages/specification/prescriptions-for-patients.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/specification/prescriptions-for-patients.yaml b/packages/specification/prescriptions-for-patients.yaml index 5ec5d91a7..a7e61d293 100644 --- a/packages/specification/prescriptions-for-patients.yaml +++ b/packages/specification/prescriptions-for-patients.yaml @@ -429,7 +429,7 @@ x-nhsd-apim: secret: prescriptions-for-patients-mtls-1 target-identity: - name: nhs-login-nhs-number - header: "nhs-login-nhs-number" + header: "nhsd-login-user" ratelimiting: proxy: limit: 20000 From b7b70eec150164b08735585d34ec829b8e8262df Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Thu, 18 Dec 2025 10:41:16 +0000 Subject: [PATCH 32/45] Adjust to nhsd-nhslogin-user Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- packages/specification/prescriptions-for-patients.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/specification/prescriptions-for-patients.yaml b/packages/specification/prescriptions-for-patients.yaml index a7e61d293..eac70a0f4 100644 --- a/packages/specification/prescriptions-for-patients.yaml +++ b/packages/specification/prescriptions-for-patients.yaml @@ -429,7 +429,7 @@ x-nhsd-apim: secret: prescriptions-for-patients-mtls-1 target-identity: - name: nhs-login-nhs-number - header: "nhsd-login-user" + header: "nhsd-nhslogin-user" ratelimiting: proxy: limit: 20000 From 7224f63d15b3d5cefd28ee9430528d88d5657cb7 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:32:04 +0000 Subject: [PATCH 33/45] Introduce proofing level check Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- packages/getMyPrescriptions/src/extractNHSNumber.ts | 10 ++++++++++ packages/getMyPrescriptions/src/getMyPrescriptions.ts | 8 ++++---- packages/specification/prescriptions-for-patients.yaml | 2 ++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 618558491..d38acc8a8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -100,7 +100,7 @@ jobs: STACK_NAME: pfp-sandbox TARGET_ENVIRONMENT: dev APIGEE_ENVIRONMENT: internal-dev-sandbox - ENABLE_MUTUAL_TLS: true + ENABLE_MUTUAL_TLS: false MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_sandbox_code TRUSTSTORE_FILE: pfp-sandbox-truststore.pem diff --git a/packages/getMyPrescriptions/src/extractNHSNumber.ts b/packages/getMyPrescriptions/src/extractNHSNumber.ts index ea7071000..229b7e064 100644 --- a/packages/getMyPrescriptions/src/extractNHSNumber.ts +++ b/packages/getMyPrescriptions/src/extractNHSNumber.ts @@ -1,3 +1,5 @@ +import type {EventHeaders} from "./types" + export class NHSNumberValidationError extends Error { constructor(msg: string) { super(msg) @@ -7,6 +9,14 @@ export class NHSNumberValidationError extends Error { } } +export function extractNHSNumberFromHeaders(headers: EventHeaders): string { + if (headers["nhs-login-identity-proofing-level"]) { + return validateNHSNumber(headers["nhsd-nhslogin-user"]!) + } else { + return extractNHSNumber(headers["nhsd-nhslogin-user"]) + } +} + export function extractNHSNumber(nhsloginUser: string | undefined): string { if (nhsloginUser === undefined || nhsloginUser === null) { throw new NHSNumberValidationError("nhsdloginUser not passed in") diff --git a/packages/getMyPrescriptions/src/getMyPrescriptions.ts b/packages/getMyPrescriptions/src/getMyPrescriptions.ts index 8ca4c9664..2c47fc719 100644 --- a/packages/getMyPrescriptions/src/getMyPrescriptions.ts +++ b/packages/getMyPrescriptions/src/getMyPrescriptions.ts @@ -23,11 +23,12 @@ import { TraceIDs, ResponseFunc } from "./responses" -import {extractNHSNumber, NHSNumberValidationError, validateNHSNumber} from "./extractNHSNumber" +import {extractNHSNumberFromHeaders, NHSNumberValidationError, validateNHSNumber} from "./extractNHSNumber" import {deepCopy, hasTimedOut, jobWithTimeout} from "./utils" import {buildStatusUpdateData, shouldGetStatusUpdates} from "./statusUpdate" import {extractOdsCodes, isolateOperationOutcome} from "./fhirUtils" import {pfpConfig, PfPConfig} from "@pfp-common/utilities" +import type {EventHeaders} from "./types" const LOG_LEVEL = process.env.LOG_LEVEL as LogLevel export const logger = new Logger({serviceName: "getMyPrescriptions", logLevel: LOG_LEVEL}) @@ -41,8 +42,6 @@ const SERVICE_SEARCH_TIMEOUT_MS = 5_000 export const DELEGATED_ACCESS_HDR = "delegatedaccess" export const DELEGATED_ACCESS_SUB_HDR = "x-nhsd-subject-nhs-number" -type EventHeaders = Record - export type GetMyPrescriptionsEvent = { rawHeaders: Record headers: EventHeaders @@ -149,6 +148,7 @@ async function eventHandler( params.pfpConfig, statusUpdateData ) } catch (error) { + logger.info("Error caught in getMyPrescriptions handler", {error}) if (error instanceof NHSNumberValidationError) { return INVALID_NHS_NUMBER_RESPONSE } else { @@ -162,7 +162,7 @@ export function adaptHeadersToSpine(headers: EventHeaders): EventHeaders { logger.debug("Testing if delegated access enabled", {headers}) if (!headers[DELEGATED_ACCESS_HDR] || headers[DELEGATED_ACCESS_HDR].toLowerCase() !== "true") { logger.info("Subject access request detected") - headers["nhsNumber"] = extractNHSNumber(headers["nhsd-nhslogin-user"]) + headers["nhsNumber"] = extractNHSNumberFromHeaders(headers) } else { logger.info("Delegated access request detected") let subjectNHSNumber = headers[DELEGATED_ACCESS_SUB_HDR] diff --git a/packages/specification/prescriptions-for-patients.yaml b/packages/specification/prescriptions-for-patients.yaml index eac70a0f4..1aee96801 100644 --- a/packages/specification/prescriptions-for-patients.yaml +++ b/packages/specification/prescriptions-for-patients.yaml @@ -430,6 +430,8 @@ x-nhsd-apim: target-identity: - name: nhs-login-nhs-number header: "nhsd-nhslogin-user" + - name: nhs-login-identity-proofing-level + header: "nhs-login-identity-proofing-level" ratelimiting: proxy: limit: 20000 From 22789ea1d6b9bbfcc221108e44f2e78cce4accfd Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:34:46 +0000 Subject: [PATCH 34/45] Duh Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- packages/getMyPrescriptions/src/extractNHSNumber.ts | 3 +++ packages/getMyPrescriptions/src/types.ts | 1 + 2 files changed, 4 insertions(+) create mode 100644 packages/getMyPrescriptions/src/types.ts diff --git a/packages/getMyPrescriptions/src/extractNHSNumber.ts b/packages/getMyPrescriptions/src/extractNHSNumber.ts index 229b7e064..63f0eaf02 100644 --- a/packages/getMyPrescriptions/src/extractNHSNumber.ts +++ b/packages/getMyPrescriptions/src/extractNHSNumber.ts @@ -11,6 +11,7 @@ export class NHSNumberValidationError extends Error { export function extractNHSNumberFromHeaders(headers: EventHeaders): string { if (headers["nhs-login-identity-proofing-level"]) { + // Proxygen spec will include proofing level header, whereas non-proxygen API will not return validateNHSNumber(headers["nhsd-nhslogin-user"]!) } else { return extractNHSNumber(headers["nhsd-nhslogin-user"]) @@ -18,6 +19,8 @@ export function extractNHSNumberFromHeaders(headers: EventHeaders): string { } export function extractNHSNumber(nhsloginUser: string | undefined): string { + // This function is only relevant for non-proxygen API which prepends proofing level + // to the front of the nhs number ie. P9:1234567890 if (nhsloginUser === undefined || nhsloginUser === null) { throw new NHSNumberValidationError("nhsdloginUser not passed in") } diff --git a/packages/getMyPrescriptions/src/types.ts b/packages/getMyPrescriptions/src/types.ts new file mode 100644 index 000000000..6cb83f96e --- /dev/null +++ b/packages/getMyPrescriptions/src/types.ts @@ -0,0 +1 @@ +export type EventHeaders = Record From 5c7f4e016548449a862a0a4f0cffa74faab70463 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:55:18 +0000 Subject: [PATCH 35/45] Application name attribute output as header to origin Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- packages/specification/prescriptions-for-patients.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/specification/prescriptions-for-patients.yaml b/packages/specification/prescriptions-for-patients.yaml index 1aee96801..dd6d94ee1 100644 --- a/packages/specification/prescriptions-for-patients.yaml +++ b/packages/specification/prescriptions-for-patients.yaml @@ -432,6 +432,13 @@ x-nhsd-apim: header: "nhsd-nhslogin-user" - name: nhs-login-identity-proofing-level header: "nhs-login-identity-proofing-level" + target-attributes: + - name: developer.app.name + required: true + header: "nhsd-application-name" + - name: developer.app.id + required: true + header: "nhsd-application-id" ratelimiting: proxy: limit: 20000 From a72ddc2ca4461bb1e48fac72740a7bb9199148f9 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:08:05 +0000 Subject: [PATCH 36/45] dont require it Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- packages/specification/prescriptions-for-patients.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/specification/prescriptions-for-patients.yaml b/packages/specification/prescriptions-for-patients.yaml index dd6d94ee1..4866ca17b 100644 --- a/packages/specification/prescriptions-for-patients.yaml +++ b/packages/specification/prescriptions-for-patients.yaml @@ -434,10 +434,10 @@ x-nhsd-apim: header: "nhs-login-identity-proofing-level" target-attributes: - name: developer.app.name - required: true + required: false header: "nhsd-application-name" - name: developer.app.id - required: true + required: false header: "nhsd-application-id" ratelimiting: proxy: From dab4654381a3bd9249c34157e8fe5e52912bcce6 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Thu, 18 Dec 2025 16:54:43 +0000 Subject: [PATCH 37/45] Fix reg tests and uts Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/run_regression_tests.yml | 72 ++++++++++++++++--- .../tests/extractNHSNumber.test.ts | 43 ++++++++++- 2 files changed, 106 insertions(+), 9 deletions(-) diff --git a/.github/workflows/run_regression_tests.yml b/.github/workflows/run_regression_tests.yml index f2a885489..cfc69eaae 100644 --- a/.github/workflows/run_regression_tests.yml +++ b/.github/workflows/run_regression_tests.yml @@ -67,7 +67,7 @@ jobs: env: PYTHON_CONFIGURE_OPTS: --enable-shared - - name: Run Regression Testing + - name: Run Regression Testing Non-Proxygen working-directory: scripts env: TARGET_ENVIRONMENT: ${{ inputs.ENVIRONMENT }} @@ -75,14 +75,70 @@ jobs: GITHUB-TOKEN: ${{ steps.generate-token.outputs.token }} run: | if [[ "$TARGET_ENVIRONMENT" != "prod" && "$TARGET_ENVIRONMENT" != "ref" ]]; then - # this should be the tag of the tests you want to run - REGRESSION_TEST_REPO_TAG=v3.3.1 + REGRESSION_TEST_REPO_TAG="AEA-6037" # This is the tag or branch of the regression test code to run, usually a version tag like v3.1.0 or a branch name + REGRESSION_TEST_WORKFLOW_TAG="v3.6.1" # This is the tag of the github workflow to run, usually the same as REGRESSION_TEST_REPO_TAG - # this should be the tag of the regression test workflow you want to run - # This will normally be the same as REGRESSION_TEST_REPO_TAG - REGRESSION_TEST_WORKFLOW_TAG=v3.3.1 + if [[ -z "$REGRESSION_TEST_REPO_TAG" || -z "$REGRESSION_TEST_WORKFLOW_TAG" ]]; then + echo "Error: One or both tag variables are not set" >&2 + exit 1 + fi + + # HELPER IF STATEMENT - It will automatically determine the correct Git URL to use based on the REGRESSION_TEST_WORKFLOW_TAG value + if [[ "$REGRESSION_TEST_WORKFLOW_TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + echo "REGRESSION_TEST_WORKFLOW_TAG is a version tag, using tag link" + curl "https://raw.githubusercontent.com/NHSDigital/electronic-prescription-service-api-regression-tests/refs/tags/${REGRESSION_TEST_WORKFLOW_TAG}/scripts/run_regression_tests.py" -o run_regression_tests.py + else + echo "REGRESSION_TEST_WORKFLOW_TAG doesn't look like a version tag, using branch link" + curl "https://raw.githubusercontent.com/NHSDigital/electronic-prescription-service-api-regression-tests/refs/heads/${REGRESSION_TEST_REPO_TAG}/scripts/run_regression_tests.py" -o run_regression_tests.py + fi + + if [[ ! -f run_regression_tests.py ]]; then + echo "Error: run_regression_tests.py not found" >&2 + exit 1 + fi + + poetry install + echo Running regression tests in the "$TARGET_ENVIRONMENT" environment + poetry run python -u run_regression_tests.py \ + --env="$TARGET_ENVIRONMENT" \ + --pr_label="$VERSION_NUMBER" \ + --token=${{ steps.generate-token.outputs.token }} \ + --is_called_from_github=true \ + --product=${{ inputs.REGRESSION_TEST_PRODUCT }} \ + --regression_test_repo_tag "${REGRESSION_TEST_REPO_TAG}" \ + --regression_test_workflow_tag "${REGRESSION_TEST_WORKFLOW_TAG}" + fi + + - name: Run Regression Testing Proxygen + working-directory: scripts + env: + TARGET_ENVIRONMENT: ${{ inputs.ENVIRONMENT }} + VERSION_NUMBER: ${{ inputs.VERSION_NUMBER }} + GITHUB-TOKEN: ${{ steps.generate-token.outputs.token }} + run: | + if [[ "$TARGET_ENVIRONMENT" != "prod" && "$TARGET_ENVIRONMENT" != "ref" ]]; then + REGRESSION_TEST_REPO_TAG="AEA-6037" # This is the tag or branch of the regression test code to run, usually a version tag like v3.1.0 or a branch name + REGRESSION_TEST_WORKFLOW_TAG="v3.6.1" # This is the tag of the github workflow to run, usually the same as REGRESSION_TEST_REPO_TAG + + if [[ -z "$REGRESSION_TEST_REPO_TAG" || -z "$REGRESSION_TEST_WORKFLOW_TAG" ]]; then + echo "Error: One or both tag variables are not set" >&2 + exit 1 + fi + + # HELPER IF STATEMENT - It will automatically determine the correct Git URL to use based on the REGRESSION_TEST_WORKFLOW_TAG value + if [[ "$REGRESSION_TEST_WORKFLOW_TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + echo "REGRESSION_TEST_WORKFLOW_TAG is a version tag, using tag link" + curl "https://raw.githubusercontent.com/NHSDigital/electronic-prescription-service-api-regression-tests/refs/tags/${REGRESSION_TEST_WORKFLOW_TAG}/scripts/run_regression_tests.py" -o run_regression_tests.py + else + echo "REGRESSION_TEST_WORKFLOW_TAG doesn't look like a version tag, using branch link" + curl "https://raw.githubusercontent.com/NHSDigital/electronic-prescription-service-api-regression-tests/refs/heads/${REGRESSION_TEST_REPO_TAG}/scripts/run_regression_tests.py" -o run_regression_tests.py + fi + + if [[ ! -f run_regression_tests.py ]]; then + echo "Error: run_regression_tests.py not found" >&2 + exit 1 + fi - curl https://raw.githubusercontent.com/NHSDigital/electronic-prescription-service-api-regression-tests/refs/tags/${REGRESSION_TEST_WORKFLOW_TAG}/scripts/run_regression_tests.py -o run_regression_tests.py poetry install echo Running regression tests in the "$TARGET_ENVIRONMENT" environment poetry run python -u run_regression_tests.py \ @@ -90,7 +146,7 @@ jobs: --pr_label="$VERSION_NUMBER" \ --token=${{ steps.generate-token.outputs.token }} \ --is_called_from_github=true \ - --product ${{ inputs.REGRESSION_TEST_PRODUCT }} \ + --product="PFP-PROXYGEN" \ --regression_test_repo_tag "${REGRESSION_TEST_REPO_TAG}" \ --regression_test_workflow_tag "${REGRESSION_TEST_WORKFLOW_TAG}" fi diff --git a/packages/getMyPrescriptions/tests/extractNHSNumber.test.ts b/packages/getMyPrescriptions/tests/extractNHSNumber.test.ts index 4821955ac..78cf82bf6 100644 --- a/packages/getMyPrescriptions/tests/extractNHSNumber.test.ts +++ b/packages/getMyPrescriptions/tests/extractNHSNumber.test.ts @@ -1,4 +1,9 @@ -import {extractNHSNumber, NHSNumberValidationError, validateNHSNumber} from "../src/extractNHSNumber" +import { + extractNHSNumber, + extractNHSNumberFromHeaders, + NHSNumberValidationError, + validateNHSNumber +} from "../src/extractNHSNumber" import "jest" type failureTestData = {nhsdLoginUser: string | undefined; errorMessage: string; scenarioDescription: string} @@ -61,3 +66,39 @@ describe("validateNHSNumber function", () => { }).toThrow(new NHSNumberValidationError(`Invalid check digit in NHS number ${nhsNumber}`)) }) }) + +describe("extractNHSNumberFromHeaders function", () => { + it("should extract NHS number using validateNHSNumber when proofing level header is present", () => { + const headers = { + "nhs-login-identity-proofing-level": "P9", + "nhsd-nhslogin-user": "9912003071" + } + const result = extractNHSNumberFromHeaders(headers) + expect(result).toBe("9912003071") + }) + + it("should extract NHS number using extractNHSNumber when proofing level header is absent", () => { + const headers = { + "nhsd-nhslogin-user": "P9:9912003071" + } + const result = extractNHSNumberFromHeaders(headers) + expect(result).toBe("9912003071") + }) + + it("should throw error when proofing level header is present but NHS number is invalid", () => { + const headers = { + "nhs-login-identity-proofing-level": "P9", + "nhsd-nhslogin-user": "9912003072" + } + expect(() => { + extractNHSNumberFromHeaders(headers) + }).toThrow(new NHSNumberValidationError("Invalid check digit in NHS number 9912003072")) + }) + + it("should throw error when proofing level header is absent and nhsd-nhslogin-user is undefined", () => { + const headers = {} + expect(() => { + extractNHSNumberFromHeaders(headers) + }).toThrow(new NHSNumberValidationError("nhsdloginUser not passed in")) + }) +}) From 9a8918e47920c88db149fdbc8c560da25b186bd8 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Thu, 18 Dec 2025 17:08:07 +0000 Subject: [PATCH 38/45] Disable MTLS Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 45a24205d..e78351aff 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -105,7 +105,7 @@ jobs: ARTIFACT_BUCKET_PREFIX: PR-${{needs.get_issue_number.outputs.issue_number}} TARGET_ENVIRONMENT: dev APIGEE_ENVIRONMENT: internal-dev - ENABLE_MUTUAL_TLS: true + ENABLE_MUTUAL_TLS: false MTLS_KEY: prescriptions-for-patients-mtls-1 BUILD_ARTIFACT: packaged_code TRUSTSTORE_FILE: pfp-truststore-pr.pem # temporary From 90d6711f327f1ee6f4872c86de8006a87e078cb5 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Fri, 19 Dec 2025 09:39:09 +0000 Subject: [PATCH 39/45] Use the branch for proxygen tests to use correct workflow Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/run_regression_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_regression_tests.yml b/.github/workflows/run_regression_tests.yml index cfc69eaae..b7b9cd0fb 100644 --- a/.github/workflows/run_regression_tests.yml +++ b/.github/workflows/run_regression_tests.yml @@ -118,7 +118,7 @@ jobs: run: | if [[ "$TARGET_ENVIRONMENT" != "prod" && "$TARGET_ENVIRONMENT" != "ref" ]]; then REGRESSION_TEST_REPO_TAG="AEA-6037" # This is the tag or branch of the regression test code to run, usually a version tag like v3.1.0 or a branch name - REGRESSION_TEST_WORKFLOW_TAG="v3.6.1" # This is the tag of the github workflow to run, usually the same as REGRESSION_TEST_REPO_TAG + REGRESSION_TEST_WORKFLOW_TAG="AEA-6037" # This is the tag of the github workflow to run, usually the same as REGRESSION_TEST_REPO_TAG if [[ -z "$REGRESSION_TEST_REPO_TAG" || -z "$REGRESSION_TEST_WORKFLOW_TAG" ]]; then echo "Error: One or both tag variables are not set" >&2 From 6f61460390fa8028524daed5438099c8c964a251 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Fri, 19 Dec 2025 10:11:47 +0000 Subject: [PATCH 40/45] Both use branch? Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/run_regression_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_regression_tests.yml b/.github/workflows/run_regression_tests.yml index b7b9cd0fb..b304e2dc1 100644 --- a/.github/workflows/run_regression_tests.yml +++ b/.github/workflows/run_regression_tests.yml @@ -76,7 +76,7 @@ jobs: run: | if [[ "$TARGET_ENVIRONMENT" != "prod" && "$TARGET_ENVIRONMENT" != "ref" ]]; then REGRESSION_TEST_REPO_TAG="AEA-6037" # This is the tag or branch of the regression test code to run, usually a version tag like v3.1.0 or a branch name - REGRESSION_TEST_WORKFLOW_TAG="v3.6.1" # This is the tag of the github workflow to run, usually the same as REGRESSION_TEST_REPO_TAG + REGRESSION_TEST_WORKFLOW_TAG="AEA-6037" # This is the tag of the github workflow to run, usually the same as REGRESSION_TEST_REPO_TAG if [[ -z "$REGRESSION_TEST_REPO_TAG" || -z "$REGRESSION_TEST_WORKFLOW_TAG" ]]; then echo "Error: One or both tag variables are not set" >&2 From 1821e3eb0e5ec7b1e4fb75715174594f5fa9f575 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Fri, 19 Dec 2025 11:02:38 +0000 Subject: [PATCH 41/45] Kick off pipeline From 07c3e8b2e70a7b0615e913d76d73cb2e41dab9a7 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Fri, 19 Dec 2025 15:17:49 +0000 Subject: [PATCH 42/45] Kick off pipeline2 From f9ecf4be4c65b51cbaaa39eb6029be944fe529ac Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Fri, 19 Dec 2025 15:36:24 +0000 Subject: [PATCH 43/45] fix target environment Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index e78351aff..9b24836aa 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -133,7 +133,7 @@ jobs: with: STACK_NAME: pfp-pr-${{needs.get_issue_number.outputs.issue_number}}-sandbox ARTIFACT_BUCKET_PREFIX: PR-sandbox-${{needs.get_issue_number.outputs.issue_number}} - TARGET_ENVIRONMENT: dev-pr + TARGET_ENVIRONMENT: dev APIGEE_ENVIRONMENT: internal-dev-sandbox ENABLE_MUTUAL_TLS: false MTLS_KEY: prescriptions-for-patients-mtls-1 From d632fcb19785b888d8b39f8d03166119d667f24e Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Fri, 19 Dec 2025 15:50:04 +0000 Subject: [PATCH 44/45] Remove sandbox environment on PRs Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/pull_request.yml | 51 +++++++++++++++--------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 9b24836aa..4db38557d 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -126,29 +126,28 @@ jobs: TARGET_SPINE_SERVER: ${{ secrets.DEV_TARGET_SPINE_SERVER }} TARGET_SERVICE_SEARCH_SERVER: ${{ secrets.DEV_TARGET_SERVICE_SEARCH_SERVER }} PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} - - release_sandbox_code: - needs: [get_issue_number, package_code, get_commit_id] - uses: ./.github/workflows/sam_release_code.yml - with: - STACK_NAME: pfp-pr-${{needs.get_issue_number.outputs.issue_number}}-sandbox - ARTIFACT_BUCKET_PREFIX: PR-sandbox-${{needs.get_issue_number.outputs.issue_number}} - TARGET_ENVIRONMENT: dev - APIGEE_ENVIRONMENT: internal-dev-sandbox - ENABLE_MUTUAL_TLS: false - MTLS_KEY: prescriptions-for-patients-mtls-1 - BUILD_ARTIFACT: packaged_sandbox_code - TRUSTSTORE_FILE: pfp-sandbox-truststore.pem - VERSION_NUMBER: PR-${{ needs.get_issue_number.outputs.issue_number }} - COMMIT_ID: ${{ needs.get_commit_id.outputs.commit_id }} - LOG_LEVEL: DEBUG - LOG_RETENTION_DAYS: 30 - STATE_MACHINE_LOG_LEVEL: ALL - RUN_REGRESSION_TESTS: false - FORWARD_CSOC_LOGS: false - secrets: - REGRESSION_TESTS_PEM: ${{ secrets.REGRESSION_TESTS_PEM }} - CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_DEPLOY_ROLE }} - TARGET_SPINE_SERVER: sandbox - TARGET_SERVICE_SEARCH_SERVER: sandbox - PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} +# release_sandbox_code: +# needs: [get_issue_number, package_code, get_commit_id] +# uses: ./.github/workflows/sam_release_code.yml +# with: +# STACK_NAME: pfp-pr-${{needs.get_issue_number.outputs.issue_number}}-sandbox +# ARTIFACT_BUCKET_PREFIX: PR-sandbox-${{needs.get_issue_number.outputs.issue_number}} +# TARGET_ENVIRONMENT: dev +# APIGEE_ENVIRONMENT: internal-dev-sandbox +# ENABLE_MUTUAL_TLS: false +# MTLS_KEY: prescriptions-for-patients-mtls-1 +# BUILD_ARTIFACT: packaged_sandbox_code +# TRUSTSTORE_FILE: pfp-sandbox-truststore.pem +# VERSION_NUMBER: PR-${{ needs.get_issue_number.outputs.issue_number }} +# COMMIT_ID: ${{ needs.get_commit_id.outputs.commit_id }} +# LOG_LEVEL: DEBUG +# LOG_RETENTION_DAYS: 30 +# STATE_MACHINE_LOG_LEVEL: ALL +# RUN_REGRESSION_TESTS: false +# FORWARD_CSOC_LOGS: false +# secrets: +# REGRESSION_TESTS_PEM: ${{ secrets.REGRESSION_TESTS_PEM }} +# CLOUD_FORMATION_DEPLOY_ROLE: ${{ secrets.DEV_CLOUD_FORMATION_DEPLOY_ROLE }} +# TARGET_SPINE_SERVER: sandbox +# TARGET_SERVICE_SEARCH_SERVER: sandbox +# PROXYGEN_ROLE: ${{ secrets.PROXYGEN_PTL_ROLE }} From 260f5978206637ae49a5ee737828dc932b9f92f7 Mon Sep 17 00:00:00 2001 From: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> Date: Fri, 19 Dec 2025 16:23:42 +0000 Subject: [PATCH 45/45] Set latest regression test version for PFP Proxygen changes Signed-off-by: Connor Avery <214469360+connoravo-nhs@users.noreply.github.com> --- .github/workflows/run_regression_tests.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/run_regression_tests.yml b/.github/workflows/run_regression_tests.yml index b304e2dc1..089507de2 100644 --- a/.github/workflows/run_regression_tests.yml +++ b/.github/workflows/run_regression_tests.yml @@ -75,8 +75,8 @@ jobs: GITHUB-TOKEN: ${{ steps.generate-token.outputs.token }} run: | if [[ "$TARGET_ENVIRONMENT" != "prod" && "$TARGET_ENVIRONMENT" != "ref" ]]; then - REGRESSION_TEST_REPO_TAG="AEA-6037" # This is the tag or branch of the regression test code to run, usually a version tag like v3.1.0 or a branch name - REGRESSION_TEST_WORKFLOW_TAG="AEA-6037" # This is the tag of the github workflow to run, usually the same as REGRESSION_TEST_REPO_TAG + REGRESSION_TEST_REPO_TAG="v3.7.0" # This is the tag or branch of the regression test code to run, usually a version tag like v3.1.0 or a branch name + REGRESSION_TEST_WORKFLOW_TAG="v3.7.0" # This is the tag of the github workflow to run, usually the same as REGRESSION_TEST_REPO_TAG if [[ -z "$REGRESSION_TEST_REPO_TAG" || -z "$REGRESSION_TEST_WORKFLOW_TAG" ]]; then echo "Error: One or both tag variables are not set" >&2 @@ -117,8 +117,8 @@ jobs: GITHUB-TOKEN: ${{ steps.generate-token.outputs.token }} run: | if [[ "$TARGET_ENVIRONMENT" != "prod" && "$TARGET_ENVIRONMENT" != "ref" ]]; then - REGRESSION_TEST_REPO_TAG="AEA-6037" # This is the tag or branch of the regression test code to run, usually a version tag like v3.1.0 or a branch name - REGRESSION_TEST_WORKFLOW_TAG="AEA-6037" # This is the tag of the github workflow to run, usually the same as REGRESSION_TEST_REPO_TAG + REGRESSION_TEST_REPO_TAG="v3.7.0" # This is the tag or branch of the regression test code to run, usually a version tag like v3.1.0 or a branch name + REGRESSION_TEST_WORKFLOW_TAG="v3.7.0" # This is the tag of the github workflow to run, usually the same as REGRESSION_TEST_REPO_TAG if [[ -z "$REGRESSION_TEST_REPO_TAG" || -z "$REGRESSION_TEST_WORKFLOW_TAG" ]]; then echo "Error: One or both tag variables are not set" >&2