---
module: incident.processing-rules
title: Processing Rules
tab: Architect
order: 30
audience: dev
---

> **Architecture view.** How Processing Rules are built and how events flow through them. All rule storage + evaluation is owned by **hiveops-incident**; Adoons suggestions are delegated to **hiveops-ai** over Kafka + a sync proxy. Grounded in code 2026-07-01. See [platform.service-ownership].

## Services involved

| Service | Role in this feature |
|---------|----------------------|
| **hiveops-incident** | Owns rule tables, CRUD controllers, and the evaluation engine (`IncidentAutoCreationService`). Serves the frontend directly. |
| **hiveops-devices** | Produces `hiveops.device.events`; incident's `DeviceEventConsumer` drives auto-creation, which is where opening rules are evaluated. |
| **hiveops-ai (Adoons)** | Generates rule suggestions. Reached two ways: sync proxy (`AdoonsController`) and async via Kafka. |
| **hiveops-agent-proxy** | Agents post journal events here; proxy forwards to incident `/api/internal/journal-events`, feeding `JournalEventService` (which records Event Exceptions + triggers auto-creation/recovery). |

## Data model (all in `hiveiq_incident`, Flyway-managed)

| Table | Entity | Purpose |
|-------|--------|---------|
| `ticket_processing_rules` | `TicketProcessingRule` | Opening rules: `event_type`, `action` (CREATE_INCIDENT/SUPPRESS/OPEN_AND_CLOSE), `override_severity`, `override_incident_type`, `text_pattern`, `institution`, `enabled`, `draft`, `version` |
| `ticket_processing_rule_audit` | `TicketProcessingRuleAudit` | Full change log per rule (History view) |
| `incident_closing_rules` | `IncidentClosingRule` | Closing rules: `trigger_event_type`, `close_incident_types` (CSV), `text_pattern`, `target_status` (RESOLVED/CLOSED), `institution`, `enabled`, `version` |
| `event_exceptions` | `EventException` | Unrecognised event types, aggregated per ATM with occurrence count + first/last seen + sample |
| `rule_suggestions` | `RuleSuggestion` | Async Adoons suggestion rows: `request_id` (UUID), `kind` (PROCESSING/CLOSING), `status` (PENDING/READY/FAILED), suggested_* fields, `institution`, `requested_by` |

See [platform.data-architecture].

## Data flow — opening rules (the core path)

```
device event ──► hiveops.device.events ──► DeviceEventConsumer
   (also: agent journal event ──► agent-proxy ──► /api/internal/journal-events ──► JournalEventService)
                                              │
                                              ▼
                              IncidentAutoCreationService
                                              │
                          findApplicableRule(eventType, institution, details)
                                              │
        ┌──────────────┬───────────────────────────────┬───────────────────────┐
    SUPPRESS       OPEN_AND_CLOSE                  CREATE_INCIDENT           no rule → default
   (skip create)  (create + immediate close,       (create incident,        (built-in behaviour)
                   transition OPEN→CLOSED)          apply override sev/type)
```

Rule selection precedence inside `findApplicableRule`:
1. Filter enabled rules for the event type (`findEnabledByEventType`).
2. Drop rules whose `text_pattern` (if set) is not `contains`-ed by the lowercased event details.
3. Prefer **institution-scoped** rules (rule institution key → institution name, compared to ATM institution) over **Global** (`institution` null/blank).
4. Within a scope, **text-pattern-specific** rules win over catch-all (`Comparator` on pattern presence).
5. No match → built-in default incident behaviour.

## Data flow — closing rules

`IncidentAutoCreationService.processRecovery(event)` runs on recovery events: applies the built-in `RECOVERY_MAP` first, then `closingRuleService.findEnabledByTriggerEventType(...)`, resolving/closing incidents whose type is in the rule's `close_incident_types` CSV, to the rule's `target_status`.

## Data flow — Event Exceptions

When `JournalEventService` ingests an event whose type isn't recognised, it upserts an `event_exceptions` row (increment `occurrence_count`, update `last_seen`) rather than creating an incident. The screen reads these via `EventExceptionService.findAll()` and admins Dismiss them (single row or by type).

## Adoons rule suggestions — two paths

**Sync proxy** (`AdoonsController`, `/api/adoons/**`): validates user JWT, then calls hiveops-ai with `X-Internal-Secret`.
- `GET /status` → hiveops-ai `/actuator/health`
- `POST /suggest-rule` → hiveops-ai `POST /api/adoons/suggest-rule`
- `POST /suggest-closing-rule` → hiveops-ai `POST /api/adoons/suggest-closing-rule`

**Async / Kafka** (`AdoonsSuggestionController` + `RuleSuggestionAsyncService`, `/api/adoons/rule-suggestions`):

```
POST /api/adoons/rule-suggestions (kind=PROCESSING|CLOSING)
        │  persist RuleSuggestion(status=PENDING), return 202 + requestId
        ▼
RuleSuggestionProducer ──► adoons.rule-suggestion.requested ──► hiveops-ai
                                                                    │  (generates)
        RuleSuggestionResultConsumer ◄── adoons.rule-suggestion.ready ◄─┘
        (group hiveops-incident-adoons) → update row status READY/FAILED + suggested_*
        ▼
Frontend polls GET /api/adoons/rule-suggestions[/{requestId}] (institution-scoped)
```

See [platform.kafka].

## Kafka topics (this feature)

| Topic | Direction | Class | Group |
|-------|-----------|-------|-------|
| `hiveops.device.events` | consume | `DeviceEventConsumer` | `hiveops-incident-device-sync` |
| `adoons.rule-suggestion.requested` | produce | `RuleSuggestionProducer` | — |
| `adoons.rule-suggestion.ready` | consume | `RuleSuggestionResultConsumer` | `hiveops-incident-adoons` |

## Key API endpoints

- Opening rules: `GET/POST /api/ticket-processing-rules`, `/drafts`, `/{id}` (PUT), `/{id}/enabled` (PATCH), `/{id}/approve` (PATCH), `/{id}/audit`, `/audit`, DELETE `/{id}`
- Closing rules: `GET/POST /api/incident-closing-rules`, `/{id}` (PUT), `/{id}/enabled` (PATCH), DELETE `/{id}`
- Event exceptions: `GET /api/event-exceptions`, DELETE `/{id}`, DELETE `/by-type/{eventTypeRaw}`
- Adoons: `/api/adoons/status|suggest-rule|suggest-closing-rule|rule-suggestions`

Related: [platform.data-architecture] · [platform.kafka] · [platform.service-ownership] · [technical.incident]
