diff --git a/.github/workflows/build-docker-images.yml b/.github/workflows/build-docker-images.yml
index e9b19e87cf..aaa96281de 100644
--- a/.github/workflows/build-docker-images.yml
+++ b/.github/workflows/build-docker-images.yml
@@ -38,8 +38,8 @@ on:
default: us-east-1
type: choice
options:
- - us-east-1
- - us-west-2
+ - us-east-1
+ - us-west-2
required: true
permissions:
@@ -63,6 +63,13 @@ jobs:
name: "bfd-mgmt-eft-sftp-outbound-transfer-lambda",
dockerfile: "ops/jenkins/bfd-build-eft-sftp-outbound-transfer-lambda/Dockerfile",
contextDir: "ops/terraform/services/eft/lambda_src/sftp_outbound_transfer",
+ platform: "linux/amd64",
+ },
+ {
+ name: "bfd-mgmt-pipeline-ccw-manifests-verifier-lambda",
+ dockerfile: "ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/Dockerfile",
+ contextDir: "ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src",
+ platform: "linux/arm64",
},
]
runs-on: ubuntu-latest
@@ -128,9 +135,9 @@ jobs:
tags: ${{ steps.setup_tags.outputs.image_tags }}
# AWS Lambda does not support multi-platform images, something that is enabled by default
# by this Action via the "provenance" flag. Until AWS Lambda supports this feature
- # properly, we must explicitly disable provenance and specify the amd64 platform.
+ # properly, we must explicitly disable provenance and specify the platform directly.
# See https://github.com/docker/buildx/issues/1533
provenance: false
- platforms: "linux/amd64"
+ platforms: ${{ matrix.image.platform }}
env:
DOCKER_BUILDKIT: 1
diff --git a/.gitignore b/.gitignore
index 51a73044b1..b4cb866a13 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@
!.github
!.sensitive-files
!.terraform-docs.yml
+!.python-version
# Ignore everything within top-level dist directory
/dist/**/*
diff --git a/apps/bfd-data-fda/pom.xml b/apps/bfd-data-fda/pom.xml
index 8080790836..f535735101 100644
--- a/apps/bfd-data-fda/pom.xml
+++ b/apps/bfd-data-fda/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
gov.cms.bfd.data.fda.utility
diff --git a/apps/bfd-data-npi/pom.xml b/apps/bfd-data-npi/pom.xml
index 9302cd6bd6..66197bd282 100644
--- a/apps/bfd-data-npi/pom.xml
+++ b/apps/bfd-data-npi/pom.xml
@@ -3,7 +3,7 @@
gov.cms.bfd
bfd-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
gov.cms.bfd.data.npi
diff --git a/apps/bfd-db-migrator/pom.xml b/apps/bfd-db-migrator/pom.xml
index 2bf304a31d..113e6df8e5 100644
--- a/apps/bfd-db-migrator/pom.xml
+++ b/apps/bfd-db-migrator/pom.xml
@@ -5,7 +5,7 @@
gov.cms.bfd
bfd-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-db-migrator
diff --git a/apps/bfd-model/bfd-model-codebook-data/pom.xml b/apps/bfd-model/bfd-model-codebook-data/pom.xml
index 8c17f3162f..c7e96b8582 100644
--- a/apps/bfd-model/bfd-model-codebook-data/pom.xml
+++ b/apps/bfd-model/bfd-model-codebook-data/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-model-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-model-codebook-data
diff --git a/apps/bfd-model/bfd-model-codebook-library/pom.xml b/apps/bfd-model/bfd-model-codebook-library/pom.xml
index 12d171adce..31c4d73d79 100644
--- a/apps/bfd-model/bfd-model-codebook-library/pom.xml
+++ b/apps/bfd-model/bfd-model-codebook-library/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-model-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-model-codebook-library
diff --git a/apps/bfd-model/bfd-model-codebook-plugin/pom.xml b/apps/bfd-model/bfd-model-codebook-plugin/pom.xml
index 7a157da2ac..0409468140 100644
--- a/apps/bfd-model/bfd-model-codebook-plugin/pom.xml
+++ b/apps/bfd-model/bfd-model-codebook-plugin/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-model-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-model-codebook-plugin
diff --git a/apps/bfd-model/bfd-model-dsl-codegen/bfd-model-dsl-codegen-library/pom.xml b/apps/bfd-model/bfd-model-dsl-codegen/bfd-model-dsl-codegen-library/pom.xml
index 508aa12b82..078ec487db 100644
--- a/apps/bfd-model/bfd-model-dsl-codegen/bfd-model-dsl-codegen-library/pom.xml
+++ b/apps/bfd-model/bfd-model-dsl-codegen/bfd-model-dsl-codegen-library/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-model-dsl-codegen-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-model-dsl-codegen-library
diff --git a/apps/bfd-model/bfd-model-dsl-codegen/bfd-model-dsl-codegen-plugin/pom.xml b/apps/bfd-model/bfd-model-dsl-codegen/bfd-model-dsl-codegen-plugin/pom.xml
index 73decad378..8bd28f2188 100644
--- a/apps/bfd-model/bfd-model-dsl-codegen/bfd-model-dsl-codegen-plugin/pom.xml
+++ b/apps/bfd-model/bfd-model-dsl-codegen/bfd-model-dsl-codegen-plugin/pom.xml
@@ -5,11 +5,11 @@
gov.cms.bfd
bfd-model-dsl-codegen-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-model-dsl-codegen-plugin
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
maven-plugin
diff --git a/apps/bfd-model/bfd-model-dsl-codegen/pom.xml b/apps/bfd-model/bfd-model-dsl-codegen/pom.xml
index c2e6ee9164..5599b1c21d 100644
--- a/apps/bfd-model/bfd-model-dsl-codegen/pom.xml
+++ b/apps/bfd-model/bfd-model-dsl-codegen/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-model-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-model-dsl-codegen-parent
diff --git a/apps/bfd-model/bfd-model-rda/pom.xml b/apps/bfd-model/bfd-model-rda/pom.xml
index 3b26d58c7f..1ef84308b9 100644
--- a/apps/bfd-model/bfd-model-rda/pom.xml
+++ b/apps/bfd-model/bfd-model-rda/pom.xml
@@ -5,7 +5,7 @@
gov.cms.bfd
bfd-model-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-model-rda
diff --git a/apps/bfd-model/bfd-model-rif-samples/pom.xml b/apps/bfd-model/bfd-model-rif-samples/pom.xml
index f59406df63..04137a151c 100644
--- a/apps/bfd-model/bfd-model-rif-samples/pom.xml
+++ b/apps/bfd-model/bfd-model-rif-samples/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-model-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-model-rif-samples
diff --git a/apps/bfd-model/bfd-model-rif/mappings/PartDEvent.yaml b/apps/bfd-model/bfd-model-rif/mappings/PartDEvent.yaml
index f1c20eef49..105ceedd16 100644
--- a/apps/bfd-model/bfd-model-rif/mappings/PartDEvent.yaml
+++ b/apps/bfd-model/bfd-model-rif/mappings/PartDEvent.yaml
@@ -67,7 +67,7 @@ mappings:
dbName: prscrbr_id
name: prescriberId
nullable: false
- sqlType: varchar(15)
+ sqlType: varchar(35)
- comment: RX Service Reference Number (https://www.ccwdata.org/cs/groups/public/documents/datadictionary/rx_srvc_rfrnc_num.txt)
dbName: rx_srvc_rfrnc_num
name: prescriptionReferenceNumber
@@ -77,7 +77,7 @@ mappings:
dbName: prod_srvc_id
name: nationalDrugCode
nullable: false
- sqlType: varchar(19)
+ sqlType: varchar(40)
- comment: Plan Contract Record ID (https://www.ccwdata.org/cs/groups/public/documents/datadictionary/plan_cntrct_rec_id.txt)
dbName: plan_cntrct_rec_id
name: planContractId
@@ -219,7 +219,7 @@ mappings:
- comment: Submission Clarification Code (https://www.ccwdata.org/cs/groups/public/documents/datadictionary/submsn_clr_cd.txt)
dbName: submsn_clr_cd
name: submissionClarificationCode
- sqlType: varchar(2)
+ sqlType: varchar(3)
- comment: LAST_UPDATED (https://bluebutton.cms.gov/resources/variables/lastUpdated)
dbName: last_updated
name: lastUpdated
diff --git a/apps/bfd-model/bfd-model-rif/pom.xml b/apps/bfd-model/bfd-model-rif/pom.xml
index 059a4257ac..58996343ac 100644
--- a/apps/bfd-model/bfd-model-rif/pom.xml
+++ b/apps/bfd-model/bfd-model-rif/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-model-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-model-rif
diff --git a/apps/bfd-model/bfd-model-rif/src/main/resources/db/migration/V20250121143014662__update_pde_col_widths.sql b/apps/bfd-model/bfd-model-rif/src/main/resources/db/migration/V20250121143014662__update_pde_col_widths.sql
new file mode 100644
index 0000000000..7f1d2be8bc
--- /dev/null
+++ b/apps/bfd-model/bfd-model-rif/src/main/resources/db/migration/V20250121143014662__update_pde_col_widths.sql
@@ -0,0 +1,8 @@
+ALTER TABLE ccw.partd_events
+ALTER COLUMN prscrbr_id type varchar(35);
+
+ALTER TABLE ccw.partd_events
+ALTER COLUMN prod_srvc_id type varchar(40);
+
+ALTER TABLE ccw.partd_events
+ALTER COLUMN submsn_clr_cd type varchar(3);
diff --git a/apps/bfd-model/pom.xml b/apps/bfd-model/pom.xml
index 562bb7b530..0f38797ee9 100644
--- a/apps/bfd-model/pom.xml
+++ b/apps/bfd-model/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-model-parent
diff --git a/apps/bfd-ops/pom.xml b/apps/bfd-ops/pom.xml
index 8f503268b7..9f271c72e1 100644
--- a/apps/bfd-ops/pom.xml
+++ b/apps/bfd-ops/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-ops
diff --git a/apps/bfd-pipeline/bfd-pipeline-app/pom.xml b/apps/bfd-pipeline/bfd-pipeline-app/pom.xml
index 78edba30ec..6f93ddc1b3 100644
--- a/apps/bfd-pipeline/bfd-pipeline-app/pom.xml
+++ b/apps/bfd-pipeline/bfd-pipeline-app/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-pipeline-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-pipeline-app
diff --git a/apps/bfd-pipeline/bfd-pipeline-ccw-rif/pom.xml b/apps/bfd-pipeline/bfd-pipeline-ccw-rif/pom.xml
index 9a9de24ad9..b306ac80ff 100644
--- a/apps/bfd-pipeline/bfd-pipeline-ccw-rif/pom.xml
+++ b/apps/bfd-pipeline/bfd-pipeline-ccw-rif/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-pipeline-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-pipeline-ccw-rif
diff --git a/apps/bfd-pipeline/bfd-pipeline-rda-bridge/pom.xml b/apps/bfd-pipeline/bfd-pipeline-rda-bridge/pom.xml
index 1d531f7b85..fcee5925ed 100644
--- a/apps/bfd-pipeline/bfd-pipeline-rda-bridge/pom.xml
+++ b/apps/bfd-pipeline/bfd-pipeline-rda-bridge/pom.xml
@@ -5,7 +5,7 @@
gov.cms.bfd
bfd-pipeline-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-pipeline-rda-bridge
diff --git a/apps/bfd-pipeline/bfd-pipeline-rda-grpc-apps/pom.xml b/apps/bfd-pipeline/bfd-pipeline-rda-grpc-apps/pom.xml
index b3de49bd0e..bca8230dbd 100644
--- a/apps/bfd-pipeline/bfd-pipeline-rda-grpc-apps/pom.xml
+++ b/apps/bfd-pipeline/bfd-pipeline-rda-grpc-apps/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-pipeline-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-pipeline-rda-grpc-apps
diff --git a/apps/bfd-pipeline/bfd-pipeline-rda-grpc/pom.xml b/apps/bfd-pipeline/bfd-pipeline-rda-grpc/pom.xml
index 34673236cd..f711b5b831 100644
--- a/apps/bfd-pipeline/bfd-pipeline-rda-grpc/pom.xml
+++ b/apps/bfd-pipeline/bfd-pipeline-rda-grpc/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-pipeline-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-pipeline-rda-grpc
diff --git a/apps/bfd-pipeline/bfd-pipeline-shared-test-utils/pom.xml b/apps/bfd-pipeline/bfd-pipeline-shared-test-utils/pom.xml
index d6557495bc..5559245e75 100644
--- a/apps/bfd-pipeline/bfd-pipeline-shared-test-utils/pom.xml
+++ b/apps/bfd-pipeline/bfd-pipeline-shared-test-utils/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-pipeline-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-pipeline-shared-test-utils
diff --git a/apps/bfd-pipeline/bfd-pipeline-shared-utils/pom.xml b/apps/bfd-pipeline/bfd-pipeline-shared-utils/pom.xml
index bfcd64ee4b..ad9d17274d 100644
--- a/apps/bfd-pipeline/bfd-pipeline-shared-utils/pom.xml
+++ b/apps/bfd-pipeline/bfd-pipeline-shared-utils/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-pipeline-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-pipeline-shared-utils
diff --git a/apps/bfd-pipeline/pom.xml b/apps/bfd-pipeline/pom.xml
index 35033e4480..b7cbe59366 100644
--- a/apps/bfd-pipeline/pom.xml
+++ b/apps/bfd-pipeline/pom.xml
@@ -5,7 +5,7 @@
gov.cms.bfd
bfd-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-pipeline-parent
diff --git a/apps/bfd-server/bfd-server-docs/pom.xml b/apps/bfd-server/bfd-server-docs/pom.xml
index d85bdf203f..04e1330de9 100644
--- a/apps/bfd-server/bfd-server-docs/pom.xml
+++ b/apps/bfd-server/bfd-server-docs/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-server-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-server-docs
diff --git a/apps/bfd-server/bfd-server-image/pom.xml b/apps/bfd-server/bfd-server-image/pom.xml
index 13e09ecd6e..cf9fe30c28 100644
--- a/apps/bfd-server/bfd-server-image/pom.xml
+++ b/apps/bfd-server/bfd-server-image/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-server-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-server-image
diff --git a/apps/bfd-server/bfd-server-launcher-sample/pom.xml b/apps/bfd-server/bfd-server-launcher-sample/pom.xml
index d41aede9ce..bc60c1b7c9 100644
--- a/apps/bfd-server/bfd-server-launcher-sample/pom.xml
+++ b/apps/bfd-server/bfd-server-launcher-sample/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-server-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-server-launcher-sample
diff --git a/apps/bfd-server/bfd-server-launcher/pom.xml b/apps/bfd-server/bfd-server-launcher/pom.xml
index 831c8b034a..639b404492 100644
--- a/apps/bfd-server/bfd-server-launcher/pom.xml
+++ b/apps/bfd-server/bfd-server-launcher/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-server-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-server-launcher
diff --git a/apps/bfd-server/bfd-server-shared-utils/pom.xml b/apps/bfd-server/bfd-server-shared-utils/pom.xml
index 236fbf6eb3..3e525f8b24 100644
--- a/apps/bfd-server/bfd-server-shared-utils/pom.xml
+++ b/apps/bfd-server/bfd-server-shared-utils/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-server-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-server-shared-utils
diff --git a/apps/bfd-server/bfd-server-war/pom.xml b/apps/bfd-server/bfd-server-war/pom.xml
index 7c2573700c..f3c1d90386 100644
--- a/apps/bfd-server/bfd-server-war/pom.xml
+++ b/apps/bfd-server/bfd-server-war/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-server-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-server-war
diff --git a/apps/bfd-server/pom.xml b/apps/bfd-server/pom.xml
index 52f362d2b8..004debf703 100644
--- a/apps/bfd-server/pom.xml
+++ b/apps/bfd-server/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-server-parent
diff --git a/apps/bfd-shared-test-utils/pom.xml b/apps/bfd-shared-test-utils/pom.xml
index c6d53ff6f2..90f6a5c7c2 100644
--- a/apps/bfd-shared-test-utils/pom.xml
+++ b/apps/bfd-shared-test-utils/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-shared-test-utils
diff --git a/apps/bfd-shared-utils/pom.xml b/apps/bfd-shared-utils/pom.xml
index f48b4c3aa4..da61ec2953 100644
--- a/apps/bfd-shared-utils/pom.xml
+++ b/apps/bfd-shared-utils/pom.xml
@@ -4,7 +4,7 @@
gov.cms.bfd
bfd-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
bfd-shared-utils
diff --git a/apps/pom.xml b/apps/pom.xml
index 05b750dc59..50050919dc 100644
--- a/apps/pom.xml
+++ b/apps/pom.xml
@@ -3,7 +3,7 @@
gov.cms.bfd
bfd-parent
- 2.175.0-SNAPSHOT
+ 2.176.0-SNAPSHOT
pom
bfd-parent
@@ -65,7 +65,7 @@
21
- 2025-01-16T21:29:31Z
+ 2025-01-22T16:46:25Z
true
jacoco
diff --git a/apps/utils/locust_tests/README.md b/apps/utils/locust_tests/README.md
index b9a3c0e9dc..d64f78bb8d 100644
--- a/apps/utils/locust_tests/README.md
+++ b/apps/utils/locust_tests/README.md
@@ -9,7 +9,7 @@ to avoid caching affecting the response times of repeat runs.
These tests are intended to be run from a server instance which has access permissions to reach out to the BFD endpoints. How to
do this is outside the scope of this document, but instructions for this can be found in this more detailed run guide on confluence:
-https://confluence.cms.gov/display/BB2/Run+the+BFD+Load+Tests.
+https://confluence.cms.gov/display/BFD/2022+Run+the+BFD+Load+Tests.
The following test suites ([Locustfiles](https://docs.locust.io/en/stable/writing-a-locustfile.html)) are available to run:
@@ -22,7 +22,7 @@ The following test suites ([Locustfiles](https://docs.locust.io/en/stable/writin
| Load Testing Suite | `high_volume_suite.py` | Used to exhibit distributed load on a target BFD Server to produce performance metrics under stress. Invoked by the `bfd-run-server-load` Jenkins pipeline job |
## Dependencies
-> **Important:** This project is targeting Python 3.8. Ensure that your local Python is version 3.8 **before** attempting to work in this project!
+> **Important:** This project is targeting Python 3.11. Ensure that your local Python is version 3.11 **before** attempting to work in this project!
> A good utility for managing multiple Python versions along with [virtualenv](https://virtualenv.pypa.io/en/latest/)s is [`pew`](https://github.com/berdario/pew).
The tests use a few python libraries that will need to be installed on the run box prior to starting the tests.
diff --git a/apps/utils/locust_tests/dev-requirements.txt b/apps/utils/locust_tests/dev-requirements.txt
index b098adfb28..f59c5e6e2d 100644
--- a/apps/utils/locust_tests/dev-requirements.txt
+++ b/apps/utils/locust_tests/dev-requirements.txt
@@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
-# pip-compile --allow-unsafe --constraint=requirements.txt --generate-hashes --output-file=dev-requirements.txt dev-requirements.in
+# pip-compile --allow-unsafe --constraint=requirements.txt --generate-hashes --no-reuse-hashes --output-file=dev-requirements.txt --strip-extras dev-requirements.in
#
astroid==2.15.6 \
--hash=sha256:389656ca57b6108f939cf5d2f9a2a825a3be50ba9d589670f393236e0a03b91c \
diff --git a/apps/utils/locust_tests/requirements.in b/apps/utils/locust_tests/requirements.in
index 54060f62c3..e3b3972cb0 100644
--- a/apps/utils/locust_tests/requirements.in
+++ b/apps/utils/locust_tests/requirements.in
@@ -6,9 +6,9 @@ setuptools>=70.0.0
flask==2.3.3
flask-cors==5.0.0
requests==2.32.2
-gevent==23.9.1
+gevent==24.10.1
urllib3==1.26.19
-werkzeug==3.0.3
-jinja2==3.1.4
+werkzeug==3.0.6
+jinja2==3.1.5
idna>=3.7
certifi==2024.7.4
\ No newline at end of file
diff --git a/apps/utils/locust_tests/requirements.txt b/apps/utils/locust_tests/requirements.txt
index c571c41860..a747c2009c 100644
--- a/apps/utils/locust_tests/requirements.txt
+++ b/apps/utils/locust_tests/requirements.txt
@@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
-# pip-compile --allow-unsafe --generate-hashes --no-reuse-hashes --output-file=requirements.txt requirements.in
+# pip-compile --allow-unsafe --generate-hashes --no-reuse-hashes --output-file=requirements.txt --strip-extras requirements.in
#
blinker==1.6.3 \
--hash=sha256:152090d27c1c5c722ee7e48504b02d76502811ce02e1523553b4cf8c8b3d3a8d \
@@ -22,6 +22,7 @@ brotli==1.1.0 \
--hash=sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208 \
--hash=sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48 \
--hash=sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354 \
+ --hash=sha256:0737ddb3068957cf1b054899b0883830bb1fec522ec76b1098f9b6e0f02d9419 \
--hash=sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a \
--hash=sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128 \
--hash=sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c \
@@ -29,43 +30,67 @@ brotli==1.1.0 \
--hash=sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9 \
--hash=sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a \
--hash=sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3 \
+ --hash=sha256:1b2c248cd517c222d89e74669a4adfa5577e06ab68771a529060cf5a156e9757 \
+ --hash=sha256:1e9a65b5736232e7a7f91ff3d02277f11d339bf34099a56cdab6a8b3410a02b2 \
--hash=sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438 \
--hash=sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578 \
--hash=sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b \
--hash=sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b \
--hash=sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68 \
+ --hash=sha256:2a24c50840d89ded6c9a8fdc7b6ed3692ed4e86f1c4a4a938e1e92def92933e0 \
--hash=sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d \
+ --hash=sha256:2feb1d960f760a575dbc5ab3b1c00504b24caaf6986e2dc2b01c09c87866a943 \
--hash=sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd \
--hash=sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409 \
+ --hash=sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28 \
--hash=sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da \
--hash=sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50 \
+ --hash=sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f \
--hash=sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0 \
+ --hash=sha256:3ee8a80d67a4334482d9712b8e83ca6b1d9bc7e351931252ebef5d8f7335a547 \
--hash=sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180 \
+ --hash=sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0 \
--hash=sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d \
+ --hash=sha256:4410f84b33374409552ac9b6903507cdb31cd30d2501fc5ca13d18f73548444a \
+ --hash=sha256:494994f807ba0b92092a163a0a283961369a65f6cbe01e8891132b7a320e61eb \
--hash=sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112 \
--hash=sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc \
+ --hash=sha256:4f3607b129417e111e30637af1b56f24f7a49e64763253bbc275c75fa887d4b2 \
--hash=sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265 \
--hash=sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327 \
--hash=sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95 \
+ --hash=sha256:58d4b711689366d4a03ac7957ab8c28890415e267f9b6589969e74b6e42225ec \
--hash=sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd \
+ --hash=sha256:5dab0844f2cf82be357a0eb11a9087f70c5430b2c241493fc122bb6f2bb0917c \
+ --hash=sha256:5e55da2c8724191e5b557f8e18943b1b4839b8efc3ef60d65985bcf6f587dd38 \
--hash=sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914 \
--hash=sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0 \
--hash=sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a \
--hash=sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7 \
+ --hash=sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368 \
+ --hash=sha256:6974f52a02321b36847cd19d1b8e381bf39939c21efd6ee2fc13a28b0d99348c \
--hash=sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0 \
+ --hash=sha256:6c6e0c425f22c1c719c42670d561ad682f7bfeeef918edea971a79ac5252437f \
--hash=sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451 \
--hash=sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f \
+ --hash=sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8 \
--hash=sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e \
--hash=sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248 \
+ --hash=sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c \
--hash=sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91 \
--hash=sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724 \
+ --hash=sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7 \
--hash=sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966 \
+ --hash=sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9 \
--hash=sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97 \
--hash=sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d \
+ --hash=sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5 \
--hash=sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf \
--hash=sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac \
+ --hash=sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b \
--hash=sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951 \
--hash=sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74 \
+ --hash=sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648 \
--hash=sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60 \
--hash=sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c \
--hash=sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1 \
@@ -76,27 +101,44 @@ brotli==1.1.0 \
--hash=sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460 \
--hash=sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751 \
--hash=sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9 \
+ --hash=sha256:a7e53012d2853a07a4a79c00643832161a910674a893d296c9f1259859a289d2 \
+ --hash=sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0 \
--hash=sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1 \
--hash=sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474 \
+ --hash=sha256:aea440a510e14e818e67bfc4027880e2fb500c2ccb20ab21c7a7c8b5b4703d75 \
+ --hash=sha256:af6fa6817889314555aede9a919612b23739395ce767fe7fcbea9a80bf140fe5 \
+ --hash=sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f \
--hash=sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2 \
+ --hash=sha256:c247dd99d39e0338a604f8c2b3bc7061d5c2e9e2ac7ba9cc1be5a69cb6cd832f \
+ --hash=sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb \
--hash=sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6 \
--hash=sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9 \
+ --hash=sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111 \
--hash=sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2 \
+ --hash=sha256:cb1dac1770878ade83f2ccdf7d25e494f05c9165f5246b46a621cc849341dc01 \
--hash=sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467 \
--hash=sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619 \
--hash=sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf \
--hash=sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408 \
--hash=sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579 \
--hash=sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84 \
+ --hash=sha256:d2b35ca2c7f81d173d2fadc2f4f31e88cc5f7a39ae5b6db5513cf3383b0e0ec7 \
+ --hash=sha256:d342778ef319e1026af243ed0a07c97acf3bad33b9f29e7ae6a1f68fd083e90c \
+ --hash=sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284 \
+ --hash=sha256:d7702622a8b40c49bffb46e1e3ba2e81268d5c04a34f460978c6b5517a34dd52 \
--hash=sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b \
--hash=sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59 \
--hash=sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752 \
+ --hash=sha256:e4fe605b917c70283db7dfe5ada75e04561479075761a0b3866c081d035b01c1 \
--hash=sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80 \
+ --hash=sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839 \
--hash=sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0 \
--hash=sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2 \
--hash=sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3 \
--hash=sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64 \
+ --hash=sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089 \
--hash=sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643 \
+ --hash=sha256:f31859074d57b4639318523d6ffdca586ace54271a73ad23ad021acd807eb14b \
--hash=sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e \
--hash=sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985 \
--hash=sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596 \
@@ -227,47 +269,45 @@ flask-cors==5.0.0 \
# via
# -r requirements.in
# locust
-gevent==23.9.1 \
- --hash=sha256:272cffdf535978d59c38ed837916dfd2b5d193be1e9e5dcc60a5f4d5025dd98a \
- --hash=sha256:2c7b5c9912378e5f5ccf180d1fdb1e83f42b71823483066eddbe10ef1a2fcaa2 \
- --hash=sha256:36a549d632c14684bcbbd3014a6ce2666c5f2a500f34d58d32df6c9ea38b6535 \
- --hash=sha256:4368f341a5f51611411ec3fc62426f52ac3d6d42eaee9ed0f9eebe715c80184e \
- --hash=sha256:43daf68496c03a35287b8b617f9f91e0e7c0d042aebcc060cadc3f049aadd653 \
- --hash=sha256:455e5ee8103f722b503fa45dedb04f3ffdec978c1524647f8ba72b4f08490af1 \
- --hash=sha256:45792c45d60f6ce3d19651d7fde0bc13e01b56bb4db60d3f32ab7d9ec467374c \
- --hash=sha256:4e24c2af9638d6c989caffc691a039d7c7022a31c0363da367c0d32ceb4a0648 \
- --hash=sha256:52b4abf28e837f1865a9bdeef58ff6afd07d1d888b70b6804557e7908032e599 \
- --hash=sha256:52e9f12cd1cda96603ce6b113d934f1aafb873e2c13182cf8e86d2c5c41982ea \
- --hash=sha256:5f3c781c84794926d853d6fb58554dc0dcc800ba25c41d42f6959c344b4db5a6 \
- --hash=sha256:62d121344f7465e3739989ad6b91f53a6ca9110518231553fe5846dbe1b4518f \
- --hash=sha256:65883ac026731ac112184680d1f0f1e39fa6f4389fd1fc0bf46cc1388e2599f9 \
- --hash=sha256:707904027d7130ff3e59ea387dddceedb133cc742b00b3ffe696d567147a9c9e \
- --hash=sha256:72c002235390d46f94938a96920d8856d4ffd9ddf62a303a0d7c118894097e34 \
- --hash=sha256:7532c17bc6c1cbac265e751b95000961715adef35a25d2b0b1813aa7263fb397 \
- --hash=sha256:78eebaf5e73ff91d34df48f4e35581ab4c84e22dd5338ef32714264063c57507 \
- --hash=sha256:7c1abc6f25f475adc33e5fc2dbcc26a732608ac5375d0d306228738a9ae14d3b \
- --hash=sha256:7c28e38dcde327c217fdafb9d5d17d3e772f636f35df15ffae2d933a5587addd \
- --hash=sha256:7ccf0fd378257cb77d91c116e15c99e533374a8153632c48a3ecae7f7f4f09fe \
- --hash=sha256:921dda1c0b84e3d3b1778efa362d61ed29e2b215b90f81d498eb4d8eafcd0b7a \
- --hash=sha256:a2898b7048771917d85a1d548fd378e8a7b2ca963db8e17c6d90c76b495e0e2b \
- --hash=sha256:a3c5e9b1f766a7a64833334a18539a362fb563f6c4682f9634dea72cbe24f771 \
- --hash=sha256:ada07076b380918829250201df1d016bdafb3acf352f35e5693b59dceee8dd2e \
- --hash=sha256:b101086f109168b23fa3586fccd1133494bdb97f86920a24dc0b23984dc30b69 \
- --hash=sha256:bf456bd6b992eb0e1e869e2fd0caf817f0253e55ca7977fd0e72d0336a8c1c6a \
- --hash=sha256:bf7af500da05363e66f122896012acb6e101a552682f2352b618e541c941a011 \
- --hash=sha256:c3e5d2fa532e4d3450595244de8ccf51f5721a05088813c1abd93ad274fe15e7 \
- --hash=sha256:c84d34256c243b0a53d4335ef0bc76c735873986d478c53073861a92566a8d71 \
- --hash=sha256:d163d59f1be5a4c4efcdd13c2177baaf24aadf721fdf2e1af9ee54a998d160f5 \
- --hash=sha256:d57737860bfc332b9b5aa438963986afe90f49645f6e053140cfa0fa1bdae1ae \
- --hash=sha256:dbb22a9bbd6a13e925815ce70b940d1578dbe5d4013f20d23e8a11eddf8d14a7 \
- --hash=sha256:dcb8612787a7f4626aa881ff15ff25439561a429f5b303048f0fca8a1c781c39 \
- --hash=sha256:dd6c32ab977ecf7c7b8c2611ed95fa4aaebd69b74bf08f4b4960ad516861517d \
- --hash=sha256:de350fde10efa87ea60d742901e1053eb2127ebd8b59a7d3b90597eb4e586599 \
- --hash=sha256:e1ead6863e596a8cc2a03e26a7a0981f84b6b3e956101135ff6d02df4d9a6b07 \
- --hash=sha256:ed7a048d3e526a5c1d55c44cb3bc06cfdc1947d06d45006cc4cf60dedc628904 \
- --hash=sha256:f632487c87866094546a74eefbca2c74c1d03638b715b6feb12e80120960185a \
- --hash=sha256:fae8d5b5b8fa2a8f63b39f5447168b02db10c888a3e387ed7af2bd1b8612e543 \
- --hash=sha256:fde6402c5432b835fbb7698f1c7f2809c8d6b2bd9d047ac1f5a7c1d5aa569303
+gevent==24.10.1 \
+ --hash=sha256:075c72450103c6d151c1b5c96dca0c991b61655e50e6947ab9e08a532788f976 \
+ --hash=sha256:0b6e3f64694bdf90c245bc3b17468542c9b222a087c8ae2f67850351c7ebb6dd \
+ --hash=sha256:1281474d088f8d708adb1e87d6acdde3d5f936ee1bc4722d75ac623f4e1ccdf7 \
+ --hash=sha256:14948bd7dae9784d83a2f7ebf51c70d3d53684723f4a78a5e4a368187bc9bccd \
+ --hash=sha256:16b96b0abe1473e27849800a1f3241ec05a09a06da14be33207a5e2b7a982711 \
+ --hash=sha256:28028532c286003da2fab4380f3c82ea4042147a5119518693578ef8aec36c84 \
+ --hash=sha256:2bf4ab090ea02e528d6c92e51be1a3797f65a5be325d896d7edb267d89ea34c8 \
+ --hash=sha256:34bdcaba413f3a0b2bd3432e41dd12dd3b915e19ae683e7cdb5a71514186980e \
+ --hash=sha256:3f14933aa07babdfee1b1552d5eb46573c422132f25692dbd72cef2583d8f34a \
+ --hash=sha256:40e16c27e9d114b5dd6f6e03b705ca849fd8563a291613d09f7822a5bcbfe4d2 \
+ --hash=sha256:415da2f25e835a1d0750b75dc883a570319a41051bd26b024a709227ec86a78b \
+ --hash=sha256:42bce9eae88b8cdad092a913ead9a4c81310708993120982c7539bd1eb1425cf \
+ --hash=sha256:477fc1a09dd61544d2c53b1cfc4775996e27cfb549a5eb00ed6db4175a34b046 \
+ --hash=sha256:539b833b6c8a729ed9d8010d14de1fe5a7eea7db51abdc585e95640d0c65ae54 \
+ --hash=sha256:5e46ff8f4dfe99f5c2fe74f5d68785bb116100f4d23e55e7b0479bff811a0819 \
+ --hash=sha256:63aacdc8067fc66c7d50e845e8d407c6027ff7d88aed13b761337855c0dae50d \
+ --hash=sha256:6b081a761919ba84f7f48b99622304404da32a9aec721ba8648dbcab147b07b9 \
+ --hash=sha256:6dd5a32e3f6cf8d317ef1e2ed9f380f957881d31b04f3a1b92d900d918a06c16 \
+ --hash=sha256:71eb75e8421d44f3abec0b79f85df51e68c59831156f5b25a8891201d3049b5e \
+ --hash=sha256:75b5e85a88b95b4dc62cac60bdf17bb6ab0ab99b44cbb5d1833218a209694f2e \
+ --hash=sha256:7bf86426936211876149d4b75980987042313a3548d466b04cd1713d1aab7d28 \
+ --hash=sha256:816834f9eef17864c87390ea8e6ccbf8aecab84b84c683ec5f2a95aea00a748e \
+ --hash=sha256:818e4b608cfdcb00a1ee7b19622e2bc31613fddc34747f0d16b611f16f6e3fb2 \
+ --hash=sha256:92d1e3afbec8cb4b7897be629aea524da237163adcf2a38d0795e6fd479699f6 \
+ --hash=sha256:9abd11884562ec108fe8271edcd942453ae0e4d68565c8616045cf40ba9ed8f6 \
+ --hash=sha256:9be9a2d3d9c0829077dc22ec1be2d906fd57204bb0a7810fcb3bcfc1521a8507 \
+ --hash=sha256:a1a480e5f2f109a2597dd2aab8b59606d79ef05e95fe84c9ac76461873e3ada0 \
+ --hash=sha256:b3dfea44933f6fc10e060b240ec1c25f3e94616d5a0c4f4146f6bf365d616bab \
+ --hash=sha256:bb15f6eff0a030f6e74e2fe44dff0884cb31489ad0e89402f3d5dfd2928f6e85 \
+ --hash=sha256:c4007fba5f95191c77dfad54fc70011f1c927fbef11d4ae5779796037436efe4 \
+ --hash=sha256:cab473b6fb7ea67827ce8ffbd769c00044a8e29c3e0de4254c1b95a0bb8ff186 \
+ --hash=sha256:cc2d9ee27126ab25b1d183841a5577ce2cf3aa15ab521cce4534f6d826d3e0f3 \
+ --hash=sha256:d7d13100489e984c75d7cc31c0ba99ffb295ae39ced392630711ab0b88b41e54 \
+ --hash=sha256:e161df2af05ffafa99937f33bf8a41c326e831889bd2aa556c0b07f45a46732f \
+ --hash=sha256:e51cb033d25cbf4b646d80adad3574cff70aa923d71f233953910115ebc9ba17 \
+ --hash=sha256:e6bf97a51fbda758011808436c18a17105fb2e75050eb521f79a0fa36c77f755 \
+ --hash=sha256:ed46d2a6b3e97b6449e061d21229f8c8a2719502579a107f094e4731a69b601c \
+ --hash=sha256:ee7ce02499eb684b2d377a294a6de136ed12158b500cebeb499dda1105ebcf0a
# via
# -r requirements.in
# geventhttpclient
@@ -382,64 +422,80 @@ geventhttpclient==2.0.11 \
--hash=sha256:f509176bc7754b1181375a25ec6909425a5997e58c98ea29a36fe8b6a376852f \
--hash=sha256:f5d73be013a7a2a357eb27d18e5990c773365f63f50a43eaf357d6efb1fd46a6
# via locust
-greenlet==3.0.1 \
- --hash=sha256:0a02d259510b3630f330c86557331a3b0e0c79dac3d166e449a39363beaae174 \
- --hash=sha256:0b6f9f8ca7093fd4433472fd99b5650f8a26dcd8ba410e14094c1e44cd3ceddd \
- --hash=sha256:100f78a29707ca1525ea47388cec8a049405147719f47ebf3895e7509c6446aa \
- --hash=sha256:1757936efea16e3f03db20efd0cd50a1c86b06734f9f7338a90c4ba85ec2ad5a \
- --hash=sha256:19075157a10055759066854a973b3d1325d964d498a805bb68a1f9af4aaef8ec \
- --hash=sha256:19bbdf1cce0346ef7341705d71e2ecf6f41a35c311137f29b8a2dc2341374565 \
- --hash=sha256:20107edf7c2c3644c67c12205dc60b1bb11d26b2610b276f97d666110d1b511d \
- --hash=sha256:22f79120a24aeeae2b4471c711dcf4f8c736a2bb2fabad2a67ac9a55ea72523c \
- --hash=sha256:2847e5d7beedb8d614186962c3d774d40d3374d580d2cbdab7f184580a39d234 \
- --hash=sha256:28e89e232c7593d33cac35425b58950789962011cc274aa43ef8865f2e11f46d \
- --hash=sha256:329c5a2e5a0ee942f2992c5e3ff40be03e75f745f48847f118a3cfece7a28546 \
- --hash=sha256:337322096d92808f76ad26061a8f5fccb22b0809bea39212cd6c406f6a7060d2 \
- --hash=sha256:3fcc780ae8edbb1d050d920ab44790201f027d59fdbd21362340a85c79066a74 \
- --hash=sha256:41bdeeb552d814bcd7fb52172b304898a35818107cc8778b5101423c9017b3de \
- --hash=sha256:4eddd98afc726f8aee1948858aed9e6feeb1758889dfd869072d4465973f6bfd \
- --hash=sha256:52e93b28db27ae7d208748f45d2db8a7b6a380e0d703f099c949d0f0d80b70e9 \
- --hash=sha256:55d62807f1c5a1682075c62436702aaba941daa316e9161e4b6ccebbbf38bda3 \
- --hash=sha256:5805e71e5b570d490938d55552f5a9e10f477c19400c38bf1d5190d760691846 \
- --hash=sha256:599daf06ea59bfedbec564b1692b0166a0045f32b6f0933b0dd4df59a854caf2 \
- --hash=sha256:60d5772e8195f4e9ebf74046a9121bbb90090f6550f81d8956a05387ba139353 \
- --hash=sha256:696d8e7d82398e810f2b3622b24e87906763b6ebfd90e361e88eb85b0e554dc8 \
- --hash=sha256:6e6061bf1e9565c29002e3c601cf68569c450be7fc3f7336671af7ddb4657166 \
- --hash=sha256:80ac992f25d10aaebe1ee15df45ca0d7571d0f70b645c08ec68733fb7a020206 \
- --hash=sha256:816bd9488a94cba78d93e1abb58000e8266fa9cc2aa9ccdd6eb0696acb24005b \
- --hash=sha256:85d2b77e7c9382f004b41d9c72c85537fac834fb141b0296942d52bf03fe4a3d \
- --hash=sha256:87c8ceb0cf8a5a51b8008b643844b7f4a8264a2c13fcbcd8a8316161725383fe \
- --hash=sha256:89ee2e967bd7ff85d84a2de09df10e021c9b38c7d91dead95b406ed6350c6997 \
- --hash=sha256:8bef097455dea90ffe855286926ae02d8faa335ed8e4067326257cb571fc1445 \
- --hash=sha256:8d11ebbd679e927593978aa44c10fc2092bc454b7d13fdc958d3e9d508aba7d0 \
- --hash=sha256:91e6c7db42638dc45cf2e13c73be16bf83179f7859b07cfc139518941320be96 \
- --hash=sha256:97e7ac860d64e2dcba5c5944cfc8fa9ea185cd84061c623536154d5a89237884 \
- --hash=sha256:990066bff27c4fcf3b69382b86f4c99b3652bab2a7e685d968cd4d0cfc6f67c6 \
- --hash=sha256:9fbc5b8f3dfe24784cee8ce0be3da2d8a79e46a276593db6868382d9c50d97b1 \
- --hash=sha256:ac4a39d1abae48184d420aa8e5e63efd1b75c8444dd95daa3e03f6c6310e9619 \
- --hash=sha256:b2c02d2ad98116e914d4f3155ffc905fd0c025d901ead3f6ed07385e19122c94 \
- --hash=sha256:b2d3337dcfaa99698aa2377c81c9ca72fcd89c07e7eb62ece3f23a3fe89b2ce4 \
- --hash=sha256:b489c36d1327868d207002391f662a1d163bdc8daf10ab2e5f6e41b9b96de3b1 \
- --hash=sha256:b641161c302efbb860ae6b081f406839a8b7d5573f20a455539823802c655f63 \
- --hash=sha256:b8ba29306c5de7717b5761b9ea74f9c72b9e2b834e24aa984da99cbfc70157fd \
- --hash=sha256:b9934adbd0f6e476f0ecff3c94626529f344f57b38c9a541f87098710b18af0a \
- --hash=sha256:ce85c43ae54845272f6f9cd8320d034d7a946e9773c693b27d620edec825e376 \
- --hash=sha256:cf868e08690cb89360eebc73ba4be7fb461cfbc6168dd88e2fbbe6f31812cd57 \
- --hash=sha256:d2905ce1df400360463c772b55d8e2518d0e488a87cdea13dd2c71dcb2a1fa16 \
- --hash=sha256:d57e20ba591727da0c230ab2c3f200ac9d6d333860d85348816e1dca4cc4792e \
- --hash=sha256:d6a8c9d4f8692917a3dc7eb25a6fb337bff86909febe2f793ec1928cd97bedfc \
- --hash=sha256:d923ff276f1c1f9680d32832f8d6c040fe9306cbfb5d161b0911e9634be9ef0a \
- --hash=sha256:daa7197b43c707462f06d2c693ffdbb5991cbb8b80b5b984007de431493a319c \
- --hash=sha256:dbd4c177afb8a8d9ba348d925b0b67246147af806f0b104af4d24f144d461cd5 \
- --hash=sha256:dc4d815b794fd8868c4d67602692c21bf5293a75e4b607bb92a11e821e2b859a \
- --hash=sha256:e9d21aaa84557d64209af04ff48e0ad5e28c5cca67ce43444e939579d085da72 \
- --hash=sha256:ea6b8aa9e08eea388c5f7a276fabb1d4b6b9d6e4ceb12cc477c3d352001768a9 \
- --hash=sha256:eabe7090db68c981fca689299c2d116400b553f4b713266b130cfc9e2aa9c5a9 \
- --hash=sha256:f2f6d303f3dee132b322a14cd8765287b8f86cdc10d2cb6a6fae234ea488888e \
- --hash=sha256:f33f3258aae89da191c6ebaa3bc517c6c4cbc9b9f689e5d8452f7aedbb913fa8 \
- --hash=sha256:f7bfb769f7efa0eefcd039dd19d843a4fbfbac52f1878b1da2ed5793ec9b1a65 \
- --hash=sha256:f89e21afe925fcfa655965ca8ea10f24773a1791400989ff32f467badfe4a064 \
- --hash=sha256:fa24255ae3c0ab67e613556375a4341af04a084bd58764731972bcbc8baeba36
+greenlet==3.1.1 \
+ --hash=sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e \
+ --hash=sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7 \
+ --hash=sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01 \
+ --hash=sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1 \
+ --hash=sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159 \
+ --hash=sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563 \
+ --hash=sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83 \
+ --hash=sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9 \
+ --hash=sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395 \
+ --hash=sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa \
+ --hash=sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942 \
+ --hash=sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1 \
+ --hash=sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441 \
+ --hash=sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22 \
+ --hash=sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9 \
+ --hash=sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0 \
+ --hash=sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba \
+ --hash=sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3 \
+ --hash=sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1 \
+ --hash=sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6 \
+ --hash=sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291 \
+ --hash=sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39 \
+ --hash=sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d \
+ --hash=sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467 \
+ --hash=sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475 \
+ --hash=sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef \
+ --hash=sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c \
+ --hash=sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511 \
+ --hash=sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c \
+ --hash=sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822 \
+ --hash=sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a \
+ --hash=sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8 \
+ --hash=sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d \
+ --hash=sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01 \
+ --hash=sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145 \
+ --hash=sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80 \
+ --hash=sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13 \
+ --hash=sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e \
+ --hash=sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b \
+ --hash=sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1 \
+ --hash=sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef \
+ --hash=sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc \
+ --hash=sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff \
+ --hash=sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120 \
+ --hash=sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437 \
+ --hash=sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd \
+ --hash=sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981 \
+ --hash=sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36 \
+ --hash=sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a \
+ --hash=sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798 \
+ --hash=sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7 \
+ --hash=sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761 \
+ --hash=sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0 \
+ --hash=sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e \
+ --hash=sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af \
+ --hash=sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa \
+ --hash=sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c \
+ --hash=sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42 \
+ --hash=sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e \
+ --hash=sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81 \
+ --hash=sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e \
+ --hash=sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617 \
+ --hash=sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc \
+ --hash=sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de \
+ --hash=sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111 \
+ --hash=sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383 \
+ --hash=sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70 \
+ --hash=sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6 \
+ --hash=sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4 \
+ --hash=sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011 \
+ --hash=sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803 \
+ --hash=sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79 \
+ --hash=sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f
# via gevent
idna==3.7 \
--hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \
@@ -451,9 +507,9 @@ itsdangerous==2.1.2 \
--hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \
--hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a
# via flask
-jinja2==3.1.4 \
- --hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \
- --hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d
+jinja2==3.1.5 \
+ --hash=sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb \
+ --hash=sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb
# via
# -r requirements.in
# flask
@@ -801,9 +857,9 @@ urllib3==1.26.19 \
# -r requirements.in
# botocore
# requests
-werkzeug==3.0.3 \
- --hash=sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18 \
- --hash=sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8
+werkzeug==3.0.6 \
+ --hash=sha256:1bc0c2310d2fbb07b1dd1105eba2f7af72f322e1e455f2f93c993bee8c8a5f17 \
+ --hash=sha256:a8dd59d4de28ca70471a34cba79bed5f7ef2e036a76b3ab0835474246eb41f8d
# via
# -r requirements.in
# flask
diff --git a/ops/ansible/roles/bfd-pipeline/templates/bfd-pipeline-service.sh.j2 b/ops/ansible/roles/bfd-pipeline/templates/bfd-pipeline-service.sh.j2
index 7d4c1476ee..1c36fde164 100644
--- a/ops/ansible/roles/bfd-pipeline/templates/bfd-pipeline-service.sh.j2
+++ b/ops/ansible/roles/bfd-pipeline/templates/bfd-pipeline-service.sh.j2
@@ -5,8 +5,8 @@
# Force UTC time
export TZ=UTC
-export BFD_CCW_JOB_ENABLED={{ enabled if pipeline_instance_type == 'ccw' else 'false' }} {# derived from terraform control plane #}{{ '\n' }}
-export BFD_RDA_JOB_ENABLED={{ enabled if pipeline_instance_type == 'rda' else 'false' }} {# derived from terraform control plane #}{{ '\n' }}
+export BFD_CCW_JOB_ENABLED={{ job_enabled if pipeline_instance_type == 'ccw' else 'false' }} {# derived from terraform control plane #}{{ '\n' }}
+export BFD_RDA_JOB_ENABLED={{ job_enabled if pipeline_instance_type == 'rda' else 'false' }} {# derived from terraform control plane #}{{ '\n' }}
export BFD_DB_URL='{{ db_url }}'
diff --git a/ops/terraform/env/mgmt/github-actions-iam.tf b/ops/terraform/env/mgmt/github-actions-iam.tf
index 02aa145ebb..e34af0ac03 100644
--- a/ops/terraform/env/mgmt/github-actions-iam.tf
+++ b/ops/terraform/env/mgmt/github-actions-iam.tf
@@ -82,6 +82,7 @@ resource "aws_iam_policy" "github_actions_ecr" {
"arn:aws:ecr:us-east-1:${local.account_id}:repository/bfd-server",
"arn:aws:ecr:us-east-1:${local.account_id}:repository/bfd-pipeline-app",
"arn:aws:ecr:us-east-1:${local.account_id}:repository/bfd-mgmt-eft-sftp-outbound-transfer-lambda",
+ "arn:aws:ecr:us-east-1:${local.account_id}:repository/bfd-mgmt-pipeline-ccw-manifests-verifier-lambda",
]
Sid = "AllowPushPull"
},
diff --git a/ops/terraform/services/base/values/ephemeral.yaml b/ops/terraform/services/base/values/ephemeral.yaml
index 7cad04b131..a7a2927fdd 100644
--- a/ops/terraform/services/base/values/ephemeral.yaml
+++ b/ops/terraform/services/base/values/ephemeral.yaml
@@ -24,6 +24,8 @@
/bfd/${env}/pipeline/nonsensitive/ccw/instance_type: c6a.4xlarge
/bfd/${env}/pipeline/nonsensitive/ccw/rif_thread_multiple_claims: "25"
/bfd/${env}/pipeline/nonsensitive/ccw/slis_repeater_lambda_invoke_rate: 15 minutes
+/bfd/${env}/pipeline/nonsensitive/ccw/slo/weekend_data_availability/verifier/enabled: false
+/bfd/${env}/pipeline/nonsensitive/ccw/slo/weekend_data_availability/verifier/alert_topic: UNDEFINED
/bfd/${env}/pipeline/nonsensitive/rda/grpc/inprocess_server/mode: UNDEFINED
/bfd/${env}/pipeline/nonsensitive/rda/grpc/inprocess_server/s3/region: us-east-1
/bfd/${env}/pipeline/nonsensitive/rda/grpc/inprocess_server/s3/bucket: UNDEFINED
diff --git a/ops/terraform/services/base/values/prod-sbx.yaml b/ops/terraform/services/base/values/prod-sbx.yaml
index e5676c60a3..825d431f77 100644
--- a/ops/terraform/services/base/values/prod-sbx.yaml
+++ b/ops/terraform/services/base/values/prod-sbx.yaml
@@ -93,6 +93,8 @@
/bfd/${env}/pipeline/nonsensitive/ccw/new_relic/app_name: BFD Pipeline ccw (${env})
/bfd/${env}/pipeline/nonsensitive/ccw/rif_thread_multiple_claims: "25"
/bfd/${env}/pipeline/nonsensitive/ccw/slis_repeater_lambda_invoke_rate: 1 minutes
+/bfd/${env}/pipeline/nonsensitive/ccw/slo/weekend_data_availability/verifier/enabled: true
+/bfd/${env}/pipeline/nonsensitive/ccw/slo/weekend_data_availability/verifier/alert_topics: bfd-prod-sbx-cloudwatch-alarms-slack-bfd-warnings
/bfd/${env}/pipeline/nonsensitive/rda/grpc/max_idle_seconds: "600"
/bfd/${env}/pipeline/nonsensitive/rda/grpc/server_type: InProcess
/bfd/${env}/pipeline/nonsensitive/rda/grpc/inprocess_server/mode: S3
diff --git a/ops/terraform/services/base/values/prod.yaml b/ops/terraform/services/base/values/prod.yaml
index 12af7fcd4a..a74f4c41a4 100644
--- a/ops/terraform/services/base/values/prod.yaml
+++ b/ops/terraform/services/base/values/prod.yaml
@@ -140,6 +140,8 @@
/bfd/${env}/pipeline/nonsensitive/ccw/new_relic/app_name: BFD Pipeline ccw (${env})
/bfd/${env}/pipeline/nonsensitive/ccw/rif_thread_multiple_claims: "25"
/bfd/${env}/pipeline/nonsensitive/ccw/slis_repeater_lambda_invoke_rate: 1 minutes
+/bfd/${env}/pipeline/nonsensitive/ccw/slo/weekend_data_availability/verifier/enabled: true
+/bfd/${env}/pipeline/nonsensitive/ccw/slo/weekend_data_availability/verifier/alert_topics: bfd-prod-cloudwatch-alarms,bfd-prod-cloudwatch-alarms-slack-bfd-alerts
/bfd/${env}/pipeline/nonsensitive/rda/grpc/max_idle_seconds: "600"
/bfd/${env}/pipeline/nonsensitive/rda/grpc/server_type: Remote
/bfd/${env}/pipeline/nonsensitive/rda/grpc/inprocess_server/mode: UNDEFINED
diff --git a/ops/terraform/services/base/values/test.yaml b/ops/terraform/services/base/values/test.yaml
index a6eff04eb0..e3d73ef88b 100644
--- a/ops/terraform/services/base/values/test.yaml
+++ b/ops/terraform/services/base/values/test.yaml
@@ -142,6 +142,8 @@
/bfd/${env}/pipeline/nonsensitive/ccw/new_relic/app_name: BFD Pipeline ccw (${env})
/bfd/${env}/pipeline/nonsensitive/ccw/rif_thread_multiple_claims: "25"
/bfd/${env}/pipeline/nonsensitive/ccw/slis_repeater_lambda_invoke_rate: 1 minutes
+/bfd/${env}/pipeline/nonsensitive/ccw/slo/weekend_data_availability/verifier/enabled: true
+/bfd/${env}/pipeline/nonsensitive/ccw/slo/weekend_data_availability/verifier/alert_topics: bfd-test-cloudwatch-alarms-slack-bfd-test
/bfd/${env}/pipeline/nonsensitive/rda/grpc/max_idle_seconds: "600"
/bfd/${env}/pipeline/nonsensitive/rda/grpc/server_type: Remote
/bfd/${env}/pipeline/nonsensitive/rda/grpc/inprocess_server/mode: UNDEFINED
diff --git a/ops/terraform/services/pipeline/README.md b/ops/terraform/services/pipeline/README.md
index 4047284afa..f9d61b29fa 100644
--- a/ops/terraform/services/pipeline/README.md
+++ b/ops/terraform/services/pipeline/README.md
@@ -89,6 +89,7 @@
| [aws_sns_topic.bfd_notices_slack_alarm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/sns_topic) | data source |
| [aws_sns_topic.bfd_test_slack_alarm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/sns_topic) | data source |
| [aws_sns_topic.ok](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/sns_topic) | data source |
+| [aws_ssm_parameter.verifier_enabled](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
| [aws_ssm_parameters_by_path.nonsensitive_ccw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameters_by_path) | data source |
| [aws_ssm_parameters_by_path.nonsensitive_common](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameters_by_path) | data source |
| [aws_ssm_parameters_by_path.nonsensitive_rda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameters_by_path) | data source |
diff --git a/ops/terraform/services/pipeline/data-sources.tf b/ops/terraform/services/pipeline/data-sources.tf
index 7756425d32..bff771e89e 100644
--- a/ops/terraform/services/pipeline/data-sources.tf
+++ b/ops/terraform/services/pipeline/data-sources.tf
@@ -114,6 +114,10 @@ data "aws_ssm_parameters_by_path" "nonsensitive_rda" {
path = "/bfd/${local.env}/${local.service}/nonsensitive/rda"
}
+data "aws_ssm_parameter" "verifier_enabled" {
+ name = "/bfd/${local.env}/${local.service}/nonsensitive/ccw/slo/weekend_data_availability/verifier/enabled"
+}
+
# TODO: this needs to be defined in common
data "aws_sns_topic" "alarm" {
count = local.is_prod ? 1 : 0
diff --git a/ops/terraform/services/pipeline/main.tf b/ops/terraform/services/pipeline/main.tf
index 569b9e46c9..6ebe6f5f61 100644
--- a/ops/terraform/services/pipeline/main.tf
+++ b/ops/terraform/services/pipeline/main.tf
@@ -152,6 +152,8 @@ locals {
for k, v in local.pipeline_variant_configs : k => local.pipeline_variant_configs[k]
if local.pipeline_variant_configs[k].enabled && k == "ccw"
}
+
+ ccw_manifests_verifier_enabled = tobool(nonsensitive(data.aws_ssm_parameter.verifier_enabled.value))
}
# TODO: Determine if resource could be consolidated with RDA variant if RDA becomes on-demand
@@ -447,3 +449,16 @@ module "bfd_pipeline_scheduler" {
name = aws_autoscaling_group.this["ccw"].name
}
}
+
+module "bfd_pipeline_ccw_manifests_verifier" {
+ count = local.pipeline_variant_configs.ccw.enabled && local.ccw_manifests_verifier_enabled ? 1 : 0
+
+ source = "./modules/bfd_pipeline_ccw_manifests_verifier"
+
+ db_cluster_identifier = local.db_cluster_identifier
+ etl_bucket_id = aws_s3_bucket.this.id
+ vpc_name = local.vpc_name
+ bfd_version = local.latest_bfd_release
+ kms_config_key_alias = local.nonsensitive_common_config["kms_config_key_alias"]
+ kms_key_alias = local.kms_key_id
+}
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/.terraform-docs.yml b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/.terraform-docs.yml
new file mode 100644
index 0000000000..eb6117e251
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/.terraform-docs.yml
@@ -0,0 +1,60 @@
+formatter: markdown table
+sections:
+ show:
+ - requirements
+ - inputs
+ - resources
+ - outputs
+ - data-sources
+
+# this `content` string is implemented as a golang template https://pkg.go.dev/text/template
+# updates here correspond to `{{ .Content }}` in `output.template` setting below
+content: |-
+ {{ .Requirements }}
+
+
+
+ {{ .Inputs }}
+
+
+
+ {{ .Resources }}
+
+
+
+ {{ .Outputs }}
+
+output:
+ file: README.md
+ mode: inject
+ template: |-
+
+
+ {{ .Content }}
+
+
+sort:
+ enabled: true
+ by: required
+
+settings:
+ indent: 2
+ default: true
+ required: true
+ type: true
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/README.md b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/README.md
new file mode 100644
index 0000000000..4961845a79
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/README.md
@@ -0,0 +1,89 @@
+# `bfd_pipeline_ccw_manifests_verifier` Module
+
+This sub-module contains the Terraform IaC and Python Lambda source code for the per-environment `ccw_manifests_verifier` Lambda. This Lambda runs based on an EventBridge `cron` schedule that is configured to run the Lambda every Monday at 9 AM ET. The Lambda will then reconcile the state of CCW dataset manifests in the environment's ETL S3 Bucket prefixed with `Incoming/` and `Synthetic/Incoming/` and if there are any manifests that are not in the database as having been processed or they are not in the database at all the Lambda will send an alert to a configured SNS Topic (for `prod` this SNS Topic will send notifications to Splunk On Call, triggering an Incident).
+
+This solution implements the `Weekend data load availability` SLO.
+
+
+
+## Requirements
+
+No requirements.
+
+
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [bfd\_version](#input\_bfd\_version) | BFD Lambda version to deploy | `string` | n/a | yes |
+| [db\_cluster\_identifier](#input\_db\_cluster\_identifier) | Cluster ID of the target database | `string` | n/a | yes |
+| [etl\_bucket\_id](#input\_etl\_bucket\_id) | Bucket ID of the Pipeline ETL S3 Bucket | `string` | n/a | yes |
+| [kms\_config\_key\_alias](#input\_kms\_config\_key\_alias) | Alias/ID of the config CMK | `string` | n/a | yes |
+| [kms\_key\_alias](#input\_kms\_key\_alias) | Alias/ID of the main CMK | `string` | n/a | yes |
+| [vpc\_name](#input\_vpc\_name) | Name of the current VPC | `string` | n/a | yes |
+
+
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [aws_iam_policy.kms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
+| [aws_iam_policy.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
+| [aws_iam_policy.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
+| [aws_iam_policy.scheduler_invoke_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
+| [aws_iam_policy.sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
+| [aws_iam_policy.ssm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
+| [aws_iam_role.scheduler_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
+| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
+| [aws_iam_role_policy_attachment.invoke_lambda_policy_to_scheduler_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
+| [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
+| [aws_lambda_function.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource |
+| [aws_scheduler_schedule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/scheduler_schedule) | resource |
+| [aws_scheduler_schedule_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/scheduler_schedule_group) | resource |
+| [aws_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
+| [aws_security_group_rule.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
+| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
+| [aws_ecr_image.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_image) | data source |
+| [aws_ecr_repository.ecr](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_repository) | data source |
+| [aws_iam_policy_document.kms_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.lambda_role_assume_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.logs_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.rds_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.scheduler_invoke_lambda_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.scheduler_role_assume_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.sns_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.ssm_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_kms_key.cmk](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_key) | data source |
+| [aws_kms_key.config_cmk](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_key) | data source |
+| [aws_rds_cluster.cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/rds_cluster) | data source |
+| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
+| [aws_security_group.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/security_group) | data source |
+| [aws_sns_topic.alert_topic](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/sns_topic) | data source |
+| [aws_ssm_parameter.alert_topic](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
+| [aws_subnets.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source |
+| [aws_vpc.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source |
+
+
+
+## Outputs
+
+No outputs.
+
\ No newline at end of file
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/data-sources.tf b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/data-sources.tf
new file mode 100644
index 0000000000..d3da5a2455
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/data-sources.tf
@@ -0,0 +1,63 @@
+data "aws_region" "current" {}
+
+data "aws_caller_identity" "current" {}
+
+data "aws_vpc" "main" {
+ filter {
+ name = "tag:Name"
+ values = [var.vpc_name]
+ }
+}
+
+data "aws_kms_key" "cmk" {
+ key_id = var.kms_key_alias
+}
+
+data "aws_kms_key" "config_cmk" {
+ key_id = var.kms_config_key_alias
+}
+
+data "aws_ecr_repository" "ecr" {
+ name = "bfd-mgmt-${local.service}-${local.lambda_name}-lambda"
+}
+
+data "aws_ecr_image" "this" {
+ repository_name = data.aws_ecr_repository.ecr.name
+ image_tag = var.bfd_version
+}
+
+data "aws_subnets" "main" {
+ filter {
+ name = "vpc-id"
+ values = [data.aws_vpc.main.id]
+ }
+ filter {
+ name = "tag:Layer"
+ values = [local.layer]
+ }
+}
+
+data "aws_security_group" "rds" {
+ vpc_id = data.aws_vpc.main.id
+ filter {
+ name = "tag:Name"
+ values = [var.db_cluster_identifier]
+ }
+}
+
+data "aws_rds_cluster" "cluster" {
+ cluster_identifier = var.db_cluster_identifier
+}
+
+data "aws_ssm_parameter" "alert_topics" {
+ name = "/bfd/${local.env}/${local.service}/nonsensitive/ccw/slo/weekend_data_availability/verifier/alert_topics"
+}
+
+data "aws_sns_topic" "alert_topic" {
+ count = length(local.alert_topics)
+ name = local.alert_topics[count.index]
+}
+
+data "aws_s3_bucket" "etl_bucket" {
+ bucket = var.etl_bucket_id
+}
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/iam.tf b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/iam.tf
new file mode 100644
index 0000000000..97d2b11a80
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/iam.tf
@@ -0,0 +1,188 @@
+data "aws_iam_policy_document" "logs_policy_doc" {
+ statement {
+ sid = "AllowLogGroupCreate"
+ actions = ["logs:CreateLogGroup"]
+ resources = ["arn:aws:logs:${local.region}:${local.account_id}:*"]
+ }
+
+ statement {
+ sid = "AllowLogStreamControl"
+ actions = ["logs:CreateLogStream", "logs:PutLogEvents"]
+ resources = [
+ "arn:aws:logs:${local.region}:${local.account_id}:log-group:/aws/lambda/${local.lambda_full_name}:*"
+ ]
+ }
+}
+
+resource "aws_iam_policy" "logs" {
+ name = "${local.lambda_full_name}-logs"
+ description = join("", [
+ "Permissions for the ${local.lambda_full_name} Lambda to write to its corresponding ",
+ "CloudWatch Log Group and Log Stream",
+ ])
+
+ policy = data.aws_iam_policy_document.logs_policy_doc.json
+}
+
+data "aws_iam_policy_document" "ssm_policy_doc" {
+ statement {
+ actions = ["ssm:GetParameter"]
+ resources = [
+ "arn:aws:ssm:${local.region}:${local.account_id}:parameter/bfd/${local.env}/pipeline/sensitive/db/username",
+ "arn:aws:ssm:${local.region}:${local.account_id}:parameter/bfd/${local.env}/pipeline/sensitive/db/password"
+ ]
+ }
+}
+
+resource "aws_iam_policy" "ssm" {
+ name = "${local.lambda_full_name}-ssm"
+ description = "Permissions for the ${local.lambda_full_name} Lambda to get relevant SSM parameters"
+ policy = data.aws_iam_policy_document.ssm_policy_doc.json
+}
+
+data "aws_iam_policy_document" "rds_policy_doc" {
+ statement {
+ sid = "AllowDescribeCluster"
+ actions = ["rds:DescribeDBClusters"]
+ resources = [data.aws_rds_cluster.cluster.arn]
+ }
+}
+
+resource "aws_iam_policy" "rds" {
+ name = "${local.lambda_full_name}-rds"
+ description = "Permissions for the ${local.lambda_full_name} Lambda to describe the ${data.aws_rds_cluster.cluster.cluster_identifier} cluster"
+ policy = data.aws_iam_policy_document.rds_policy_doc.json
+}
+
+data "aws_iam_policy_document" "kms_policy_doc" {
+ statement {
+ sid = "AllowDecryptionOfConfigKeys"
+ actions = ["kms:Decrypt"]
+ resources = local.kms_config_key_arns
+ }
+
+ statement {
+ sid = "AllowEncryptionAndDecryptionOfMasterKeys"
+ actions = [
+ "kms:Encrypt",
+ "kms:Decrypt",
+ "kms:ReEncrypt*",
+ "kms:GenerateDataKey*",
+ "kms:DescribeKey",
+ ]
+ resources = [local.kms_key_id]
+ }
+}
+
+resource "aws_iam_policy" "kms" {
+ name = "${local.lambda_full_name}-kms"
+ description = join("", [
+ "Permissions for the ${local.lambda_full_name} Lambda to decrypt config KMS keys and encrypt ",
+ "and decrypt master KMS keys for ${local.env}"
+ ])
+
+ policy = data.aws_iam_policy_document.kms_policy_doc.json
+}
+
+data "aws_iam_policy_document" "s3_policy_doc" {
+ statement {
+ actions = ["s3:ListBucket"]
+ resources = [data.aws_s3_bucket.etl_bucket.arn]
+ }
+}
+
+resource "aws_iam_policy" "s3" {
+ name = "${local.lambda_full_name}-s3"
+ description = "Permissions for the ${local.lambda_full_name} Lambda to list objects in the ${var.etl_bucket_id} Bucket"
+ policy = data.aws_iam_policy_document.s3_policy_doc.json
+}
+
+data "aws_iam_policy_document" "sns_policy_doc" {
+ statement {
+ sid = "AllowPublish"
+ actions = ["SNS:Publish"]
+ resources = data.aws_sns_topic.alert_topic[*].arn
+ }
+}
+
+resource "aws_iam_policy" "sns" {
+ name = "${local.lambda_full_name}-sns"
+ description = "Permissions for the ${local.lambda_full_name} Lambda to publish to the configured SNS Topic(s)"
+ policy = data.aws_iam_policy_document.sns_policy_doc.json
+}
+
+data "aws_iam_policy_document" "lambda_role_assume_policy_doc" {
+ statement {
+ actions = ["sts:AssumeRole"]
+ principals {
+ type = "Service"
+ identifiers = ["lambda.amazonaws.com"]
+ }
+ }
+}
+
+resource "aws_iam_role" "this" {
+ name = local.lambda_full_name
+ path = "/"
+ description = "Role for ${local.lambda_full_name} Lambda"
+ assume_role_policy = data.aws_iam_policy_document.lambda_role_assume_policy_doc.json
+ force_detach_policies = true
+}
+
+resource "aws_iam_role_policy_attachment" "this" {
+ for_each = {
+ logs = aws_iam_policy.logs.arn,
+ ssm = aws_iam_policy.ssm.arn,
+ rds = aws_iam_policy.rds.arn
+ kms = aws_iam_policy.kms.arn,
+ s3 = aws_iam_policy.s3.arn,
+ sns = aws_iam_policy.sns.arn,
+ vpc = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
+ }
+
+ role = aws_iam_role.this.name
+ policy_arn = each.value
+}
+
+data "aws_iam_policy_document" "scheduler_invoke_lambda_policy_doc" {
+ statement {
+ actions = ["lambda:InvokeFunction"]
+ resources = [aws_lambda_function.this.arn]
+ }
+}
+
+resource "aws_iam_policy" "scheduler_invoke_lambda" {
+ name = "${local.lambda_full_name}-scheduler-assumee-allow-lambda-invoke"
+ description = join("", [
+ "Permissions for EventBridge Scheduler assumed role to invoke the ",
+ "${local.lambda_full_name} Lambda"
+ ])
+
+ policy = data.aws_iam_policy_document.scheduler_invoke_lambda_policy_doc.json
+}
+
+data "aws_iam_policy_document" "scheduler_role_assume_policy_doc" {
+ statement {
+ actions = ["sts:AssumeRole"]
+ principals {
+ type = "Service"
+ identifiers = ["scheduler.amazonaws.com"]
+ }
+ }
+}
+
+resource "aws_iam_role" "scheduler_assume_role" {
+ name = "${local.lambda_full_name}-scheduler-assumee"
+ path = "/"
+ description = join("", [
+ "Role for EventBridge Scheduler allowing permissions to invoke the ",
+ "${local.lambda_full_name} Lambda"
+ ])
+ assume_role_policy = data.aws_iam_policy_document.scheduler_role_assume_policy_doc.json
+ force_detach_policies = true
+}
+
+resource "aws_iam_role_policy_attachment" "invoke_lambda_policy_to_scheduler_assume_role" {
+ role = aws_iam_role.scheduler_assume_role.name
+ policy_arn = aws_iam_policy.scheduler_invoke_lambda.arn
+}
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/.python-version b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/.python-version
new file mode 100644
index 0000000000..24ee5b1be9
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/.python-version
@@ -0,0 +1 @@
+3.13
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/Dockerfile b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/Dockerfile
new file mode 100644
index 0000000000..afda8163a5
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/Dockerfile
@@ -0,0 +1,28 @@
+FROM ghcr.io/astral-sh/uv:0.5.22 AS uv
+# First, bundle the dependencies into the task root.
+FROM public.ecr.aws/lambda/python:3.13-arm64 AS builder
+# Enable bytecode compilation, to improve cold-start performance.
+ENV UV_COMPILE_BYTECODE=1
+# Disable installer metadata, to create a deterministic layer.
+ENV UV_NO_INSTALLER_METADATA=1
+# Enable copy mode to support bind mount caching.
+ENV UV_LINK_MODE=copy
+# Bundle the dependencies into the Lambda task root via `uv pip install --target`.
+#
+# Omit any local packages (`--no-emit-workspace`) and development dependencies (`--no-dev`).
+# This ensures that the Docker layer cache is only invalidated when the `pyproject.toml` or `uv.lock`
+# files change, but remains robust to changes in the application code.
+COPY pyproject.toml .
+COPY uv.lock .
+RUN --mount=from=uv,source=/uv,target=/bin/uv \
+ --mount=type=cache,target=/root/.cache/uv \
+ uv export --frozen --no-emit-workspace --no-dev --no-editable -o requirements.txt && \
+ uv pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"
+
+FROM public.ecr.aws/lambda/python:3.13-arm64
+# Copy the runtime dependencies from the builder stage.
+COPY --from=builder ${LAMBDA_TASK_ROOT} ${LAMBDA_TASK_ROOT}
+# Copy the application code.
+COPY . ${LAMBDA_TASK_ROOT}/app
+CMD [ "app.ccw_manifests_verifier.handler" ]
+
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/Dockerfile.dockerignore b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/Dockerfile.dockerignore
new file mode 100644
index 0000000000..6c2bd56902
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/Dockerfile.dockerignore
@@ -0,0 +1,4 @@
+*
+!pyproject.toml
+!uv.lock
+!ccw_manifests_verifier.py
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/README.md b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/README.md
new file mode 100644
index 0000000000..68912196b8
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/README.md
@@ -0,0 +1,25 @@
+# `ccw-manifests-verifier` Lambda Source
+
+This subdirectory contains the Python source code for the `ccw-manifests-verifier` Lambda.
+
+## Environment Setup
+
+It is assumed you are using `pyright`/`pylance` for type-checking, `uv` for virtual environment and dependency management, and `ruff` for linting, formatting, and import sorting.
+
+1. Install `uv`:
+
+ ```bash
+ brew install uv
+ ```
+
+2. Setup Python 3.13 virtual environment:
+
+ ```bash
+ uv sync
+ ```
+
+3. Your virtual environment is now setup! By default, it is available under `.venv`; using VS Code, this Virtual Environment can be chosen using the `Python: Select Interpreter` command
+
+## Updating/managing dependencies
+
+See [`Managing dependencies`](https://docs.astral.sh/uv/concepts/projects/dependencies/) and [`Locking and syncing`](https://docs.astral.sh/uv/concepts/projects/sync/) in the `uv` docs for more information.
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/ccw_manifests_verifier.py b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/ccw_manifests_verifier.py
new file mode 100644
index 0000000000..69a8935292
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/ccw_manifests_verifier.py
@@ -0,0 +1,242 @@
+"""Source code for ccw-manifests-verifier Lambda.
+
+This Lambda verifies that all recently modified CCW manifests in S3 are marked as "COMPLETED" in the
+database. If any are not, this Lambda will send an alert to the provided alert SNS Topic (expected
+to be the Splunk On Call Topic in prod).
+"""
+
+import itertools
+import os
+from datetime import UTC, datetime, timedelta
+from typing import Annotated, Any
+
+import boto3
+import psycopg
+from aws_lambda_powertools import Logger
+from aws_lambda_powertools.utilities import parameters
+from aws_lambda_powertools.utilities.typing import LambdaContext
+from botocore.config import Config
+from psycopg.rows import dict_row
+from pydantic import BaseModel, Field, TypeAdapter
+
+REGION = os.environ.get("AWS_CURRENT_REGION", "us-east-1")
+BFD_ENVIRONMENT = os.environ.get("BFD_ENVIRONMENT", "")
+DB_CLUSTER_NAME = os.environ.get("DB_CLUSTER_NAME", "")
+ETL_BUCKET_ID = os.environ.get("ETL_BUCKET_ID", "")
+ALERT_TOPIC_ARNS = [arn.strip() for arn in os.environ.get("ALERT_TOPIC_ARNS", "").split(",")]
+BOTO_CONFIG = Config(
+ region_name=REGION,
+ # Instructs boto3 to retry upto 10 times using an exponential backoff
+ retries={
+ "total_max_attempts": 10,
+ "mode": "adaptive",
+ },
+)
+
+logger = Logger()
+
+
+class ManifestFilesResultModel(BaseModel):
+ """Pydantic model modeling columns returned from the s3_manifest_files database table."""
+
+ s3_key: str
+ status: str
+
+
+class SplunkOnCallNotificationModel(BaseModel):
+ """Pydantic model modeling the message that Splunk On Call expects from AWS alerts.
+
+ The Splunk On Call integration we use to send alerts from AWS expects that alerts originate from
+ CloudWatch Alarms. This is true for every alert except this one, so rather than installing
+ another integration we simply create a fake CloudWatch Alarm message. This is why the serialized
+ fields are named strangely and all but the "alert_message" field default to unusual values.
+ Additionally, this Lambda is mostly relevant for prod for which alerts will be sent to the
+ corresponding Splunk On Call Topic
+ """
+
+ alert_message: Annotated[str, Field(serialization_alias="NewStateReason")]
+ alert_description: Annotated[
+ str,
+ Field(
+ serialization_alias="AlarmDescription",
+ default_factory=lambda: (
+ "Pseudo-Alarm alert generated by the ccw-manifests-verifier that alerts when the "
+ f"{BFD_ENVIRONMENT} CCW Pipeline fails to load all available manifests over the "
+ 'previous weekend by Monday at 9 AM ET. See the "alarm reason" for details on '
+ "the failing manifests"
+ ),
+ ),
+ ]
+ alert_name: Annotated[
+ str,
+ Field(serialization_alias="AlarmName", default="weekend-data-load-availability-failure"),
+ ]
+ state: Annotated[str, Field(serialization_alias="NewStateValue", default="ALARM")]
+ change_time: Annotated[
+ datetime,
+ Field(serialization_alias="StateChangeTime", default_factory=lambda: datetime.now(UTC)),
+ ]
+
+
+def create_splunk_sns_notification(
+ unprocessed_manifests: list[str],
+) -> SplunkOnCallNotificationModel:
+ """Create a SplunkOnCallNotificationModel with an appropriate alert message.
+
+ :param unprocessed_manifests: List of unprocessed manifests to alert upon
+ :type unprocessed_manifests: list[str]
+ :return: A model with a message indicating the unprocessed manifests
+ :rtype: SplunkOnCallNotificationModel
+ """
+ return SplunkOnCallNotificationModel.model_validate({
+ "alert_message": (
+ f"{BFD_ENVIRONMENT} CCW Pipeline failed to load {len(unprocessed_manifests)}"
+ f" manifest(s) over the weekend: {', '.join(unprocessed_manifests)}"
+ )
+ })
+
+
+@logger.inject_lambda_context(clear_state=True, log_event=True)
+def handler(event: dict[Any, Any], context: LambdaContext) -> None: # noqa: ARG001
+ """Lambda event handler function called when an EventBridge Scheduler Event is received.
+
+ Args:
+ event (dict[Any, Any]): EventBridge Scheduler event details. Unused
+ context (LambdaContext): Lambda execution context. Unused
+
+ Raises:
+ RuntimeError: If any AWS API operations fail
+ """
+ try:
+ if not all([REGION, BFD_ENVIRONMENT, DB_CLUSTER_NAME, ETL_BUCKET_ID, ALERT_TOPIC_ARNS]):
+ raise RuntimeError("Not all necessary environment variables were defined")
+
+ rds_client = boto3.client("rds", config=BOTO_CONFIG)
+ described_clusters = rds_client.describe_db_clusters(
+ DBClusterIdentifier=DB_CLUSTER_NAME
+ ).get("DBClusters", [])
+ try:
+ reader_endpoint = next(
+ cluster_detail["ReaderEndpoint"]
+ for cluster_detail in described_clusters
+ if "ReaderEndpoint" in cluster_detail
+ )
+ except StopIteration as exc:
+ raise RuntimeError(
+ "describe-db-clusters returned invalid data for "
+ f"{DB_CLUSTER_NAME}: {described_clusters!s}"
+ ) from exc
+ db_username = parameters.get_parameter(
+ f"/bfd/{BFD_ENVIRONMENT}/pipeline/sensitive/db/username", decrypt=True
+ )
+ db_password = parameters.get_parameter(
+ f"/bfd/{BFD_ENVIRONMENT}/pipeline/sensitive/db/password", decrypt=True
+ )
+
+ logger.info(
+ "Connecting to %s as Pipeline user in %s cluster...",
+ reader_endpoint,
+ DB_CLUSTER_NAME,
+ )
+ with (
+ psycopg.connect(
+ host=reader_endpoint,
+ user=db_username,
+ password=db_password,
+ port=5432,
+ dbname="fhirdb",
+ ) as conn,
+ conn.cursor(row_factory=dict_row) as curs,
+ ):
+ logger.info("Connected to %s", reader_endpoint)
+ two_weeks_ago = datetime.now(UTC) - timedelta(weeks=2)
+
+ # Retrieve all manifests in the Incoming paths in s3 that were recently modified in the
+ # past 2 weeks. These manifests will be reconciled against their status in the database
+ logger.info(
+ "Discovering manifest(s) last modified after %s from S3 in Incoming...",
+ two_weeks_ago.isoformat(),
+ )
+ s3_resource = boto3.resource("s3", config=BOTO_CONFIG)
+ etl_bucket = s3_resource.Bucket(ETL_BUCKET_ID)
+ all_incoming_objects = itertools.chain(
+ etl_bucket.objects.filter(Prefix="Incoming/"),
+ etl_bucket.objects.filter(Prefix="Synthetic/Incoming/"),
+ )
+ recent_s3_manifest_keys = [
+ object.key
+ for object in all_incoming_objects
+ if "manifest.xml" in object.key
+ and object.last_modified.astimezone(UTC) > two_weeks_ago
+ ]
+ logger.info(
+ "Discovered %d S3 manifest(s) modified after %s",
+ len(recent_s3_manifest_keys),
+ two_weeks_ago.isoformat(),
+ )
+
+ # Retrieve all manifests and their state that were discovered in the past 2 weeks from
+ # the database. This list will be the source of truth against which the manifests in s3
+ # will be verified against
+ logger.info(
+ "Retrieving manifest(s) discovered since %s from the database",
+ two_weeks_ago.isoformat(),
+ )
+ raw_results = curs.execute(
+ """
+ SELECT s3_key, status FROM ccw.s3_manifest_files
+ WHERE discovery_timestamp > %s;
+ """,
+ (two_weeks_ago,),
+ ).fetchall()
+ db_manifest_files = TypeAdapter(list[ManifestFilesResultModel]).validate_python(
+ raw_results
+ )
+ logger.info(
+ "Retrieved %d manifest(s) from the database discovered after %s",
+ len(db_manifest_files),
+ two_weeks_ago.isoformat(),
+ )
+
+ # Reconcile the retrieved recently modified s3 manifests in Incoming with the manifests
+ # and their state in the database. If any s3 manifests either are not in the COMPLETED
+ # state or simply aren't in the database, the Pipeline failed to finish loading over the
+ # weekend and we should alert
+ logger.info(
+ "Verifying all %d S3 manifest(s) have been loaded...", len(recent_s3_manifest_keys)
+ )
+ unprocessed_manifests = [
+ s3_manifest
+ for s3_manifest in recent_s3_manifest_keys
+ if not any(
+ s3_manifest == db_manifest.s3_key and db_manifest.status == "COMPLETED"
+ for db_manifest in db_manifest_files
+ )
+ ]
+ if len(unprocessed_manifests) == 0:
+ logger.info("All manifests in S3 have been loaded by the Pipeline. Stopping")
+ return
+
+ # If we get here, there are unprocessed manifests. We need to send an alert to the alert
+ # topic(s)
+ logger.info(
+ "%d manifest(s) failed to load over the weekend; publishing notification(s) to "
+ "topic(s) %s; (manifest(s): %s)",
+ len(unprocessed_manifests),
+ ", ".join(arn.split(":")[-1] for arn in ALERT_TOPIC_ARNS),
+ ", ".join(unprocessed_manifests),
+ )
+ sns_client = boto3.client("sns", config=BOTO_CONFIG)
+ sns_message = create_splunk_sns_notification(
+ unprocessed_manifests=unprocessed_manifests
+ ).model_dump_json(by_alias=True)
+ for topic_arn in ALERT_TOPIC_ARNS:
+ logger.info("Publishing message to %s...", topic_arn)
+ sns_client.publish(
+ TopicArn=topic_arn,
+ Message=sns_message,
+ )
+ logger.info("Published message to %s successfully", topic_arn)
+ except Exception:
+ logger.exception("Unrecoverable exception raised")
+ raise
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/pyproject.toml b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/pyproject.toml
new file mode 100644
index 0000000000..ee028184c8
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/pyproject.toml
@@ -0,0 +1,78 @@
+[project]
+# Support Python 3.13+.
+requires-python = ">=3.13"
+name = "ccw-manifests-verifier"
+version = "1.0.0"
+dependencies = [
+ "aws-lambda-powertools[all]>=3.4.1",
+ "boto3>=1.36.3",
+ "psycopg[binary]>=3.2.4",
+ "pydantic>=2.10.5",
+]
+
+[dependency-groups]
+dev = [
+ "boto3-stubs[rds,s3,sns]>=1.36.3",
+ "ruff>=0.9.2",
+ "uv>=0.5.22",
+]
+
+[tool.ruff]
+# Set the maximum line length to 100.
+line-length = 100
+
+[tool.ruff.lint]
+select = [
+ "D", # pydocstyle
+ "E501",
+ # pycodestyle
+ "E",
+ # Pyflakes
+ "F",
+ # pyupgrade
+ "UP",
+ # flake8-bugbear
+ "B",
+ # flake8-simplify
+ "SIM",
+ # isort
+ "I",
+ "ANN",
+ "LOG",
+ "G",
+ "PT",
+ "RSE",
+ "PIE",
+ "RET",
+ "SLF",
+ "ARG",
+ "PTH",
+ "PLE",
+ "PLW",
+ "PERF",
+ "FURB",
+ "RUF",
+]
+
+[tool.ruff.lint.pydocstyle]
+convention = "pep257"
+
+[tool.ruff.format]
+quote-style = "double"
+indent-style = "space"
+docstring-code-format = true
+
+[tool.pyright]
+# ...
+typeCheckingMode = "strict"
+venvPath = "."
+venv = ".venv"
+reportMissingTypeStubs = "none"
+# Usage of _some_ of Powertools for AWS Lambda necessitates disabling some of Pyright's strict mode
+# features, sadly. The Powertools team seems to be aware of this incompatibility, but it seems
+# unlikely that any improvements will be made.
+reportUnknownMemberType = false
+reportUnknownVariableType = false
+reportUnknownArgumentType = false
+reportUnknownParameterType = false
+
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/uv.lock b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/uv.lock
new file mode 100644
index 0000000000..544635d5dc
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/lambda_src/uv.lock
@@ -0,0 +1,550 @@
+version = 1
+requires-python = ">=3.13"
+
+[[package]]
+name = "annotated-types"
+version = "0.7.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 },
+]
+
+[[package]]
+name = "attrs"
+version = "24.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/48/c8/6260f8ccc11f0917360fc0da435c5c9c7504e3db174d5a12a1494887b045/attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff", size = 805984 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/89/aa/ab0f7891a01eeb2d2e338ae8fecbe57fcebea1a24dbb64d45801bfab481d/attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308", size = 63397 },
+]
+
+[[package]]
+name = "aws-encryption-sdk"
+version = "4.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "attrs" },
+ { name = "boto3" },
+ { name = "cryptography" },
+ { name = "wrapt" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/da/51/feccabe29a3ee9b5a9e85bc9a7b0c4967a75a38458643e034d9c3551b6fa/aws-encryption-sdk-4.0.0.tar.gz", hash = "sha256:57df8b5c1b9f18db4373c6e8e65563791063a71be93d0849950ed365272db354", size = 257055 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c1/b8/5c1fc95f2082eb946eddfd38430ec3b0a9b7f566456fd9cc6da17e2b57c8/aws_encryption_sdk-4.0.0-py2.py3-none-any.whl", hash = "sha256:a94483785dff2cd166ccb8f3a15cdfe5cba7a3717f6604543c816a3a32f7c412", size = 98448 },
+]
+
+[[package]]
+name = "aws-lambda-powertools"
+version = "3.4.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jmespath" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/64/c8/9822b65596e656ffc17240c76ed954eb956a90c6cae1a38b07273f459e3a/aws_lambda_powertools-3.4.1.tar.gz", hash = "sha256:c5cb323ef1a6669e80409cff9e7b5b0a63581b93a65f750984e71bc4de5f22b6", size = 651066 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/15/ef/d38ab06eddedd79d05b670b945c40645ee0e329ebf6ea238833e4462d9a7/aws_lambda_powertools-3.4.1-py3-none-any.whl", hash = "sha256:41f2898d90b0c21e09386cc7d1c0070c360dc877d3b24b2cc118df9534d8f759", size = 766154 },
+]
+
+[package.optional-dependencies]
+all = [
+ { name = "aws-encryption-sdk" },
+ { name = "aws-xray-sdk" },
+ { name = "fastjsonschema" },
+ { name = "jsonpath-ng" },
+ { name = "pydantic" },
+ { name = "pydantic-settings" },
+]
+
+[[package]]
+name = "aws-xray-sdk"
+version = "2.14.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "botocore" },
+ { name = "wrapt" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e0/6c/8e7fb2a45f20afc5c19d52807b560793fb48b0feca1de7de116b62a7893e/aws_xray_sdk-2.14.0.tar.gz", hash = "sha256:aab843c331af9ab9ba5cefb3a303832a19db186140894a523edafc024cc0493c", size = 93976 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/41/69/b417833a8926fa5491e5346d7c233bf7d8a9b12ba1f4ef41ccea2494000c/aws_xray_sdk-2.14.0-py2.py3-none-any.whl", hash = "sha256:cfbe6feea3d26613a2a869d14c9246a844285c97087ad8f296f901633554ad94", size = 101922 },
+]
+
+[[package]]
+name = "boto3"
+version = "1.36.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "botocore" },
+ { name = "jmespath" },
+ { name = "s3transfer" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/07/12/b9ad4c3dd6e6044243d08bae076795e41357651683f4fad99d5828c4291c/boto3-1.36.3.tar.gz", hash = "sha256:53a5307f6a3526ee2f8590e3c45efa504a3ea4532c1bfe4926c0c19bf188d141", size = 110987 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/79/97/4697aa8050e306d6139815996adeb263ddc83024399a188e8b42587665db/boto3-1.36.3-py3-none-any.whl", hash = "sha256:f9843a5d06f501d66ada06f5a5417f671823af2cf319e36ceefa1bafaaaaa953", size = 139165 },
+]
+
+[[package]]
+name = "boto3-stubs"
+version = "1.36.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "botocore-stubs" },
+ { name = "types-s3transfer" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ea/38/635c362ec0060e2974d1e5c0daf80532097debe57fecad035e648be05483/boto3_stubs-1.36.3.tar.gz", hash = "sha256:f4a0ac68202e699486f7fb7283985edd1709300633ba29feb4c79ce488ce59fe", size = 98583 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/58/0a/43bb865ae3d9312b5f4068244aca3c8664a6ba9f28bd617c43e677f8fff8/boto3_stubs-1.36.3-py3-none-any.whl", hash = "sha256:aa89073b98a071fa05a080ec11d7912667dc157bd89dd5b7e323bd9ecc67e77e", size = 68234 },
+]
+
+[package.optional-dependencies]
+rds = [
+ { name = "mypy-boto3-rds" },
+]
+s3 = [
+ { name = "mypy-boto3-s3" },
+]
+sns = [
+ { name = "mypy-boto3-sns" },
+]
+
+[[package]]
+name = "botocore"
+version = "1.36.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jmespath" },
+ { name = "python-dateutil" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/3a/61/69eb06a803c83e0da733b60b2bc65880c18ef2dee19ee10cf8732794a3c1/botocore-1.36.3.tar.gz", hash = "sha256:775b835e979da5c96548ed1a0b798101a145aec3cd46541d62e27dda5a94d7f8", size = 13507880 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9f/14/f952fed35b9c04aa66453b5fb5d1262a5a9f5dfdcb396d387c1ff0c6da41/botocore-1.36.3-py3-none-any.whl", hash = "sha256:536ab828e6f90dbb000e3702ac45fd76642113ae2db1b7b1373ad24104e89255", size = 13304681 },
+]
+
+[[package]]
+name = "botocore-stubs"
+version = "1.36.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "types-awscrt" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/5a/ea/09d44698e081b3da7c967a090764386ca32469c416831f2a88236253c6e0/botocore_stubs-1.36.3.tar.gz", hash = "sha256:30437070ba1df6f0549b1ded723aca74d06850610c7df002d643e0aa9f4c4520", size = 41198 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e2/0b/2ab3c4aada20473f989aa7c69a85a70a5ad531c681392d7f649be96322d0/botocore_stubs-1.36.3-py3-none-any.whl", hash = "sha256:af32c6127f507b66762749c7c8a78ba2a22aac86097d15b2097f2bfb4faf1ac3", size = 64004 },
+]
+
+[[package]]
+name = "ccw-manifests-verifier"
+version = "1.0.0"
+source = { virtual = "." }
+dependencies = [
+ { name = "aws-lambda-powertools", extra = ["all"] },
+ { name = "boto3" },
+ { name = "psycopg", extra = ["binary"] },
+ { name = "pydantic" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "boto3-stubs", extra = ["rds", "s3", "sns"] },
+ { name = "ruff" },
+ { name = "uv" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "aws-lambda-powertools", extras = ["all"], specifier = ">=3.4.1" },
+ { name = "boto3", specifier = ">=1.36.3" },
+ { name = "psycopg", extras = ["binary"], specifier = ">=3.2.4" },
+ { name = "pydantic", specifier = ">=2.10.5" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "boto3-stubs", extras = ["rds", "s3", "sns"], specifier = ">=1.36.3" },
+ { name = "ruff", specifier = ">=0.9.2" },
+ { name = "uv", specifier = ">=0.5.22" },
+]
+
+[[package]]
+name = "cffi"
+version = "1.17.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pycparser" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 },
+ { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 },
+ { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 },
+ { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 },
+ { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 },
+ { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 },
+ { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 },
+ { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 },
+ { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 },
+ { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 },
+ { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 },
+]
+
+[[package]]
+name = "cryptography"
+version = "44.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/91/4c/45dfa6829acffa344e3967d6006ee4ae8be57af746ae2eba1c431949b32c/cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02", size = 710657 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/55/09/8cc67f9b84730ad330b3b72cf867150744bf07ff113cda21a15a1c6d2c7c/cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123", size = 6541833 },
+ { url = "https://files.pythonhosted.org/packages/7e/5b/3759e30a103144e29632e7cb72aec28cedc79e514b2ea8896bb17163c19b/cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092", size = 3922710 },
+ { url = "https://files.pythonhosted.org/packages/5f/58/3b14bf39f1a0cfd679e753e8647ada56cddbf5acebffe7db90e184c76168/cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f", size = 4137546 },
+ { url = "https://files.pythonhosted.org/packages/98/65/13d9e76ca19b0ba5603d71ac8424b5694415b348e719db277b5edc985ff5/cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb", size = 3915420 },
+ { url = "https://files.pythonhosted.org/packages/b1/07/40fe09ce96b91fc9276a9ad272832ead0fddedcba87f1190372af8e3039c/cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b", size = 4154498 },
+ { url = "https://files.pythonhosted.org/packages/75/ea/af65619c800ec0a7e4034207aec543acdf248d9bffba0533342d1bd435e1/cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543", size = 3932569 },
+ { url = "https://files.pythonhosted.org/packages/c7/af/d1deb0c04d59612e3d5e54203159e284d3e7a6921e565bb0eeb6269bdd8a/cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e", size = 4016721 },
+ { url = "https://files.pythonhosted.org/packages/bd/69/7ca326c55698d0688db867795134bdfac87136b80ef373aaa42b225d6dd5/cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e", size = 4240915 },
+ { url = "https://files.pythonhosted.org/packages/ef/d4/cae11bf68c0f981e0413906c6dd03ae7fa864347ed5fac40021df1ef467c/cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053", size = 2757925 },
+ { url = "https://files.pythonhosted.org/packages/64/b1/50d7739254d2002acae64eed4fc43b24ac0cc44bf0a0d388d1ca06ec5bb1/cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd", size = 3202055 },
+ { url = "https://files.pythonhosted.org/packages/11/18/61e52a3d28fc1514a43b0ac291177acd1b4de00e9301aaf7ef867076ff8a/cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591", size = 6542801 },
+ { url = "https://files.pythonhosted.org/packages/1a/07/5f165b6c65696ef75601b781a280fc3b33f1e0cd6aa5a92d9fb96c410e97/cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7", size = 3922613 },
+ { url = "https://files.pythonhosted.org/packages/28/34/6b3ac1d80fc174812486561cf25194338151780f27e438526f9c64e16869/cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc", size = 4137925 },
+ { url = "https://files.pythonhosted.org/packages/d0/c7/c656eb08fd22255d21bc3129625ed9cd5ee305f33752ef2278711b3fa98b/cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289", size = 3915417 },
+ { url = "https://files.pythonhosted.org/packages/ef/82/72403624f197af0db6bac4e58153bc9ac0e6020e57234115db9596eee85d/cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7", size = 4155160 },
+ { url = "https://files.pythonhosted.org/packages/a2/cd/2f3c440913d4329ade49b146d74f2e9766422e1732613f57097fea61f344/cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c", size = 3932331 },
+ { url = "https://files.pythonhosted.org/packages/7f/df/8be88797f0a1cca6e255189a57bb49237402b1880d6e8721690c5603ac23/cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64", size = 4017372 },
+ { url = "https://files.pythonhosted.org/packages/af/36/5ccc376f025a834e72b8e52e18746b927f34e4520487098e283a719c205e/cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285", size = 4239657 },
+ { url = "https://files.pythonhosted.org/packages/46/b0/f4f7d0d0bcfbc8dd6296c1449be326d04217c57afb8b2594f017eed95533/cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417", size = 2758672 },
+ { url = "https://files.pythonhosted.org/packages/97/9b/443270b9210f13f6ef240eff73fd32e02d381e7103969dc66ce8e89ee901/cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede", size = 3202071 },
+]
+
+[[package]]
+name = "fastjsonschema"
+version = "2.21.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/8b/50/4b769ce1ac4071a1ef6d86b1a3fb56cdc3a37615e8c5519e1af96cdac366/fastjsonschema-2.21.1.tar.gz", hash = "sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4", size = 373939 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/90/2b/0817a2b257fe88725c25589d89aec060581aabf668707a8d03b2e9e0cb2a/fastjsonschema-2.21.1-py3-none-any.whl", hash = "sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667", size = 23924 },
+]
+
+[[package]]
+name = "jmespath"
+version = "1.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256 },
+]
+
+[[package]]
+name = "jsonpath-ng"
+version = "1.7.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "ply" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/6d/86/08646239a313f895186ff0a4573452038eed8c86f54380b3ebac34d32fb2/jsonpath-ng-1.7.0.tar.gz", hash = "sha256:f6f5f7fd4e5ff79c785f1573b394043b39849fb2bb47bcead935d12b00beab3c", size = 37838 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/35/5a/73ecb3d82f8615f32ccdadeb9356726d6cae3a4bbc840b437ceb95708063/jsonpath_ng-1.7.0-py3-none-any.whl", hash = "sha256:f3d7f9e848cba1b6da28c55b1c26ff915dc9e0b1ba7e752a53d6da8d5cbd00b6", size = 30105 },
+]
+
+[[package]]
+name = "mypy-boto3-rds"
+version = "1.36.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/68/9d/e4345ea340bda05bae47afcc1753be3bac0345bddf4fa68a82e0482725f5/mypy_boto3_rds-1.36.0.tar.gz", hash = "sha256:3d4ed0f364233b0315bbe2e42bcd373277c7a489687dfae5593238f26a6bfb53", size = 84298 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ff/29/d4b527a95bb3cf15075143a2584c7d670c1910344f8a0bcc96dfb2a40e5c/mypy_boto3_rds-1.36.0-py3-none-any.whl", hash = "sha256:47d6df5dc70f83d91139755675cefa95d2107e9d82efe51f70679b7c42b6d73e", size = 90223 },
+]
+
+[[package]]
+name = "mypy-boto3-s3"
+version = "1.36.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c9/fe/243fb2134226fe8b0dd1ba24e5b8eec5fd1cd14f37c1c16dec3620cfd778/mypy_boto3_s3-1.36.0.tar.gz", hash = "sha256:80a881847b0e1fbc5edcad8b2870c110e31e7ef128db42402b70c159b7e93d5a", size = 73116 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/71/d8/cef1025f6bf3b38d04afcfc2c27cbcfa202708ed97e20cf0e1282af205e4/mypy_boto3_s3-1.36.0-py3-none-any.whl", hash = "sha256:a65ccb6be7b7ebf907887268d44975e435b1fc1164fc0a25de310e2b832f7e91", size = 79692 },
+]
+
+[[package]]
+name = "mypy-boto3-sns"
+version = "1.36.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/5d/f7/f244090974cf5cb4aeee01aa55ca29b85cc6453c0d3d1a899f1a556497e6/mypy_boto3_sns-1.36.3.tar.gz", hash = "sha256:d521f45f4788a4c11d1715dfe6c2af857eb94f7664b19753a3c656fb11bafa6f", size = 33151 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ee/35/3caccee6b1aa84a4f1ef5be3685e8a59c1445a12fef85f4da6ad7a202e7a/mypy_boto3_sns-1.36.3-py3-none-any.whl", hash = "sha256:af855273757693d9612f3a33d725d9084fcafdc1dd40975e7db00f2c5573e6d4", size = 40004 },
+]
+
+[[package]]
+name = "ply"
+version = "3.11"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e5/69/882ee5c9d017149285cab114ebeab373308ef0f874fcdac9beb90e0ac4da/ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3", size = 159130 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce", size = 49567 },
+]
+
+[[package]]
+name = "psycopg"
+version = "3.2.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "tzdata", marker = "sys_platform == 'win32'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e0/f2/954b1467b3e2ca5945b83b5e320268be1f4df486c3e8ffc90f4e4b707979/psycopg-3.2.4.tar.gz", hash = "sha256:f26f1346d6bf1ef5f5ef1714dd405c67fb365cfd1c6cea07de1792747b167b92", size = 156109 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/49/15114d5f7ee68983f4e1a24d47e75334568960352a07c6f0e796e912685d/psycopg-3.2.4-py3-none-any.whl", hash = "sha256:43665368ccd48180744cab26b74332f46b63b7e06e8ce0775547a3533883d381", size = 198716 },
+]
+
+[package.optional-dependencies]
+binary = [
+ { name = "psycopg-binary", marker = "implementation_name != 'pypy'" },
+]
+
+[[package]]
+name = "psycopg-binary"
+version = "3.2.4"
+source = { registry = "https://pypi.org/simple" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/25/e2/f56675aada063762f08559b6969e47e1313f269fc1682c16457c13da8186/psycopg_binary-3.2.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:81ab801c0d35830c876bf0d1edc8e7dd2f73aa2b04fe24eb812159c0b054d149", size = 3846854 },
+ { url = "https://files.pythonhosted.org/packages/7b/8b/8c4a66b2b3db494367df0299535b7d2df78f303334228c517b8d00c411d5/psycopg_binary-3.2.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c09e02ce1124eb6638b3381df050a8cf88aedfad4522f939945cda49050a990c", size = 3932292 },
+ { url = "https://files.pythonhosted.org/packages/84/e8/618d45f77cebce73d75497c95685a0902aea3783386d9335ce486c69e13a/psycopg_binary-3.2.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a249cdc6a5c2b5088a8677acba66b291e5237524739ab3d27498e1ef189312f5", size = 4493785 },
+ { url = "https://files.pythonhosted.org/packages/c4/87/fc30318e6b97e723e017e7dc88d0f721bbfb749de1a6e414e52d4ac54c9a/psycopg_binary-3.2.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2960ba8a5c0ad75e184f6d8bf76bdf023708999efe75fe4e13445136c1cd206", size = 4304874 },
+ { url = "https://files.pythonhosted.org/packages/91/30/1d127e651c21cd77befaf361c7c3b9001bfff51ac38027e8fce598ba0701/psycopg_binary-3.2.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dae2e50b0d3425c167eebbedc3553f7c811dbc0dbfc737b6877f68a03be7daf", size = 4541296 },
+ { url = "https://files.pythonhosted.org/packages/0d/5e/22c824cb38745c1c744cec85d227190727c564afb75960ce0057ca15fd84/psycopg_binary-3.2.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03bf7ee7e0002c2cce43ecb923ec510358056eb2e44a96afaeb0424518f35206", size = 4255756 },
+ { url = "https://files.pythonhosted.org/packages/b3/83/ae8783dec3f7e39df8a4056e4d383926ffec531970c0b415d48d9fd4a2c2/psycopg_binary-3.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5f5c85eeb63b1a8a6b026eef57f5da36ff215ce9a6a3bb8e20a409670d6cfbda", size = 3845918 },
+ { url = "https://files.pythonhosted.org/packages/be/f7/fb7bffb0c4c45a5a82fe324e4f7b176075a4c5372e546a038858dd13c7ab/psycopg_binary-3.2.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8c7b95899d4d6d23c5cc46cb3419e8e6ca68d867509432ee1487042564a1ea55", size = 3315429 },
+ { url = "https://files.pythonhosted.org/packages/81/a3/29f4993a239d6a3fb18ef8681d9990c007f5f73bdd2e21f65f07ac55ad6f/psycopg_binary-3.2.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fa4acea9ca20a567c3872a5afab2084751530bb57b8fb6b52820d5c54e7c8c3b", size = 3399388 },
+ { url = "https://files.pythonhosted.org/packages/25/5b/925171cbfa2e3d1ccb7f4c005d0d5db609ba796c1d08a23c42825b09c554/psycopg_binary-3.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c487f35a1905bb15da927c1fc05f70f3d29f0e21fb4ba21d360a0da9c755f20", size = 3436702 },
+ { url = "https://files.pythonhosted.org/packages/b6/47/25b2b85b8fcabf99bfa92b4b0d587894c01576bf0b2bf137c243d1eb1070/psycopg_binary-3.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:80297c3a9f7b5a6afdb0d8f220661ccd796e5c9128c44b32c41267f7daefd37f", size = 2779196 },
+]
+
+[[package]]
+name = "pycparser"
+version = "2.22"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 },
+]
+
+[[package]]
+name = "pydantic"
+version = "2.10.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-types" },
+ { name = "pydantic-core" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/6a/c7/ca334c2ef6f2e046b1144fe4bb2a5da8a4c574e7f2ebf7e16b34a6a2fa92/pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff", size = 761287 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/58/26/82663c79010b28eddf29dcdd0ea723439535fa917fce5905885c0e9ba562/pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53", size = 431426 },
+]
+
+[[package]]
+name = "pydantic-core"
+version = "2.27.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 },
+ { url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 },
+ { url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 },
+ { url = "https://files.pythonhosted.org/packages/b1/1c/b6f402cfc18ec0024120602bdbcebc7bdd5b856528c013bd4d13865ca473/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", size = 1868888 },
+ { url = "https://files.pythonhosted.org/packages/bd/7b/8cb75b66ac37bc2975a3b7de99f3c6f355fcc4d89820b61dffa8f1e81677/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", size = 2037738 },
+ { url = "https://files.pythonhosted.org/packages/c8/f1/786d8fe78970a06f61df22cba58e365ce304bf9b9f46cc71c8c424e0c334/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", size = 2685138 },
+ { url = "https://files.pythonhosted.org/packages/a6/74/d12b2cd841d8724dc8ffb13fc5cef86566a53ed358103150209ecd5d1999/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", size = 1997025 },
+ { url = "https://files.pythonhosted.org/packages/a0/6e/940bcd631bc4d9a06c9539b51f070b66e8f370ed0933f392db6ff350d873/pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", size = 2004633 },
+ { url = "https://files.pythonhosted.org/packages/50/cc/a46b34f1708d82498c227d5d80ce615b2dd502ddcfd8376fc14a36655af1/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", size = 1999404 },
+ { url = "https://files.pythonhosted.org/packages/ca/2d/c365cfa930ed23bc58c41463bae347d1005537dc8db79e998af8ba28d35e/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", size = 2130130 },
+ { url = "https://files.pythonhosted.org/packages/f4/d7/eb64d015c350b7cdb371145b54d96c919d4db516817f31cd1c650cae3b21/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", size = 2157946 },
+ { url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 },
+ { url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 },
+ { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 },
+]
+
+[[package]]
+name = "pydantic-settings"
+version = "2.7.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pydantic" },
+ { name = "python-dotenv" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/73/7b/c58a586cd7d9ac66d2ee4ba60ca2d241fa837c02bca9bea80a9a8c3d22a9/pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93", size = 79920 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b4/46/93416fdae86d40879714f72956ac14df9c7b76f7d41a4d68aa9f71a0028b/pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd", size = 29718 },
+]
+
+[[package]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 },
+]
+
+[[package]]
+name = "python-dotenv"
+version = "1.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 },
+]
+
+[[package]]
+name = "ruff"
+version = "0.9.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/80/63/77ecca9d21177600f551d1c58ab0e5a0b260940ea7312195bd2a4798f8a8/ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0", size = 3553799 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/af/b9/0e168e4e7fb3af851f739e8f07889b91d1a33a30fca8c29fa3149d6b03ec/ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347", size = 11652408 },
+ { url = "https://files.pythonhosted.org/packages/2c/22/08ede5db17cf701372a461d1cb8fdde037da1d4fa622b69ac21960e6237e/ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00", size = 11587553 },
+ { url = "https://files.pythonhosted.org/packages/42/05/dedfc70f0bf010230229e33dec6e7b2235b2a1b8cbb2a991c710743e343f/ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4", size = 11020755 },
+ { url = "https://files.pythonhosted.org/packages/df/9b/65d87ad9b2e3def67342830bd1af98803af731243da1255537ddb8f22209/ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d", size = 11826502 },
+ { url = "https://files.pythonhosted.org/packages/93/02/f2239f56786479e1a89c3da9bc9391120057fc6f4a8266a5b091314e72ce/ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c", size = 11390562 },
+ { url = "https://files.pythonhosted.org/packages/c9/37/d3a854dba9931f8cb1b2a19509bfe59e00875f48ade632e95aefcb7a0aee/ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f", size = 12548968 },
+ { url = "https://files.pythonhosted.org/packages/fa/c3/c7b812bb256c7a1d5553433e95980934ffa85396d332401f6b391d3c4569/ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684", size = 13187155 },
+ { url = "https://files.pythonhosted.org/packages/bd/5a/3c7f9696a7875522b66aa9bba9e326e4e5894b4366bd1dc32aa6791cb1ff/ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d", size = 12704674 },
+ { url = "https://files.pythonhosted.org/packages/be/d6/d908762257a96ce5912187ae9ae86792e677ca4f3dc973b71e7508ff6282/ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df", size = 14529328 },
+ { url = "https://files.pythonhosted.org/packages/2d/c2/049f1e6755d12d9cd8823242fa105968f34ee4c669d04cac8cea51a50407/ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247", size = 12385955 },
+ { url = "https://files.pythonhosted.org/packages/91/5a/a9bdb50e39810bd9627074e42743b00e6dc4009d42ae9f9351bc3dbc28e7/ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e", size = 11810149 },
+ { url = "https://files.pythonhosted.org/packages/e5/fd/57df1a0543182f79a1236e82a79c68ce210efb00e97c30657d5bdb12b478/ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe", size = 11479141 },
+ { url = "https://files.pythonhosted.org/packages/dc/16/bc3fd1d38974f6775fc152a0554f8c210ff80f2764b43777163c3c45d61b/ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb", size = 12014073 },
+ { url = "https://files.pythonhosted.org/packages/47/6b/e4ca048a8f2047eb652e1e8c755f384d1b7944f69ed69066a37acd4118b0/ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a", size = 12435758 },
+ { url = "https://files.pythonhosted.org/packages/c2/40/4d3d6c979c67ba24cf183d29f706051a53c36d78358036a9cd21421582ab/ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145", size = 9796916 },
+ { url = "https://files.pythonhosted.org/packages/c3/ef/7f548752bdb6867e6939489c87fe4da489ab36191525fadc5cede2a6e8e2/ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5", size = 10773080 },
+ { url = "https://files.pythonhosted.org/packages/0e/4e/33df635528292bd2d18404e4daabcd74ca8a9853b2e1df85ed3d32d24362/ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6", size = 10001738 },
+]
+
+[[package]]
+name = "s3transfer"
+version = "0.11.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "botocore" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/1a/aa/fdd958c626b00e3f046d4004363e7f1a2aba4354f78d65ceb3b217fa5eb8/s3transfer-0.11.1.tar.gz", hash = "sha256:3f25c900a367c8b7f7d8f9c34edc87e300bde424f779dc9f0a8ae4f9df9264f6", size = 146952 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5f/ce/22673f4a85ccc640735b4f8d12178a0f41b5d3c6eda7f33756d10ce56901/s3transfer-0.11.1-py3-none-any.whl", hash = "sha256:8fa0aa48177be1f3425176dfe1ab85dcd3d962df603c3dbfc585e6bf857ef0ff", size = 84111 },
+]
+
+[[package]]
+name = "six"
+version = "1.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
+]
+
+[[package]]
+name = "types-awscrt"
+version = "0.23.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/dd/97/c62253e8ed65562c67b2138339444cc77507c8ee01c091e02ead1311e4b8/types_awscrt-0.23.6.tar.gz", hash = "sha256:405bce8c281f9e7c6c92a229225cc0bf10d30729a6a601123213389bd524b8b1", size = 15124 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/21/f1/0f0869d35c1b746df98d60016f898eb49db208747a4ed2de81b58f48ecd8/types_awscrt-0.23.6-py3-none-any.whl", hash = "sha256:fbf9c221af5607b24bf17f8431217ce8b9a27917139edbc984891eb63fd5a593", size = 19025 },
+]
+
+[[package]]
+name = "types-s3transfer"
+version = "0.11.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f0/01/0169c095070a8cb97baf075246b8804390082ee189d344a6767eb89849cd/types_s3transfer-0.11.1.tar.gz", hash = "sha256:6ab89d4d76bcbf6d494582949963b4672347e8daa397d9790f3684b4fcf873c4", size = 14055 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0c/87/2452812a3d57a13af13a23239da6c781a079e508bc70a44df576ce76b7c1/types_s3transfer-0.11.1-py3-none-any.whl", hash = "sha256:ddb20d103361c2d7cf95e9e73468cdd12f049f503b1512e6fdfe5a66fa086d2d", size = 19487 },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.12.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
+]
+
+[[package]]
+name = "tzdata"
+version = "2025.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/43/0f/fa4723f22942480be4ca9527bbde8d43f6c3f2fe8412f00e7f5f6746bc8b/tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", size = 194950 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762 },
+]
+
+[[package]]
+name = "urllib3"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 },
+]
+
+[[package]]
+name = "uv"
+version = "0.5.22"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ef/22/3e634cc4caf0a5acae08fc7ad80a76cf01a0be779ceb2cde3e14e164c1eb/uv-0.5.22.tar.gz", hash = "sha256:12f78366075bcff63e926f2beaf9dafe92f94368c736f4d63a64f4c6a2072af5", size = 2662375 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4f/40/f40aec432b7d53faa2e8a3bf155adaf2876ff8b327b7d2d43f5af7d7c213/uv-0.5.22-py3-none-linux_armv6l.whl", hash = "sha256:7b4024a82616e08f8e2361ae113bf74b8bef6f028835eb1300678eb9182e1bdc", size = 15317990 },
+ { url = "https://files.pythonhosted.org/packages/be/36/a482fde2e4b762bc0838f5dcf195d2a7b5dd06ccdd5ab23004ac9451f34d/uv-0.5.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:32658bb5c8637a437b2a209b937e11beba7600dea600c672edef180b4748a729", size = 15474569 },
+ { url = "https://files.pythonhosted.org/packages/bf/c7/462bc209bd6f9f4fc3db428b345a70fd59296ee914be090389c4f6f6a9f8/uv-0.5.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1ace09ab8028a2d596b84d8814ff78ce2a13f1e8a1e664523e6a6eeb9ef50aad", size = 14382343 },
+ { url = "https://files.pythonhosted.org/packages/a0/e8/cc973a1fd0ebff01a7ddff903d2782a280f5588da4ed57ea70dad0a403e4/uv-0.5.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:9c9dda5ea4bcd49b0a7c36da6f1a0fd7a74fced354de3971f40c8176c5398d8a", size = 14836795 },
+ { url = "https://files.pythonhosted.org/packages/8b/69/fa8ef336f799bd185e0a218ff28d39ca930295882edc972019abda23c166/uv-0.5.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f2f35104b3121d26bc1e2a19444cae589ec7307314d0b4788f1d784fab41748", size = 15052067 },
+ { url = "https://files.pythonhosted.org/packages/23/18/ab10457abe0cac1cbee327c31c2a96001f4318451e0017f4727a3962045a/uv-0.5.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25e50a3216fd3370c8fad7c9c23539997e160cbc2e5121e0a8ca21d47a6bbcac", size = 15788379 },
+ { url = "https://files.pythonhosted.org/packages/c2/24/c8b296df29cd92c825db8c60ae0799bd977fe1c91712599e1fa5d9bea8b5/uv-0.5.22-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ead10e1c0f443cf9921d73c18c65935b502bd4eb3cc1bbbbb43e0e7435a31dbd", size = 16705352 },
+ { url = "https://files.pythonhosted.org/packages/34/7f/2cdf72eb49b99d222e6eb264515ff8433572ff8574cafcf8a910c816c459/uv-0.5.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8674f547ddf9b988d12120fa14a8eca4730b019869a2bacf11a89a6de788e6e6", size = 16428333 },
+ { url = "https://files.pythonhosted.org/packages/c8/a5/74b580945594dcc444f9a1bce64f3c081a04d9c9f435340ae044da2416d9/uv-0.5.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cedf06ebfa2b233450b7f71a16c90f103ea68f415f45e61ec691554c03cccdb", size = 20752598 },
+ { url = "https://files.pythonhosted.org/packages/fc/86/fddff1dd7c894bb4de44a66bc4372c9b3d64138f63bced3e0f919ca8f0ab/uv-0.5.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2f1eb24426680a22ca9a824f2af83a5e9b2179d709cd1b48ddd10e81e249d9c", size = 16118825 },
+ { url = "https://files.pythonhosted.org/packages/7d/ef/860249b83023dfbcb2dc4f4ef66082a8e45504138fdaf9631d96b0221e3d/uv-0.5.22-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:9b3e4bcee00b9f343c29bcd8251a739727f60c16870148336b5a97f94bb26a7b", size = 15122109 },
+ { url = "https://files.pythonhosted.org/packages/e7/82/05ef1cf9de48a456969b40e08dae0d5afb9fc9b8ed6e25d42d4cdf2e4ab6/uv-0.5.22-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:82261745216bdb3faa80eab99fa7ebe7918fdde77b78a191e9f1a7f45450c405", size = 15043439 },
+ { url = "https://files.pythonhosted.org/packages/9a/8a/782bdbbdd0d8623c807fedda6b11c3ab4c063dcf4940e7e88f3e652d51bb/uv-0.5.22-py3-none-musllinux_1_1_i686.whl", hash = "sha256:ee27c6bc80b59ec8680c7a9bff9716aaa082e403b03986425f6c4f7a4b2f2a7e", size = 15434092 },
+ { url = "https://files.pythonhosted.org/packages/fa/fc/f267ef26fd75846f49a6e1e1ff61c18357046d6d0688409d70a16e21bae5/uv-0.5.22-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:4c03ad206af6c521d05a9b6c8f1f265b5a9390858e7095f0b7354bb2a86a33f1", size = 16247589 },
+ { url = "https://files.pythonhosted.org/packages/7c/51/01277ba4e7139820921ffa09bca3143d854b38d77d1fc80dc7c6ab3a0c69/uv-0.5.22-py3-none-win32.whl", hash = "sha256:34235a5b50c8b03b7c4f4be8dc3f021802672bd3152812a7f05710d67459bf76", size = 15326817 },
+ { url = "https://files.pythonhosted.org/packages/72/ee/f53d2f8f24b1f9420f85dec8d573772aa41b5a01211198112d9ce4cbb6df/uv-0.5.22-py3-none-win_amd64.whl", hash = "sha256:8c57f65b570508fb6a460001f187fffebbc7665e9c642cefbca3719bc48f078f", size = 16657665 },
+]
+
+[[package]]
+name = "wrapt"
+version = "1.17.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ce/b9/0ffd557a92f3b11d4c5d5e0c5e4ad057bd9eb8586615cdaf901409920b14/wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", size = 53800 },
+ { url = "https://files.pythonhosted.org/packages/c0/ef/8be90a0b7e73c32e550c73cfb2fa09db62234227ece47b0e80a05073b375/wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", size = 38824 },
+ { url = "https://files.pythonhosted.org/packages/36/89/0aae34c10fe524cce30fe5fc433210376bce94cf74d05b0d68344c8ba46e/wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", size = 38920 },
+ { url = "https://files.pythonhosted.org/packages/3b/24/11c4510de906d77e0cfb5197f1b1445d4fec42c9a39ea853d482698ac681/wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", size = 88690 },
+ { url = "https://files.pythonhosted.org/packages/71/d7/cfcf842291267bf455b3e266c0c29dcb675b5540ee8b50ba1699abf3af45/wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", size = 80861 },
+ { url = "https://files.pythonhosted.org/packages/d5/66/5d973e9f3e7370fd686fb47a9af3319418ed925c27d72ce16b791231576d/wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", size = 89174 },
+ { url = "https://files.pythonhosted.org/packages/a7/d3/8e17bb70f6ae25dabc1aaf990f86824e4fd98ee9cadf197054e068500d27/wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", size = 86721 },
+ { url = "https://files.pythonhosted.org/packages/6f/54/f170dfb278fe1c30d0ff864513cff526d624ab8de3254b20abb9cffedc24/wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", size = 79763 },
+ { url = "https://files.pythonhosted.org/packages/4a/98/de07243751f1c4a9b15c76019250210dd3486ce098c3d80d5f729cba029c/wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", size = 87585 },
+ { url = "https://files.pythonhosted.org/packages/f9/f0/13925f4bd6548013038cdeb11ee2cbd4e37c30f8bfd5db9e5a2a370d6e20/wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", size = 36676 },
+ { url = "https://files.pythonhosted.org/packages/bf/ae/743f16ef8c2e3628df3ddfd652b7d4c555d12c84b53f3d8218498f4ade9b/wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", size = 38871 },
+ { url = "https://files.pythonhosted.org/packages/3d/bc/30f903f891a82d402ffb5fda27ec1d621cc97cb74c16fea0b6141f1d4e87/wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", size = 56312 },
+ { url = "https://files.pythonhosted.org/packages/8a/04/c97273eb491b5f1c918857cd26f314b74fc9b29224521f5b83f872253725/wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", size = 40062 },
+ { url = "https://files.pythonhosted.org/packages/4e/ca/3b7afa1eae3a9e7fefe499db9b96813f41828b9fdb016ee836c4c379dadb/wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", size = 40155 },
+ { url = "https://files.pythonhosted.org/packages/89/be/7c1baed43290775cb9030c774bc53c860db140397047cc49aedaf0a15477/wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", size = 113471 },
+ { url = "https://files.pythonhosted.org/packages/32/98/4ed894cf012b6d6aae5f5cc974006bdeb92f0241775addad3f8cd6ab71c8/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", size = 101208 },
+ { url = "https://files.pythonhosted.org/packages/ea/fd/0c30f2301ca94e655e5e057012e83284ce8c545df7661a78d8bfca2fac7a/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", size = 109339 },
+ { url = "https://files.pythonhosted.org/packages/75/56/05d000de894c4cfcb84bcd6b1df6214297b8089a7bd324c21a4765e49b14/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", size = 110232 },
+ { url = "https://files.pythonhosted.org/packages/53/f8/c3f6b2cf9b9277fb0813418e1503e68414cd036b3b099c823379c9575e6d/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", size = 100476 },
+ { url = "https://files.pythonhosted.org/packages/a7/b1/0bb11e29aa5139d90b770ebbfa167267b1fc548d2302c30c8f7572851738/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", size = 106377 },
+ { url = "https://files.pythonhosted.org/packages/6a/e1/0122853035b40b3f333bbb25f1939fc1045e21dd518f7f0922b60c156f7c/wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", size = 37986 },
+ { url = "https://files.pythonhosted.org/packages/09/5e/1655cf481e079c1f22d0cabdd4e51733679932718dc23bf2db175f329b76/wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", size = 40750 },
+ { url = "https://files.pythonhosted.org/packages/2d/82/f56956041adef78f849db6b289b282e72b55ab8045a75abad81898c28d19/wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", size = 23594 },
+]
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/main.tf b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/main.tf
new file mode 100644
index 0000000000..2f814c3271
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/main.tf
@@ -0,0 +1,111 @@
+locals {
+ env = terraform.workspace
+ service = "pipeline"
+ layer = "app"
+ service_name_prefix = "bfd-${local.env}-${local.service}"
+
+ account_id = data.aws_caller_identity.current.account_id
+ region = data.aws_region.current.name
+ vpc_id = data.aws_vpc.main.id
+ kms_key_id = data.aws_kms_key.cmk.arn
+ kms_config_key_arns = flatten(
+ [
+ for v in data.aws_kms_key.config_cmk.multi_region_configuration :
+ concat(v.primary_key[*].arn, v.replica_keys[*].arn)
+ ]
+ )
+
+ lambda_name = "ccw-manifests-verifier"
+ lambda_full_name = "${local.service_name_prefix}-${local.lambda_name}"
+ lambda_src = replace(local.lambda_name, "-", "_")
+ lambda_image_uri = "${data.aws_ecr_repository.ecr.repository_url}:${var.bfd_version}"
+
+ alert_topics = [for v in split(",", nonsensitive(data.aws_ssm_parameter.alert_topics.value)) : trimspace(v)]
+}
+
+
+resource "aws_scheduler_schedule_group" "this" {
+ name = "${local.lambda_full_name}-lambda-schedules"
+}
+
+resource "aws_scheduler_schedule" "this" {
+ name = "${local.lambda_full_name}-mon-9am-et"
+ group_name = aws_scheduler_schedule_group.this.name
+
+ flexible_time_window {
+ mode = "OFF"
+ }
+
+ # Schedule specifies to run every Monday at 9 AM ET
+ schedule_expression = "cron(0 9 ? * MON *)"
+ schedule_expression_timezone = "America/New_York"
+
+ target {
+ arn = aws_lambda_function.this.arn
+ role_arn = aws_iam_role.scheduler_assume_role.arn
+ }
+}
+
+resource "aws_lambda_function" "this" {
+ depends_on = [aws_iam_role_policy_attachment.this]
+
+ function_name = local.lambda_full_name
+
+ description = join("", [
+ "Lambda that reconciles the state of manifest files in S3 in the Incoming paths against their ",
+ "state in the database verifying that they have been loaded. If any are unloaded, an alert is ",
+ "sent"
+ ])
+
+ kms_key_arn = local.kms_key_id
+ image_uri = local.lambda_image_uri
+ source_code_hash = trimprefix(data.aws_ecr_image.this.id, "sha256:")
+ architectures = ["arm64"]
+ package_type = "Image"
+ memory_size = 128
+ timeout = 60
+
+ tags = {
+ Name = local.lambda_full_name
+ }
+
+ environment {
+ variables = {
+ BFD_ENVIRONMENT = local.env
+ DB_CLUSTER_NAME = var.db_cluster_identifier
+ ETL_BUCKET_ID = var.etl_bucket_id
+ ALERT_TOPIC_ARNS = join(",", data.aws_sns_topic.alert_topic[*].arn)
+ }
+ }
+
+ role = aws_iam_role.this.arn
+
+ vpc_config {
+ security_group_ids = [aws_security_group.this.id]
+ subnet_ids = data.aws_subnets.main.ids
+ }
+}
+
+resource "aws_security_group" "this" {
+ description = "Allow egress from ${local.lambda_full_name} Lambda"
+ name = local.lambda_full_name
+ tags = { Name = local.lambda_full_name }
+ vpc_id = data.aws_vpc.main.id
+
+ egress {
+ from_port = 0
+ protocol = "-1"
+ to_port = 0
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+}
+
+resource "aws_security_group_rule" "rds" {
+ type = "ingress"
+ from_port = 5432
+ to_port = 5432
+ protocol = "tcp"
+ description = "Allow ${local.lambda_full_name} access to ${var.db_cluster_identifier}"
+ security_group_id = data.aws_security_group.rds.id
+ source_security_group_id = aws_security_group.this.id
+}
diff --git a/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/variables.tf b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/variables.tf
new file mode 100644
index 0000000000..c162f3175d
--- /dev/null
+++ b/ops/terraform/services/pipeline/modules/bfd_pipeline_ccw_manifests_verifier/variables.tf
@@ -0,0 +1,29 @@
+variable "vpc_name" {
+ type = string
+ description = "Name of the current VPC"
+}
+
+variable "bfd_version" {
+ type = string
+ description = "BFD Lambda version to deploy"
+}
+
+variable "kms_key_alias" {
+ type = string
+ description = "Alias/ID of the main CMK"
+}
+
+variable "kms_config_key_alias" {
+ type = string
+ description = "Alias/ID of the config CMK"
+}
+
+variable "db_cluster_identifier" {
+ type = string
+ description = "Cluster ID of the target database"
+}
+
+variable "etl_bucket_id" {
+ type = string
+ description = "Bucket ID of the Pipeline ETL S3 Bucket"
+}
diff --git a/ops/terraform/services/pipeline/user-data.sh.tftpl b/ops/terraform/services/pipeline/user-data.sh.tftpl
index 1afde5f50d..672bc6137c 100644
--- a/ops/terraform/services/pipeline/user-data.sh.tftpl
+++ b/ops/terraform/services/pipeline/user-data.sh.tftpl
@@ -18,20 +18,20 @@ aws ssm get-parameters-by-path \
--path "/bfd/${env}/pipeline/nonsensitive/${pipeline_instance}" \
--recursive \
--region us-east-1 \
- --query 'Parameters' | jq 'map({(.Name|split("/")|last): .Value})|add' > pipeline_vars.json
+ --query 'Parameters' | jq 'map({(.Name|split("/")[6:]|join("_")): .Value})|add' > pipeline_vars.json
# shared pipeline variables
aws ssm get-parameters-by-path \
--path "/bfd/${env}/pipeline/nonsensitive/" \
--region us-east-1 \
- --query 'Parameters' | jq 'map({(.Name|split("/")|last): .Value})|add' > shared_pipeline_vars.json
+ --query 'Parameters' | jq 'map({(.Name|split("/")[5:]|join("_")): .Value})|add' > shared_pipeline_vars.json
# common service variables
aws ssm get-parameters-by-path \
--path "/bfd/${env}/common/nonsensitive/" \
--recursive \
--region us-east-1 \
- --query 'Parameters' | jq 'map({(.Name|split("/")|last): .Value})|add' > common_vars.json
+ --query 'Parameters' | jq 'map({(.Name|split("/")[5:]|join("_")): .Value})|add' > common_vars.json
new_relic_sensitive="$(aws ssm get-parameters-by-path \
--with-decryption \