Skip to content

Commit 65481fd

Browse files
Merge remote-tracking branch 'origin/main' into feature/CCM-12997
2 parents ca58f3b + c8a3e39 commit 65481fd

File tree

105 files changed

+3520
-670
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+3520
-670
lines changed

.github/CODEOWNERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
/docs/ @NHSDigital/nhs-notify-supplier-api
88
/infrastructure/terraform/ @NHSDigital/nhs-notify-platform @NHSDigital/nhs-notify-supplier-api-admins
99

10+
# Root level AGENTS.md owned by platform.
11+
AGENTS.md @NHSDigital/nhs-notify-platform
12+
1013
# Codeowners must be final check
1114
/.github/CODEOWNERS @NHSDigital/nhs-notify-code-owners
1215
/CODEOWNERS @NHSDigital/nhs-notify-code-owners

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,8 @@ dist
2727
/sandbox/*.log
2828
/sandbox-staging
2929
/specification/api/components/examples
30+
/specification/api/components/x-nhsd-apim/x-nhsd-apim.yml
31+
/specification/api/components/security-schemes/security-schemes.yml
32+
/specification/api/components/security/security.yml
33+
/specification/api/components/parameters/authorization/authorization.yml
3034
/scripts/JWT/*.pem

.gitleaksignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ b1f85a7faf54eaf66074d7a6daa093aefe6b3ebe:sdk/python/pyproject.toml:ipv4:25
1717
d8aaf7e033bf78fff491caa148897be266b60f67:src/src.sln:ipv4:3
1818
e12407e09151898bfd8d049d57eee9db9977d56b:.github/copilot-instructions.md:generic-api-key:213
1919
4ad86108d4e08cd410061e8842dd3a2b3bee4867:scripts/JWT/README.md:generic-api-key:38
20+
504844c9838740c8c5235024919f0775ad817cde:pact-contracts/pacts/letter-rendering/supplier-api-letter-request-prepared.json:generic-api-key:10

AGENTS.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# AGENTS.md
2+
<!-- vale off -->
3+
4+
## Scope
5+
6+
This file is for **AI agents** working within NHS Notify repositories.
7+
Humans should read `README.md` and the docs for how we actually work day to day.
8+
Keep anything language or tool-specific in nested `AGENTS.md` files (for example under `infrastructure/terraform` or `lambdas`).
9+
10+
## Repository Layout (high level)
11+
12+
At a glance, the main areas are:
13+
14+
- `infrastructure/terraform/` – Terraform components, and shared modules for AWS accounts and environments.
15+
- `lambdas/` – TypeScript lambda projects (each with their own `package.json`, Jest config, etc.). Root level packages.json defines workspaces and scripts. Tests for the lambda are stored in `lambdas/{name}/src/__test`.
16+
- `src/` and `utils/` – Shared code and utilities (for example `utils/logger`).
17+
- `docs/` – Documentation site, ADRs, RFCS, and other long‑form docs.
18+
- `.github/workflows/` and `.github/actions/` – GitHub Actions workflows and composite actions.
19+
- `scripts/` – Helper scripts and tooling used by humans and workflows.
20+
- `tests/` – Cross‑cutting tests and harnesses for the repo.
21+
22+
Agents should look for a nested `AGENTS.md` in or near these areas before making non‑trivial changes.
23+
24+
## Root package.json – role and usage
25+
26+
The root `package.json` is the orchestration manifestgit co for this repo. It does not ship application code; it wires up shared dev tooling and delegates to workspace-level projects.
27+
28+
- Workspaces: Declares the set of npm workspaces (e.g. under `lambdas/`, `utils/`, `tests/`, `scripts/`). Agents should add a new workspace path here when introducing a new npm project.
29+
- Scripts: Provides top-level commands that fan out across workspaces using `--workspaces` (lint, typecheck, unit tests) and project-specific runners (e.g. `lambda-build`).
30+
- Dev tool dependencies: Centralises Jest, TypeScript, ESLint configurations and plugins to keep versions consistent across workspaces. Workspace projects should rely on these unless a local override is strictly needed.
31+
- Overrides/resolutions: Pins transitive dependencies (e.g. Jest/react-is) to avoid ecosystem conflicts. Agents must not remove overrides without verifying tests across all workspaces.
32+
33+
Agent guidance:
34+
35+
- Before adding or removing a workspace, update the root `workspaces` array and ensure CI scripts still succeed with `npm run lint`, `npm run typecheck`, and `npm run test:unit` at the repo root.
36+
- When adding repo-wide scripts, keep names consistent with existing patterns (e.g. `lint`, `lint:fix`, `typecheck`, `test:unit`, `lambda-build`) and prefer `--workspaces` fan-out.
37+
- Do not publish from the root. If adding a new workspace intended for publication, mark that workspace package as `private: false` and keep the root as private.
38+
- Validate changes by running the repo pre-commit hooks: `make githooks-run`.
39+
40+
Success criteria for changes affecting the root `package.json`:
41+
42+
- `npm run lint`, `npm run typecheck`, and `npm run test:unit` pass at the repo root.
43+
- Workspace discovery is correct (new projects appear under `npm run typecheck --workspaces`).
44+
- No regression in lambda build tooling (`npm run lambda-build`).
45+
46+
## What Agents Can / Can’t Do
47+
48+
Agents **can**:
49+
50+
- Propose changes to code, tests, GitHub workflows, Terraform, and docs.
51+
- Suggest new scripts, Make targets, or composite actions by copying existing patterns.
52+
- Run tests to validate proposed solutions.
53+
54+
Agents **must not**:
55+
56+
- Create, push, or merge branches or PRs.
57+
- Introduce new technologies, providers, or big architectural patterns without clearly calling out that an ADR is needed.
58+
- Invent secrets or hard‑code real credentials anywhere.
59+
60+
## Working With This Repo
61+
62+
- All dependencies can be setup using the command `make config` from the repository root.
63+
- **Don’t guess commands.** Derive them from what’s already here or ask for guidance form the human user:
64+
- Prefer `Makefile` targets, `scripts/`, `.github/workflows/`, and `.github/actions/`.
65+
- For Terraform, follow `infrastructure/terraform/{components,modules}` and respect `versions.tf`.
66+
- Keep diffs small and focused. Avoid mixing refactors with behaviour changes unless you explain why.
67+
68+
## Quality Expectations
69+
70+
When proposing a change, agents should:
71+
72+
- Keep code formatted and idiomatic (Terraform, TypeScript, Bash, YAML).
73+
- Stick to existing patterns where available (for example `utils/logger`, composite actions under `.github/actions`).
74+
- Use available information on best practices within the specific area of the codebase.
75+
- **Always** run local pre-commit hooks from the repo root with:
76+
77+
```sh
78+
pre-commit run \
79+
--config scripts/config/pre-commit.yaml
80+
```
81+
82+
to catch formatting and basic lint issues. Domain specific checks will be defined in appropriate nested AGENTS.md files.
83+
84+
- Suggest at least one extra validation step (for example `npm test` in a lambda, or triggering a specific workflow).
85+
- Any required follow up activites which fall outside of the current task's scope should be clearly marked with a 'TODO: CCM-12345' comment. The human user should be prompted to create and provide a JIRA ticket ID to be added to the comment.
86+
87+
## Security & Safety
88+
89+
- All agent-generated changes **must** be reviewed and merged by a human.
90+
- Provide a concise, clear summary of the proposed changes to make human review easier (what changed, why (refer directly to the guidance in relevant Agents.MD files when applicable), and how it was validated). It should be directly pastable into the PR description and make it clear that AI assistance was used.
91+
- Never output real secrets or tokens. Use placeholders and rely on the GitHub/AWS secrets already wired into workflows.
92+
93+
## Escalation / Blockers
94+
95+
If you are blocked by an unavailable secret, unclear architectural constraint, missing upstream module, or failing tooling you cannot safely fix, stop and ask a single clear clarifying question rather than guessing.

Makefile

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,32 +46,26 @@ publish-oas:
4646
npm run publish-oas
4747

4848
set-authorization: guard-APIM_ENV
49-
@ AUTHORIZATION=authorization-$$APIM_ENV.yml \
50-
envsubst '$${AUTHORIZATION}' \
51-
< specification/api/components/parameters/authorization/authorization-template.yml > specification/api/components/parameters/authorization/authorization.yml
49+
SPEC_DIR=./specification/api/components/environments
50+
COMPONENT_DIR=./specification/api/components/parameters/authorization
51+
./scripts/build/substitute_build_env.sh $$COMPONENT_DIR/authorization-template.yml $$SPEC_DIR/$$APIM_ENV.env $$COMPONENT_DIR/authorization.yml
5252

53-
set-target: guard-APIM_ENV
54-
@ TARGET=target-$$APIM_ENV.yml \
55-
envsubst '$${TARGET}' \
56-
< specification/api/components/x-nhsd-apim/target-template.yml > specification/api/components/x-nhsd-apim/target.yml
57-
58-
set-access: guard-APIM_ENV
59-
@ ACCESS=access-$$APIM_ENV.yml \
60-
envsubst '$${ACCESS}' \
61-
< specification/api/components/x-nhsd-apim/access-template.yml > specification/api/components/x-nhsd-apim/access.yml
53+
set-nhsd-apim: guard-APIM_ENV
54+
SPEC_DIR=./specification/api/components/environments
55+
COMPONENT_DIR=./specification/api/components/x-nhsd-apim
56+
./scripts/build/substitute_build_env.sh $$COMPONENT_DIR/x-nhsd-apim-template.yml $$SPEC_DIR/$$APIM_ENV.env $$COMPONENT_DIR/x-nhsd-apim.yml
6257

6358
set-security: guard-APIM_ENV
64-
@ SECURITY=security-$$APIM_ENV.yml \
65-
envsubst '$${SECURITY}' \
66-
< specification/api/components/security/security-template.yml > specification/api/components/security/security.yml
67-
@ SECURITY_SCHEMES=security-schemes-$$APIM_ENV.yml \
68-
envsubst '$${SECURITY_SCHEMES}' \
69-
< specification/api/components/security-schemes/security-schemes-template.yml > specification/api/components/security-schemes/security-schemes.yml
59+
SPEC_DIR=./specification/api/components/environments
60+
COMPONENT_DIR=./specification/api/components/security
61+
./scripts/build/substitute_build_env.sh $$COMPONENT_DIR/security-template.yml $$SPEC_DIR/$$APIM_ENV.env $$COMPONENT_DIR/security.yml
62+
COMPONENT_DIR=./specification/api/components/security-schemes
63+
./scripts/build/substitute_build_env.sh $$COMPONENT_DIR/security-schemes-template.yml $$SPEC_DIR/$$APIM_ENV.env $$COMPONENT_DIR/security-schemes.yml
64+
7065

7166
construct-spec: guard-APIM_ENV
67+
$(MAKE) set-nhsd-apim APIM_ENV=$$APIM_ENV
7268
$(MAKE) set-authorization APIM_ENV=$$APIM_ENV
73-
$(MAKE) set-target APIM_ENV=$$APIM_ENV
74-
$(MAKE) set-access APIM_ENV=$$APIM_ENV
7569
$(MAKE) set-security APIM_ENV=$$APIM_ENV
7670

7771
build-json-oas-spec: guard-APIM_ENV
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
resource "aws_lambda_event_source_mapping" "letter_updates_transformer_kinesis" {
2+
event_source_arn = aws_kinesis_stream.letter_change_stream.arn
3+
function_name = module.letter_updates_transformer.function_arn
4+
starting_position = "LATEST"
5+
batch_size = 10
6+
maximum_batching_window_in_seconds = 1
7+
8+
depends_on = [
9+
module.letter_updates_transformer # ensures updates transformer exists
10+
]
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
resource "aws_kinesis_stream" "letter_change_stream" {
2+
name = "${local.csi}-letter-change-stream"
3+
shard_count = 1
4+
retention_period = 24
5+
}
6+
7+
resource "aws_dynamodb_kinesis_streaming_destination" "letter_streaming_destination" {
8+
stream_arn = aws_kinesis_stream.letter_change_stream.arn
9+
table_name = aws_dynamodb_table.letters.name
10+
approximate_creation_date_time_precision = "MILLISECOND"
11+
}

infrastructure/terraform/components/api/module_lambda_letter_updates_transformer.tf

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,35 +36,39 @@ module "letter_updates_transformer" {
3636
log_subscription_role_arn = local.acct.log_subscription_role_arn
3737

3838
lambda_env_vars = merge(local.common_lambda_env_vars, {
39-
EVENTPUB_SNS_TOPIC_ARN = module.eventpub.sns_topic.arn
39+
EVENTPUB_SNS_TOPIC_ARN = "${module.eventpub.sns_topic.arn}"
4040
})
4141
}
4242

4343
data "aws_iam_policy_document" "letter_updates_transformer_lambda" {
4444
statement {
45-
sid = "KMSPermissions"
45+
sid = "AllowSNSPublish"
4646
effect = "Allow"
4747

4848
actions = [
49-
"kms:Decrypt",
50-
"kms:GenerateDataKey",
49+
"sns:Publish"
5150
]
5251

5352
resources = [
54-
module.kms.key_arn,
53+
module.eventpub.sns_topic.arn
5554
]
5655
}
5756

5857
statement {
59-
sid = "AllowSNSPublish"
58+
sid = "AllowKinesisGet"
6059
effect = "Allow"
6160

6261
actions = [
63-
"sns:Publish"
62+
"kinesis:GetRecords",
63+
"kinesis:GetShardIterator",
64+
"kinesis:DescribeStream",
65+
"kinesis:DescribeStreamSummary",
66+
"kinesis:ListShards",
67+
"kinesis:ListStreams",
6468
]
6569

6670
resources = [
67-
module.eventpub.sns_topic.arn
71+
aws_kinesis_stream.letter_change_stream.arn
6872
]
6973
}
7074
}

internal/events/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,5 @@
5050
"typecheck": "tsc --noEmit"
5151
},
5252
"types": "dist/index.d.ts",
53-
"version": "1.0.3"
53+
"version": "1.0.5"
5454
}

internal/events/src/domain/letter.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ The identifier will be included as the origin domain in the subject of any corre
7676
examples: ["1y3q9v1zzzz"],
7777
}),
7878

79+
supplierId: z.string().meta({
80+
title: "Supplier ID",
81+
description: "Supplier ID allocated to the letter during creation.",
82+
examples: ["supplier-1"],
83+
}),
84+
7985
groupId: z.string().meta({
8086
title: "Group ID",
8187
description:

0 commit comments

Comments
 (0)