wxccai/README.md
jmcqueen 1070967870 Initial commit: Webex CC + Jira + xAI service
Core capabilities:
- Jira ticket lifecycle: status, update, comment, transitions, close
- JSM Store Support request creation with Assets object resolution
- Assets AQL diagnostic probe endpoint with schema/type introspection
- Webex transcript ingestion (audio + JSON + human-readable) with
  restricted-visibility summary comments
- Grok-powered single-ticket and open-tickets-by-reporter summaries

Repo hygiene:
- .gitignore covering .env, node_modules, logs, IDE dirs
- .env.example documenting every env var
- discover-ss-*.js scripts refactored to read credentials from .env
- README covering setup, endpoints, and the Assets scope-vs-role gotcha

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-01 15:23:20 -04:00

84 lines
3.8 KiB
Markdown

# wxcc-ai
Node/Express service that wires Webex Contact Center summaries, Jira tickets (core + JSM Store Support), and xAI Grok summarization into a single set of internal HTTP endpoints.
## Setup
```bash
npm install
cp .env.example .env
# fill in JIRA_*, XAI_*, and optionally the Assets values
npm run dev
```
The server listens on `PORT` (default `1866`).
## Environment variables
See [`.env.example`](./.env.example) for the full list. The important ones:
| Var | Purpose |
| --- | --- |
| `JIRA_CLOUD_ID` | If set, requests use `https://api.atlassian.com/ex/jira/{cloudId}`. |
| `JIRA_BASE_URL` | Fallback for legacy site URLs (`https://your-site.atlassian.net`). |
| `JIRA_EMAIL`, `JIRA_API_TOKEN` | Basic auth to Jira. `JIRA_AUTH_TYPE=bearer` switches to bearer. |
| `JIRA_SERVICE_DESK_ID` | Numeric JSM service desk id for Store Support. |
| `JIRA_ASSETS_WORKSPACE_ID` | Assets workspace id (auto-discovered if omitted). |
| `JIRA_ASSETS_STORE_SCHEMA_ID`, `_OBJECT_TYPE_ID` | Locate the Store schema/type. |
| `JIRA_ASSETS_STORE_NUMBER_ATTRIBUTE[_ID]` | Attribute name (or id) holding the store number in Assets. |
| `JIRA_STORE_CUSTOM_FIELD_ID` | Custom field on the JSM request that holds the Store Assets reference. |
| `XAI_API_KEY`, `XAI_BASE_URL` | Grok credentials for summary generation. |
## Endpoints
Base path: `/api/wxccai`.
### Read
- `GET /getticket?jiraKey=CS-1234` — Grok-summarized single ticket.
- `GET /open-tickets-by-reporter?email=user@example.com` — Grok-summarized list of open tickets a person reported.
- `GET /ticket/:key/status` — raw status fields (no Grok).
- `GET /ticket/:key/transitions` — available workflow transitions.
### Write
- `PATCH /ticket/:key` — body: `{ summary?, description?, priority?, labels?, assigneeAccountId?, additional? }`
- `POST /ticket/:key/comment` — body: `{ text, internal? }`
- `POST /ticket/:key/close` — body: `{ transitionName?, resolution?, comment?, internal? }` (auto-picks the first "done" transition when `transitionName` omitted).
### Store Support (JSM requests)
- `GET /ssRequestTypes` — supported `subType` values + Assets config summary.
- `POST /createSSRequest` — body includes `subType`, `summary`, `storeNumber` (auto-resolved via Assets), `onBehalfOf`, `description`, `additional`.
### Webex webhook
- `POST /issueTranscript/:jiraKey` — attaches audio + JSON transcript + human-readable transcript, then posts a restricted-visibility summary comment.
### Debug (non-production only)
- `GET /debug/assetsProbe?storeNumber=305` — runs several AQL variants against Jira Assets and returns visible schemas + object-type detail + a computed diagnosis. Returns 404 when `NODE_ENV=production`.
## Jira Assets gotcha
`createSSRequest` resolves a store number to an Assets object reference (`customfield_10261`). Two independent permission layers must both grant access, or every AQL query silently returns `total: 0`:
1. **OAuth scopes** on the API token: `read:cmdb-schema:jira`, `read:cmdb-type:jira`, `read:cmdb-object:jira`, `read:cmdb-attribute:jira` (and the `write:` equivalents for updates).
2. **Object Schema role membership** in Jira Assets itself — the underlying user needs to be added to a role on the Store schema in Jira → Assets → Object schemas → Configure → Roles.
If AQL keeps returning `total: 0` with HTTP 200, run the probe endpoint above; the `diagnosis` field will tell you exactly which layer is missing.
## Docker
```bash
npm run docker:build
npm run docker:run
```
The image runs as a non-root user and exposes `1866`. `HEALTHCHECK` pings `GET /health`.
## Repo hygiene
- Secrets live only in `.env`, which is `.gitignore`d.
- The two `discover-ss-*.js` helper scripts read from `.env` — never hardcode credentials in them.
- The debug logger no longer echoes the outbound `Authorization` header. Rotate any token that appears in older `logs/*.log` files.