New: [AEA-6543] - Create new unattended release dispensing endpoint#4523
New: [AEA-6543] - Create new unattended release dispensing endpoint#4523
Conversation
…h it between application restricted or user restricted. Then, update the OAS spec to host the two endpoints.
|
This PR is linked to a ticket in an NHS Digital JIRA Project. Here's a handy link to the ticket: AEA-6543 |
There was a problem hiding this comment.
Pull request overview
This PR splits the dispensing release interaction into two endpoints to reduce confusion between user-restricted vs application-restricted access, and updates the coordinator validation plus API specifications accordingly.
Changes:
- Added a new
POST /Task/$release-unattendedendpoint alongside the existingPOST /Task/$release. - Refactored coordinator release routing/validation to optionally allow application-restricted scope checks for nominated (no
group-identifier) downloads. - Updated OAS/spec docs (and Postman collection) to include and describe the new endpoint.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| postman/dispensing_collection.json | Updates nominated release request to call $release-unattended. |
| packages/specification/fhir-dispensing.yaml | Adds $release-unattended path and references it across error tables/publication metadata. |
| packages/specification/electronic-prescription-service-api.yaml | Documents application-restricted access mode and adds $release-unattended path entry. |
| packages/specification/electronic-prescription-service-api.template.yaml | Template doc updates to reflect $release-unattended and access-mode wording. |
| packages/coordinator/tests/services/validation/parameters-validator.spec.ts | Updates/extends scope validation tests for nominated release + application-restricted option. |
| packages/coordinator/src/services/validation/parameters-validator.ts | Adds options object to verifyParameters and gates scope validation based on allowApplicationRestricted. |
| packages/coordinator/src/routes/dispense/release.ts | Introduces shared handler factory and registers new $release-unattended route. |
| const prescriptionIdParameter = getIdentifierParameterOrNullByName(parameters.parameter, "group-identifier") | ||
| const permissionErrors = prescriptionIdParameter | ||
| ? validatePermittedAttendedDispenseMessage(scope) | ||
| : validatePermittedUnattendedDispenseMessage(scope) | ||
| const permissionErrors = !prescriptionIdParameter && allowApplicationRestricted | ||
| ? validatePermittedUnattendedDispenseMessage(scope) | ||
| : validatePermittedAttendedDispenseMessage(scope) |
There was a problem hiding this comment.
allowApplicationRestricted changes which scope validator runs, but the rest of verifyParameters still enforces the attended/user-restricted agent requirements (e.g. it always reads the agent parameter and requires PractitionerRole.telecom). If application-restricted release is meant to work without practitioner details (per PR description), this function needs to skip/relax agent/practitioner validation when application-restricted access is being used (or when allowApplicationRestricted + app scope is detected).
| { | ||
| method: "POST" as RouteDefMethods, | ||
| path: `${BASE_PATH}/Task/$release`, | ||
| handler: createReleaseHandler(false) | ||
| }, | ||
| { | ||
| method: "POST" as RouteDefMethods, | ||
| path: `${BASE_PATH}/Task/$release-unattended`, | ||
| handler: createReleaseHandler(true) | ||
| } |
There was a problem hiding this comment.
The new /Task/$release-unattended route introduces new behavior (separate endpoint + application-restricted support), but there are no route-level tests covering that this path is registered and behaves as expected (e.g. scope handling and audit hash logging). Please add coverage similar to existing /Task/$release route tests so regressions are caught.
| test("accepts nominated release when unattended application-restricted access is enabled", () => { | ||
| const result = verifyParameters( | ||
| validAttendedNominatedParameters, | ||
| DISPENSING_APP_SCOPE, | ||
| "test_sds_user_id", | ||
| "test_sds_role_id", | ||
| {allowApplicationRestricted: true, checkAccessTokenSDSRoleID: false} | ||
| ) | ||
| expect(result).toEqual([]) |
There was a problem hiding this comment.
The new tests exercise application-restricted scope handling, but they don't cover the key contract change described in the PR (that application-restricted requests can omit practitioner details). Consider adding a test case where the release-unattended/application-restricted flow succeeds without PractitionerRole.practitioner and/or telecom (and ensure the validator implements that behavior).
…lease endpoints. These are the cases I think are useful but I'm not convinced how necessary they are. Better safe than sorry though
|



Summary
Details
The release endpoint supporting two distinct modes will be confusing - application restricted access does not require the practitioner details, but user-restricted does.
I'm breaking it up into two endpoints. I've refactored the handler function to take a boolean argument that enables or disables the check for practitioner details, and I'm updating the OAS spec to host both endpoints.
The copy is subject to change. Currently, I've mostly copy-pasted, and added in the
$release-unattendedwherever$releaseis referenced.