From e6ba613fdafc2697304723769bc735b81c7628dc Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:37:31 +0000 Subject: [PATCH 01/15] CCM-14325: Make PDM uploader use PDM mock --- .../components/dl/aws_api_gateway_deployment_pdm_mock.tf | 2 +- .../aws_api_gateway_integration_create_document_reference.tf | 2 +- .../dl/aws_api_gateway_integration_get_document_reference.tf | 2 +- .../dl/aws_api_gateway_method_create_document_reference.tf | 2 +- .../dl/aws_api_gateway_method_get_document_reference.tf | 2 +- .../dl/aws_api_gateway_resource_document_reference.tf | 2 +- .../dl/aws_api_gateway_resource_document_reference_id.tf | 2 +- .../terraform/components/dl/aws_api_gateway_resource_fhir.tf | 2 +- .../dl/aws_api_gateway_resource_patient_data_manager.tf | 2 +- .../terraform/components/dl/aws_api_gateway_resource_r4.tf | 2 +- .../components/dl/aws_api_gateway_rest_api_pdm_mock.tf | 2 +- .../terraform/components/dl/aws_api_gateway_stage_pdm_mock.tf | 2 +- .../dl/aws_cloudwatch_log_group_pdm_mock_gateway.tf | 2 +- .../components/dl/aws_lambda_permission_pdm_mock_gateway.tf | 2 +- infrastructure/terraform/components/dl/locals.tf | 2 +- .../terraform/components/dl/module_lambda_pdm_mock.tf | 4 ++-- .../terraform/components/dl/module_lambda_pdm_poll.tf | 2 +- .../terraform/components/dl/module_lambda_pdm_uploader.tf | 2 +- 18 files changed, 19 insertions(+), 19 deletions(-) diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_deployment_pdm_mock.tf b/infrastructure/terraform/components/dl/aws_api_gateway_deployment_pdm_mock.tf index c6c39b1b0..b3d9a305f 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_deployment_pdm_mock.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_deployment_pdm_mock.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_deployment" "pdm_mock" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 depends_on = [ aws_api_gateway_integration.create_document_reference, diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_integration_create_document_reference.tf b/infrastructure/terraform/components/dl/aws_api_gateway_integration_create_document_reference.tf index 3d8568b4b..4db48b6cc 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_integration_create_document_reference.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_integration_create_document_reference.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_integration" "create_document_reference" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 rest_api_id = aws_api_gateway_rest_api.pdm_mock[0].id resource_id = aws_api_gateway_resource.document_reference[0].id diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_integration_get_document_reference.tf b/infrastructure/terraform/components/dl/aws_api_gateway_integration_get_document_reference.tf index 6ac602e68..67a329e69 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_integration_get_document_reference.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_integration_get_document_reference.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_integration" "get_document_reference" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 rest_api_id = aws_api_gateway_rest_api.pdm_mock[0].id resource_id = aws_api_gateway_resource.document_reference_id[0].id diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_method_create_document_reference.tf b/infrastructure/terraform/components/dl/aws_api_gateway_method_create_document_reference.tf index c2d1d30c9..773b9f2eb 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_method_create_document_reference.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_method_create_document_reference.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_method" "create_document_reference" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 rest_api_id = aws_api_gateway_rest_api.pdm_mock[0].id resource_id = aws_api_gateway_resource.document_reference[0].id diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_method_get_document_reference.tf b/infrastructure/terraform/components/dl/aws_api_gateway_method_get_document_reference.tf index 56ac1b430..f8bb677fe 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_method_get_document_reference.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_method_get_document_reference.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_method" "get_document_reference" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 rest_api_id = aws_api_gateway_rest_api.pdm_mock[0].id resource_id = aws_api_gateway_resource.document_reference_id[0].id diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_resource_document_reference.tf b/infrastructure/terraform/components/dl/aws_api_gateway_resource_document_reference.tf index e3238ab02..aafefe818 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_resource_document_reference.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_resource_document_reference.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_resource" "document_reference" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 rest_api_id = aws_api_gateway_rest_api.pdm_mock[0].id parent_id = aws_api_gateway_resource.r4[0].id diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_resource_document_reference_id.tf b/infrastructure/terraform/components/dl/aws_api_gateway_resource_document_reference_id.tf index bdc24b46e..5ebe66d6a 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_resource_document_reference_id.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_resource_document_reference_id.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_resource" "document_reference_id" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 rest_api_id = aws_api_gateway_rest_api.pdm_mock[0].id parent_id = aws_api_gateway_resource.document_reference[0].id diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_resource_fhir.tf b/infrastructure/terraform/components/dl/aws_api_gateway_resource_fhir.tf index 24dbdbb49..e11412ab1 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_resource_fhir.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_resource_fhir.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_resource" "fhir" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 rest_api_id = aws_api_gateway_rest_api.pdm_mock[0].id parent_id = aws_api_gateway_resource.patient_data_manager[0].id diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_resource_patient_data_manager.tf b/infrastructure/terraform/components/dl/aws_api_gateway_resource_patient_data_manager.tf index d08d6b43c..bc3b1326a 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_resource_patient_data_manager.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_resource_patient_data_manager.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_resource" "patient_data_manager" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 rest_api_id = aws_api_gateway_rest_api.pdm_mock[0].id parent_id = aws_api_gateway_rest_api.pdm_mock[0].root_resource_id diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_resource_r4.tf b/infrastructure/terraform/components/dl/aws_api_gateway_resource_r4.tf index e5075157e..e008f32b9 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_resource_r4.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_resource_r4.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_resource" "r4" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 rest_api_id = aws_api_gateway_rest_api.pdm_mock[0].id parent_id = aws_api_gateway_resource.fhir[0].id diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_rest_api_pdm_mock.tf b/infrastructure/terraform/components/dl/aws_api_gateway_rest_api_pdm_mock.tf index b9dd89141..14053b9ac 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_rest_api_pdm_mock.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_rest_api_pdm_mock.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_rest_api" "pdm_mock" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 name = "${var.project}-${var.environment}-pdm-mock" description = "PDM Mock API for testing integration with Patient Data Manager" diff --git a/infrastructure/terraform/components/dl/aws_api_gateway_stage_pdm_mock.tf b/infrastructure/terraform/components/dl/aws_api_gateway_stage_pdm_mock.tf index 28cfd8d7b..439b2877f 100644 --- a/infrastructure/terraform/components/dl/aws_api_gateway_stage_pdm_mock.tf +++ b/infrastructure/terraform/components/dl/aws_api_gateway_stage_pdm_mock.tf @@ -1,5 +1,5 @@ resource "aws_api_gateway_stage" "pdm_mock" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 deployment_id = aws_api_gateway_deployment.pdm_mock[0].id rest_api_id = aws_api_gateway_rest_api.pdm_mock[0].id diff --git a/infrastructure/terraform/components/dl/aws_cloudwatch_log_group_pdm_mock_gateway.tf b/infrastructure/terraform/components/dl/aws_cloudwatch_log_group_pdm_mock_gateway.tf index fe9f3bd9c..be8b2710e 100644 --- a/infrastructure/terraform/components/dl/aws_cloudwatch_log_group_pdm_mock_gateway.tf +++ b/infrastructure/terraform/components/dl/aws_cloudwatch_log_group_pdm_mock_gateway.tf @@ -1,5 +1,5 @@ resource "aws_cloudwatch_log_group" "pdm_mock_gateway" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 name = "/aws/apigateway/${var.project}-${var.environment}-pdm-mock" retention_in_days = var.log_retention_in_days diff --git a/infrastructure/terraform/components/dl/aws_lambda_permission_pdm_mock_gateway.tf b/infrastructure/terraform/components/dl/aws_lambda_permission_pdm_mock_gateway.tf index 92000d638..30ed8dd15 100644 --- a/infrastructure/terraform/components/dl/aws_lambda_permission_pdm_mock_gateway.tf +++ b/infrastructure/terraform/components/dl/aws_lambda_permission_pdm_mock_gateway.tf @@ -1,5 +1,5 @@ resource "aws_lambda_permission" "pdm_mock_gateway" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 statement_id = "AllowAPIGatewayInvoke" action = "lambda:InvokeFunction" diff --git a/infrastructure/terraform/components/dl/locals.tf b/infrastructure/terraform/components/dl/locals.tf index 5838de640..aff937496 100644 --- a/infrastructure/terraform/components/dl/locals.tf +++ b/infrastructure/terraform/components/dl/locals.tf @@ -4,7 +4,7 @@ locals { apim_keystore_s3_bucket = "nhs-${var.aws_account_id}-${var.region}-${var.environment}-${var.component}-static-assets" apim_private_key_ssm_parameter_name = "/${var.component}/${var.environment}/apim/private_key" aws_lambda_functions_dir_path = "../../../../lambdas" - deploy_pdm_mock = var.enable_pdm_mock + pdm_url = var.enable_pdm_mock ? aws_api_gateway_stage.pdm_mock[0].invoke_url : var.apim_base_url firehose_output_path_prefix = "kinesis-firehose-output" log_destination_arn = "arn:aws:logs:${var.region}:${var.shared_infra_account_id}:destination:nhs-main-obs-firehose-logs" mock_mesh_endpoint = "s3://${module.s3bucket_non_pii_data.bucket}/mock-mesh" diff --git a/infrastructure/terraform/components/dl/module_lambda_pdm_mock.tf b/infrastructure/terraform/components/dl/module_lambda_pdm_mock.tf index b4ce63136..f2ca8c596 100644 --- a/infrastructure/terraform/components/dl/module_lambda_pdm_mock.tf +++ b/infrastructure/terraform/components/dl/module_lambda_pdm_mock.tf @@ -1,5 +1,5 @@ module "pdm_mock" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip" function_name = "pdm-mock" @@ -37,7 +37,7 @@ module "pdm_mock" { } data "aws_iam_policy_document" "pdm_mock" { - count = local.deploy_pdm_mock ? 1 : 0 + count = var.enable_pdm_mock ? 1 : 0 statement { sid = "KMSPermissions" diff --git a/infrastructure/terraform/components/dl/module_lambda_pdm_poll.tf b/infrastructure/terraform/components/dl/module_lambda_pdm_poll.tf index 5ee748b1b..e61ce63cc 100644 --- a/infrastructure/terraform/components/dl/module_lambda_pdm_poll.tf +++ b/infrastructure/terraform/components/dl/module_lambda_pdm_poll.tf @@ -35,7 +35,7 @@ module "pdm_poll" { log_subscription_role_arn = local.acct.log_subscription_role_arn lambda_env_vars = { - "APIM_BASE_URL" = local.deploy_pdm_mock ? aws_api_gateway_stage.pdm_mock[0].invoke_url : var.apim_base_url + "APIM_BASE_URL" = local.pdm_url "APIM_ACCESS_TOKEN_SSM_PARAMETER_NAME" = local.apim_access_token_ssm_parameter_name "EVENT_PUBLISHER_EVENT_BUS_ARN" = aws_cloudwatch_event_bus.main.arn "EVENT_PUBLISHER_DLQ_URL" = module.sqs_event_publisher_errors.sqs_queue_url diff --git a/infrastructure/terraform/components/dl/module_lambda_pdm_uploader.tf b/infrastructure/terraform/components/dl/module_lambda_pdm_uploader.tf index 6bf6bb396..1afbe733e 100644 --- a/infrastructure/terraform/components/dl/module_lambda_pdm_uploader.tf +++ b/infrastructure/terraform/components/dl/module_lambda_pdm_uploader.tf @@ -35,7 +35,7 @@ module "pdm_uploader" { log_subscription_role_arn = local.acct.log_subscription_role_arn lambda_env_vars = { - "APIM_BASE_URL" = var.apim_base_url + "APIM_BASE_URL" = local.pdm_url "APIM_ACCESS_TOKEN_SSM_PARAMETER_NAME" = local.apim_access_token_ssm_parameter_name "EVENT_PUBLISHER_EVENT_BUS_ARN" = aws_cloudwatch_event_bus.main.arn "EVENT_PUBLISHER_DLQ_URL" = module.sqs_event_publisher_errors.sqs_queue_url From 33c3e948e1a9a83f5a09825481269dc7ba88a90c Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:37:52 +0000 Subject: [PATCH 02/15] CCM-14325: Dependency updates --- docs/package-lock.json | 15 ++++++----- package-lock.json | 33 ++++++++++++++++-------- src/eventcatalog/package-lock.json | 41 ++++++++++++++++-------------- src/eventcatalog/package.json | 6 ++++- 4 files changed, 59 insertions(+), 36 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 76c905173..9f15a54f7 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -1911,10 +1911,13 @@ } }, "node_modules/dompurify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", - "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.2.tgz", + "integrity": "sha512-6obghkliLdmKa56xdbLOpUZ43pAR6xFy1uOrxBaIDjT+yaRuuybLjGS9eVBoSR/UPU5fq3OXClEHLJNGvbxKpQ==", "license": "(MPL-2.0 OR Apache-2.0)", + "engines": { + "node": ">=20" + }, "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -2195,9 +2198,9 @@ } }, "node_modules/immutable": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", - "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", + "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", "dev": true, "license": "MIT" }, diff --git a/package-lock.json b/package-lock.json index 1844d3128..e3f1e01d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6169,13 +6169,13 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.8.tgz", - "integrity": "sha512-Ql8elcUdYCha83Ol7NznBsgN5GVZnv3vUd86fEc6waU6oUdY0T1O9NODkEEOS/Uaogr87avDrUC6DSeM4oXjZg==", + "version": "3.972.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.10.tgz", + "integrity": "sha512-OnejAIVD+CxzyAUrVic7lG+3QRltyja9LoNqCE/1YVs8ichoTbJlVSaZ9iSMcnHLyzrSNtvaOGjSDRP+d/ouFA==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.13.0", - "fast-xml-parser": "5.3.6", + "fast-xml-parser": "5.4.1", "tslib": "^2.6.2" }, "engines": { @@ -13109,10 +13109,22 @@ ], "license": "BSD-3-Clause" }, + "node_modules/fast-xml-builder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.0.0.tgz", + "integrity": "sha512-fpZuDogrAgnyt9oDDz+5DBz0zgPdPZz6D4IR7iESxRXElrlGTRkHJ9eEt+SACRJwT0FNFrt71DFQIUFBJfX/uQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/fast-xml-parser": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.6.tgz", - "integrity": "sha512-QNI3sAvSvaOiaMl8FYU4trnEzCwiRr8XMWgAHzlrWpTSj+QaCSvOf1h82OEP1s4hiAXhnbXSyFWCf4ldZzZRVA==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.4.1.tgz", + "integrity": "sha512-BQ30U1mKkvXQXXkAGcuyUA/GA26oEB7NzOtsxCDtyu62sjGw5QraKFhx2Em3WQNjPw9PG6MQ9yuIIgkSDfGu5A==", "funding": [ { "type": "github", @@ -13121,6 +13133,7 @@ ], "license": "MIT", "dependencies": { + "fast-xml-builder": "^1.0.0", "strnum": "^2.1.2" }, "bin": { @@ -19912,9 +19925,9 @@ } }, "node_modules/strnum": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.2.tgz", - "integrity": "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.0.tgz", + "integrity": "sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==", "funding": [ { "type": "github", diff --git a/src/eventcatalog/package-lock.json b/src/eventcatalog/package-lock.json index d4b8fde44..363f85268 100644 --- a/src/eventcatalog/package-lock.json +++ b/src/eventcatalog/package-lock.json @@ -11402,10 +11402,13 @@ } }, "node_modules/dompurify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", - "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.2.tgz", + "integrity": "sha512-6obghkliLdmKa56xdbLOpUZ43pAR6xFy1uOrxBaIDjT+yaRuuybLjGS9eVBoSR/UPU5fq3OXClEHLJNGvbxKpQ==", "license": "(MPL-2.0 OR Apache-2.0)", + "engines": { + "node": ">=20" + }, "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -14490,9 +14493,9 @@ } }, "node_modules/jsonpath": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.2.1.tgz", - "integrity": "sha512-Jl6Jhk0jG+kP3yk59SSeGq7LFPR4JQz1DU0K+kXTysUhMostbhU3qh5mjTuf0PqFcXpAT7kvmMt9WxV10NyIgQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.3.0.tgz", + "integrity": "sha512-0kjkYHJBkAy50Z5QzArZ7udmvxrJzkpKYW27fiF//BrMY7TQibYLl+FYIXN2BiYmwMIVzSfD8aDRj6IzgBX2/w==", "license": "MIT", "dependencies": { "esprima": "1.2.5", @@ -22151,9 +22154,9 @@ "license": "MIT" }, "node_modules/sax": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", + "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", "license": "BlueOak-1.0.0", "engines": { "node": ">=11.0.0" @@ -23047,9 +23050,9 @@ } }, "node_modules/svgo": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", - "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz", + "integrity": "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==", "license": "MIT", "dependencies": { "commander": "^11.1.0", @@ -23058,7 +23061,7 @@ "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", - "sax": "^1.4.1" + "sax": "^1.5.0" }, "bin": { "svgo": "bin/svgo.js" @@ -23198,9 +23201,9 @@ } }, "node_modules/tar": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.9.tgz", - "integrity": "sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.10.tgz", + "integrity": "sha512-8mOPs1//5q/rlkNSPcCegA6hiHJYDmSLEI8aMH/CdSQJNWztHC9WHNam5zdQlfpTwB9Xp7IBEsHfV5LKMJGVAw==", "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", @@ -23613,9 +23616,9 @@ "license": "MIT" }, "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", "license": "MIT" }, "node_modules/undici": { diff --git a/src/eventcatalog/package.json b/src/eventcatalog/package.json index b2fc0fb5d..8bc324488 100644 --- a/src/eventcatalog/package.json +++ b/src/eventcatalog/package.json @@ -7,7 +7,11 @@ }, "name": "digital-letters", "overrides": { - "minimatch": "^10.2.4" + "astro-compress": { + "svgo": "^4.0.1" + }, + "minimatch": "^10.2.4", + "underscore": "^1.13.8" }, "private": true, "scripts": { From b54e094789cac569aca9afc6d8ccfaa1a9e123b1 Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:33:26 +0000 Subject: [PATCH 03/15] CCM-14325: Remove authentication from PDM mock --- .../terraform/components/dl/README.md | 2 - .../terraform/components/dl/locals.tf | 1 + .../components/dl/module_lambda_pdm_poll.tf | 2 +- .../dl/module_lambda_pdm_uploader.tf | 2 +- .../dl/ssm_parameter_access_token.tf | 5 +- .../terraform/components/dl/variables.tf | 12 --- lambdas/pdm-mock-lambda/README.md | 4 - .../src/__tests__/authenticator.test.ts | 74 ------------------- .../src/__tests__/container.test.ts | 15 ---- .../src/__tests__/index.test.ts | 30 +------- lambdas/pdm-mock-lambda/src/authenticator.ts | 66 ----------------- lambdas/pdm-mock-lambda/src/container.ts | 5 -- lambdas/pdm-mock-lambda/src/index.ts | 9 +-- 13 files changed, 7 insertions(+), 220 deletions(-) delete mode 100644 lambdas/pdm-mock-lambda/src/__tests__/authenticator.test.ts delete mode 100644 lambdas/pdm-mock-lambda/src/authenticator.ts diff --git a/infrastructure/terraform/components/dl/README.md b/infrastructure/terraform/components/dl/README.md index 959d5e6a1..786ba961e 100644 --- a/infrastructure/terraform/components/dl/README.md +++ b/infrastructure/terraform/components/dl/README.md @@ -40,8 +40,6 @@ No requirements. | [mesh\_poll\_schedule](#input\_mesh\_poll\_schedule) | Schedule to poll MESH for messages | `string` | `"rate(5 minutes)"` | no | | [metadata\_refresh\_schedule](#input\_metadata\_refresh\_schedule) | Schedule for refreshing reporting metadata. | `string` | `"cron(10 6-22 * * ? *)"` | no | | [parent\_acct\_environment](#input\_parent\_acct\_environment) | Name of the environment responsible for the acct resources used, affects things like DNS zone. Useful for named dev environments | `string` | `"main"` | no | -| [pdm\_mock\_access\_token](#input\_pdm\_mock\_access\_token) | Mock access token for PDM API authentication (used in local/dev environments) | `string` | `"mock-pdm-token"` | no | -| [pdm\_use\_non\_mock\_token](#input\_pdm\_use\_non\_mock\_token) | Whether to use the shared APIM access token from SSM (/component/environment/apim/access\_token) instead of the mock token | `bool` | `false` | no | | [pii\_data\_retention\_policy\_days](#input\_pii\_data\_retention\_policy\_days) | The number of days for data retention policy for PII | `number` | `534` | no | | [project](#input\_project) | The name of the tfscaffold project | `string` | n/a | yes | | [queue\_batch\_size](#input\_queue\_batch\_size) | maximum number of queue items to process | `number` | `10` | no | diff --git a/infrastructure/terraform/components/dl/locals.tf b/infrastructure/terraform/components/dl/locals.tf index aff937496..30c199a62 100644 --- a/infrastructure/terraform/components/dl/locals.tf +++ b/infrastructure/terraform/components/dl/locals.tf @@ -4,6 +4,7 @@ locals { apim_keystore_s3_bucket = "nhs-${var.aws_account_id}-${var.region}-${var.environment}-${var.component}-static-assets" apim_private_key_ssm_parameter_name = "/${var.component}/${var.environment}/apim/private_key" aws_lambda_functions_dir_path = "../../../../lambdas" + pdm_access_token_ssm_parameter_name = var.enable_pdm_mock ? "" : "${local.apim_access_token_ssm_parameter_name}" pdm_url = var.enable_pdm_mock ? aws_api_gateway_stage.pdm_mock[0].invoke_url : var.apim_base_url firehose_output_path_prefix = "kinesis-firehose-output" log_destination_arn = "arn:aws:logs:${var.region}:${var.shared_infra_account_id}:destination:nhs-main-obs-firehose-logs" diff --git a/infrastructure/terraform/components/dl/module_lambda_pdm_poll.tf b/infrastructure/terraform/components/dl/module_lambda_pdm_poll.tf index e61ce63cc..c4172356d 100644 --- a/infrastructure/terraform/components/dl/module_lambda_pdm_poll.tf +++ b/infrastructure/terraform/components/dl/module_lambda_pdm_poll.tf @@ -36,7 +36,7 @@ module "pdm_poll" { lambda_env_vars = { "APIM_BASE_URL" = local.pdm_url - "APIM_ACCESS_TOKEN_SSM_PARAMETER_NAME" = local.apim_access_token_ssm_parameter_name + "APIM_ACCESS_TOKEN_SSM_PARAMETER_NAME" = local.pdm_access_token_ssm_parameter_name "EVENT_PUBLISHER_EVENT_BUS_ARN" = aws_cloudwatch_event_bus.main.arn "EVENT_PUBLISHER_DLQ_URL" = module.sqs_event_publisher_errors.sqs_queue_url "POLL_MAX_RETRIES" = 10 diff --git a/infrastructure/terraform/components/dl/module_lambda_pdm_uploader.tf b/infrastructure/terraform/components/dl/module_lambda_pdm_uploader.tf index 1afbe733e..ca3d8a983 100644 --- a/infrastructure/terraform/components/dl/module_lambda_pdm_uploader.tf +++ b/infrastructure/terraform/components/dl/module_lambda_pdm_uploader.tf @@ -36,7 +36,7 @@ module "pdm_uploader" { lambda_env_vars = { "APIM_BASE_URL" = local.pdm_url - "APIM_ACCESS_TOKEN_SSM_PARAMETER_NAME" = local.apim_access_token_ssm_parameter_name + "APIM_ACCESS_TOKEN_SSM_PARAMETER_NAME" = local.pdm_access_token_ssm_parameter_name "EVENT_PUBLISHER_EVENT_BUS_ARN" = aws_cloudwatch_event_bus.main.arn "EVENT_PUBLISHER_DLQ_URL" = module.sqs_event_publisher_errors.sqs_queue_url } diff --git a/infrastructure/terraform/components/dl/ssm_parameter_access_token.tf b/infrastructure/terraform/components/dl/ssm_parameter_access_token.tf index 06bcc66fd..8bc514985 100644 --- a/infrastructure/terraform/components/dl/ssm_parameter_access_token.tf +++ b/infrastructure/terraform/components/dl/ssm_parameter_access_token.tf @@ -2,9 +2,8 @@ resource "aws_ssm_parameter" "access_token" { name = local.apim_access_token_ssm_parameter_name description = "Access token for APIM" type = "SecureString" - value = jsonencode({ - tokens = [] - }) + value = jsonencode({}) + tags = merge(local.default_tags, { Backup = "true" }) lifecycle { diff --git a/infrastructure/terraform/components/dl/variables.tf b/infrastructure/terraform/components/dl/variables.tf index f00728d99..700e1e666 100644 --- a/infrastructure/terraform/components/dl/variables.tf +++ b/infrastructure/terraform/components/dl/variables.tf @@ -122,18 +122,6 @@ variable "ttl_poll_schedule" { default = "rate(10 minutes)" # Every 10 minutes } -variable "pdm_mock_access_token" { - type = string - description = "Mock access token for PDM API authentication (used in local/dev environments)" - default = "mock-pdm-token" -} - -variable "pdm_use_non_mock_token" { - type = bool - description = "Whether to use the shared APIM access token from SSM (/component/environment/apim/access_token) instead of the mock token" - default = false -} - variable "apim_base_url" { type = string description = "The URL used to send requests to PDM" diff --git a/lambdas/pdm-mock-lambda/README.md b/lambdas/pdm-mock-lambda/README.md index c0ec5b0cd..18367161b 100644 --- a/lambdas/pdm-mock-lambda/README.md +++ b/lambdas/pdm-mock-lambda/README.md @@ -19,7 +19,6 @@ Creates a new PDM DocumentReference. ```bash curl -X POST https:///patient-data-manager/FHIR/R4/DocumentReference \ - -H "Authorization: Bearer " \ -H "Content-Type: application/fhir+json" \ -H "X-Request-ID: 4a0e5f18-1747-4438-ac52-5ba2c21575f5" \ -d '{}' @@ -27,7 +26,6 @@ curl -X POST https:///patient-data-manager/FHIR/R4/DocumentRefe **Headers:** -- `Authorization: Bearer ` - Authentication token is not validated and can be any string value. - `Content-Type: application/fhir+json` - Required content type. - `X-Request-ID: ` - This uuid will be used as the DocumentReference `id` in the response. @@ -69,14 +67,12 @@ Retrieves a specific PDM DocumentReference by ID. ```bash curl https:///patient-data-manager/FHIR/R4/DocumentReference/test-id \ - -H "Authorization: Bearer " \ -H "Content-Type: application/fhir+json" \ -H "X-Request-ID: 848b67ea-eeaa-3620-a388-e4e8594ff2e3" ``` **Headers:** -- `Authorization: Bearer ` - Authentication token is not validated and can be any string value. - `Content-Type: application/fhir+json` - Required content type. - `X-Request-ID: ` - Used for request tracking and correlation. This isn't part of the ID or response that gets returned. diff --git a/lambdas/pdm-mock-lambda/src/__tests__/authenticator.test.ts b/lambdas/pdm-mock-lambda/src/__tests__/authenticator.test.ts deleted file mode 100644 index 86db5e8c3..000000000 --- a/lambdas/pdm-mock-lambda/src/__tests__/authenticator.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { Logger } from 'utils'; -import { createAuthenticator } from 'authenticator'; - -const mockLogger: Logger = { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - child: jest.fn(), -} as any; - -describe('Authenticator', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - describe('with mock token', () => { - it('should authenticate successfully with valid Bearer token', async () => { - const authenticator = createAuthenticator(mockLogger); - - const result = await authenticator({ - headers: { Authorization: 'Bearer test-token' }, - }); - - expect(result.isValid).toBe(true); - }); - - it('should reject request with missing Authorization header', async () => { - const authenticator = createAuthenticator(mockLogger); - - const result = await authenticator({ headers: {} }); - - expect(result.isValid).toBe(false); - expect(result).toHaveProperty('error'); - expect((result as { isValid: false; error: any }).error).toBeDefined(); - expect((result as { isValid: false; error: any }).error.statusCode).toBe( - 401, - ); - expect((result as { isValid: false; error: any }).error.body).toContain( - 'ACCESS_DENIED', - ); - expect((result as { isValid: false; error: any }).error.body).toContain( - 'Missing Authentication Token', - ); - }); - - it('should reject request with invalid token type', async () => { - const authenticator = createAuthenticator(mockLogger); - - const result = await authenticator({ - headers: { Authorization: 'Basic test-token' }, - }); - - expect(result.isValid).toBe(false); - expect(result).toHaveProperty('error'); - expect((result as { isValid: false; error: any }).error.statusCode).toBe( - 401, - ); - expect((result as { isValid: false; error: any }).error.body).toContain( - 'Invalid Access Token', - ); - }); - - it('should handle lowercase authorization header', async () => { - const authenticator = createAuthenticator(mockLogger); - - const result = await authenticator({ - headers: { authorization: 'Bearer test-token' }, - }); - - expect(result.isValid).toBe(true); - }); - }); -}); diff --git a/lambdas/pdm-mock-lambda/src/__tests__/container.test.ts b/lambdas/pdm-mock-lambda/src/__tests__/container.test.ts index 4cfda0ac9..f46136ecd 100644 --- a/lambdas/pdm-mock-lambda/src/__tests__/container.test.ts +++ b/lambdas/pdm-mock-lambda/src/__tests__/container.test.ts @@ -35,16 +35,11 @@ describe('Container', () => { it('should create a container with all required dependencies', () => { expect(container).toBeDefined(); - expect(container.authenticator).toBeDefined(); expect(container.getResourceHandler).toBeDefined(); expect(container.createResourceHandler).toBeDefined(); expect(container.logger).toBeDefined(); }); - it('should create an authenticator function', () => { - expect(typeof container.authenticator).toBe('function'); - }); - it('should create a getResourceHandler function', () => { expect(typeof container.getResourceHandler).toBe('function'); }); @@ -74,14 +69,4 @@ describe('Container', () => { expect(result).toBeDefined(); expect(result.statusCode).toBeDefined(); }); - - it('should create authenticator that can be called', async () => { - const mockEvent = { - headers: { Authorization: 'Bearer test-token' }, - }; - - const result = await container.authenticator(mockEvent); - expect(result).toBeDefined(); - expect(result.isValid).toBeDefined(); - }); }); diff --git a/lambdas/pdm-mock-lambda/src/__tests__/index.test.ts b/lambdas/pdm-mock-lambda/src/__tests__/index.test.ts index a056396bc..2453cacdd 100644 --- a/lambdas/pdm-mock-lambda/src/__tests__/index.test.ts +++ b/lambdas/pdm-mock-lambda/src/__tests__/index.test.ts @@ -66,7 +66,6 @@ const createMockEvent = ( }; describe('Lambda Handler Integration', () => { - let mockAuthenticator: jest.Mock; let mockGetResourceHandler: jest.Mock; let mockCreateResourceHandler: jest.Mock; @@ -74,33 +73,11 @@ describe('Lambda Handler Integration', () => { jest.clearAllMocks(); const container = createContainer(); - mockAuthenticator = container.authenticator as jest.Mock; mockGetResourceHandler = container.getResourceHandler as jest.Mock; mockCreateResourceHandler = container.createResourceHandler as jest.Mock; }); - it('should return authentication error when authentication fails', async () => { - mockAuthenticator.mockResolvedValue({ - isValid: false, - error: { - statusCode: 401, - body: JSON.stringify({ error: 'Unauthorized' }), - }, - }); - - const event = createMockEvent(); - const response = (await handler( - event, - {} as Context, - {} as Callback, - )) as APIGatewayProxyResult; - - expect(response.statusCode).toBe(401); - expect(mockGetResourceHandler).not.toHaveBeenCalled(); - }); - it('should route GET requests to getResourceHandler', async () => { - mockAuthenticator.mockResolvedValue({ isValid: true }); mockGetResourceHandler.mockResolvedValue({ statusCode: 200, body: JSON.stringify({ id: 'test-id' }), @@ -117,13 +94,11 @@ describe('Lambda Handler Integration', () => { {} as Callback, )) as APIGatewayProxyResult; - expect(mockAuthenticator).toHaveBeenCalledWith(event); expect(mockGetResourceHandler).toHaveBeenCalledWith(event); expect(response.statusCode).toBe(200); }); it('should route POST requests to createResourceHandler', async () => { - mockAuthenticator.mockResolvedValue({ isValid: true }); mockCreateResourceHandler.mockResolvedValue({ statusCode: 201, body: JSON.stringify({ id: 'new-id' }), @@ -141,14 +116,11 @@ describe('Lambda Handler Integration', () => { {} as Callback, )) as APIGatewayProxyResult; - expect(mockAuthenticator).toHaveBeenCalledWith(event); expect(mockCreateResourceHandler).toHaveBeenCalledWith(event); expect(response.statusCode).toBe(201); }); it('should return 404 for unsupported endpoints', async () => { - mockAuthenticator.mockResolvedValue({ isValid: true }); - const event = createMockEvent({ httpMethod: 'DELETE', path: '/unsupported', @@ -165,7 +137,7 @@ describe('Lambda Handler Integration', () => { }); it('should handle unexpected errors gracefully', async () => { - mockAuthenticator.mockRejectedValue(new Error('Unexpected error')); + mockGetResourceHandler.mockRejectedValue(new Error('Unexpected error')); const event = createMockEvent(); const response = (await handler( diff --git a/lambdas/pdm-mock-lambda/src/authenticator.ts b/lambdas/pdm-mock-lambda/src/authenticator.ts deleted file mode 100644 index 000de2dbe..000000000 --- a/lambdas/pdm-mock-lambda/src/authenticator.ts +++ /dev/null @@ -1,66 +0,0 @@ -import type { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda'; -import type { Logger } from 'utils'; - -export type AuthResult = - | { isValid: true } - | { isValid: false; error: APIGatewayProxyResult }; - -export const createAuthenticator = (logger: Logger) => { - return async ( - event: Pick, - ): Promise => { - const authHeader = - event.headers?.Authorization || event.headers?.authorization; - - if (!authHeader) { - logger.warn('Missing Authorization header'); - return { - isValid: false, - error: { - statusCode: 401, - body: JSON.stringify({ - resourceType: 'OperationOutcome', - issue: [ - { - severity: 'error', - code: 'forbidden', - details: { - coding: [{ code: 'ACCESS_DENIED' }], - }, - diagnostics: 'Missing Authentication Token', - }, - ], - }), - }, - }; - } - - const [tokenType] = authHeader.split(' '); - - if (tokenType !== 'Bearer') { - logger.warn(tokenType, 'Invalid token type'); - return { - isValid: false, - error: { - statusCode: 401, - body: JSON.stringify({ - resourceType: 'OperationOutcome', - issue: [ - { - severity: 'error', - code: 'forbidden', - details: { - coding: [{ code: 'ACCESS_DENIED' }], - }, - diagnostics: 'Invalid Access Token', - }, - ], - }), - }, - }; - } - - logger.debug('Authentication successful'); - return { isValid: true }; - }; -}; diff --git a/lambdas/pdm-mock-lambda/src/container.ts b/lambdas/pdm-mock-lambda/src/container.ts index 2824c4652..c8e8caea6 100644 --- a/lambdas/pdm-mock-lambda/src/container.ts +++ b/lambdas/pdm-mock-lambda/src/container.ts @@ -1,25 +1,20 @@ import { logger } from 'utils'; -import { createAuthenticator } from 'authenticator'; import { createCreateResourceHandler, createGetResourceHandler, } from 'handlers'; export interface Container { - authenticator: ReturnType; getResourceHandler: ReturnType; createResourceHandler: ReturnType; logger: typeof logger; } export const createContainer = (): Container => { - const authenticator = createAuthenticator(logger); - const getResourceHandler = createGetResourceHandler(logger); const createResourceHandler = createCreateResourceHandler(logger); return { - authenticator, getResourceHandler, createResourceHandler, logger, diff --git a/lambdas/pdm-mock-lambda/src/index.ts b/lambdas/pdm-mock-lambda/src/index.ts index d1d185d1e..49b36cefb 100644 --- a/lambdas/pdm-mock-lambda/src/index.ts +++ b/lambdas/pdm-mock-lambda/src/index.ts @@ -11,8 +11,7 @@ export const handler: Handler< APIGatewayProxyEvent, APIGatewayProxyResult > = async (event: APIGatewayProxyEvent): Promise => { - const { authenticator, createResourceHandler, getResourceHandler, logger } = - container; + const { createResourceHandler, getResourceHandler, logger } = container; try { const { requestId } = event.requestContext; @@ -26,12 +25,6 @@ export const handler: Handler< hasAuth: !!event.headers?.Authorization, }); - const authResult = await authenticator(event); - if (!authResult.isValid) { - logger.warn('Authentication failed', { requestId, httpMethod, path }); - return authResult.error; - } - if ( httpMethod === 'GET' && path.includes('/patient-data-manager/FHIR/R4/DocumentReference/') From 4f007c98bd7269690d4d712cb37286214822468f Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Mon, 9 Mar 2026 12:10:48 +0000 Subject: [PATCH 04/15] CCM-14325: Update PDM upload rejected component test --- infrastructure/terraform/components/dl/locals.tf | 2 +- .../pdm-uploader.component.spec.ts | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/infrastructure/terraform/components/dl/locals.tf b/infrastructure/terraform/components/dl/locals.tf index 30c199a62..07f8842f7 100644 --- a/infrastructure/terraform/components/dl/locals.tf +++ b/infrastructure/terraform/components/dl/locals.tf @@ -4,7 +4,7 @@ locals { apim_keystore_s3_bucket = "nhs-${var.aws_account_id}-${var.region}-${var.environment}-${var.component}-static-assets" apim_private_key_ssm_parameter_name = "/${var.component}/${var.environment}/apim/private_key" aws_lambda_functions_dir_path = "../../../../lambdas" - pdm_access_token_ssm_parameter_name = var.enable_pdm_mock ? "" : "${local.apim_access_token_ssm_parameter_name}" + pdm_access_token_ssm_parameter_name = var.enable_pdm_mock ? "" : local.apim_access_token_ssm_parameter_name pdm_url = var.enable_pdm_mock ? aws_api_gateway_stage.pdm_mock[0].invoke_url : var.apim_base_url firehose_output_path_prefix = "kinesis-firehose-output" log_destination_arn = "arn:aws:logs:${var.region}:${var.shared_infra_account_id}:destination:nhs-main-obs-firehose-logs" diff --git a/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts b/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts index 276c9ffd7..ce5eab2bc 100644 --- a/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts +++ b/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts @@ -114,20 +114,15 @@ test.describe('Digital Letters - Upload to PDM', () => { }); test('should send a pdm.resource.submission.rejected event following an error from PDM', async () => { - // Note: I suspect this will fail once we are using the PDM Mock and will need amending. const eventId = uuidv4(); const letterId = uuidv4(); const resourceKey = `test/${letterId}`; const messageUri = `s3://${LETTERS_S3_BUCKET_NAME}/${resourceKey}`; - const messageReference = uuidv4(); + const messageReference = 'error-500-internal'; // This reference causes the PDM mock to return an error. const senderId = SENDER_ID_SKIPS_NOTIFY; const meshMessageId = '12345'; - const invalidPdmRequest = { - ...pdmRequest, - unexpectedField: 'I should not be here', - }; - await putDataS3(invalidPdmRequest, { + await putDataS3(pdmRequest, { Bucket: LETTERS_S3_BUCKET_NAME, Key: resourceKey, }); From 2fe819e77bbc5dc896c7d2a5d6ea39145db2b07e Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Mon, 9 Mar 2026 13:51:38 +0000 Subject: [PATCH 05/15] CCM-14325: Disable PDM mock by default --- infrastructure/terraform/components/dl/README.md | 2 +- infrastructure/terraform/components/dl/variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/infrastructure/terraform/components/dl/README.md b/infrastructure/terraform/components/dl/README.md index 786ba961e..37fb64fb8 100644 --- a/infrastructure/terraform/components/dl/README.md +++ b/infrastructure/terraform/components/dl/README.md @@ -23,7 +23,7 @@ No requirements. | [enable\_event\_anomaly\_detection](#input\_enable\_event\_anomaly\_detection) | Enable CloudWatch anomaly detection alarm for core notifier queue message reception | `bool` | `true` | no | | [enable\_event\_cache](#input\_enable\_event\_cache) | Enable caching of events to an S3 bucket | `bool` | `true` | no | | [enable\_mock\_mesh](#input\_enable\_mock\_mesh) | Enable mock mesh access (dev only). Grants lambda permission to read mock-mesh prefix in non-pii bucket. | `bool` | `false` | no | -| [enable\_pdm\_mock](#input\_enable\_pdm\_mock) | Flag indicating whether to deploy PDM mock API (should be false in production environments) | `bool` | `true` | no | +| [enable\_pdm\_mock](#input\_enable\_pdm\_mock) | Flag indicating whether to deploy PDM mock API (should be false in production environments) | `bool` | `false` | no | | [enable\_sns\_delivery\_logging](#input\_enable\_sns\_delivery\_logging) | Enable SNS Delivery Failure Notifications | `bool` | `true` | no | | [environment](#input\_environment) | The name of the tfscaffold environment | `string` | n/a | yes | | [event\_anomaly\_band\_width](#input\_event\_anomaly\_band\_width) | The width of the anomaly detection band. Higher values (e.g. 4-6) reduce sensitivity and noise, lower values (e.g. 2-3) increase sensitivity. Recommended: 2-4. | `number` | `3` | no | diff --git a/infrastructure/terraform/components/dl/variables.tf b/infrastructure/terraform/components/dl/variables.tf index 700e1e666..1c68e5134 100644 --- a/infrastructure/terraform/components/dl/variables.tf +++ b/infrastructure/terraform/components/dl/variables.tf @@ -166,7 +166,7 @@ variable "force_destroy" { variable "enable_pdm_mock" { type = bool description = "Flag indicating whether to deploy PDM mock API (should be false in production environments)" - default = true + default = false } variable "aws_account_type" { From 128076f1b0592c9a19146f86c6151a60d4af7188 Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Mon, 9 Mar 2026 16:43:13 +0000 Subject: [PATCH 06/15] CCM-14325: Fix core notifier in fresh dynamic environments --- infrastructure/terraform/components/dl/README.md | 1 + .../components/dl/module_lambda_core_notifier.tf | 2 +- infrastructure/terraform/components/dl/variables.tf | 11 +++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/infrastructure/terraform/components/dl/README.md b/infrastructure/terraform/components/dl/README.md index 37fb64fb8..fc6491069 100644 --- a/infrastructure/terraform/components/dl/README.md +++ b/infrastructure/terraform/components/dl/README.md @@ -19,6 +19,7 @@ No requirements. | [core\_notify\_url](#input\_core\_notify\_url) | The URL used to send requests to Notify | `string` | `"https://sandbox.api.service.nhs.uk"` | no | | [default\_cloudwatch\_event\_bus\_name](#input\_default\_cloudwatch\_event\_bus\_name) | The name of the default cloudwatch event bus. This is needed as GuardDuty Scan Result events are sent to the default bus | `string` | `"default"` | no | | [default\_tags](#input\_default\_tags) | A map of default tags to apply to all taggable resources within the component | `map(string)` | `{}` | no | +| [enable\_core\_notify\_auth](#input\_enable\_core\_notify\_auth) | Whether to send auth tokens with core notify API calls. | `bool` | `true` | no | | [enable\_dynamodb\_delete\_protection](#input\_enable\_dynamodb\_delete\_protection) | Enable DynamoDB Delete Protection on all Tables | `bool` | `true` | no | | [enable\_event\_anomaly\_detection](#input\_enable\_event\_anomaly\_detection) | Enable CloudWatch anomaly detection alarm for core notifier queue message reception | `bool` | `true` | no | | [enable\_event\_cache](#input\_enable\_event\_cache) | Enable caching of events to an S3 bucket | `bool` | `true` | no | diff --git a/infrastructure/terraform/components/dl/module_lambda_core_notifier.tf b/infrastructure/terraform/components/dl/module_lambda_core_notifier.tf index b8afbba60..f1a62b1ad 100644 --- a/infrastructure/terraform/components/dl/module_lambda_core_notifier.tf +++ b/infrastructure/terraform/components/dl/module_lambda_core_notifier.tf @@ -36,7 +36,7 @@ module "core_notifier" { lambda_env_vars = { "APIM_BASE_URL" = var.core_notify_url - "APIM_ACCESS_TOKEN_SSM_PARAMETER_NAME" = local.apim_access_token_ssm_parameter_name + "APIM_ACCESS_TOKEN_SSM_PARAMETER_NAME" = var.enable_core_notify_auth ? local.apim_access_token_ssm_parameter_name : "" "EVENT_PUBLISHER_EVENT_BUS_ARN" = aws_cloudwatch_event_bus.main.arn "EVENT_PUBLISHER_DLQ_URL" = module.sqs_event_publisher_errors.sqs_queue_url "ENVIRONMENT" = var.environment diff --git a/infrastructure/terraform/components/dl/variables.tf b/infrastructure/terraform/components/dl/variables.tf index 1c68e5134..64439ee8c 100644 --- a/infrastructure/terraform/components/dl/variables.tf +++ b/infrastructure/terraform/components/dl/variables.tf @@ -134,6 +134,17 @@ variable "core_notify_url" { default = "https://sandbox.api.service.nhs.uk" } +variable "enable_core_notify_auth" { + type = bool + description = "Whether to send auth tokens with core notify API calls." + default = true + + validation { + condition = var.environment == "prod" ? var.enable_core_notify_auth == true : true + error_message = "enable_core_notify_auth must be set to true when environment is 'prod'." + } +} + variable "apim_auth_token_url" { type = string description = "URL to generate an APIM auth token" From 4e11eaca70f501e71da97eda96cdd739c3bd441a Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:56:40 +0000 Subject: [PATCH 07/15] CCM-14325: Code review fixes --- lambdas/pdm-mock-lambda/src/__tests__/index.test.ts | 2 -- .../pdm-uploader.component.spec.ts | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lambdas/pdm-mock-lambda/src/__tests__/index.test.ts b/lambdas/pdm-mock-lambda/src/__tests__/index.test.ts index 2453cacdd..a00e58362 100644 --- a/lambdas/pdm-mock-lambda/src/__tests__/index.test.ts +++ b/lambdas/pdm-mock-lambda/src/__tests__/index.test.ts @@ -8,7 +8,6 @@ import { createContainer } from 'container'; import { handler } from '..'; jest.mock('container', () => { - const mockAuthenticator = jest.fn(); const mockGetResourceHandler = jest.fn(); const mockCreateResourceHandler = jest.fn(); const mockLogger = { @@ -21,7 +20,6 @@ jest.mock('container', () => { return { createContainer: jest.fn(() => ({ - authenticator: mockAuthenticator, getResourceHandler: mockGetResourceHandler, createResourceHandler: mockCreateResourceHandler, logger: mockLogger, diff --git a/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts b/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts index ce5eab2bc..f45c43aac 100644 --- a/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts +++ b/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts @@ -121,8 +121,12 @@ test.describe('Digital Letters - Upload to PDM', () => { const messageReference = 'error-500-internal'; // This reference causes the PDM mock to return an error. const senderId = SENDER_ID_SKIPS_NOTIFY; const meshMessageId = '12345'; + const invalidPdmRequest = { + ...pdmRequest, + unexpectedField: 'I should not be here', + }; - await putDataS3(pdmRequest, { + await putDataS3(invalidPdmRequest, { Bucket: LETTERS_S3_BUCKET_NAME, Key: resourceKey, }); From 76e993323aa5486e5a0af8a8b582023a88996aa6 Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:59:43 +0000 Subject: [PATCH 08/15] CCM-14325: Update flag name --- infrastructure/terraform/components/dl/README.md | 2 +- .../terraform/components/dl/module_lambda_core_notifier.tf | 2 +- infrastructure/terraform/components/dl/variables.tf | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/infrastructure/terraform/components/dl/README.md b/infrastructure/terraform/components/dl/README.md index fc6491069..c399ebf32 100644 --- a/infrastructure/terraform/components/dl/README.md +++ b/infrastructure/terraform/components/dl/README.md @@ -16,10 +16,10 @@ No requirements. | [aws\_account\_id](#input\_aws\_account\_id) | The AWS Account ID (numeric) | `string` | n/a | yes | | [aws\_account\_type](#input\_aws\_account\_type) | The AWS Account Type | `string` | n/a | yes | | [component](#input\_component) | The variable encapsulating the name of this component | `string` | `"dl"` | no | +| [core\_notify\_include\_auth\_header](#input\_core\_notify\_include\_auth\_header) | Whether to send auth tokens with core notify API calls. | `bool` | `true` | no | | [core\_notify\_url](#input\_core\_notify\_url) | The URL used to send requests to Notify | `string` | `"https://sandbox.api.service.nhs.uk"` | no | | [default\_cloudwatch\_event\_bus\_name](#input\_default\_cloudwatch\_event\_bus\_name) | The name of the default cloudwatch event bus. This is needed as GuardDuty Scan Result events are sent to the default bus | `string` | `"default"` | no | | [default\_tags](#input\_default\_tags) | A map of default tags to apply to all taggable resources within the component | `map(string)` | `{}` | no | -| [enable\_core\_notify\_auth](#input\_enable\_core\_notify\_auth) | Whether to send auth tokens with core notify API calls. | `bool` | `true` | no | | [enable\_dynamodb\_delete\_protection](#input\_enable\_dynamodb\_delete\_protection) | Enable DynamoDB Delete Protection on all Tables | `bool` | `true` | no | | [enable\_event\_anomaly\_detection](#input\_enable\_event\_anomaly\_detection) | Enable CloudWatch anomaly detection alarm for core notifier queue message reception | `bool` | `true` | no | | [enable\_event\_cache](#input\_enable\_event\_cache) | Enable caching of events to an S3 bucket | `bool` | `true` | no | diff --git a/infrastructure/terraform/components/dl/module_lambda_core_notifier.tf b/infrastructure/terraform/components/dl/module_lambda_core_notifier.tf index f1a62b1ad..048c4d289 100644 --- a/infrastructure/terraform/components/dl/module_lambda_core_notifier.tf +++ b/infrastructure/terraform/components/dl/module_lambda_core_notifier.tf @@ -36,7 +36,7 @@ module "core_notifier" { lambda_env_vars = { "APIM_BASE_URL" = var.core_notify_url - "APIM_ACCESS_TOKEN_SSM_PARAMETER_NAME" = var.enable_core_notify_auth ? local.apim_access_token_ssm_parameter_name : "" + "APIM_ACCESS_TOKEN_SSM_PARAMETER_NAME" = var.core_notify_include_auth_header ? local.apim_access_token_ssm_parameter_name : "" "EVENT_PUBLISHER_EVENT_BUS_ARN" = aws_cloudwatch_event_bus.main.arn "EVENT_PUBLISHER_DLQ_URL" = module.sqs_event_publisher_errors.sqs_queue_url "ENVIRONMENT" = var.environment diff --git a/infrastructure/terraform/components/dl/variables.tf b/infrastructure/terraform/components/dl/variables.tf index 64439ee8c..7cb28ff09 100644 --- a/infrastructure/terraform/components/dl/variables.tf +++ b/infrastructure/terraform/components/dl/variables.tf @@ -134,14 +134,14 @@ variable "core_notify_url" { default = "https://sandbox.api.service.nhs.uk" } -variable "enable_core_notify_auth" { +variable "core_notify_include_auth_header" { type = bool description = "Whether to send auth tokens with core notify API calls." default = true validation { - condition = var.environment == "prod" ? var.enable_core_notify_auth == true : true - error_message = "enable_core_notify_auth must be set to true when environment is 'prod'." + condition = var.environment != "dev" ? var.core_notify_include_auth_header == true : true + error_message = "core_notify_include_auth_header must be set to true when environment is not 'dev'." } } From 26ea8ae01de504078b78cef761ba7a37330f7eb6 Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Tue, 10 Mar 2026 14:11:01 +0000 Subject: [PATCH 09/15] CCM-14325: Fix variable validation --- infrastructure/terraform/components/dl/variables.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infrastructure/terraform/components/dl/variables.tf b/infrastructure/terraform/components/dl/variables.tf index 7cb28ff09..61cc23bbb 100644 --- a/infrastructure/terraform/components/dl/variables.tf +++ b/infrastructure/terraform/components/dl/variables.tf @@ -140,8 +140,8 @@ variable "core_notify_include_auth_header" { default = true validation { - condition = var.environment != "dev" ? var.core_notify_include_auth_header == true : true - error_message = "core_notify_include_auth_header must be set to true when environment is not 'dev'." + condition = var.environment == "prod" ? var.core_notify_include_auth_header == true : true + error_message = "core_notify_include_auth_header must be set to true when environment is 'prod'." } } From ac43ee55fb6368e9d54a8e4522314083a4770212 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Fri, 13 Mar 2026 08:16:14 +0000 Subject: [PATCH 10/15] CCM-14325: update mock PDM to allow unique error trigger values --- .../pdm-mock-lambda/src/__tests__/handlers.test.ts | 14 +++++++------- lambdas/pdm-mock-lambda/src/handlers.ts | 4 ++-- .../pdm-uploader.component.spec.ts | 10 ++++++++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/lambdas/pdm-mock-lambda/src/__tests__/handlers.test.ts b/lambdas/pdm-mock-lambda/src/__tests__/handlers.test.ts index d70357243..3743aa4e6 100644 --- a/lambdas/pdm-mock-lambda/src/__tests__/handlers.test.ts +++ b/lambdas/pdm-mock-lambda/src/__tests__/handlers.test.ts @@ -157,37 +157,37 @@ describe('GET Resource Handler', () => { describe('error scenarios', () => { it.each([ { - id: 'error-400-invalid', + id: 'error-400-invalid-a1b2c3', expectedStatus: 400, expectedCode: 'INVALID_VALUE', }, { - id: 'error-401-unauthorized', + id: 'error-401-unauthorized-d4e5f6', expectedStatus: 401, expectedCode: 'UNAUTHORISED', }, { - id: 'error-403-forbidden', + id: 'error-403-forbidden-7g8h9i', expectedStatus: 403, expectedCode: 'FORBIDDEN', }, { - id: 'error-404-notfound', + id: 'error-404-notfound-a1b2c3', expectedStatus: 404, expectedCode: 'RESOURCE_NOT_FOUND', }, { - id: 'error-429-ratelimit', + id: 'error-429-ratelimit-j8f6l1', expectedStatus: 429, expectedCode: 'TOO_MANY_REQUESTS', }, { - id: 'error-500-internal', + id: 'error-500-internal-i9j0k1', expectedStatus: 500, expectedCode: 'INTERNAL_ERROR', }, { - id: 'error-503-unavailable', + id: 'error-503-unavailable-j1k2l3', expectedStatus: 503, expectedCode: 'SERVICE_UNAVAILABLE', }, diff --git a/lambdas/pdm-mock-lambda/src/handlers.ts b/lambdas/pdm-mock-lambda/src/handlers.ts index a7b5ad1d2..6d8d257fe 100644 --- a/lambdas/pdm-mock-lambda/src/handlers.ts +++ b/lambdas/pdm-mock-lambda/src/handlers.ts @@ -225,7 +225,7 @@ export const createGetResourceHandler = (logger: Logger) => { ); } - const errorScenario = ERROR_SCENARIOS.find((s) => s.id === resourceId); + const errorScenario = ERROR_SCENARIOS.find((s) => s.id.startsWith(resourceId)); if (errorScenario) { logger.debug('Triggering error scenario', { resourceId, @@ -293,7 +293,7 @@ export const createCreateResourceHandler = (logger: Logger) => { requestId, }); - const errorScenario = ERROR_SCENARIOS.find((s) => s.id === resourceId); + const errorScenario = ERROR_SCENARIOS.find((s) => s.id.startsWith(resourceId)); if (errorScenario) { logger.debug('Triggering error scenario', { resourceId, diff --git a/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts b/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts index 4a9d0c146..b01d6b12f 100644 --- a/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts +++ b/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts @@ -114,16 +114,22 @@ test.describe('Digital Letters - Upload to PDM', () => { }); test('should send a pdm.resource.submission.rejected event following an error from PDM', async () => { + // Two mechanisms are used to trigger errors from PDM in this test + // - the first is a specific messageReference which the mock PDM is configured to return an error for. + // - the second is an unexpected field in the PDM request which causes the real PDM to return an error. + const messageReference = `error-500-internal-${uuidv4()}`; + const unexpectedField = 'I should not be here'; + const eventId = uuidv4(); const letterId = uuidv4(); const resourceKey = `test/${letterId}`; const messageUri = `s3://${LETTERS_S3_BUCKET_NAME}/${resourceKey}`; - const messageReference = 'error-500-internal'; // This reference causes the PDM mock to return an error. const senderId = SENDER_ID_SKIPS_NOTIFY; const meshMessageId = '12345'; + const invalidPdmRequest = { ...pdmRequest, - unexpectedField: 'I should not be here', + unexpectedField }; await putDataS3(invalidPdmRequest, { From 48c7556686c5d0ed42bdadf23babb88abb91ae44 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Fri, 13 Mar 2026 08:16:58 +0000 Subject: [PATCH 11/15] CCM-14325: fix for incorrect file prefix --- .../terraform/components/dl/module_lambda_file_scanner.tf | 2 +- .../file-scanner.component.spec.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/infrastructure/terraform/components/dl/module_lambda_file_scanner.tf b/infrastructure/terraform/components/dl/module_lambda_file_scanner.tf index f5aa878c1..8c82c5caf 100644 --- a/infrastructure/terraform/components/dl/module_lambda_file_scanner.tf +++ b/infrastructure/terraform/components/dl/module_lambda_file_scanner.tf @@ -37,7 +37,7 @@ module "file_scanner" { lambda_env_vars = { "DOCUMENT_REFERENCE_BUCKET" = module.s3bucket_pii_data.bucket "UNSCANNED_FILES_BUCKET" = local.unscanned_files_bucket - "UNSCANNED_FILES_PATH_PREFIX" = var.environment + "UNSCANNED_FILES_PATH_PREFIX" = local.csi "EVENT_PUBLISHER_EVENT_BUS_ARN" = aws_cloudwatch_event_bus.main.arn "EVENT_PUBLISHER_DLQ_URL" = module.sqs_event_publisher_errors.sqs_queue_url } diff --git a/tests/playwright/digital-letters-component-tests/file-scanner.component.spec.ts b/tests/playwright/digital-letters-component-tests/file-scanner.component.spec.ts index 1a394d32e..48b277fb7 100644 --- a/tests/playwright/digital-letters-component-tests/file-scanner.component.spec.ts +++ b/tests/playwright/digital-letters-component-tests/file-scanner.component.spec.ts @@ -2,6 +2,7 @@ import { expect, test } from '@playwright/test'; import { ENV, FILE_SCANNER_DLQ_NAME, + PREFIX_DL_FILES, REGION, } from 'constants/backend-constants'; import itemDequeuedValidator from 'digital-letters-events/ItemDequeued.js'; @@ -28,7 +29,7 @@ test.describe('File Scanner', () => { test('should extract PDF from DocumentReference and store in unscanned bucket with metadata', async () => { const messageReference = uuidv4(); const senderId = 'TEST_SENDER_001'; - const documentReferenceKey = messageReference; + const documentReferenceKey = `${PREFIX_DL_FILES}${messageReference}`; const pdfContent = Buffer.from('Sample PDF content for test'); const documentReference = { @@ -80,7 +81,7 @@ test('should extract PDF from DocumentReference and store in unscanned bucket wi ); await expectToPassEventually(async () => { - const expectedKey = `${ENV}/${messageReference}.pdf`; + const expectedKey = `${PREFIX_DL_FILES}${messageReference}.pdf`; const expectedUri = `s3://${UNSCANNED_FILES_BUCKET}/${expectedKey}`; const storedPdf = await getS3ObjectBufferFromUri(expectedUri); From dddd7a51fc9b76324a7ca0b21f8195a2a163c6a3 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Fri, 13 Mar 2026 08:24:42 +0000 Subject: [PATCH 12/15] CCM-14325: linting --- lambdas/pdm-mock-lambda/src/handlers.ts | 8 ++++++-- .../pdm-uploader.component.spec.ts | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lambdas/pdm-mock-lambda/src/handlers.ts b/lambdas/pdm-mock-lambda/src/handlers.ts index 6d8d257fe..bb0334963 100644 --- a/lambdas/pdm-mock-lambda/src/handlers.ts +++ b/lambdas/pdm-mock-lambda/src/handlers.ts @@ -225,7 +225,9 @@ export const createGetResourceHandler = (logger: Logger) => { ); } - const errorScenario = ERROR_SCENARIOS.find((s) => s.id.startsWith(resourceId)); + const errorScenario = ERROR_SCENARIOS.find((s) => + s.id.startsWith(resourceId), + ); if (errorScenario) { logger.debug('Triggering error scenario', { resourceId, @@ -293,7 +295,9 @@ export const createCreateResourceHandler = (logger: Logger) => { requestId, }); - const errorScenario = ERROR_SCENARIOS.find((s) => s.id.startsWith(resourceId)); + const errorScenario = ERROR_SCENARIOS.find((s) => + s.id.startsWith(resourceId), + ); if (errorScenario) { logger.debug('Triggering error scenario', { resourceId, diff --git a/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts b/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts index b01d6b12f..e5ba36dcd 100644 --- a/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts +++ b/tests/playwright/digital-letters-component-tests/pdm-uploader.component.spec.ts @@ -129,7 +129,7 @@ test.describe('Digital Letters - Upload to PDM', () => { const invalidPdmRequest = { ...pdmRequest, - unexpectedField + unexpectedField, }; await putDataS3(invalidPdmRequest, { From 2603d12cd705a5d092d2746808bd686d382c2d16 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Fri, 13 Mar 2026 08:34:31 +0000 Subject: [PATCH 13/15] CCM-14325: fix logic --- lambdas/pdm-mock-lambda/src/handlers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lambdas/pdm-mock-lambda/src/handlers.ts b/lambdas/pdm-mock-lambda/src/handlers.ts index bb0334963..cf3519fd6 100644 --- a/lambdas/pdm-mock-lambda/src/handlers.ts +++ b/lambdas/pdm-mock-lambda/src/handlers.ts @@ -226,7 +226,7 @@ export const createGetResourceHandler = (logger: Logger) => { } const errorScenario = ERROR_SCENARIOS.find((s) => - s.id.startsWith(resourceId), + resourceId.startsWith(s.id), ); if (errorScenario) { logger.debug('Triggering error scenario', { @@ -296,7 +296,7 @@ export const createCreateResourceHandler = (logger: Logger) => { }); const errorScenario = ERROR_SCENARIOS.find((s) => - s.id.startsWith(resourceId), + resourceId.startsWith(s.id), ); if (errorScenario) { logger.debug('Triggering error scenario', { From ca62294c691edba62e848a91e02d657b0c52b223 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Tue, 17 Mar 2026 11:50:58 +0000 Subject: [PATCH 14/15] CCM-14325: revert tf module downgrade --- infrastructure/terraform/components/dl/README.md | 2 +- .../terraform/components/dl/module_lambda_pdm_mock.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/infrastructure/terraform/components/dl/README.md b/infrastructure/terraform/components/dl/README.md index 8cfd41bca..114d77e76 100644 --- a/infrastructure/terraform/components/dl/README.md +++ b/infrastructure/terraform/components/dl/README.md @@ -70,7 +70,7 @@ No requirements. | [mesh\_download](#module\_mesh\_download) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.0.6/terraform-lambda.zip | n/a | | [mesh\_poll](#module\_mesh\_poll) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.0.6/terraform-lambda.zip | n/a | | [move\_scanned\_files](#module\_move\_scanned\_files) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.0.6/terraform-lambda.zip | n/a | -| [pdm\_mock](#module\_pdm\_mock) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a | +| [pdm\_mock](#module\_pdm\_mock) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.0.6/terraform-lambda.zip | n/a | | [pdm\_poll](#module\_pdm\_poll) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.0.6/terraform-lambda.zip | n/a | | [pdm\_uploader](#module\_pdm\_uploader) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.0.6/terraform-lambda.zip | n/a | | [print\_analyser](#module\_print\_analyser) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.0.6/terraform-lambda.zip | n/a | diff --git a/infrastructure/terraform/components/dl/module_lambda_pdm_mock.tf b/infrastructure/terraform/components/dl/module_lambda_pdm_mock.tf index f2ca8c596..e4f04231c 100644 --- a/infrastructure/terraform/components/dl/module_lambda_pdm_mock.tf +++ b/infrastructure/terraform/components/dl/module_lambda_pdm_mock.tf @@ -1,6 +1,6 @@ module "pdm_mock" { count = var.enable_pdm_mock ? 1 : 0 - source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip" + source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.0.6/terraform-lambda.zip" function_name = "pdm-mock" description = "A lambda function for mocking PDM (Patient Data Manager) API endpoints" From 15404a0745f0dd9869ead347b57f8712ee65319a Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Tue, 17 Mar 2026 12:10:56 +0000 Subject: [PATCH 15/15] CCM-14325: trivy fixes --- .../assets/ADR-003/examples/python/requirements.txt | 2 +- package-lock.json | 4 +++- src/eventcatalog/package-lock.json | 12 ++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/adr/assets/ADR-003/examples/python/requirements.txt b/docs/adr/assets/ADR-003/examples/python/requirements.txt index b7e317b4b..2217ba554 100644 --- a/docs/adr/assets/ADR-003/examples/python/requirements.txt +++ b/docs/adr/assets/ADR-003/examples/python/requirements.txt @@ -1,2 +1,2 @@ -PyJWT==2.8.0 +PyJWT==2.12.0 requests==2.32.4 diff --git a/package-lock.json b/package-lock.json index 4f719db40..177d60c7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13677,7 +13677,9 @@ } }, "node_modules/flatted": { - "version": "3.3.3", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz", + "integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==", "dev": true, "license": "ISC" }, diff --git a/src/eventcatalog/package-lock.json b/src/eventcatalog/package-lock.json index c47f88334..6ca1bd378 100644 --- a/src/eventcatalog/package-lock.json +++ b/src/eventcatalog/package-lock.json @@ -12206,9 +12206,9 @@ "license": "Apache-2.0" }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz", + "integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==", "license": "ISC" }, "node_modules/flattie": { @@ -23622,9 +23622,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz", - "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.4.tgz", + "integrity": "sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==", "license": "MIT", "engines": { "node": ">=20.18.1"