Skip to content

Runbook: Escalation Sites & Site Emails

Manage escalation sites and their associated email addresses. Sites identify the locations used by the escalation routing system. Each site has a short code (e.g. P1234) and a human-readable description; one or more email addresses can be attached to it.

Prerequisite: complete CLI Setup before proceeding.


Background

Two entities are managed here:

  • Escalation sites — named locations (e.g. P1234 — Acme Regional Office). The site code is used to cross-reference data loaded by other scripts; the description is shown to users.
  • Site emails — email addresses attached to a site. These addresses receive escalation notifications when a request is routed to that site.

Two approaches are available depending on the scale of the change:

Approach When to use
CLI Add, update, or remove individual sites or email addresses.
Bulk script Initial data load or full replacement from a master file. Requires database access (VPN).

Escalation Site Management (CLI)

All commands below target PROD. Swap --profile prod for --profile uat to target UAT.

List all sites

altaforge-ra-cli --profile prod api admin escalation-site list

Output is a JSON array. The id field is the SITE_ID required by other commands.

[
  { "id": 1, "siteCode": "P1234", "siteDescription": "Acme Regional Office", "clientName": "AARA" },
  { "id": 2, "siteCode": "P5678", "siteDescription": "Metro Service Centre", "clientName": "AARA" }
]

Add a site

altaforge-ra-cli --profile prod api admin escalation-site add P9999 "New Branch Office"

Update a site

At least one of --site-code or --description must be provided:

altaforge-ra-cli --profile prod api admin escalation-site update <SITE_ID> --description "Updated Description"
altaforge-ra-cli --profile prod api admin escalation-site update <SITE_ID> --site-code P0000
altaforge-ra-cli --profile prod api admin escalation-site update <SITE_ID> --site-code P0000 --description "New Code and Name"

Delete a site

altaforge-ra-cli --profile prod api admin escalation-site delete <SITE_ID>

Warning: Deleting a site also removes all email addresses associated with it. Run site-email list --site-id <SITE_ID> first to understand the impact.


Site Email Management (CLI)

List site emails

List all email addresses across all sites:

altaforge-ra-cli --profile prod api admin site-email list

Filter by site (use one of):

altaforge-ra-cli --profile prod api admin site-email list --site-id <SITE_ID>
altaforge-ra-cli --profile prod api admin site-email list --site-code P1234

Output is a JSON array. The id field is the EMAIL_ID required to update or delete an address.

[
  { "id": 10, "escalationSiteId": 1, "email": "office@example.com" },
  { "id": 11, "escalationSiteId": 1, "email": "backup@example.com" }
]

Add an email address to a site

Pass either the site ID (integer) or the site code (string) as the first argument:

altaforge-ra-cli --profile prod api admin site-email add P1234 new-contact@example.com
altaforge-ra-cli --profile prod api admin site-email add 1 new-contact@example.com

Add multiple email addresses (idempotent)

Use add-if-missing when adding a batch of site/email pairs across environments. Each pair is checked first — addresses already present are skipped rather than duplicated. Pass site-code/email pairs as positional arguments:

altaforge-ra-cli --profile stg api admin site-email add-if-missing \
  P331 contact-a@example.com \
  P332 contact-b@example.com \
  P333 contact-c@example.com

Output per pair is either SKIP [PXXX] email (already present) or ADD [PXXX] email followed by the created record. Run the same command against each environment once confirmed:

altaforge-ra-cli --profile stg  api admin site-email add-if-missing P331 contact@example.com P332 contact2@example.com
altaforge-ra-cli --profile uat  api admin site-email add-if-missing P331 contact@example.com P332 contact2@example.com
altaforge-ra-cli --profile prod api admin site-email add-if-missing P331 contact@example.com P332 contact2@example.com

Update an email address

altaforge-ra-cli --profile prod api admin site-email update <EMAIL_ID> updated@example.com

Use site-email list --site-code P1234 to find the EMAIL_ID.

Remove an email address

altaforge-ra-cli --profile prod api admin site-email delete <EMAIL_ID>

Bulk Load (Requires Database Access)

Use the bulk scripts when loading an initial dataset or replacing all records for a client from a master file. These scripts connect directly to the database — you must be on VPN.

1. Configure scripts/.env

The scripts read credentials from scripts/.env at the repository root. Create or update it before each run if targeting a different environment.

DATABASE_URL=postgresql+asyncpg://<user>:<password>@<host>:5432/<database>
Engine URL format
PostgreSQL postgresql+asyncpg://user:password@host:5432/dbname
MSSQL (Azure AD auth) mssql+aioodbc://host:1433/dbname?driver=ODBC+Driver+18+for+SQL+Server&authentication=ActiveDirectoryInteractive
MSSQL (SQL auth) mssql+aioodbc://user:password@host:1433/dbname?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes

The database is not publicly accessible. You must be connected to the virtual network (VPN or equivalent) to reach it.

2. Load sites

Warning: CLEAR=--clear permanently removes all existing sites (and their emails) for the client before loading. Any site not present in the file will be lost. Before running, confirm that the file is the complete and authoritative dataset — not just the rows you are adding or changing.

Always use CLEAR=--clear unless you have been explicitly told to append.

CSV format — required columns: p_number (maps to site code) and registry_name (maps to description). Optionally include a client_name column per row; otherwise CLIENT= is required:

make load-sites FILE="path/to/sites.csv" CLIENT=AARA CLEAR=--clear

JSON format — top-level array of {"site_code": "...", "site_description": "..."} objects. CLIENT= is required for JSON files:

make load-sites FILE="path/to/sites.json" CLIENT=AARA CLEAR=--clear

Without CLEAR=--clear, existing site rows are upserted (missing rows are inserted; descriptions that differ are updated). With CLEAR=--clear, all existing sites for the client are atomically replaced, and associated site emails are also removed (foreign key cascade).

3. Load site emails

Site records must exist before loading emails. Run make load-sites first.

Warning: CLEAR=--clear permanently removes all existing site email rows for the client before loading. Any email not present in the file will be lost. Confirm the file is the complete dataset before running.

UAT warning: check email addresses before loading

Site emails are used to route real escalation notifications. Do not load production email addresses into UAT — doing so risks sending test traffic to live support inboxes. Before loading into UAT, replace every address in the file with a safe test address (e.g. request.testing@example.com). Use a separate copy of the file — do not modify the master.

JSON format — top-level array of {"site_code": "...", "email": "..."} objects. CLIENT= is required for JSON files:

make load-site-emails FILE="path/to/site_emails.json" CLIENT=AARA CLEAR=--clear

CSV format — required columns: site_code and email. Optionally include client_name:

make load-site-emails FILE="path/to/site_emails.csv" CLIENT=AARA CLEAR=--clear

Without CLEAR=--clear, new email rows are appended to existing ones. With CLEAR=--clear, all existing site email rows for the client are atomically replaced.

Note: To share a single JSON file between both commands, include site_code, site_description, and email in each object. load-sites ignores email and load-site-emails ignores site_description. A file containing only site_code + email is not sufficient for load-sites.

If the script exits with an error before printing the success message, the database has not been modified — the transaction was rolled back.

4. Verify the load

After loading, confirm the counts in the script output look correct. If you are unsure, ask a developer to verify via the application or a direct database query.


Escalation

If a command returns an unexpected error, escalate to the development team with:

  • The exact command run.
  • The full error output.
  • The environment (UAT or PROD) and approximate time.