---
module: analytics.adoons
title: Adoons Insights
tab: Internal
order: 20
audience: internal
---

> **Internal · ops/support/admin.** Written 2026-07-01 from `hiveops-analytics` source. Verify against code before relying on specifics.

## What this screen actually is

The **Adoons Insights** (a.k.a. "Fleet Insights") tab is a thin card list over a plain REST + JPA store. Each card is one row in the `ai_insights` table, served by **hiveops-analytics** (port **8089**, prod host port **8012**, NGINX `/api/analytics/`). There is **no AI/ML generation inside analytics** — insights only exist because something `POST`ed them.

- **Owner service:** `hiveops-analytics`
- **Table:** `ai_insights` in DB `hiveiq_analytics`
- **Frontend:** `AdoonsTab.svelte` → `analyticsAPI.getActiveInsights()` on load and on **Refresh**.

## Roles required

| Action | Endpoint | Auth |
|--------|----------|------|
| View active insights | `GET /api/analytics/insights/active` | Any authenticated JWT |
| View all (paged) | `GET /api/analytics/insights` | Any authenticated JWT |
| **Publish an insight** | `POST /api/analytics/insights` | **`hasAnyRole('MSP_ADMIN','BCOS_ADMIN')`** |
| Dismiss one (Refresh ✕) | `PATCH /api/analytics/insights/{id}/acknowledge` | Any authenticated JWT |
| Dismiss all | `DELETE /api/analytics/insights/active` | Any authenticated JWT |

**Admin-only action = publishing.** Only MSP_ADMIN / BCOS_ADMIN can create insight cards. Everyone else can read and dismiss.

## How a card gets on the screen

1. A publisher (Adoons / an operator with an admin JWT) calls `POST /api/analytics/insights` with `{category, severity, title, body, [snapshotId], [expiresAt]}`.
2. Row is written to `ai_insights`; `published_at` defaults to now.
3. It shows in `/insights/active` until it is **acknowledged** or its `expires_at` passes.
4. Acknowledged rows older than 30 days are purged nightly (`@Scheduled cron = "0 0 3 * * *"`).

`GET /insights/active` returns only rows where `acknowledged = false AND (expires_at IS NULL OR expires_at > now)`, newest first.

## First things to check when it misbehaves

**"No active fleet insights" but there should be some**
- Confirm rows exist: query `ai_insights` in `hiveiq_analytics` (Postgres on **10.10.10.188** via ProxyJump).
- Check they aren't all `acknowledged = true` or past `expires_at` — the active query hides both.
- Remember: analytics does **not** self-generate insights. If nothing is `POST`ing them, the tab is *correctly* empty. Check whoever owns publishing (external Adoons/AI job — not in this repo).

**Cards won't load / error bar shows**
- The SPA calls `/api/analytics/insights/active`. Hit it directly with a real JWT and expect `200` + a JSON array.
- All `/api/analytics/**` require an `Authorization: Bearer <jwt>` header (only `/api/public/**` and `/actuator/health` are open). A `401/403` here = missing/expired token or wrong `role`.
- Downstream summary endpoints (incident/journal/mgmt) do **not** feed this tab — insights are self-contained. A red insights panel is an analytics-only problem.

**Publish returns 403**
- Caller's JWT `role` is not `MSP_ADMIN` or `BCOS_ADMIN`. Only publish is role-gated.

**Publish returns 400**
- `category` must be one of `ANOMALY | TREND | RECOMMENDATION | SUMMARY`; `severity` must be one of `INFO | WARNING | CRITICAL`. Any other value fails `valueOf(...)`. `title`/`body`/`category`/`severity` are all `@NotBlank`.

**Dismiss (✕) does nothing / card reappears on refresh**
- `AdoonsTab.dismiss()` **swallows errors silently** (empty `catch`). If the `PATCH .../acknowledge` fails (e.g. 404 for a stale id, or auth), the card stays and no error is shown. Test the PATCH directly to see the real status.

**Severity colour looks wrong (card renders blue instead of orange)**
- Known mismatch: backend severities are `INFO | WARNING | CRITICAL`, but the frontend colour map only keys `CRITICAL/HIGH/MEDIUM/LOW/INFO`. A `WARNING` insight has **no colour entry** and falls back to the INFO blue. If you need a visible non-critical warning, that's a frontend gap, not bad data.

## Manual publish (support/testing)

```bash
curl -s -X POST https://api.bcos.cloud/analytics/api/analytics/insights \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"category":"TREND","severity":"WARNING","title":"Test insight","body":"Manual test.","expiresAt":"2026-08-01T00:00:00Z"}'
```

Cross-links: [technical.analytics], [platform.service-ownership].
