2026-03-31

  • CDK
    • need to look at CFN parameter to set secret value direct in AWS safely
    • example in tracker UI from Matt

Eval of different approaches to writing secret values to AWS secrets

Short answer: you can use a CfnParameter with NoEcho to supply an initial secret value at deploy time, and that is much safer than hardcoding a secret in CDK, but it is still not the safest pattern overall. The safest pattern is to separate secret creation from secret value initialization.

For this repo, I would think about it in three levels.

Best Pattern Create the secret resource with CDK, but do not set the real value in the CloudFormation template at all. Then initialise or update the value out of band, for example from CI/CD, a one-off bootstrap script, or a secure operator step using AWS CLI or the console.

Why this is safest:

The secret never appears in source code. The secret never needs to be embedded in the synthesized template. You avoid passing plaintext through CloudFormation inputs. This also fits the direction your stack already uses today: workload Lambdas consume imported secret identifiers and read them at runtime, rather than baking secret values into Lambda env vars. You can see that in Functions.ts, where the functions receive secret ARNs and use the shared secret-access policies. The repo memory also notes that PR stacks already import shared secrets instead of creating their own in service-search-shared-secret-pr.md.

Acceptable Pattern Use a CfnParameter with NoEcho and pass that into a secret resource during deploy.

That means:

CDK defines a parameter like ServiceSearchApiKey with NoEcho true. During deploy, the operator or pipeline supplies the value. The secret resource is created from that parameter. This is usually what people mean when they suggest CfnParameter.

Why it helps:

The value is not committed to git. It is not hardcoded in CDK. CloudFormation masks it in most normal views. Why it is not ideal:

CloudFormation still processes the plaintext value. It becomes part of the deployment transaction, so you are still trusting CloudFormation handling rather than keeping the value entirely outside the stack definition. It is easier to leak accidentally in deployment tooling if someone passes it on the command line or logs it. So: better than hardcoding, worse than out-of-band initialization.

What I would not do I would not put the initial secret value directly in CDK code, context, environment variables that get synthesized, or Lambda environment variables. Your repo has CDK’s secret-usage checks enabled in cdk.json, which is a good sign that the intended direction is to avoid that class of mistake.

For your case specifically, I would recommend one of these two approaches:

Stable shared secret stack Create the secret once in a stable shared stack, initialise it outside CloudFormation, then export ARN or name and keep importing it into the application stack. That aligns well with your current imported-secret model in Functions.ts.

Application-owned secret with external bootstrap Let this CDK stack create the secret container, but run a follow-up secure step after deploy that sets the value only if it is missing. That gives you safe first-time initialization without putting the value into the template.

If you want a direct answer to “should I use CfnParameter?”:

Yes, if you need a quick, deploy-time-supplied initial value and want to avoid hardcoding. No, if you want the strongest leakage protection. In that case, create the secret with CDK and initialise it outside CloudFormation. The main tradeoff is simple:

CfnParameter with NoEcho is convenient. Out-of-band initialization is safer. If you want, I can sketch the exact CDK shape for both options:

Secret created by CDK plus external initialization step Secret created from a NoEcho CfnParameter Shared account-resources secret pattern matching the way this repo already imports secrets

2026-03-30

  • 6372
    • create PR, repeat reg test and splunk to show get ap name and id
    • trace in apigee if needed
  • supplier PfP query from Danielle
    • overlaps with failing non-nominated reg tests?
    • benefits from 6372 tests and query
  • CDK
    • ready to build release and get first PfP PR merged
    • rework postXxxx scripts into base image
    • couple of little updates, inc. ability to disable domain record creation (for CPT)
    • => new PR: https://github.com/NHSDigital/eps-cdk-utils/pull/648
    • Jim suggests I complete the whole thing pulling his params bit from PfP #2518
  • PfP returning 408
    • I think this is a misunderstanding and should be 504

2026-03-27

  • CDK
    • chasing the review comments to get 3 constructs merged
  • 6372
    • ran regression tests and produced
      index=app_prescriptions_dev
      source=aws:loggroup:/aws/lambda/pfp-GetMyPrescriptions
      | spath "message.x-request-id"
      | search "message.x-request-id"="1b3cd0ce-4f84-4e85-8d75-895e0bf1a6cf"
      
      to show application is coming thru as ‘unknown’
    • add both app name and id
    • then figure out report implications and Ant’s concern about name.

2026-03-26

  • CDK
    • Add JSDoc
    • try to add make cdk-delete but assumes proxygen deployment that is not there
    • refactor constants to their own file
    • chat to Jim about his additions
  • 6358
    • had to defer post-dated test rollout to get thru he release since gsul is not yet exposed on API gateway.
    • should be ok now that release cut has been made, so long as 1.16.8-beta is deployed to prod first.
  • retro

2026-03-25

  • 6254
    • review and address copilot comments
    • bump the revew tomorrow
  • 6256
    • rebase
  • 6257
    • rebase
    • resolve copilot comments
  • 6358
    • get PR merged, take a cut, create the RFC and RFC tracker
    • Apotec have a space in the name, Ant wants us to use ids
    • cannot change dynamo GSI so needed another PR
  • 6372
    • app name into pfp report

2026-03-24

2026-03-23

2026-03-20

2026-03-19

  • 6399
    • prepared PR
  • 6055
    • lots of suggestions from copilot review
      • a lot of dross, but did prompt me to rework environment.py more in line with others
  • 6257
    • ready for local testing

2026-03-18

  • revised release process
    • what happens when qa finds an issue
      • revert or fix forward
    • what about one offs, eg suppliers?
      • continue as now
  • 6257
    • exploring

2026-03-17

  • 6385
    • response applied change in powertools
  • 5963
    • awaiting review
  • 6055
    • thru logging identified that Dynamo projection was not loading the post-dated attribute
  • 6254
    • seems to be in good shape?
    • question mark over how to deploy
      • the make cdk-* in cpt seem good but unsure about how to do pr stack vs regular
    • decided to stack the PRs and see if I can get thru more / all
  • 6256
    • set copilot running

2026-03-16

2026-03-13: vacation

2026-03-12

2026-03-11

2026-03-10

  • mark PRs temp as suggested by Ant
  • psu blocking release (manifests as reg test failure in int)
     "User: arn:aws:sts::399793560585:assumed-role/psu-Functions-ZK9K4HF7LRZ2-UpdatePrescri-LambdaRole-0Y05Ra0EMsYM/psu-UpdatePrescriptionStatus is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:eu-west-2:399793560585:* because no identity-based policy allows the ssm:GetParameter action",
          "stack": "GetParameterError: User: arn:aws:sts::399793560585:assumed-role/psu-Functions-ZK9K4HF7LRZ2-UpdatePrescri-LambdaRole-0Y05Ra0EMsYM/psu-UpdatePrescriptionStatus is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:eu-west-2:399793560585:* because no identity-based policy allows the ssm:GetParameter action\n    at e.get (/node_modules/@aws-lambda-powertools/parameters/lib/esm/base/BaseProvider.js:92:19)\n    at process.processTicksAndRejections (node:internal/process/task_queues:103:5)\n    at async Rc.getTestPrescriptions (/packages/common/utilities/src/testConfig.ts:26:25)\n    at async _5e (/packages/updatePrescriptionStatus/src/updatePrescriptionStatus.ts:74:28)\n    at async T5e (/packages/updatePrescriptionStatus/src/updatePrescriptionStatus.ts:155:5)\n    at async CPe (/node_modules/@middy/core/index.js:152:23)\n    at async BufferedInvokeProcessor.d (/node_modules/@middy/core/executionModeStandard.js:15:20)\n    at async BufferedInvokeProcessor.processInvoke (file:///var/runtime/index.mjs:1092:22)\n    at async _Runtime.processSingleConcurrent (file:///var/runtime/index.mjs:1178:7)\n    at async _Runtime.start (file:///var/runtime/index.mjs:1165:7)",
    
    • confirms that it is the attempt to read TEST_PRESCRIPTIONS_1
  • fhir facade also blocking release:

  features/eps_fhir_dispensing/dispense_prescriptions.feature:23  I can release a prescription using application-restricted signed JWT session

- leave that with Ant & Jim to fix the onboarding app
- 6165
- updated `set_github_secrets.py` with SSv3 hosts
- now PR secret is not populated
- try to fallback to non PR secret
- fails due to permissions (not part of same stack)
- eventually propsed use of single dev secret and removal of secret creation on PR branches
  - <https://github.com/NHSDigital/prescriptionsforpatients/pull/2463>
- Fixing PfP dependabots
- @middy/core 7.1.2 to 7.1.3 is an upstream incompatibility between middy and aws powertools => close
- @middy/input-output-logger from 7.1.2 to 7.1.3: I initially thought this would be the same, but actually a simple adaption
  <https://github.com/NHSDigital/eps-prescription-status-update-api/pull/2825>

## 2026-03-09

- merge issues
- Ant is going to make some changes that should allow dependabot to merge to main ignoring trivy
- pfp: 13 PRs
- FHIR facade: 9
- psu: 18
- PfP regression
- convinced myself that it is Service Search (Integration Testing) and contacted Conrad
- turned out to be URL, and that in turn was due to Ant re-running account resources set_github_secret.py
- which was not updated for v3
- roadmap


## 2026-03-06

- release issues
- pfp: dev
- psu: qa
- cpt: qa
-> sent to APIM
- discovered PfP regression tests are failing on distance selling
- somewhat speculative fix restoring the Subscription-Key that appeared promising
  but failed on merge: https://github.com/NHSDigital/electronic-prescription-service-api-regression-tests/actions/runs/22774723977/job/66064950124
- 6055
- tidy the regression tests but still failing

## 2026-03-05

- 6055
- return to regression testing branch
- chasing dependabot with Connor and Matt today.


## 2026-03-04

- 6055
- debug logging
- queries
- Bewell
- PfP disappearing repeat prescriptions
- chasing dependabot
- Jim extended e2e test duration

## 2026-03-03

- chasing dependabot
- 6055
- further investigations

## 2026-03-02

- 0000
- asked copilot to migrate jest to vitest on pfp
- 5963
- 2 pages of dependabots!
- logger change requested by Matt is done.
- chasing a clean build
- PfP blocked by APIM resource cleanup issue.

## 2026-02-27

- 6165
- secrets layer merged
  - get secrets merge and release: https://github.com/NHSDigital/electronic-prescription-service-get-secrets/pull/818/
  - PfP test PR and merge: https://github.com/NHSDigital/prescriptionsforpatients/pull/2422
  - Merge tracker: https://github.com/NHSDigital/electronic-prescription-service-clinical-prescription-tracker/pull/1744 Please tell me if this is wrong, but if the current secret's not used we need get-secrets out first
  - wait a release cycle
  - remove secre
- 6254
- set copilot off and running
- 6270 (and others)
- make pfp release cut