---
module: incident.processing-rules
title: Processing Rules
tab: Claude
order: 40
audience: dev
---

> Terse agent reference. Every endpoint/table/topic/role below is confirmed in hiveops-incident source (2026-07-01). Controller paths are as mapped in code; externally reached via NGINX `/api/incident/` (incident, port 8080).

## Ownership
- **hiveops-incident owns ALL rule data + evaluation.** Rules are NOT in journal/devices/mgmt.
- Rule evaluation engine: `IncidentAutoCreationService` (`findApplicableRule`, `processRecovery`).
- Adoons suggestions delegated to **hiveops-ai**; incident only proxies/persists.

## Endpoints (METHOD path)
Opening rules — controller `@RequestMapping("/api/ticket-processing-rules")`:
- `GET /api/ticket-processing-rules` — all
- `GET /api/ticket-processing-rules/drafts`
- `GET /api/ticket-processing-rules/audit?limit=` — recent (cap 200)
- `GET /api/ticket-processing-rules/{id}/audit`
- `POST /api/ticket-processing-rules` — admin
- `POST /api/ticket-processing-rules/drafts` — admin
- `PUT /api/ticket-processing-rules/{id}` — admin
- `PATCH /api/ticket-processing-rules/{id}/enabled` body `{enabled:bool}` — admin
- `PATCH /api/ticket-processing-rules/{id}/approve` — admin
- `DELETE /api/ticket-processing-rules/{id}` — admin

Closing rules — `@RequestMapping("/api/incident-closing-rules")`:
- `GET /api/incident-closing-rules`
- `POST /api/incident-closing-rules` — admin
- `PUT /api/incident-closing-rules/{id}` — admin
- `PATCH /api/incident-closing-rules/{id}/enabled` — admin
- `DELETE /api/incident-closing-rules/{id}` — admin

Event exceptions — `@RequestMapping("/api/event-exceptions")`:
- `GET /api/event-exceptions`
- `DELETE /api/event-exceptions/{id}` — admin
- `DELETE /api/event-exceptions/by-type/{eventTypeRaw}` — admin (URL-encode the type)

Adoons — `@RequestMapping("/api/adoons")` + `/api/adoons/rule-suggestions`:
- `GET /api/adoons/status` → proxies ai `/actuator/health`, returns `{available:bool}`
- `POST /api/adoons/suggest-rule` → ai `POST /api/adoons/suggest-rule`
- `POST /api/adoons/suggest-closing-rule` → ai `POST /api/adoons/suggest-closing-rule`
- `POST /api/adoons/rule-suggestions` body `{kind:PROCESSING|CLOSING, eventType?, logSample?, description?}` → 202 `{requestId}`
- `GET /api/adoons/rule-suggestions?kind=` — institution-scoped list
- `GET /api/adoons/rule-suggestions/{requestId}` — 403 if outside caller institution scope

## Roles
- All mutations: `@PreAuthorize("hasAnyRole('MSP_ADMIN','BCOS_ADMIN')")`.
- All GET rule/draft/audit/exception reads: authenticated, no role gate.
- `/api/adoons/rule-suggestions`: authenticated, scoped via `InstitutionContext.resolveScope()` (no admin gate).

## Tables (DB `hiveiq_incident`)
- `ticket_processing_rules`
- `ticket_processing_rule_audit`
- `incident_closing_rules`
- `event_exceptions`
- `rule_suggestions`

## Kafka topics
- consume `hiveops.device.events` (group `hiveops-incident-device-sync`) → `DeviceEventConsumer` → auto-creation → opening-rule eval
- produce `adoons.rule-suggestion.requested` (`RuleSuggestionProducer`)
- consume `adoons.rule-suggestion.ready` (group `hiveops-incident-adoons`, `RuleSuggestionResultConsumer`)

## Enums / values
- `TicketProcessingAction`: `CREATE_INCIDENT`, `SUPPRESS`, `OPEN_AND_CLOSE`
- Closing `targetStatus`: `RESOLVED` (default) | `CLOSED`
- `rule_suggestions.status`: `PENDING` | `READY` | `FAILED`; `kind`: `PROCESSING` | `CLOSING`

## Gotchas
- Opening-rule match precedence: institution-scoped > global; within scope, text-pattern-specific > catch-all.
- `text_pattern` match = case-insensitive `contains` on event details; blank/null = matches any.
- Institution match resolves rule's stored `institution` as a **KEY** → institution NAME, then compares to ATM's institution name; unresolved key falls back to raw value. Key-vs-name mismatch = rule silently falls through to global.
- Recovery/close path applies built-in `RECOVERY_MAP` BEFORE configurable closing rules.
- Unrecognised event types are recorded to `event_exceptions` by `JournalEventService`, not incidents.
- `event_type` strings are SCREAMING_SNAKE_CASE; exact match required.
- Rule eval decisions are logged (`Rule eval:` lines) — grep Loki for triage.

## Do NOT
- Do NOT add rule tables/endpoints to journal, devices, or mgmt — incident owns this domain.
- Do NOT call hiveops-ai directly for suggestions from the frontend; go through `/api/adoons/*` (JWT validated, then `X-Internal-Secret` injected).
- Do NOT assume rule `institution` is a display name — it's stored as the institution KEY.
- Do NOT expect a mutation without MSP_ADMIN/BCOS_ADMIN to succeed (403).
- Do NOT confuse Adoons with a generic "AI" in user-facing copy — it is branded **Adoons**.
- Do NOT rely on suggestion delivery if hiveops-ai is down; `/status` returning `available:false` only blocks suggestions, not rule CRUD.
