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

4.2 KiB

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:

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

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-tokensCreate 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

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