docs(alerts): rules + CLAUDE.md — inbox redesign, V17 migration

- .claude/rules/ui.md: rewrite Alerts section — sidebar trims to
  Inbox/Rules/Silences, InboxPage description updated (4 filters, row
  actions, bulk toolbar, soft-delete undo), SilenceRuleMenu documented,
  SilencesPage ?ruleId= prefill noted.
- CLAUDE.md: V17 migration entry describing enum/column/table/index
  changes for the inbox redesign.
- .claude/rules/app-classes.md AlertController bullet already updated
  in the T6 drive-by.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-21 19:21:27 +02:00
parent 9f28c69709
commit 0cd0a27452
2 changed files with 6 additions and 6 deletions

View File

@@ -36,15 +36,14 @@ The UI has 4 main tabs: **Exchanges**, **Dashboard**, **Runtime**, **Deployments
## Alerts
- **Sidebar section** (`buildAlertsTreeNodes` in `ui/src/components/sidebar-utils.ts`) — Inbox, All, Rules, Silences, History.
- **Routes** in `ui/src/router.tsx`: `/alerts`, `/alerts/inbox`, `/alerts/all`, `/alerts/history`, `/alerts/rules`, `/alerts/rules/new`, `/alerts/rules/:id`, `/alerts/silences`.
- **Sidebar section** (`buildAlertsTreeNodes` in `ui/src/components/sidebar-utils.ts`) — Inbox, Rules, Silences.
- **Routes** in `ui/src/router.tsx`: `/alerts` (redirect to inbox), `/alerts/inbox`, `/alerts/rules`, `/alerts/rules/new`, `/alerts/rules/:id`, `/alerts/silences`. No redirects for the retired `/alerts/all` and `/alerts/history` — stale URLs 404 per the clean-break policy.
- **Pages** under `ui/src/pages/Alerts/`:
- `InboxPage.tsx`user-targeted FIRING/ACK'd alerts with bulk-read.
- `AllAlertsPage.tsx` — env-wide list with state-chip filter.
- `HistoryPage.tsx` — RESOLVED alerts.
- `InboxPage.tsx`single filterable inbox. Filters: severity (multi), state (PENDING/FIRING/RESOLVED, default FIRING), Hide acked toggle (default on), Hide read toggle (default on). Row actions: Acknowledge, Mark read, Silence rule… (duration quick menu), Delete (OPERATOR+, soft-delete with undo toast wired to `useRestoreAlert`). Bulk toolbar (selection-driven): Acknowledge N · Mark N read · Silence rules · Delete N (ConfirmDialog; OPERATOR+).
- `SilenceRuleMenu.tsx` — DS `Dropdown`-based duration picker (1h / 8h / 24h / Custom…). Used by the row-level and bulk silence actions. "Custom…" navigates to `/alerts/silences?ruleId=<id>`.
- `RulesListPage.tsx` — CRUD + enable/disable toggle + env-promotion dropdown (pure UI prefill, no new endpoint).
- `RuleEditor/RuleEditorWizard.tsx` — 5-step wizard (Scope / Condition / Trigger / Notify / Review). `form-state.ts` is the single source of truth (`initialForm` / `toRequest` / `validateStep`). Seven condition-form subcomponents under `RuleEditor/condition-forms/` — including `AgentLifecycleForm.tsx` (multi-select event-type chips for the six-entry `AgentLifecycleEventType` allowlist + lookback-window input).
- `SilencesPage.tsx` — matcher-based create + end-early.
- `SilencesPage.tsx` — matcher-based create + end-early. Reads `?ruleId=` search param to prefill the Rule ID field (driven by InboxPage's "Silence rule… → Custom…" flow).
- `AlertRow.tsx` shared list row; `alerts-page.module.css` shared styling.
- **Components**:
- `NotificationBell.tsx` — polls `/alerts/unread-count` every 30 s (paused when tab hidden via TanStack Query `refetchIntervalInBackground: false`).

View File

@@ -73,6 +73,7 @@ PostgreSQL (Flyway): `cameleer-server-app/src/main/resources/db/migration/`
- V14 — Repair EXCHANGE_MATCH alert_rules persisted with fireMode=null (sets fireMode=PER_EXCHANGE + perExchangeLingerSeconds=300); paired with stricter `ExchangeMatchCondition` ctor that now rejects null fireMode.
- V15 — Discriminate open-instance uniqueness by `context->'exchange'->>'id'` so EXCHANGE_MATCH/PER_EXCHANGE emits one alert_instance per matching exchange; scalar kinds resolve to `''` and keep one-open-per-rule.
- V16 — Generalise the V15 discriminator to prefer `context->>'_subjectFingerprint'` (falls back to the V15 `exchange.id` expression for legacy rows). Enables AGENT_LIFECYCLE to emit one alert_instance per `(agent, eventType, timestamp)` via a canonical fingerprint in the evaluator firing's context.
- V17 — Alerts inbox redesign: drop `ACKNOWLEDGED` from `alert_state_enum` (ack is now orthogonal via `acked_at`), add `read_at` + `deleted_at` timestamp columns (global, no per-user tracking), drop `alert_reads` table entirely, rework the V13/V15/V16 open-rule unique index predicate to `state IN ('PENDING','FIRING') AND deleted_at IS NULL` so ack doesn't close the slot and soft-delete frees it.
ClickHouse: `cameleer-server-app/src/main/resources/clickhouse/init.sql` (run idempotently on startup)