A digital service for categorising prisoners
https://dev.offender-categorisation.service.justice.gov.uk/
You will need the following tools installed:
| Tool | Version | Reason |
|---|---|---|
| npm | ≥9.5.x | Node package manager for resolving/installing project dependencies |
| node | ≥24.18.x | NodeJS interpreter |
| docker | ≥18.x | Installing/removing/managing containers & images |
| docker-compose | ≥1.25.x | Convenience utility for grouped management of containers |
Offender-Categorisation is a nodeJS application which by default starts up and listens on URL http://localhost:3000
It has services on which it depends :
| Dependency | Description | Default | Override Env Var |
|---|---|---|---|
| prison-api | Nomis API providing prisons/offender information | http://localhost:8080 | ELITE2API_ENDPOINT_URL |
| hmpps-auth | OAuth2 API server for authenticating requests | http://localhost:9090/auth | RISK_PROFILER_ENDPOINT_URL |
| allocation-manager | Allocation manager | http://localhost:8083/ | ALLOCATION_MANAGER_ENDPOINT_URL |
| postgres (form-builder) | PostgreSQL database server for offender-categorisation | jdbc:postgresql://localhost:5432/form-builder | Uses port forwarding DB_NAME found in Lens |
| redis | Redis cache for user 'session' data (roles) | localhost:6379/tcp | |
| SQS (event) | AWS SQS queue for events | http://localhost:4566 Name: event (localstack) |
EVENT_QUEUE_URL |
| SQS (event dead letter) | AWS SQS queue for events dead letter | http://localhost:4566 Name: event (localstack) |
EVENT_DL_QUEUE_URL |
| ingress url | http://localhost:3000/ | INGRESS_URL | |
| dps url | http://localhost:3000/ | DPS_URL |
| Environment variable | Default value |
|---|---|
| GOOGLE_TAG_MANAGER_TAG | (blank) |
| APPROVED_DISPLAY_MONTHS | 6 |
| RECAT_MARGIN_MONTHS | 2 |
| FEMALE_PRISON_IDS | ['AGI', 'DWI', 'DHI', 'ESI', 'EWI', 'BZI', 'FHI', 'LNI', 'SDI', 'STI', 'NHI', 'PFI'] |
| File | Purpose |
|---|---|
| docker-compose.yml | Creates containers for all dependent services and all allows selective start, or override by env vars |
| docker-compose-test.yml | Sets up all containers for running locally |
The offender-categorisation can be run in two ways.
- if you have a high-spec machine
- if you are unable to connect to remote services
Set up port-forwarding by following the instructions here: https://dsdmoj.atlassian.net/wiki/spaces/SED/pages/3930816517/Port+Forwarding+-+Developer+Instructions
Start supporting Docker services:
docker compose up -d form-db categorisation-redis nomis-oauth2-server
Install dependencies using npm run setup
Run the application using npm run start
Either set the environment variable SQS_ENABLED=false in .env before starting the application or make sure all the SQS queues have started up in the categorisation-localstack container and categorisation-localstack-setup container has exited
The docker-compose-test.yml file starts LocalStack and SQS separately for Cypress tests. The normal Compose command does not start LocalStack.
If you're using an M4 (Apple Silicon) Mac, the nomis-oauth2-server container may crash with the following error:
[error occurred during error reporting (), id 0x5, SIGTRAP (0x5) at pc=0x0000ffff9cb771ec]
To fix this, add the following environment variable to the nomis-oauth2-server service in your docker-compose.yml:
environment:
- JAVA_TOOL_OPTIONS=-XX:UseSVE=0The other option is to run stunnel and port forward using the cloud platform guidance:
https://github.com/ministryofjustice/cloud-platform-terraform-elasticache-cluster
If running locally against elasticache with TLS_ENABLED='true' you will also need to provide the following env vars:
REDIS_AUTH_TOKEN=<from the namespace secret>
NODE_TLS_REJECT_UNAUTHORIZED=0Install dependencies
npm install
Run the application
npm run start
This app is transactional for Postgres database operations but NOT elite2 calls. So it is vital that router endpoints do all db calls BEFORE elite2 (updating) calls. Otherwise when an error occurs, Nomis could get updated with the corresponding postgres changes being rolled back.
You can log in with users stored in the seeded nomis oauth db e.g. CA_USER, password123456
The app authenticates using nomis Nomis Oauth2 Server and saves to a Postgres database.
The app uses redis (cloud platform elasticache when deployed to our environments) to store the user session.
In config.js you can see all the required variables. These are set with defaults that will allow the application to run, but you will need to add a .env file at some point.
npm run start
To automate the checking of the source code for programmatic and stylistic errors run lint using:
npm run lint
To run the jest unit tests:
npm run test
Do not run docker compose -f docker-compose.yml and docker-compose-test.yml at the same time.
Both files define a PostgreSQL container named form-builder-db on port 5432, and initialise DB_NAME=form-builder database.
The Cypress commands load feature.env, which setsDB_NAME=form-builder.
When Cypress tests run through npm run int-test or npm run int-test-ui many tests call cy.task('setUpDb').
setUpDb rolls back and reapplies the database migrations. This can remove existing data from the form-builder database used by the local application.
Do not run the Cypress integration tests if you need to preserve data in your local form-builder database.
Stop the current environment before switching:
docker compose -f docker-compose.yml down or docker compose -f docker-compose-test.yml down
These commands prevent container and port conflicts; they do not protect the database from Cypress resets.
For local running, start a test db, redis, and wiremock instance by:
docker-compose -f docker-compose-test.yml up
Then run the server in test mode by:
npm run start-feature (or npm run start-feature:dev to run with nodemon)
And then either, run tests in headless mode with:
npm run int-test
Or run tests with the cypress UI:
npm run int-test-ui