{"id":24417180,"url":"https://github.com/defra/fg-gas-backend","last_synced_at":"2026-05-19T05:40:52.314Z","repository":{"id":272584202,"uuid":"917097258","full_name":"DEFRA/fg-gas-backend","owner":"DEFRA","description":"Git repository for service fg-gas-backend","archived":false,"fork":false,"pushed_at":"2025-10-02T11:04:28.000Z","size":2227,"stargazers_count":0,"open_issues_count":10,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-02T11:24:23.334Z","etag":null,"topics":["backend","cdp","node","service"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DEFRA.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-01-15T10:53:38.000Z","updated_at":"2025-10-02T11:00:27.000Z","dependencies_parsed_at":"2025-01-15T12:52:24.474Z","dependency_job_id":"74efce4e-885e-41b8-8971-1860c6833266","html_url":"https://github.com/DEFRA/fg-gas-backend","commit_stats":null,"previous_names":["defra/fg-gas-backend"],"tags_count":131,"template":false,"template_full_name":null,"purl":"pkg:github/DEFRA/fg-gas-backend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DEFRA%2Ffg-gas-backend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DEFRA%2Ffg-gas-backend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DEFRA%2Ffg-gas-backend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DEFRA%2Ffg-gas-backend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DEFRA","download_url":"https://codeload.github.com/DEFRA/fg-gas-backend/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DEFRA%2Ffg-gas-backend/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279010792,"owners_count":26084807,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-12T02:00:06.719Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backend","cdp","node","service"],"created_at":"2025-01-20T08:15:49.516Z","updated_at":"2026-05-19T05:40:52.298Z","avatar_url":"https://github.com/DEFRA.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fg-gas-backend\n\nGrant Application Service defines and manages farming grants and applications. It is the source of truth for all grant applications and their status.\n\n- [Running with other services](#running-with-other-services)\n- [User guide](#user-guide)\n  - [Configure grant actions](#configure-grant-actions)\n- [Developer guide](#developer-guide)\n  - [Node.js](#nodejs)\n- [Local development](#local-development)\n  - [Setup](#setup)\n  - [Development](#development)\n  - [Testing](#testing)\n    - [Unit tests](#unit-tests)\n    - [Integration tests](#integration-tests)\n    - [Contract tests](#contract-tests)\n- [Service to service authentication](#service-to-service-authentication)\n  - [Minting service access tokens](#minting-service-access-tokens)\n- [HTTP client and API examples](#http-client-and-api-examples)\n- [Docker](#docker)\n- [Licence](#licence)\n  - [About the licence](#about-the-licence)\n\n## Running with other services\n\nIf you want to run this service with other farming grants applications see [fg-grants-core](https://github.com/DEFRA/fg-grants-core)\n\n## User guide\n\n### Configure grant actions\n\nAs part of the Grant Application Service, you can configure and call actions on grants.\n\nGiven a grant definition is stored in GAS as per the following example:\n\n- Note the $areaId and $segmentId in the URL, these are placeholders that will be replaced with actual values when the action is invoked.\n\n```json\n{\n  \"code\": \"my-grant-code\",\n  \"actions\": [\n    {\n      \"name\": \"land-area-calculation\",\n      \"method\": \"POST\",\n      \"url\": \"https://my-other-server.%ENVIRONMENT%.gov.uk/some-path/area-calc/$areaId/$segmentId\"\n    }\n  ]\n}\n```\n\nNote: The `%ENVIRONMENT%` placeholder will be replaced with the current CDP environment when running in a CDP environment.\n\nThis can be called via the following HTTP request:\n\n- Note the areaId and segmentId query parameters, these will be used to replace the placeholders in the URL.\n- The anotherParam query parameter is an example of additional parameters will be passed on in the URL query string.\n\n```http request\nPOST http://gas-server/grants/my-grant-code/actions/land-area-calculation/invoke?areaId=123\u0026segmentId=456\u0026anotherParam=ABC123\nContent-Type: application/json\n\n{\n  \"someKey\": \"someValue\"\n}\n```\n\nThis wil result in the following HTTP request being made to the configured URL:\n\n```http request\nPOST https://my-other-server/some-path/area-calc/123/456?code=my-grant-code\u0026anotherParam=ABC123\nContent-Type: application/json\n\n{\n  \"someKey\": \"someValue\"\n}\n```\n\n## Developer guide\n\n### Node.js\n\nPlease install Node Version Manager [nvm](https://github.com/creationix/nvm)\n\nTo use the correct version of Node.js for this application, via nvm:\n\n```bash\ncd fg-gas-backend\nnvm use\n```\n\n## Local development\n\n### Setup\n\nInstall application dependencies:\n\n```bash\nnpm install\n```\n\nCreate a `.env` file in the root of the project. You can use the `.env.example` file as a template.\n\n```bash\ncp .env.example .env\n```\n\n## SNS/SQS Message retrieval for local development\n\nTo verify an SNS message has been queued locally you will need the aws cli installed and some basic configuration.\n\n### Install Aws Cli\n\nInstall aws cli (https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)\n\n### Configure your localstack with aws config\n\nAdd the following localstack profile to your `~/.aws/config`\n\n```bash\n[profile localstack]\nregion=eu-west-1\noutput=json\nendpoint_url=http://localhost:4566\n```\n\nAdd the following config to your `~/.aws/credentials`\n\n```bash\n[localstack]\naws_access_key_id=test\naws_secret_access_key=test\n```\n\n### Query localstack\n\nThen run the following to fetch messages in the queue. The queue-url should match the output from local stack in your console environment\n\n```bash\naws sqs receive-message --queue-url http://sqs.eu-west-2.127.0.0.1:4566/000000000000/grant_application_created --profile localstack\n```\n\n### Development\n\nTo run the application in `development` mode run:\n\n```bash\nnpm run dev\n```\n\n### Testing\n\n#### Unit tests\n\nTo run the unit tests:\n\n```bash\nnpm run test:unit\n```\n\n#### Integration tests\n\nTo run the integration tests:\n\n```bash\nnpm run test:integration\n```\n\n#### Contract tests\n\nThis project uses Pact to verify consumer-provider contracts.\n\n- To run the contract tests against the Pact broker:\n\n```bash\nnpm run test:contract\n```\n\nNote: This is normally used in CI, but if running locally it requires `.env.test` to be populated with the broker details and you must be connected to the Azure VPN.\n\n- To run the contract tests locally against local pact files (helpful when developing without Azure VPN access or iterating quickly), use the provided script which sets `PACT_USE_LOCAL=true`:\n\n```bash\nnpm run test:contract:local\n```\n\nWhen `PACT_USE_LOCAL=true`, tests will read pact files from `tmp/pacts` (for example `tmp/pacts/grants-ui-fg-gas-backend.json`).\n\n## Service to service authentication\n\nThe GAS API uses simple bearer tokens for service access. Tokens are UUIDv4 values whose SHA‑256 hash is stored in MongoDB in the `access_tokens` collection.\n\nClients must send the raw token in the `Authorization` header as `Bearer \u003ctoken\u003e`.\n\n### Minting service access tokens\n\nThere is a helper script to mint access tokens and optionally write them to MongoDB:\n\nUse `scripts/mint-access-token.js` to mint a token and, if `MONGO_URI` and `MONGO_DATABASE` are set, write the hashed token to Mongo.\n\nUsage:\n\n```bash\n# Mint and write hashed token to Mongo, print raw token to console\nnode --env-file=.env scripts/mint-access-token.js [clientName] [expiresISO]\n```\n\n```bash\n# Mint and print hashed token and raw token to console\nnode scripts/mint-access-token.js [clientName] [expiresISO]\n```\n\n- `clientName` defaults to `grants-ui`.\n- `expiresISO` is optional (e.g. `2099-01-01T00:00:00Z`).\n\nThe script prints:\n\n- A confirmation message and details.\n- The hashed token if `MONGO_URI` and `MONGO_DATABASE` are not set.\n- The raw bearer token on the last line – copy and store it securely. It will not be shown again.\n\nThere is also a convenience script to mint and write the raw token to `http-client.private.env.json` to allow for local testing with `api.http`:\n\n```bash\nnpm run token:local\n```\n\nThis runs: `node --env-file=.env scripts/write-http-client-token.js local http-client 2099-01-01T00:00:00Z`.\n\nWhich uses `scripts/write-http-client-token.js` to mint a token, store in the local MongoDB and write the raw value into `http-client.private.env.json` under the chosen environment key, so `api.http` can use it immediately.\n\n### Run with manual vars:\n\n`MONGO_URI=\"mongodb://localhost:27017\" MONGO_DATABASE=fg-gas-backend node scripts/mint-access-token.js`\n\n### Minting access tokens for fg-grants-core\n\nWhen using grants core with just the case working and gas dev mode the mongo db is available on localhost and does not use a direct connection.\n\nIf you're using grants core with external apps (grants-ui for example) then the db connection is through the docker network and direct connection is\nrequired. The env-file option won't work here. You have to manually add MONGO_URI and MONGO_DATABASE to the command - see \"run with manual vars\"\n\nGeneral script usage for any environment if needed:\n\n```bash\nnode --env-file=.env scripts/write-http-client-token.js \u003cenvName\u003e [clientName] [expiresISO]\n```\n\nExamples:\n\n```bash\n# Local environment – also inserts the hash into Mongo (requires MONGO_URI/MONGO_DATABASE)\nnode --env-file=.env scripts/write-http-client-token.js local http-client 2099-01-01T00:00:00Z\n```\n\n```bash\n# Non-local environment – only updates http-client.private.env.json\nnode scripts/write-http-client-token.js dev grants-ui 2026-01-01T00:00:00Z\n```\n\nAfter running, you should see output similar to:\n\n```\nUpdated http-client.private.env.json -\u003e [local].serviceToken\n```\n\nNotes and requirements:\n\n- For local usage, ensure your `.env` provides `MONGO_URI` and `MONGO_DATABASE` so the hashed token can be stored in MongoDB.\n- `http-client.private.env.json` is git‑ignored by default. Keep tokens out of source control.\n\n## HTTP client and API examples\n\nThis repository includes `api.http` which you can run directly from JetBrains IDEs (HTTP Client) or VS Code (REST Client extension).\n\n- Base URLs are defined in `http-client.env.json` (checked in).\n- Private secrets (like the `serviceToken`) are stored in `http-client.private.env.json` (git‑ignored). Do not commit this file.\n\n`api.http` uses these variables:\n\n- `{{base}}` – selected environment base URL (for example `http://localhost:3000`).\n- `{{serviceToken}}` – a bearer token used by the API for service‑to‑service auth.\n\nTo run the requests:\n\n1. Ensure the API is running locally (see Development section), or pick a non‑local environment.\n2. Make sure `http-client.private.env.json` has a `serviceToken` for the environment you want to call. You can generate/populate this token using the scripts above.\n3. Open `api.http`, select the desired environment from the drop‑down (e.g. `local`) and send requests.\n\n## Docker\n\nLaunch GAS and dependencies via Docker Compose:\n\n```bash\ndocker compose up --watch\n```\n\n## Project structure\n\nRoutes can access use cases and schemas.\nSubscriptions can access use cases.\nUse cases can access repositories, http clients, domain classes and other use cases.\nUse cases should export a single function.\nRepositories can access db.\n\nRoutes and subscriptions should never respond with a domain object.\nDomain objects should never access use cases, repositories or subscriptions.\nRepositories should never accept or return db records.\n\n## Logging\n\nThis application uses [Pino](https://getpino.io/) for structured logging, configured with ECS (Elastic Common Schema) formatting for better observability and log analysis.\n\nLogging is configured in `src/common/logger.js`.\n\n### Basic Logging\n\nWe use entry and exit level logging patterns for better log correlation.\n\n**Entry logs** indicate the start of an operation:\n\n**Exit logs** indicate the completion of an operation:\n\n\u003e **Note**: We use consistent entry text to make it easier to correlate logs within OpenSearch.\n\n### Conditional Logging\n\nFor operations that have conditional logic between entry and exit logs, use `logger.debug()` or `logger.info()` based on relevance:\n\n**Example implementation**: See `src/grants/use-cases/add-agreement.use-case.js`\n\n### Log Levels\n\n**Warning logs** for recoverable issues:\n\n**Debug logs** for detailed diagnostic information:\n\n\u003e **Note**: Error logging (`logger.error`) is typically not required in use cases as errors are thrown and will propagate up the call stack where they can be handled and logged by the error handling middleware.\n\n### Best Practices\n\n- Use structured logging with context objects for better searchability\n- Include relevant identifiers (IDs, codes, references) in log messages\n- Keep entry and exit log messages consistent for easier correlation\n- Use appropriate log levels based on the importance of the information\n\n## Licence\n\nTHIS INFORMATION IS LICENSED UNDER THE CONDITIONS OF THE OPEN GOVERNMENT LICENCE found at:\n\n\u003chttp://www.nationalarchives.gov.uk/doc/open-government-licence/version/3\u003e\n\nThe following attribution statement MUST be cited in your products and applications when using this information.\n\n\u003e Contains public sector information licensed under the Open Government license v3\n\n### About the licence\n\nThe Open Government Licence (OGL) was developed by the Controller of Her Majesty's Stationery Office (HMSO) to enable\ninformation providers in the public sector to license the use and re-use of their information under a common open\nlicence.\n\nIt is designed to encourage use and re-use of information freely and flexibly, with only a few conditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefra%2Ffg-gas-backend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdefra%2Ffg-gas-backend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefra%2Ffg-gas-backend/lists"}