Files
cx-ui/docs/INTEGRATIONS.md
Parham Monfared 1262690276
Some checks failed
build-and-deploy / test (push) Has been cancelled
build-and-deploy / image (push) Has been cancelled
build-and-deploy / deploy (push) Has been cancelled
Split into a FastAPI backend and a React frontend, add case state and SSO
The single-file stdlib server became the limit: no way to track what had been
done about an alert, no accounts, and a UI that had to be hand-rolled in
template strings. This restructures it into something deployable.

Backend (FastAPI)
- app/ holds config, database, auth, delivery and the routers; triagelib keeps
  the triage engine unchanged, so the validated screening and runbook logic is
  untouched.
- Cases persist per alert fingerprint with a status workflow (investigating,
  customer contacted, escalated to Infra, waiting, remediated, resolved, won't
  fix, false positive), an assignee, notes and an append-only history. An alert
  that stops and re-fires lands back on the same case and counts as a reopen.
- Suppression rules move from a JSON file into the database.

Auth
- Signed session cookies over PBKDF2 local accounts, plus an OIDC flow ready for
  Authentik: users are created on first login and admin follows a group claim.
  Local login can be switched off entirely once SSO is live.

Zendesk and Jira
- Delivery is now implemented, behind three gates: the integration must be
  configured, its feature flag on, and CX_FEATURE_SEND_ENABLED on. A demo
  instance leaves the last off and cannot mail anyone. Both search before
  creating, so re-diagnosing an alert updates one ticket rather than opening
  several, and a rolling daily cap stops a loop mailing everybody.

Deployment
- Multi-stage Dockerfile builds the bundle and serves it from the API origin.
- docker-compose for local and single-host use; Gitea Actions runs the tests,
  builds the image and renders deploy/k8s with envsubst.

Two fixes found while testing: assigning a case returned a null assignee, and
add_event could leave an already-loaded history collection stale.

Known gap: the engine reaches OpenStack via `docker exec <region>-osc`, which
does not work in a pod without the CX-Tools containers alongside it.
docs/DEPLOYMENT.md sets out the three ways to close that.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 07:11:28 +01:00

134 lines
4.2 KiB
Markdown

# Enabling Zendesk and Jira
Nothing leaves this app until **three separate gates** are open. Until then the
UI builds the full payload, shows it to you, and the Send button stays disabled
with the reason written on it.
```
1. the integration is configured CX_ZENDESK_* / CX_JIRA_*
2. its feature flag is on CX_FEATURE_ZENDESK / CX_FEATURE_JIRA
3. sending is enabled globally CX_FEATURE_SEND_ENABLED
```
Gate 3 is the important one. A demo or staging instance simply leaves it off,
and then no combination of clicks can email a customer.
Check where you stand at any time on **Settings → Integrations**, or:
```bash
curl -s localhost:8080/api/health | python3 -m json.tool
```
---
## Zendesk
### 1. Create an API token
Zendesk **Admin Center → Apps and integrations → APIs → Zendesk API**, turn on
*Token access*, then **Add API token**. Copy it — Zendesk shows it once.
### 2. Decide which agent owns the tickets
Use a dedicated agent (e.g. `cx-triage@…`) rather than a person's account, so
the audit trail stays clear when someone leaves.
### 3. Set the variables
```bash
CX_FEATURE_ZENDESK=true
CX_ZENDESK_SUBDOMAIN=nexgencloud # from https://<this>.zendesk.com
CX_ZENDESK_EMAIL=cx-triage@nexgencloud.com
CX_ZENDESK_TOKEN=<the token>
CX_ZENDESK_PUBLIC_REPLY=true # false posts an internal note instead
CX_FEATURE_SEND_ENABLED=true # the master switch
```
Restart. The Send button becomes live.
### What happens on send
1. Searches for `external_id:cx-triage-<fingerprint>`.
2. If a ticket exists → adds a comment. If not → creates one, with the requester
set from the Infrahub owner, priority from the screening verdict, and tags
`cx-triage`, `alert-<kind>`.
3. Records a `zendesk_sent` event on the case and moves it to
**Customer contacted**.
So re-diagnosing the same alert updates one ticket instead of opening five.
---
## Jira
### 1. Create an API token
<https://id.atlassian.com/manage-profile/security/api-tokens> → *Create API
token*.
### 2. Confirm the project and issue type
The defaults are `INFRA` / `Task`. If your Infrastructure project uses something
else, set it — a wrong `issuetype` is the usual cause of a 400 from Jira.
### 3. Set the variables
```bash
CX_FEATURE_JIRA=true
CX_JIRA_BASE=https://nexgencloud.atlassian.net
CX_JIRA_EMAIL=cx-triage@nexgencloud.com
CX_JIRA_TOKEN=<the token>
CX_JIRA_PROJECT=INFRA
CX_JIRA_ISSUE_TYPE=Task
CX_FEATURE_SEND_ENABLED=true
```
Issues are labelled `cx-triage-<fingerprint>` and searched for before creating,
so the same alert never opens two tickets.
---
## Where the credentials go
**Never commit them.**
| Where | How |
|---|---|
| Local | `.env` (git-ignored) — copy from `.env.example` |
| Kubernetes | The `cx-triage` Secret, written by the pipeline from Gitea secrets |
| Gitea | Repository → Settings → Actions → Secrets |
The deploy job creates the Secret imperatively from the secret store, so no
credential is ever in a manifest in git.
---
## Safety rails that stay on
- Every send needs a click **and** a confirm naming the recipient.
- No auto-send: a verdict never triggers an email by itself.
- `CX_SEND_DAILY_CAP` (default 25) refuses further sends in a rolling 24 hours,
so a loop cannot mail every customer.
- The body is editable before sending.
- Every attempt is written to the case history — including failures.
- Deleting, shelving and InfraInsight edits stay copy-a-command. The read-only
guarantee is what makes this safe against production.
## First run
Point at a **Zendesk sandbox**, or send the first ticket to your own address by
editing the To field. Once one round trip looks right, switch it on for real.
## When it fails
| Symptom | Cause |
|---|---|
| Button disabled, "sending is switched off" | `CX_FEATURE_SEND_ENABLED` is false |
| Button disabled, "not configured" | A `CX_ZENDESK_*` / `CX_JIRA_*` value is missing |
| `401` from Zendesk | The email must be the **agent** address, and token access must be enabled |
| `400` from Jira | Usually `issuetype` or `project` does not exist |
| "Daily send cap reached" | Raise `CX_SEND_DAILY_CAP` if deliberate |
| "Open the case first" | The alert has no case yet — open it in the queue once |