Skip to content

feat: notification v3#1137

Merged
craigzour merged 127 commits into
mainfrom
feat/notifications-v3
Jul 6, 2026
Merged

feat: notification v3#1137
craigzour merged 127 commits into
mainfrom
feat/notifications-v3

Conversation

@thiessenp-cds

@thiessenp-cds thiessenp-cds commented Oct 27, 2025

Copy link
Copy Markdown
Contributor

This PR can only be merged after cds-snc/platform-forms-client#6824 because it requires the newest version of the connectors package (v3.0.0)

Make sure to revert last commit (THIS COMMIT IS ONLY USED TO TEST...) and integrate connectors package v3.0.0

Summary | Résumé

This PR adds push notifications for GCForms. There are two types of notifications: immediate and deferred. An immediate notification creates a record and immediately queues up Notify to send an email. A deferred notification is first created from the client and after the related process is completed the notification is queued up to send.

The utility functions can be found in the @gcforms/connector package: notification.sendImmediate(), notification.sendDeferred() and notification.enqueueDeferred().

@thiessenp-cds thiessenp-cds linked an issue Oct 27, 2025 that may be closed by this pull request
@thiessenp-cds thiessenp-cds changed the title Notifications v3 Notifications v3 (work in progress) Oct 27, 2025
@thiessenp-cds thiessenp-cds changed the title Notifications v3 (work in progress) feat: notifications DB Nov 24, 2025
@thiessenp-cds thiessenp-cds changed the title feat: notifications DB feat: notifications v3 [WIP] Nov 24, 2025
@thiessenp-cds thiessenp-cds self-assigned this Jun 19, 2026
@craigzour
craigzour self-requested a review June 25, 2026 15:24
@thiessenp-cds thiessenp-cds changed the title feat: notifications v3 feat: notification v3 Jun 25, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

⚠ Terrform update available

Terraform: 1.15.7 (using 1.15.6)
Terragrunt: 1.1.0 (using 1.0.8)

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Staging: ecr

✅   Terraform Init: success
✅   Terraform Validate: success
✅   Terraform Format: success
✅   Terraform Plan: success
✅   Conftest: success

Plan: 2 to add, 0 to change, 0 to destroy
Show summary
CHANGE NAME
add aws_ecr_lifecycle_policy.lambda["notification-lambda"]
aws_ecr_repository.lambda["notification-lambda"]
Show plan
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_ecr_lifecycle_policy.lambda["notification-lambda"] will be created
  + resource "aws_ecr_lifecycle_policy" "lambda" {
      + id          = (known after apply)
      + policy      = jsonencode(
            {
              + rules = [
                  + {
                      + action       = {
                          + type = "expire"
                        }
                      + description  = "Keep last 10 images"
                      + rulePriority = 1
                      + selection    = {
                          + countNumber = 10
                          + countType   = "imageCountMoreThan"
                          + tagStatus   = "any"
                        }
                    },
                ]
            }
        )
      + region      = "ca-central-1"
      + registry_id = (known after apply)
      + repository  = "notification-lambda"
    }

  # aws_ecr_repository.lambda["notification-lambda"] will be created
  + resource "aws_ecr_repository" "lambda" {
      + arn                  = (known after apply)
      + force_delete         = false
      + id                   = (known after apply)
      + image_tag_mutability = "MUTABLE"
      + name                 = "notification-lambda"
      + region               = "ca-central-1"
      + registry_id          = (known after apply)
      + repository_url       = (known after apply)
      + tags_all             = {
          + "CostCentre" = "forms-platform-staging"
          + "Terraform"  = "true"
          + "ssc_cbrid"  = "22DI"
        }

      + image_scanning_configuration {
          + scan_on_push = true
        }
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  ~ ecr_repository_lambda_urls                     = {
      + notification-lambda             = (known after apply)
        # (16 unchanged attributes hidden)
    }

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: plan.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "plan.tfplan"
Show Conftest results
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.api"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.forms_app_legacy_repository"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.idp"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"api-end-to-end-test-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"audit-logs-archiver-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"audit-logs-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"cognito-email-sender-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"cognito-pre-sign-up-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"file-upload-cleanup-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"file-upload-processor-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"form-archiver-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"load-testing-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"nagware-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"notification-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"notify-slack-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"reliability-dlq-consumer-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"reliability-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"response-archiver-lambda\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecr_repository.lambda[\"submission-lambda\"]"]
WARN - plan.json - main - Missing Common Tags:...

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Staging: sqs

✅   Terraform Init: success
✅   Terraform Validate: success
✅   Terraform Format: success
✅   Terraform Plan: success
✅   Conftest: success

Plan: 1 to add, 0 to change, 0 to destroy
Show summary
CHANGE NAME
add aws_sqs_queue.notification_queue
Show plan
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_sqs_queue.notification_queue will be created
  + resource "aws_sqs_queue" "notification_queue" {
      + arn                               = (known after apply)
      + content_based_deduplication       = false
      + deduplication_scope               = (known after apply)
      + delay_seconds                     = 0
      + fifo_queue                        = false
      + fifo_throughput_limit             = (known after apply)
      + id                                = (known after apply)
      + kms_data_key_reuse_period_seconds = 300
      + kms_master_key_id                 = "alias/aws/sqs"
      + max_message_size                  = 262144
      + message_retention_seconds         = 1800
      + name                              = "notification_queue"
      + name_prefix                       = (known after apply)
      + policy                            = (known after apply)
      + receive_wait_time_seconds         = 0
      + redrive_allow_policy              = (known after apply)
      + redrive_policy                    = (known after apply)
      + region                            = "ca-central-1"
      + sqs_managed_sse_enabled           = (known after apply)
      + tags                              = {
          + "ssc_cbrid" = "22DH"
        }
      + tags_all                          = {
          + "CostCentre" = "forms-platform-staging"
          + "Terraform"  = "true"
          + "ssc_cbrid"  = "22DH"
        }
      + url                               = (known after apply)
      + visibility_timeout_seconds        = 300
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + sqs_notification_queue_arn              = (known after apply)
  + sqs_notification_queue_url              = (known after apply)

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: plan.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "plan.tfplan"
Show Conftest results
WARN - plan.json - main - Missing Common Tags: ["aws_sqs_queue.api_audit_log_deadletter_queue"]
WARN - plan.json - main - Missing Common Tags: ["aws_sqs_queue.api_audit_log_queue"]
WARN - plan.json - main - Missing Common Tags: ["aws_sqs_queue.audit_log_deadletter_queue"]
WARN - plan.json - main - Missing Common Tags: ["aws_sqs_queue.audit_log_queue"]
WARN - plan.json - main - Missing Common Tags: ["aws_sqs_queue.file_upload_deadletter_queue"]
WARN - plan.json - main - Missing Common Tags: ["aws_sqs_queue.file_upload_queue"]
WARN - plan.json - main - Missing Common Tags: ["aws_sqs_queue.notification_queue"]
WARN - plan.json - main - Missing Common Tags: ["aws_sqs_queue.reliability_deadletter_queue"]
WARN - plan.json - main - Missing Common Tags: ["aws_sqs_queue.reliability_queue"]
WARN - plan.json - main - Missing Common Tags: ["aws_sqs_queue.reliability_reprocessing_queue"]

30 tests, 20 passed, 10 warnings, 0 failures, 0 exceptions

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Staging: dynamodb

✅   Terraform Init: success
✅   Terraform Validate: success
✅   Terraform Format: success
✅   Terraform Plan: success
✅   Conftest: success

Plan: 1 to add, 0 to change, 0 to destroy
Show summary
CHANGE NAME
add aws_dynamodb_table.notification
Show plan
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_dynamodb_table.notification will be created
  + resource "aws_dynamodb_table" "notification" {
      + arn                         = (known after apply)
      + billing_mode                = "PAY_PER_REQUEST"
      + deletion_protection_enabled = true
      + hash_key                    = "NotificationID"
      + id                          = (known after apply)
      + name                        = "Notification"
      + read_capacity               = (known after apply)
      + region                      = "ca-central-1"
      + stream_arn                  = (known after apply)
      + stream_label                = (known after apply)
      + stream_view_type            = (known after apply)
      + tags_all                    = {
          + "CostCentre" = "forms-platform-staging"
          + "Terraform"  = "true"
          + "ssc_cbrid"  = "22DI"
        }
      + write_capacity              = (known after apply)

      + attribute {
          + name = "NotificationID"
          + type = "S"
        }

      + global_secondary_index (known after apply)

      + global_table_witness (known after apply)

      + point_in_time_recovery {
          + enabled                 = true
          + recovery_period_in_days = (known after apply)
        }

      + server_side_encryption {
          + enabled     = true
          + kms_key_arn = "arn:aws:kms:ca-central-1:687401027353:key/1f3edb85-9eac-4da9-8c7c-43a68e339ede"
        }

      + ttl {
          + attribute_name = "TTL"
          + enabled        = true
        }

      + warm_throughput (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + dynamodb_notification_table_arn    = (known after apply)
  + dynamodb_notification_table_name   = "Notification"

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: plan.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "plan.tfplan"
Show Conftest results
WARN - plan.json - main - Missing Common Tags: ["aws_dynamodb_table.api_audit_logs"]
WARN - plan.json - main - Missing Common Tags: ["aws_dynamodb_table.audit_logs"]
WARN - plan.json - main - Missing Common Tags: ["aws_dynamodb_table.notification"]
WARN - plan.json - main - Missing Common Tags: ["aws_dynamodb_table.reliability_queue"]
WARN - plan.json - main - Missing Common Tags: ["aws_dynamodb_table.vault"]

25 tests, 20 passed, 5 warnings, 0 failures, 0 exceptions

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Staging: app

✅   Terraform Init: success
✅   Terraform Validate: success
✅   Terraform Format: success
✅   Terraform Plan: success
✅   Conftest: success

Plan: 1 to add, 6 to change, 0 to destroy
Show summary
CHANGE NAME
add aws_ecs_task_definition.form_viewer
update aws_iam_policy.forms_dynamodb
aws_iam_policy.forms_sqs
module.gc_forms_code_pipeline.aws_codebuild_project.ecs_render
module.gc_forms_code_pipeline.aws_codepipeline.this
module.gc_forms_code_pipeline.aws_iam_role.this
module.gc_forms_code_pipeline.aws_iam_role_policy.codepipeline_policy
Show plan
Resource actions are indicated with the following symbols:
  + create
  ~ update in-place
 <= read (data resources)

Terraform will perform the following actions:

  # aws_ecs_task_definition.form_viewer will be created
  + resource "aws_ecs_task_definition" "form_viewer" {
      + arn                      = (known after apply)
      + arn_without_revision     = (known after apply)
      + container_definitions    = (sensitive value)
      + cpu                      = "2048"
      + enable_fault_injection   = (known after apply)
      + execution_role_arn       = "arn:aws:iam::687401027353:role/form-viewer"
      + family                   = "form-viewer"
      + id                       = (known after apply)
      + memory                   = "4096"
      + network_mode             = "awsvpc"
      + region                   = "ca-central-1"
      + requires_compatibilities = [
          + "FARGATE",
        ]
      + revision                 = (known after apply)
      + skip_destroy             = false
      + tags_all                 = {
          + "CostCentre" = "forms-platform-staging"
          + "Terraform"  = "true"
          + "ssc_cbrid"  = "22DI"
        }
      + task_role_arn            = "arn:aws:iam::687401027353:role/form-viewer"
      + track_latest             = false
    }

  # aws_iam_policy.forms_dynamodb will be updated in-place
  ~ resource "aws_iam_policy" "forms_dynamodb" {
        id               = "arn:aws:iam::687401027353:policy/forms_dynamodb"
        name             = "forms_dynamodb"
      ~ policy           = jsonencode(
          ~ {
              ~ Statement = [
                  ~ {
                      ~ Resource = [
                            # (2 unchanged elements hidden)
                            "arn:aws:dynamodb:ca-central-1:687401027353:table/ReliabilityQueue",
                          + "arn:aws:dynamodb:ca-central-1:687401027353:table/Notification",
                        ]
                      - Sid      = ""
                        # (2 unchanged attributes hidden)
                    },
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {
            "ssc_cbrid" = "22DH"
        }
        # (7 unchanged attributes hidden)
    }

  # aws_iam_policy.forms_sqs will be updated in-place
  ~ resource "aws_iam_policy" "forms_sqs" {
        id               = "arn:aws:iam::687401027353:policy/forms_sqs"
        name             = "forms_sqs"
      ~ policy           = jsonencode(
          ~ {
              ~ Statement = [
                  ~ {
                      ~ Resource = [
                            "arn:aws:sqs:ca-central-1:687401027353:reliability_reprocessing_queue",
                          + "arn:aws:sqs:ca-central-1:687401027353:notification_queue",
                            "arn:aws:sqs:ca-central-1:687401027353:audit_log_queue",
                        ]
                        # (2 unchanged attributes hidden)
                    },
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {
            "ssc_cbrid" = "22DH"
        }
        # (7 unchanged attributes hidden)
    }

  # module.gc_forms_code_pipeline.data.aws_ecs_task_definition.this will be read during apply
  # (depends on a resource or a module with changes pending)
 <= data "aws_ecs_task_definition" "this" {
      + arn                      = (known after apply)
      + arn_without_revision     = (known after apply)
      + container_definitions    = (known after apply)
      + cpu                      = (known after apply)
      + enable_fault_injection   = (known after apply)
      + ephemeral_storage        = (known after apply)
      + execution_role_arn       = (known after apply)
      + family                   = (known after apply)
      + id                       = (known after apply)
      + ipc_mode                 = (known after apply)
      + memory                   = (known after apply)
      + network_mode             = (known after apply)
      + pid_mode                 = (known after apply)
      + placement_constraints    = (known after apply)
      + proxy_configuration      = (known after apply)
      + region                   = (known after apply)
      + requires_compatibilities = (known after apply)
      + revision                 = (known after apply)
      + runtime_platform         = (known after apply)
      + status                   = (known after apply)
      + task_definition          = "form-viewer"
      + task_role_arn            = (known after apply)
      + volume                   = (known after apply)
    }

  # module.gc_forms_code_pipeline.data.aws_iam_policy_document.assume_role will be read during apply
  # (depends on a resource or a module with changes pending)
 <= data "aws_iam_policy_document" "assume_role" {
      + id            = (known after apply)
      + json          = (known after apply)
      + minified_json = (known after apply)

      + statement {
          + actions = [
              + "sts:AssumeRole",
            ]
          + effect  = "Allow"

          + principals {
              + identifiers = [
                  + "codebuild.amazonaws.com",
                  + "codedeploy.amazonaws.com",
                  + "codepipeline.amazonaws.com",
                ]
              + type        = "Service"
            }
        }
    }

  # module.gc_forms_code_pipeline.data.aws_iam_policy_document.codepipeline_policy will be read during apply
  # (config refers to values not yet known)
 <= data "aws_iam_policy_document" "codepipeline_policy" {
      + id            = (known after apply)
      + json          = (known after apply)
      + minified_json = (known after apply)

      + statement {
          + actions   = [
              + "s3:GetBucketVersioning",
              + "s3:GetObject",
              + "s3:GetObjectVersion",
              + "s3:PutObject",
              + "s3:PutObjectAcl",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:s3:::gc-forms-web-app-687401027353-pipeline",
              + "arn:aws:s3:::gc-forms-web-app-687401027353-pipeline/*",
            ]
        }
      + statement {
          + actions   = [
              + "codestar-connections:UseConnection",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:codestar-connections:ca-central-1:687401027353:connection/18936475-2bc9-4aad-b9cf-f393f88022c2",
            ]
        }
      + statement {
          + actions   = [
              + "codebuild:BatchGetBuilds",
              + "codebuild:StartBuild",
            ]
          + effect    = "Allow"
          + resources = [
              + "*",
            ]
        }
      + statement {
          + actions   = [
              + "logs:CreateLogGroup",
              + "logs:CreateLogStream",
              + "logs:PutLogEvents",
            ]
          + effect    = "Allow"
          + resources = [
              + "*",
            ]
        }
      + statement {
          + actions   = [
              + "codeconnections:GetConnection",
              + "codeconnections:GetConnectionToken",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:codestar-connections:ca-central-1:687401027353:connection/18936475-2bc9-4aad-b9cf-f393f88022c2",
            ]
        }
      + statement {
          + actions   = [
              + "ecr:BatchCheckLayerAvailability",
              + "ecr:CompleteLayerUpload",
              + "ecr:DescribeRepositories",
              + "ecr:GetAuthorizationToken",
              + "ecr:GetDownloadUrlForLayer",
              + "ecr:InitiateLayerUpload",
              + "ecr:PutImage",
              + "ecr:UploadLayerPart",
            ]
          + effect    = "Allow"
          + resources = [
              + "*",
            ]
        }
      + statement {
          + actions   = [
              + "codedeploy:CreateDeployment",
              + "codedeploy:GetDeployment",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:codedeploy:*:687401027353:deploymentgroup:gc-forms-web-app/*",
            ]
        }
      + statement {
          + actions   = [
              + "codedeploy:GetApplication",
              + "codedeploy:GetApplicationRevision",
              + "codedeploy:RegisterApplicationRevision",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:codedeploy:*:687401027353:application:gc-forms-web-app",
              + "arn:aws:codedeploy:*:687401027353:application:gc-forms-web-app/*",
            ]
        }
      + statement {
          + actions   = [
              + "codedeploy:GetDeploymentConfig",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:codedeploy:*:687401027353:deploymentconfig:*",
            ]
        }
      + statement {
          + actions   = [
              + "ecs:DescribeServices",
              + "ecs:DescribeTaskDefinition",
              + "ecs:RegisterTaskDefinition",
            ]
          + effect    = "Allow"
          + resources = [
              + "*",
            ]
        }
      + statement {
          + actions   = [
              + "ec2:CreateNetworkInterface",
              + "ec2:DeleteNetworkInterface",
              + "ec2:DescribeDhcpOptions",
              + "ec2:DescribeNetworkInterfaces",
              + "ec2:DescribeSecurityGroups",
              + "ec2:DescribeSubnets",
              + "ec2:DescribeVpcs",
            ]
          + effect    = "Allow"
          + resources = [
              + "*",
            ]
        }
      + statement {
          + actions   = [
              + "ec2:CreateNetworkInterfacePermission",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:ec2:ca-central-1:687401027353:network-interface/*",
            ]
        }
      + statement {
          + actions   = [
              + "codestar-connections:UseConnection",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:iam::*:role/Service*",
            ]
        }
      + statement {
          + actions   = [
              + "iam:PassRole",
            ]
          + effect    = "Allow"
          + resources = [
              + (known after apply),
            ]
        }
      + statement {
          + actions   = [
              + "secretsmanager:GetSecretValue",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:secretsmanager:ca-central-1:687401027353:secret:database-connection-url-40YMxa",
            ]
        }
    }

  # module.gc_forms_code_pipeline.data.aws_lb_target_group.this will be read during apply
  # (depends on a resource or a module with changes pending)
 <= data "aws_lb_target_group" "this" {
      + arn                                = (known after apply)
      + arn_suffix                         = (known after apply)
      + connection_termination             = (known after apply)
      + deregistration_delay               = (known after apply)
      + health_check                       = (known after apply)
      + id                                 = (known after apply)
      + lambda_multi_value_headers_enabled = (known after apply)
      + load_balancer_arns                 = (known after apply)
      + load_balancing_algorithm_type      = (known after apply)
      + load_balancing_anomaly_mitigation  = (known after apply)
      + load_balancing_cross_zone_enabled  = (known after apply)
      + name                               = "form-viewer"
      + port                               = (known after apply)
      + preserve_client_ip                 = (known after apply)
      + protocol                           = (known after apply)
      + protocol_version                   = (known after apply)
      + proxy_protocol_v2                  = (known after apply)
      + region                             = (known after apply)
      + slow_start                         = (known after apply)
      + stickiness                         = (known after apply)
      + tags                               = (known after apply)
      + target_control_port                = (known after apply)
      + target_type                        = (known after apply)
      + vpc_id                             = (known after apply)
    }

  # module.gc_forms_code_pipeline.aws_codebuild_project.ecs_render will be updated in-place
  ~ resource "aws_codebuild_project" "ecs_render" {
        id                     = "arn:aws:codebuild:ca-central-1:687401027353:project/ECS-Render-gc-forms-web-app"
        name                   = "ECS-Render-gc-forms-web-app"
        tags                   = {
            "ssc_cbrid" = "22DH"
        }
        # (16 unchanged attributes hidden)

      ~ source {
          ~ buildspec           = (sensitive value)
            # (5 unchanged attributes hidden)
        }

        # (5 unchanged blocks hidden)
    }

  # module.gc_forms_code_pipeline.aws_codepipeline.this will be updated in-place
  ~ resource "aws_codepipeline" "this" {
        id             = "gc-forms-web-app-pipeline"
        name           = "gc-forms-web-app-pipeline"
        tags           = {
            "ssc_cbrid" = "22DH"
        }
        # (7 unchanged attributes hidden)

      ~ stage {
            name = "Build"

          ~ action {
              ~ configuration      = {
                  - "EnvironmentVariables" = (sensitive value)
                  - "PrimarySource"        = "GitSource"
                  - "ProjectName"          = "ECS-Render-gc-forms-web-app"
                } -> (known after apply)
                name               = "Render_For_ECS"
                # (11 unchanged attributes hidden)
            }
        }

        # (4 unchanged blocks hidden)
    }

  # module.gc_forms_code_pipeline.aws_iam_role.this will be updated in-place
  ~ resource "aws_iam_role" "this" {
      ~ assume_role_policy    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "sts:AssumeRole"
                      - Effect    = "Allow"
                      - Principal = {
                          - Service = [
                              - "codepipeline.amazonaws.com",
                              - "codedeploy.amazonaws.com",
                              - "codebuild.amazonaws.com",
                            ]
                        }
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        id                    = "Code-Pipeline-gc-forms-web-app"
        name                  = "Code-Pipeline-gc-forms-web-app"
        tags                  = {
            "ssc_cbrid" = "22DH"
        }
        # (11 unchanged attributes hidden)

        # (1 unchanged block hidden)
    }

  # module.gc_forms_code_pipeline.aws_iam_role_policy.codepipeline_policy will be updated in-place
  ~ resource "aws_iam_role_policy" "codepipeline_policy" {
        id          = "Code-Pipeline-gc-forms-web-app:codepipeline_policy"
        name        = "codepipeline_policy"
      ~ policy      = jsonencode(
            {
              - Statement = [
                  - {
                      - Action   = [
                          - "s3:PutObjectAcl",
                          - "s3:PutObject",
                          - "s3:GetObjectVersion",
                          - "s3:GetObject",
                          - "s3:GetBucketVersioning",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:s3:::gc-forms-web-app-687401027353-pipeline/*",
                          - "arn:aws:s3:::gc-forms-web-app-687401027353-pipeline",
                        ]
                    },
                  - {
                      - Action   = "codestar-connections:UseConnection"
                      - Effect   = "Allow"
                      - Resource = "arn:aws:codestar-connections:ca-central-1:687401027353:connection/18936475-2bc9-4aad-b9cf-f393f88022c2"
                    },
                  - {
                      - Action   = [
                          - "codebuild:StartBuild",
                          - "codebuild:BatchGetBuilds",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                    },
                  - {
                      - Action   = [
                          - "logs:PutLogEvents",
                          - "logs:CreateLogStream",
                          - "logs:CreateLogGroup",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                    },
                  - {
                      - Action   = [
                          - "codeconnections:GetConnectionToken",
                          - "codeconnections:GetConnection",
                        ]
                      - Effect   = "Allow"
                      - Resource = "arn:aws:codestar-connections:ca-central-1:687401027353:connection/18936475-2bc9-4aad-b9cf-f393f88022c2"
                    },
                  - {
                      - Action   = [
                          - "ecr:UploadLayerPart",
                          - "ecr:PutImage",
                          - "ecr:InitiateLayerUpload",
                          - "ecr:GetDownloadUrlForLayer",
                          - "ecr:GetAuthorizationToken",
                          - "ecr:DescribeRepositories",
                          - "ecr:CompleteLayerUpload",
                          - "ecr:BatchCheckLayerAvailability",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                    },
                  - {
                      - Action   = [
                          - "codedeploy:GetDeployment",
                          - "codedeploy:CreateDeployment",
                        ]
                      - Effect   = "Allow"
                      - Resource = "arn:aws:codedeploy:*:687401027353:deploymentgroup:gc-forms-web-app/*"
                    },
                  - {
                      - Action   = [
                          - "codedeploy:RegisterApplicationRevision",
                          - "codedeploy:GetApplicationRevision",
                          - "codedeploy:GetApplication",
                        ]
                      - Effect   = "Allow"
                      - Resource = [
                          - "arn:aws:codedeploy:*:687401027353:application:gc-forms-web-app/*",
                          - "arn:aws:codedeploy:*:687401027353:application:gc-forms-web-app",
                        ]
                    },
                  - {
                      - Action   = "codedeploy:GetDeploymentConfig"
                      - Effect   = "Allow"
                      - Resource = "arn:aws:codedeploy:*:687401027353:deploymentconfig:*"
                    },
                  - {
                      - Action   = [
                          - "ecs:RegisterTaskDefinition",
                          - "ecs:DescribeTaskDefinition",
                          - "ecs:DescribeServices",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                    },
                  - {
                      - Action   = [
                          - "ec2:DescribeVpcs",
                          - "ec2:DescribeSubnets",
                          - "ec2:DescribeSecurityGroups",
                          - "ec2:DescribeNetworkInterfaces",
                          - "ec2:DescribeDhcpOptions",
                          - "ec2:DeleteNetworkInterface",
                          - "ec2:CreateNetworkInterface",
                        ]
                      - Effect   = "Allow"
                      - Resource = "*"
                    },
                  - {
                      - Action   = "ec2:CreateNetworkInterfacePermission"
                      - Effect   = "Allow"
                      - Resource = "arn:aws:ec2:ca-central-1:687401027353:network-interface/*"
                    },
                  - {
                      - Action   = "codestar-connections:UseConnection"
                      - Effect   = "Allow"
                      - Resource = "arn:aws:iam::*:role/Service*"
                    },
                  - {
                      - Action   = "iam:PassRole"
                      - Effect   = "Allow"
                      - Resource = "arn:aws:iam::687401027353:role/form-viewer"
                    },
                  - {
                      - Action   = "secretsmanager:GetSecretValue"
                      - Effect   = "Allow"
                      - Resource = "arn:aws:secretsmanager:ca-central-1:687401027353:secret:database-connection-url-40YMxa"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (2 unchanged attributes hidden)
    }

Plan: 1 to add, 6 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: plan.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "plan.tfplan"
Show Conftest results
WARN - plan.json - main - Missing Common Tags: ["aws_appautoscaling_target.forms[0]"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.forms"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecs_cluster.forms"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecs_service.form_viewer"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecs_task_definition.form_viewer"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.cognito"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.ecs_xray"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.forms_audit_logs"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.forms_dynamodb"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.forms_kms"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.forms_secrets_manager"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.forms_sqs"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_role.forms"]
WARN - plan.json - main - Missing Common Tags: ["module.gc_forms_code_pipeline.aws_codebuild_project.ecs_render"]
WARN - plan.json - main - Missing Common Tags: ["module.gc_forms_code_pipeline.aws_codedeploy_app.this"]
WARN - plan.json - main - Missing Common Tags: ["module.gc_forms_code_pipeline.aws_codedeploy_deployment_group.this"]
WARN - plan.json - main - Missing Common Tags: ["module.gc_forms_code_pipeline.aws_codepipeline.this"]
WARN - plan.json - main - Missing Common Tags: ["module.gc_forms_code_pipeline.aws_codestarconnections_connection.this"]
WARN - plan.json - main - Missing Common Tags: ["module.gc_forms_code_pipeline.aws_iam_role.this"]
WARN - plan.json - main - Missing Common Tags: ["module.gc_forms_code_pipeline.aws_s3_bucket.codepipeline_bucket"]

40 tests, 20 passed, 20 warnings, 0 failures, 0 exceptions

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Staging: lambdas

✅   Terraform Init: success
✅   Terraform Validate: success
✅   Terraform Format: success
✅   Terraform Plan: success
✅   Conftest: success

Plan: 3 to add, 2 to change, 0 to destroy
Show summary
CHANGE NAME
add aws_cloudwatch_log_group.notification
aws_lambda_event_source_mapping.notification_sqs
aws_lambda_function.notification
update aws_iam_policy.lambda_dynamodb
aws_lambda_function.reliability
Show plan
Resource actions are indicated with the following symbols:
  + create
  ~ update in-place

Terraform will perform the following actions:

  # aws_cloudwatch_log_group.notification will be created
  + resource "aws_cloudwatch_log_group" "notification" {
      + arn                         = (known after apply)
      + deletion_protection_enabled = (known after apply)
      + id                          = (known after apply)
      + kms_key_id                  = "arn:aws:kms:ca-central-1:687401027353:key/c5c2a1c2-c092-4fa1-8daf-3414f3511b1d"
      + log_group_class             = (known after apply)
      + name                        = "/aws/lambda/Notification"
      + name_prefix                 = (known after apply)
      + region                      = "ca-central-1"
      + retention_in_days           = 731
      + skip_destroy                = false
      + tags                        = {
          + "ssc_cbrid" = "22DH"
        }
      + tags_all                    = {
          + "CostCentre" = "forms-platform-staging"
          + "Terraform"  = "true"
          + "ssc_cbrid"  = "22DH"
        }
    }

  # aws_iam_policy.lambda_dynamodb will be updated in-place
  ~ resource "aws_iam_policy" "lambda_dynamodb" {
        id               = "arn:aws:iam::687401027353:policy/lambda_dynamobdb"
        name             = "lambda_dynamobdb"
      ~ policy           = jsonencode(
          ~ {
              ~ Statement = [
                  ~ {
                      ~ Resource = [
                            # (4 unchanged elements hidden)
                            "arn:aws:dynamodb:ca-central-1:687401027353:table/ReliabilityQueue",
                          + "arn:aws:dynamodb:ca-central-1:687401027353:table/Notification",
                            "arn:aws:dynamodb:ca-central-1:687401027353:table/AuditLogs/index/*",
                            # (3 unchanged elements hidden)
                        ]
                        # (2 unchanged attributes hidden)
                    },
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {
            "ssc_cbrid" = "22DH"
        }
        # (7 unchanged attributes hidden)
    }

  # aws_lambda_event_source_mapping.notification_sqs will be created
  + resource "aws_lambda_event_source_mapping" "notification_sqs" {
      + arn                           = (known after apply)
      + batch_size                    = 10
      + enabled                       = true
      + event_source_arn              = "arn:aws:sqs:ca-central-1:687401027353:notification_queue"
      + function_arn                  = (known after apply)
      + function_name                 = "notification"
      + function_response_types       = [
          + "ReportBatchItemFailures",
        ]
      + id                            = (known after apply)
      + last_modified                 = (known after apply)
      + last_processing_result        = (known after apply)
      + maximum_record_age_in_seconds = (known after apply)
      + maximum_retry_attempts        = (known after apply)
      + parallelization_factor        = (known after apply)
      + region                        = "ca-central-1"
      + state                         = (known after apply)
      + state_transition_reason       = (known after apply)
      + tags_all                      = {
          + "CostCentre" = "forms-platform-staging"
          + "Terraform"  = "true"
          + "ssc_cbrid"  = "22DI"
        }
      + uuid                          = (known after apply)

      + amazon_managed_kafka_event_source_config (known after apply)

      + self_managed_kafka_event_source_config (known after apply)
    }

  # aws_lambda_function.notification will be created
  + resource "aws_lambda_function" "notification" {
      + architectures                  = (known after apply)
      + arn                            = (known after apply)
      + code_sha256                    = (known after apply)
      + function_name                  = "notification"
      + id                             = (known after apply)
      + image_uri                      = "test_url:latest"
      + invoke_arn                     = (known after apply)
      + last_modified                  = (known after apply)
      + memory_size                    = 256
      + package_type                   = "Image"
      + publish                        = false
      + qualified_arn                  = (known after apply)
      + qualified_invoke_arn           = (known after apply)
      + region                         = "ca-central-1"
      + reserved_concurrent_executions = -1
      + response_streaming_invoke_arn  = (known after apply)
      + role                           = "arn:aws:iam::687401027353:role/iam_for_lambda"
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      + skip_destroy                   = false
      + source_code_hash               = (known after apply)
      + source_code_size               = (known after apply)
      + tags_all                       = {
          + "CostCentre" = "forms-platform-staging"
          + "Terraform"  = "true"
          + "ssc_cbrid"  = "22DI"
        }
      + timeout                        = 60
      + version                        = (known after apply)

      + environment {
          + variables = {
              + "DYNAMODB_NOTIFICATION_TABLE_NAME" = "Notification"
              + "NOTIFY_API_KEY"                   = (sensitive value)
              + "REGION"                           = "ca-central-1"
              + "TEMPLATE_ID"                      = "8d597a1b-a1d6-4e3c-8421-042a2b4158b7"
            }
        }

      + ephemeral_storage (known after apply)

      + logging_config {
          + log_format = "Text"
          + log_group  = "/aws/lambda/Notification"
        }

      + tracing_config {
          + mode = "Active"
        }

      + vpc_config {
          + ipv6_allowed_for_dual_stack = false
          + security_group_ids          = [
              + "sg-06651d69cd4d3c50f",
            ]
          + subnet_ids                  = [
              + "subnet-07e38df0760d389d1",
              + "subnet-07f9debd31e48ce64",
              + "subnet-0af8e6e3cf80f582d",
            ]
          + vpc_id                      = (known after apply)
        }
    }

  # aws_lambda_function.reliability will be updated in-place
  ~ resource "aws_lambda_function" "reliability" {
        id                             = "reliability"
        tags                           = {}
        # (31 unchanged attributes hidden)

      ~ environment {
          ~ variables = {
              + "NOTIFICATION_QUEUE_URL" = "https://sqs.ca-central-1.amazonaws.com/687401027353/notification_queue"
                # (5 unchanged elements hidden)
            }
        }

        # (4 unchanged blocks hidden)
    }

Plan: 3 to add, 2 to change, 0 to destroy.

Changes to Outputs:
  + lambda_notification_function_name              = "notification"
  + lambda_notification_log_group_name             = "/aws/lambda/Notification"

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: plan.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "plan.tfplan"
Show Conftest results
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.api_end_to_end_test_lambda_trigger"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.audit_logs_archiver_lambda_trigger"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.file_upload_cleanup_trigger"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.form_archiver_lambda_trigger"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.nagware_lambda_trigger"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.reliability_dlq_lambda_trigger"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.response_archiver_lambda_trigger"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.api_end_to_end_test"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.archive_form_templates"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.audit_logs"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.audit_logs_archiver"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.dead_letter_queue_consumer"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.file_upload"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.file_upload_cleanup"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.nagware"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.notification"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.reliability"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.response_archiver"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.submission"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.vault_integrity"]
WARN - plan.json - main - Missing Common Tags:...

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Staging: alarms

✅   Terraform Init: success
✅   Terraform Validate: success
✅   Terraform Format: success
✅   Terraform Plan: success
✅   Conftest: success

Plan: 2 to add, 0 to change, 0 to destroy
Show summary
CHANGE NAME
add aws_cloudwatch_log_subscription_filter.lambda_error_detection[&quot;notification&quot;]
aws_cloudwatch_metric_alarm.lambda_error_detection[&quot;notification&quot;]
Show plan
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_cloudwatch_log_subscription_filter.lambda_error_detection["notification"] will be created
  + resource "aws_cloudwatch_log_subscription_filter" "lambda_error_detection" {
      + apply_on_transformed_logs = (known after apply)
      + destination_arn           = "arn:aws:lambda:ca-central-1:687401027353:function:notify-slack"
      + distribution              = "ByLogStream"
      + filter_pattern            = "{($.level = \"warn\") || ($.level = \"error\")}"
      + id                        = (known after apply)
      + log_group_name            = "/aws/lambda/Notification"
      + name                      = "error_detection_in_notification_lambda_logs"
      + region                    = "ca-central-1"
      + role_arn                  = (known after apply)
    }

  # aws_cloudwatch_metric_alarm.lambda_error_detection["notification"] will be created
  + resource "aws_cloudwatch_metric_alarm" "lambda_error_detection" {
      + actions_enabled                       = true
      + alarm_actions                         = [
          + "arn:aws:sns:ca-central-1:687401027353:alert-critical",
        ]
      + alarm_description                     = "Detected error or timeout in notification lambda function (SEV2)"
      + alarm_name                            = "notification-lambda-error-detection"
      + arn                                   = (known after apply)
      + comparison_operator                   = "GreaterThanThreshold"
      + dimensions                            = {
          + "FunctionName" = "notification"
        }
      + evaluate_low_sample_count_percentiles = (known after apply)
      + evaluation_periods                    = 1
      + id                                    = (known after apply)
      + metric_name                           = "Errors"
      + namespace                             = "AWS/Lambda"
      + period                                = 60
      + region                                = "ca-central-1"
      + statistic                             = "Sum"
      + tags                                  = {
          + "ssc_cbrid" = "22DH"
        }
      + tags_all                              = {
          + "CostCentre" = "forms-platform-staging"
          + "Terraform"  = "true"
          + "ssc_cbrid"  = "22DH"
        }
      + threshold                             = 0
      + treat_missing_data                    = "notBreaching"
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Warning: Deprecated value used

  on .terraform/modules/athena/athena_access_logs/locals.tf line 6, in locals:
   6:   region     = data.aws_region.current.name

  The deprecation originates from module.athena.data.aws_region.current.name

name is deprecated. Use region instead.

(and one more similar warning elsewhere)

Warning: Argument is deprecated

  with module.athena_bucket.aws_s3_bucket.this,
  on .terraform/modules/athena_bucket/S3/main.tf line 8, in resource "aws_s3_bucket" "this":
   8: resource "aws_s3_bucket" "this" {

server_side_encryption_configuration is deprecated. Use the
aws_s3_bucket_server_side_encryption_configuration resource instead.

(and 2 more similar warnings elsewhere)

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: plan.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "plan.tfplan"
Show Conftest results
WARN - plan.json - main - Missing Common Tags: ["aws_athena_data_catalog.dynamodb"]
WARN - plan.json - main - Missing Common Tags: ["aws_athena_data_catalog.rds_data_catalog"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.code_pipeline_state_change"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.notify_slack"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.ELB_5xx_error_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.ELB_healthy_hosts"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.alb_ddos"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_cpu_utilization_high_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_lb_healthy_host_count"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_lb_unhealthy_host_count"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_memory_utilization_high_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_response_time_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.cognito_signin_exceeded"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.ddos_detected_forms_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.ddos_detected_route53_warn[0]"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.dlq_message_detector[\"api_audit_log\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.dlq_message_detector[\"app_audit_log\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.dlq_message_detector[\"file_upload\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.dlq_message_detector[\"reliability\"]"]
WARN - plan.json - main -...

@craigzour
craigzour merged commit 4599a0c into main Jul 6, 2026
18 checks passed
@craigzour
craigzour deleted the feat/notifications-v3 branch July 6, 2026 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Notifications DB

2 participants