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=--clearpermanently 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=--clearpermanently 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, andload-sitesignoresload-site-emailsignoressite_description. A file containing onlysite_code+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.