---
module: fleet.dashboard
title: Fleet Dashboard
tab: Claude
order: 40
audience: dev
---

Terse agent reference for the **Fleet Stats** dashboard (`FleetDashboard.svelte`).

## Ownership
- Service: **hiveops-fleet** (backend port 8097, DB `hiveiq_fleet`, package `com.hiveops.fleet`).
- Frontend: hiveops-fleet/frontend, port 5176, `components/FleetManagement/FleetDashboard.svelte`.
- No other service on the request path. hiveops-devices contributes only via Kafka.

## Endpoints (the only two this screen calls)
| Method | Path | Returns | Auth |
|--------|------|---------|------|
| GET | `/api/fleet/tasks/stats` (alias `/api/fleet/stats`) | `FleetDashboardStats` | `hasAnyRole('USER','CUSTOMER','ADMIN','MSP_ADMIN','BCOS_ADMIN')` |
| GET | `/api/fleet/devices` | `List<Map>` device rows | same |

- Frontend base: `http://localhost:8097/api/fleet` (dev) / `https://api.bcos.cloud/fleet` (prod).

## Tables (read-only, `hiveiq_fleet`)
- `fleet_tasks` — task counts.
- `fleet_artifacts` — artifact count.
- `device_summary` — ATM rows for the model/institution tables (Kafka mirror).

## Kafka
- Consumes `hiveops.device.events` → `DeviceEventConsumer`, groupId `hiveops-fleet-device-sync` → upserts `device_summary`.
- Produces `hiveops.fleet.task.events` (NOT read by this screen).

## Scoping
- `InstitutionContext.resolveScope()`: `ROLE_CUSTOMER`/`ROLE_MSP_ADMIN` → scoped to JWT-credential institution-key list; else `null` = unrestricted.
- `/devices` IS scoped. `/tasks/stats` is NOT (see gotchas).

## Gotchas (grounded in current code — do not "fix" the numbers blindly)
- `getStats`: `completedTasks` and `failedTasks` are hard-coded `0`. They never move.
- `getStats`: `pendingTasks` = only `AUTO_UPDATE` + `PENDING` (not all pending kinds).
- `getStats`: ignores its `institutionKeys` arg → `totalTasks`/`totalArtifacts` are GLOBAL counts even for scoped users.
- `FleetDashboardStats` DTO has NO `totalModulesReporting` field → frontend "Modules Reporting" always 0. Real module data is `GET /api/fleet/modules/summary`.
- 60s auto-refresh reloads **stats only**; ATM tables load once on mount (stale until page reload).
- Stats fetch failures are swallowed (`console.warn`), no on-screen error → zeros ≠ "no data".
- Device status → operational/offline map: `IN_SERVICE`=operational; `OUT_OF_SERVICE`/`DOWN`/`INACTIVE`=offline; other = counted in Total only.
- `device_summary` has no reconciler; stale if devices stops publishing.

## Do NOT
- Do NOT add an endpoint/table for this screen in incident/journal/devices — fleet owns it.
- Do NOT trust Completed/Failed/Modules-Reporting counters as live data (see gotchas).
- Do NOT expect `/tasks/stats` numbers to respect institution scope.
- Do NOT read `hiveops.fleet.task.events` to build this view — read `fleet_tasks` directly.
- Do NOT call hiveops-devices over HTTP to refresh ATM tables — data arrives via Kafka only.
- Do NOT restrict this screen to admin roles; `USER`/`CUSTOMER` are allowed to read.
