Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
532dd4e
npm(deps): bump default-browser-id from 5.0.0 to 5.0.1
dependabot[bot] Nov 17, 2025
db0f034
Merge dependabot/npm_and_yarn/develop/default-browser-id-5.0.1 into E…
github-actions[bot] Nov 17, 2025
0cf391f
Merge dependabot/npm_and_yarn/develop/default-browser-5.3.0 into ERSS…
github-actions[bot] Nov 17, 2025
6e8e44c
Merge dependabot/npm_and_yarn/develop/types/node-24.10.1 into ERSSUP-…
github-actions[bot] Nov 17, 2025
33b9468
npm(deps): bump default-browser-id from 5.0.0 to 5.0.1
dependabot[bot] Nov 26, 2025
8cbcb83
Merge branch 'develop' into ERSSUP-91505-combine-prs-npm-2025-11-17
balalsaleh-nhs Dec 2, 2025
f2a486b
Merge branch 'develop' into dependabot/npm_and_yarn/develop/default-b…
balalsaleh-nhs Dec 3, 2025
fcc2d1d
sandbox-npm(deps): bump @hapi/cryptiles from 6.0.1 to 6.0.3 in /sandbox
dependabot[bot] Dec 17, 2025
a103c2f
npm(deps): bump form-data from 4.0.4 to 4.0.5
dependabot[bot] Dec 17, 2025
9316a6b
sandbox-npm(deps-dev): bump @eslint/eslintrc in /sandbox
dependabot[bot] Dec 17, 2025
ada559b
pip(deps): bump exceptiongroup from 1.3.0 to 1.3.1
dependabot[bot] Dec 17, 2025
6f4bca7
pip(deps): bump pytest-check from 2.6.0 to 2.6.2
dependabot[bot] Dec 17, 2025
d2498ae
pip(deps-dev): bump pydantic from 2.12.4 to 2.12.5
dependabot[bot] Dec 17, 2025
e5d9458
pip(deps): bump rpds-py from 0.29.0 to 0.30.0
dependabot[bot] Dec 17, 2025
4e490a7
pip(deps): bump urllib3 from 2.5.0 to 2.6.0
dependabot[bot] Dec 17, 2025
b8a36c2
Merge branch 'develop' into dependabot/npm_and_yarn/develop/default-b…
balalsaleh-nhs Dec 29, 2025
245c0ec
Bump undici from 6.22.0 to 6.23.0
dependabot[bot] Jan 15, 2026
909e98a
sandbox-npm(deps-dev): bump @eslint-community/eslint-utils in /sandbox
dependabot[bot] Jan 16, 2026
f12a8d8
sandbox-npm(deps-dev): bump esquery from 1.6.0 to 1.7.0 in /sandbox
dependabot[bot] Jan 16, 2026
32d3293
sandbox-npm(deps-dev): bump globals from 16.5.0 to 17.0.0 in /sandbox
dependabot[bot] Jan 16, 2026
e1479a3
Merge branch 'develop' into dependabot/npm_and_yarn/undici-6.23.0
EdwardWills-nhs Jan 30, 2026
e7ce8d3
Bump minimatch from 3.1.2 to 3.1.5 in /sandbox
dependabot[bot] Feb 28, 2026
8456b43
Merge pull request #2696 from NHSDigital/feature/RAA-5299
EdwardWills-nhs Mar 2, 2026
5757299
Merge branch 'develop' into dependabot/npm_and_yarn/develop/form-data…
EdwardWills-nhs Mar 3, 2026
85da876
Merge branch 'develop' into ERSSUP-91505-combine-prs-npm-2025-11-17
EdwardWills-nhs Mar 3, 2026
7477525
Merge branch 'develop' into dependabot/npm_and_yarn/develop/default-b…
EdwardWills-nhs Mar 3, 2026
2b9cfaa
Merge pull request #2634 from NHSDigital/dependabot/npm_and_yarn/deve…
EdwardWills-nhs Mar 3, 2026
7ad9fc3
Merge branch 'develop' into dependabot/npm_and_yarn/develop/form-data…
EdwardWills-nhs Mar 3, 2026
48d9153
npm(deps-dev): bump spdx-license-ids from 3.0.22 to 3.0.23
dependabot[bot] Mar 4, 2026
f25ef4f
npm(deps): bump core-js from 3.46.0 to 3.48.0
dependabot[bot] Mar 4, 2026
0b24be8
npm(deps): bump react from 19.2.0 to 19.2.4
dependabot[bot] Mar 4, 2026
4f8c97b
Bump authlib from 1.6.6 to 1.6.7
dependabot[bot] Mar 4, 2026
f526732
Merge branch 'develop' into ERSSUP-91505-combine-prs-npm-2025-11-17
EdwardWills-nhs Mar 5, 2026
19a96b2
Merge pull request #2635 from NHSDigital/ERSSUP-91505-combine-prs-npm…
EdwardWills-nhs Mar 5, 2026
4abe1d8
Merge branch 'develop' into dependabot/npm_and_yarn/develop/form-data…
EdwardWills-nhs Mar 5, 2026
82b7534
Merge branch 'develop' into dependabot/pip/authlib-1.6.7
EdwardWills-nhs Mar 5, 2026
85844fc
Merge branch 'develop' into dependabot/npm_and_yarn/develop/core-js-3…
EdwardWills-nhs Mar 5, 2026
89b4b8a
Merge branch 'develop' into dependabot/npm_and_yarn/develop/react-19.2.4
EdwardWills-nhs Mar 5, 2026
24eb3bb
Merge branch 'develop' into dependabot/npm_and_yarn/develop/spdx-lice…
EdwardWills-nhs Mar 5, 2026
d394b72
Merge dependabot/npm_and_yarn/develop/core-js-3.48.0 into 5429-combin…
github-actions[bot] Mar 5, 2026
8886627
Merge dependabot/npm_and_yarn/develop/form-data-4.0.5 into 5429-combi…
github-actions[bot] Mar 5, 2026
8ab2b82
Merge pull request #2703 from NHSDigital/5429-combine-prs-npm-2026-03-05
EdwardWills-nhs Mar 5, 2026
d2a02ae
npm(deps): bump default-browser from 5.3.0 to 5.5.0
dependabot[bot] Mar 6, 2026
f33e71c
npm(deps): bump react-dom from 19.2.0 to 19.2.4
dependabot[bot] Mar 6, 2026
2abdcaa
Merge branch 'develop' into dependabot/pip/authlib-1.6.7
EdwardWills-nhs Mar 6, 2026
196e8a1
Merge pull request #2702 from NHSDigital/dependabot/pip/authlib-1.6.7
EdwardWills-nhs Mar 9, 2026
152216a
Bump dompurify from 3.3.0 to 3.3.2
dependabot[bot] Mar 9, 2026
9ecbdcd
Merge pull request #2707 from NHSDigital/dependabot/npm_and_yarn/domp…
EdwardWills-nhs Mar 9, 2026
b974fe4
Merge branch 'develop' into dependabot/npm_and_yarn/develop/react-dom…
EdwardWills-nhs Mar 9, 2026
5cffe4e
Merge dependabot/npm_and_yarn/develop/react-dom-19.2.4 into 5483-comb…
github-actions[bot] Mar 9, 2026
07bfbce
Merge dependabot/npm_and_yarn/develop/default-browser-5.5.0 into 5483…
github-actions[bot] Mar 9, 2026
2855435
Merge dependabot/npm_and_yarn/develop/react-19.2.4 into 5483-combine-…
github-actions[bot] Mar 9, 2026
240f608
Merge dependabot/npm_and_yarn/develop/spdx-license-ids-3.0.23 into 54…
github-actions[bot] Mar 9, 2026
ce4f67f
Merge pull request #2709 from NHSDigital/5483-combine-prs-npm-2026-03-09
EdwardWills-nhs Mar 10, 2026
1b4eec0
Merge dependabot/npm_and_yarn/sandbox/develop/globals-17.0.0 into 547…
github-actions[bot] Mar 10, 2026
b1cc092
Merge dependabot/npm_and_yarn/sandbox/develop/eslint-community/eslint…
github-actions[bot] Mar 10, 2026
d74d048
Merge dependabot/npm_and_yarn/sandbox/develop/esquery-1.7.0 into 5470…
github-actions[bot] Mar 10, 2026
75f34f8
Merge dependabot/npm_and_yarn/sandbox/develop/hapi/cryptiles-6.0.3 in…
github-actions[bot] Mar 10, 2026
03a53ac
Merge dependabot/npm_and_yarn/sandbox/develop/eslint/eslintrc-3.3.3 i…
github-actions[bot] Mar 10, 2026
6bfdf46
Merge branch 'develop' into 5470-combine-prs-sandbox-npm-2026-03-10
EdwardWills-nhs Mar 10, 2026
68b53b4
npm(deps): bump is-wsl from 3.1.0 to 3.1.1
dependabot[bot] Mar 11, 2026
e2a9938
npm(deps): bump fast-xml-parser from 5.3.7 to 5.5.1
dependabot[bot] Mar 11, 2026
2647f53
npm(deps): bump @types/node from 24.10.1 to 25.4.0
dependabot[bot] Mar 11, 2026
e7503cc
npm(deps): bump openapi-sampler from 1.7.0 to 1.7.2
dependabot[bot] Mar 11, 2026
30def6e
Testing build pipeline
EdwardWills-nhs Mar 9, 2026
b89f74d
[RAA-1218]-[GC]-[Updated integration tests for working RC user]-[EW]
EdwardWills-nhs Mar 17, 2026
c1026b5
Dependabot updates
EdwardWills-nhs Mar 18, 2026
f9ca615
[RAA-5746]-[GC]-[Dependabot poetry updates]-[EW]
EdwardWills-nhs Mar 18, 2026
49bd06b
Update codeowners
EdwardWills-nhs Mar 18, 2026
8890fdc
Merge pull request #2722 from NHSDigital/feature/RAA-5748
EdwardWills-nhs Mar 19, 2026
28fb13d
Merge branch 'develop' into feature/RAA-1218
EdwardWills-nhs Mar 19, 2026
e53c327
Merge branch 'develop' into feature/RAA-5746
EdwardWills-nhs Mar 19, 2026
2e927cc
Merge pull request #2721 from NHSDigital/feature/RAA-5746
EdwardWills-nhs Mar 19, 2026
bee051d
Merge branch 'develop' into feature/RAA-1218
EdwardWills-nhs Mar 19, 2026
7e4e31b
Merge branch 'develop' into 5470-combine-prs-sandbox-npm-2026-03-10
EdwardWills-nhs Mar 19, 2026
b263389
Merge dependabot/npm_and_yarn/develop/openapi-sampler-1.7.2 into 5483…
github-actions[bot] Mar 19, 2026
a0dc81b
Merge dependabot/npm_and_yarn/develop/types/node-25.4.0 into 5483-com…
github-actions[bot] Mar 19, 2026
744d747
Merge dependabot/npm_and_yarn/develop/fast-xml-parser-5.5.1 into 5483…
github-actions[bot] Mar 19, 2026
82c94ca
Merge dependabot/npm_and_yarn/develop/is-wsl-3.1.1 into 5483-combine-…
github-actions[bot] Mar 19, 2026
faffcf7
Merge branch 'develop' into 5483-combine-prs-npm-2026-03-19
EdwardWills-nhs Mar 19, 2026
5b3fa5c
Merge pull request #2723 from NHSDigital/5483-combine-prs-npm-2026-03-19
EdwardWills-nhs Mar 19, 2026
00a8733
Merge branch 'develop' into dependabot/npm_and_yarn/undici-6.23.0
EdwardWills-nhs Mar 19, 2026
bf9e05a
Merge pull request #2671 from NHSDigital/dependabot/npm_and_yarn/undi…
EdwardWills-nhs Mar 19, 2026
6cdda43
Merge branch 'develop' into 5470-combine-prs-sandbox-npm-2026-03-10
EdwardWills-nhs Mar 19, 2026
91407f7
Merge pull request #2712 from NHSDigital/5470-combine-prs-sandbox-npm…
EdwardWills-nhs Mar 19, 2026
58f86b4
Bump undici from 6.23.0 to 6.24.1
dependabot[bot] Mar 20, 2026
a210a44
Merge pull request #2734 from NHSDigital/dependabot/npm_and_yarn/undi…
EdwardWills-nhs Mar 20, 2026
6fa50a8
Merge branch 'develop' into feature/RAA-1218
EdwardWills-nhs Mar 30, 2026
f348bf8
[RAA-6144]-[GC]-[Bump npm and poetry dependencies]-[EW]
EdwardWills-nhs Mar 30, 2026
554110a
Merge pull request #2720 from NHSDigital/feature/RAA-1218
EdwardWills-nhs Mar 30, 2026
5407144
Merge branch 'develop' into feature/RAA-6144
EdwardWills-nhs Mar 30, 2026
43f5a64
Merge pull request #2742 from NHSDigital/feature/RAA-6144
EdwardWills-nhs Mar 30, 2026
fddf2dd
[RAA-6512]-[GC]-[Bumped Redocly (major) and override handlebars dep f…
EdwardWills-nhs Mar 30, 2026
dd84bbf
Delete test-output.json
EdwardWills-nhs Mar 30, 2026
1b7a6e1
Merge pull request #2744 from NHSDigital/feature/RAA-6512
georgeCraftReferrals Mar 31, 2026
8d4ab11
Bump protobufjs from 7.5.4 to 7.5.5
dependabot[bot] Apr 17, 2026
8e6d1ba
Bump cryptography from 46.0.6 to 46.0.7
dependabot[bot] Apr 8, 2026
1987055
Bump authlib from 1.6.9 to 1.6.11
dependabot[bot] Apr 17, 2026
bf99e60
Merge pull request #2761 from NHSDigital/feature/RAA-6562
EdwardWills-nhs Apr 23, 2026
b948156
npm(deps-dev): bump minimatch from 3.1.4 to 3.1.5
dependabot[bot] Apr 27, 2026
0a75d7a
npm(deps): bump fast-xml-parser from 5.5.9 to 5.7.2
dependabot[bot] Apr 27, 2026
e469709
npm(deps): bump path-expression-matcher from 1.2.0 to 1.5.0
dependabot[bot] Apr 27, 2026
d2d481c
npm(deps-dev): bump brace-expansion from 1.1.12 to 1.1.14
dependabot[bot] Apr 27, 2026
e40ec42
Merge dependabot/pip/develop/urllib3-2.6.0 into 5484-combine-prs-pip-…
github-actions[bot] May 13, 2026
c113161
Merge dependabot/pip/develop/pytest-check-2.6.2 into 5484-combine-prs…
github-actions[bot] May 13, 2026
cd297be
Merge dependabot/pip/develop/rpds-py-0.30.0 into 5484-combine-prs-pip…
github-actions[bot] May 13, 2026
6ea21f3
Merge dependabot/pip/develop/pydantic-2.12.5 into 5484-combine-prs-pi…
github-actions[bot] May 13, 2026
4cd4197
Merge dependabot/pip/develop/exceptiongroup-1.3.1 into 5484-combine-p…
github-actions[bot] May 13, 2026
e491b68
Updated poetry lock to fix conflict
EdwardWills-nhs May 13, 2026
8e30c51
Updated poetry lock to fix conflict
EdwardWills-nhs May 13, 2026
6ec85af
Updated poetry lock to fix conflict
EdwardWills-nhs May 13, 2026
eea9dae
Merge remote-tracking branch 'origin/develop' into 5484-combine-prs-p…
EdwardWills-nhs May 13, 2026
3a3c324
Merge pull request #2775 from NHSDigital/5484-combine-prs-pip-2026-05-13
EdwardWills-nhs May 13, 2026
5bed003
Merge dependabot/npm_and_yarn/develop/fast-xml-parser-5.5.10 into 736…
github-actions[bot] May 13, 2026
8f52bf6
Merge dependabot/npm_and_yarn/develop/path-expression-matcher-1.2.1 i…
github-actions[bot] May 13, 2026
9d33e98
Merge dependabot/npm_and_yarn/develop/brace-expansion-1.1.13 into 736…
github-actions[bot] May 13, 2026
7990185
Merge dependabot/npm_and_yarn/develop/minimatch-3.1.5 into 7368-combi…
github-actions[bot] May 13, 2026
b697116
Merge branch 'develop' into 7368-combine-prs-npm-2026-05-13
EdwardWills-nhs May 13, 2026
1162ae3
Merge pull request #2778 from NHSDigital/7368-combine-prs-npm-2026-05-13
EdwardWills-nhs May 13, 2026
a14d6be
Bump protobufjs from 7.5.5 to 7.5.8
dependabot[bot] May 13, 2026
0e0c107
Merge pull request #2776 from NHSDigital/dependabot/npm_and_yarn/prot…
EdwardWills-nhs May 14, 2026
8841780
Bump @hapi/content from 6.0.0 to 6.0.1 in /sandbox
dependabot[bot] Apr 23, 2026
9817ee7
[RAA-7531]-[GC]-[Bump dependencies]-[EW]
EdwardWills-nhs May 18, 2026
edf6f4b
Add Copilot context files for onboarding and developer handover
EdwardWills-nhs May 27, 2026
dd73c2e
Remove unused imports from test_user_restricted.py (F401)
EdwardWills-nhs May 27, 2026
9db13dc
Remove EUO allowlist tests and apim_app_flow_vars references
EdwardWills-nhs May 27, 2026
5af7eff
Merge pull request #2790 from NHSDigital/feature/RAA-7531
EdwardWills-nhs May 29, 2026
6e11564
fix: update vulnerable dependencies
EdwardWills-nhs May 29, 2026
97e92a9
Merge branch 'develop' into feature/RAA-7835
EdwardWills-nhs May 29, 2026
216fd3c
Merge pull request #2793 from NHSDigital/feature/RAA-7835
EdwardWills-nhs May 29, 2026
31f1b7d
[RAA-7705]-[]-[testdev environment apim support]-[DW]
dbgwilliamsnhs May 22, 2026
174433b
Merge pull request #2791 from NHSDigital/feature/RAA-7705
EdwardWills-nhs Jun 1, 2026
0a567f0
pin GitHub Actions to latest versions with commit SHAs
EdwardWills-nhs Jun 3, 2026
c5952cb
Merge pull request #2796 from NHSDigital/feature/RAA-7980
EdwardWills-nhs Jun 3, 2026
f8abefc
422 response for A042 endpoint
kevinmason-nhs Jun 3, 2026
b5807e4
Merge pull request #2797 from NHSDigital/feature/RAA-3429_OAS_update
TomKinghorn Jun 9, 2026
79b24e1
[RAA-5861]-[GC]-[Bumping version to 1.54 +minor]-[EW]
EdwardWills-nhs Jun 10, 2026
9bddc8c
Merge pull request #2807 from NHSDigital/feature/RAA-5861
EdwardWills-nhs Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@

# For version files that are updated by dependabot we have a cut down list

/sandbox/Dockerfile @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs
/sandbox/package.json @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs
/sandbox/package-lock.json @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs
/package.json @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs
/package-lock.json @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs
/poetry.lock @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs
/poetry.toml @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs
/pyproject.toml @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs
/sandbox/Dockerfile @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs @petkopetkov2
/sandbox/package.json @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs @petkopetkov2
/sandbox/package-lock.json @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs @petkopetkov2
/package.json @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs @petkopetkov2
/package-lock.json @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs @petkopetkov2
/poetry.lock @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs @petkopetkov2
/poetry.toml @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs @petkopetkov2
/pyproject.toml @daniel-mcadam-nhs @kevinmason-nhs @EdwardWills-nhs @georgeCraftReferrals @csaw-nhs @petkopetkov2
106 changes: 106 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# e-Referrals Service API β€” Copilot Context

## What is this repo?

This is the **e-Referral Service (e-RS) FHIR API** maintained by NHS Digital. It provides RESTful endpoints for creating paperless referrals from primary to secondary care. The repo contains the OpenAPI specification, an Apigee API proxy layer, a Node.js sandbox (mock server), and Python-based test suites.

This repo is the **API layer** β€” it does NOT contain the e-RS core application. The Apigee proxy forwards authenticated requests to the real e-RS backend at `/ers-api`. The sandbox returns fixture data for development and never touches the real backend.

The live API documentation is published to the [NHS Developer Hub](https://digital.nhs.uk/developer/api-catalogue/e-referral-service-fhir).

## Sibling repository

This repo has a sibling: **`e-referrals-service-patient-care-api`**. Both repos follow the same structure and procedures (environment setup, `make publish`, release process). If you know how to work in one, you can work in the other.

## Repository structure

| Directory | Purpose |
|---|---|
| `specification/` | OpenAPI 3.0 spec with components split across `components/r4/` (FHIR R4) and `components/stu3/` (FHIR STU3) |
| `sandbox/` | Node.js (Hapi) mock server. Entry: `sandbox/src/app.js`. Routes: `sandbox/src/routes/{stu3,r4}/`. Fixtures: `sandbox/src/mocks/` |
| `proxies/live/` | Production Apigee proxy (~60 policies: OAuth, ASID, ODS allowlist, rate limiting, header swapping) |
| `proxies/sandbox/` | Lightweight Apigee proxy (~11 policies, no auth) forwarding to the mock server |
| `tests/` | Python pytest suites: `sandbox/`, `integration/`, `smoke/` |
| `terraform/` | Apigee infrastructure-as-code using `api-platform-service-module` |
| `scripts/` | Build & dev utilities |
| `azure/` | Azure DevOps CI/CD pipeline definitions |
| `build/` | Generated output β€” bundled single-file OAS JSON |

## FHIR versions

- **STU3** β€” the original version, most endpoints live here
- **R4** β€” newer endpoints (business functions, healthcare services, service requests, attachments)

Routes, schemas, examples, and tests all mirror this split.

## Package management

| Ecosystem | Tool | Config file | Install |
|---|---|---|---|
| Python | **Poetry** (package-mode=false) | `pyproject.toml` / `poetry.lock` | `poetry install` |
| Node (root) | **npm** | `package.json` | `npm install` |
| Node (sandbox) | **npm** | `sandbox/package.json` | `cd sandbox && npm install` |

- Python β‰₯ 3.13 required
- Root `package.json` is only `@redocly/cli` for OAS linting/bundling
- `make install` installs all three plus git hooks

## Key make targets

```
make clean-environment # Delete the pyenv 'apigee' virtual environment
make setup-environment # Bootstrap dev environment (pyenv, Python 3.13, dependencies) β€” run in a NEW terminal after
make install # Install all deps (node + poetry + git hooks)
make lint # Lint OAS spec, sandbox JS, XML proxies, Python
make publish # Bundle OAS spec β†’ build/e-referrals-service-api.json
make serve # Preview spec docs on port 5000
make sandbox # Build & run sandbox Docker container (port 9100β†’9000)
make sandbox-tests # Run sandbox pytest suite
make release # Full release build
```

## Environment setup (first time / reset)

1. `make clean-environment` β€” removes the pyenv `apigee` virtual environment (skip on first setup)
2. Open a **new terminal** (so shell profile changes take effect)
3. `make setup-environment` β€” installs pyenv, Python 3.13, creates the `apigee` venv, installs Poetry
4. Open a **new terminal** again
5. `pyenv version` β€” should show `apigee`. If not, repeat steps 1–4
6. `make install` β€” installs Node deps (root + sandbox) and Poetry deps + git hooks

The `.python-version` file auto-activates the `apigee` venv when you `cd` into the repo.

## Release process

1. `make publish` β€” bundles the OAS spec into a single JSON file:
- Redocly CLI reads `specification/e-referrals-service-api.yaml`, resolves all `$ref`s, dereferences, and removes unused components
- Piped through `scripts/set_version.py` β€” calculates the version from git commit messages (using `+major`, `+minor`, `+setstatus` commands in commit messages) and injects it into `info.version`
- Piped through `scripts/populate_placeholders.py` β€” replaces `[[HYPERLINK_*]]` placeholders with actual markdown links for the Developer Hub
- Output: `build/e-referrals-service-api.json` β€” this is the OAS file that goes into Apigee
2. `make release` β€” runs `clean` β†’ `publish` β†’ `build_proxy` β†’ packages everything into `dist/`
3. Deployment is handled by the release management process (not individual developers) β€” the Azure DevOps release pipeline is triggered by a `v*` tag push, which deploys to Apigee environments

## CI/CD

- **Azure DevOps** pipelines in `azure/` β€” build, PR validation, release
- Extends shared templates from `NHSDigital/api-management-utils`
- Release pipeline packages spec + proxies + tests into `dist/`
- GitHub has `dependabot.yml` for dependency updates and PR/issue templates

## Branching

- **develop** β€” default working branch; create PRs from here
- **master** β€” release branch; merges to master are part of the release process

## Licensing

Dual licensed MIT + OGL (Open Government License). **No GPL or AGPL dependencies allowed** β€” this would violate the terms of those libraries' licenses. Check before adding any new package.

## Deeper context

Detailed context for specific areas is split into separate instruction files that load automatically when you're working in the relevant part of the codebase:

- `proxies/**` β†’ proxy architecture, request flow, policies, shared flows
- `sandbox/**` β†’ sandbox architecture, route handler patterns, mock response provider
- `tests/**` β†’ test structure, Actor model, activity codes, SandboxTest base class
- `specification/**` β†’ OAS workflow, examples pipeline, Redocly config
140 changes: 140 additions & 0 deletions .github/instructions/proxy.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
applyTo: "proxies/**"
description: "Apigee proxy architecture, request flow, policies, shared flows, and how to modify proxy configuration"
---

# Apigee Proxy Architecture

The `proxies/` directory contains two independent Apigee API proxy bundles that share the same base path (`{{ SERVICE_BASE_PATH }}` β†’ `/referrals`).

## `proxies/live/` β€” production proxy

Forwards requests to the real e-RS backend. This is the most policy-heavy part of the repo.

### Layout

| Path | Purpose |
|---|---|
| `apiproxy/ers.xml` | Root proxy descriptor |
| `apiproxy/proxies/default.xml` | ProxyEndpoint β€” inbound routing (`_ping`, `_status`, catch-all to target) |
| `apiproxy/targets/ers-target.xml` | TargetEndpoint β€” outbound to backend via `{{ ERS_TARGET_SERVER }}`, plus all auth/error handling |
| `apiproxy/policies/` | ~60 XML policy files (see breakdown below) |
| `apiproxy/resources/jsc/` | Inline JavaScript used by policies (`IsFhirR4Path.js`, `SetCurrentTimestamp.js`, `SetStatusResponse.js`) |

### Request flow (PreFlow on TargetEndpoint)

1. `javascript.IsFhirR4Path` β€” sets `isFhirR4Path` boolean by matching `/FHIR/R4/` in the path suffix; this flag drives R4-vs-STU3 branching throughout
2. `OauthV2.VerifyAccessToken` β€” validates OAuth2 token; accepted scopes: `app:level3`, `user-nhs-id:aal3`, `user-nhs-id:aal2`
3. `FlowCallout.ExtendedAttributes` + `FlowCallout.EUOAllowlistVerify` β€” (user-restricted only, excluding `/FHIR/R4/PractitionerRole`) validates the end-user organisation ODS code against an allowlist
4. ASID validation β€” `RaiseFault.MissingAsid` if `app.asid` is empty; then `AssignMessage.PopulateAsidFromApp` + `AssignMessage.SetAsidHeader` copy the ASID onto the request
5. `AssignMessage.AddBaseUrlHeader` β€” adds the base URL header for the backend
6. `FlowCallout.ApplyRateLimiting` β€” spike arrest + quota enforcement (delegates to external shared flow β€” rate/quota values are NOT in this repo)

### Shared flows (external dependencies)

Several `FlowCallout.*` policies delegate to shared flows that are NOT defined in this repo:
- `ApplyRateLimiting` β€” spike arrest and quota enforcement (rate/quota values configured externally)
- `ExtendedAttributes` β€” retrieves extended app attributes
- `EUOAllowlistVerify` β€” validates ODS code against the end-user organisation allowlist
- `LogToSplunk` β€” audit logging

These shared flows are deployed separately to the Apigee environment. This repo only controls *when* they are called and *how* their errors are handled.

### Conditional flows (TargetEndpoint)

- **`user-restricted-flow`** (`accesstoken.auth_type == "user"`) β€” rejects app-only business functions (`AUTHORISED_APPLICATION`), swaps NHSD headers from external to internal naming, sets AAL/IAL/AMR headers, and enforces IAL β‰₯ 3
- **`app-restricted-flow`** (`accesstoken.auth_type == "app"`) β€” rejects any manually-set `x-ers-*` headers (403), then sets fixed app-restricted values for ODS, business function, user-id, and access-mode
- **`undefined-flow`** β€” catch-all that returns 403 (should never trigger)

Both flows finish with `AssignMessage.Swap.CorrelationHeader` which converts `X-Correlation-ID` β†’ `NHSD-Correlation-ID` for the backend.

### Header transformation mapping

The proxy swaps external consumer-facing headers to internal backend headers:

| External header (consumer sends) | Internal header (backend receives) |
|---|---|
| `X-Correlation-ID` | `NHSD-Correlation-ID` (appended with `.{messageid}`) |
| `nhsd-end-user-organisation-ods` | `x-ers-ods-code` |
| `nhsd-ers-business-function` | `x-ers-business-function` |
| `nhsd-ers-comm-rule-org` | `x-ers-comm-rule-org` |
| `nhsd-ers-file-name` | `x-ers-file-name` |
| `nhsd-ers-referral-id` | `x-ers-referral-id` |
| `NHSD-eRS-On-Behalf-Of-User-ID` | `x-ers-on-behalf-of-user-id` |

Additional headers set by the proxy (not from consumer input):
- `x-ers-access-mode` β€” `user` or `app`
- `x-ers-user-id` β€” from OAuth token (user) or app config (app)
- `x-ers-authentication-assurance-level` β€” from token
- `x-ers-id-assurance-level` β€” from token
- `x-ers-amr` β€” authentication method reference from token

### Response flow

- Sets `X-Request-ID` flag, swaps `x_ers_transaction_id` to the response, removes `nhsd-correlation-id` from the response

### FaultRules (TargetEndpoint)

Error responses are FHIR-version-aware β€” `isFhirR4Path` selects between R4 and pre-R4 `OperationOutcome` response shapes. Handled faults:
- OAuth token failures (scope errors β†’ AAL insufficient)
- Spike arrest / quota exceeded (rate limiting)
- Insufficient IAL (identity assurance level < 3)
- Missing ASID
- Invalid business function
- ODS header missing / not in partner allowlist
- EUO allowlist internal errors (500)

### Backend connection

- Target server: `{{ ERS_TARGET_SERVER }}` (defaults to `e-referrals-service-api`)
- Backend path: `/ers-api`
- TLS enabled; conditional truststore for feature-test (`--ft-`) environments
- I/O timeout: 180 seconds
- Jinja2 templating (`{{ }}` placeholders) is resolved at build time by `scripts/build_proxy.sh`

### Policy naming conventions

- `AssignMessage.Set.*` β€” set a header/variable to a fixed value
- `AssignMessage.Swap.*` β€” rename/transform a header between external and internal naming
- `AssignMessage.Remove.*` β€” strip a header
- `AssignMessage.SetOperationOutcome*` β€” prepare FHIR OperationOutcome error variables
- `RaiseFault.*` β€” return an HTTP error status
- `FlowCallout.*` β€” delegate to a shared flow
- `KeyValueMapOperations.*` β€” read from Apigee KVM stores

## `proxies/sandbox/` β€” sandbox proxy

Lightweight proxy that forwards to the sandbox container (Hapi.js mock server) via Apigee hosted targets.

### Key differences from live

- Only ~11 policies (vs ~60 in live) β€” no OAuth, no ASID, no rate limiting, no header swapping
- Adds CORS preflight handling (`AssignMessage.AddCors` on OPTIONS)
- Uses `DecodeJWT.FromJWTHeader` to decode (but not validate) the JWT for inspection
- Target is `{{ HOSTED_TARGET_CONNECTION }}` β€” the sandbox container deployed alongside the proxy
- No fault rules or auth enforcement

### Shared structure

Both proxies share `_ping` and `_status` flows β€” `_ping` returns a canned response directly (no backend call), `_status` uses an API key from KVM + `ServiceCallout.CallHealthcheckEndpoint`.

## Proxy build process

`scripts/build_proxy.sh` copies both proxy bundles into `build/proxies/`, and for sandbox, rsyncs the entire `sandbox/` app into `build/proxies/sandbox/apiproxy/resources/hosted/` so Apigee can run it as a hosted target.

Jinja2 template variables (e.g. `{{ SERVICE_BASE_PATH }}`, `{{ ERS_TARGET_SERVER }}`, `{{ HOSTED_TARGET_CONNECTION }}`) are resolved during the CI/CD pipeline deployment step.

## Infrastructure

- **Apigee** API gateway managed via Terraform (`terraform/main.tf`)
- Uses the `api-platform-service-module` from NHSDigital
- Backend: Azure (`azurerm` state backend)
- Proxy type auto-selects `sandbox` or `live` based on Apigee environment name

## Adding or modifying a proxy policy

1. Create/edit the XML file in `proxies/live/apiproxy/policies/` (or `sandbox/`)
2. Reference it by `<Name>` in the appropriate flow in `proxies/default.xml` or `ers-target.xml`
3. If it uses JavaScript, add the `.js` file to `apiproxy/resources/jsc/` and reference via `<ResourceURL>jsc://filename.js</ResourceURL>`
4. Run `make lint` β€” validates all proxy XML via `scripts/xml_validator.py`
5. Remember to handle both R4 and pre-R4 paths if the policy produces FHIR error responses
Loading
Loading