Files
hiveops-guide/backend/src/main/resources/content/fleet/dashboard/architect.md
T
johannes f21c783d8c fix(guide): gate Architect + Claude tabs to BCOS_ADMIN only (#16)
The 162 Architect/Claude docs were tagged 'audience: dev'. The 'dev' tier
resolves to isInternal() = ROLE_MSP_ADMIN || ROLE_BCOS_ADMIN, so every
MSP_ADMIN could read full internal architecture: source paths, DB tables,
service ports, NGINX routes. Verified live on bcos.dev as msp_a@msp1.bcos.dev.

Retag them to 'audience: bcos' (isBcos, BCOS_ADMIN only). Content-only change;
the 'dev' tier mapping is deliberately left alone so the 15 Internal, 35
Overview and 66 Testing docs stay MSP-visible.

Also add platform.guide-access documenting the audience tiers and the
per-role visibility matrix, so the access model is queryable from the Guide
instead of re-derived from source each time.

Verified: MSP module count unchanged (116 across 17 apps); no module loses
all its tabs. Guide is bcos.dev only, not deployed to production.

Closes #16

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 17:55:07 -04:00

4.7 KiB

module, title, tab, order, audience
module title tab order audience
fleet.dashboard Fleet Dashboard Architect 30 bcos

How the Fleet Stats dashboard is built. It is a thin read-only view over hiveops-fleet's own database — no cross-service HTTP at request time. Cross-link [platform.service-ownership], [platform.data-architecture], [platform.kafka].

Services involved

Concern Owner Role for this screen
Dashboard UI hiveops-fleet/frontend (Svelte, port 5176) FleetDashboard.svelte, aggregates ATMs client-side
Stats + device list API hiveops-fleet/backend (Spring Boot 3.4, port 8097) FleetApiControllerFleetTaskService.getStats(...) + DeviceSummaryRepository
Device state feed hiveops-devices Publishes hiveops.device.events; fleet mirrors it

Only hiveops-fleet is on the request path. hiveops-devices contributes asynchronously via Kafka, never a live call. This is the deliberate no-cross-service-HTTP pattern for fleet.

Data flow

Task/artifact counters (Task Statistics + Fleet Overview bars):

FleetDashboard onMount / 60s timer
  → GET /api/fleet/tasks/stats
    → FleetTaskService.getStats(InstitutionContext.resolveScope())
      → fleet_tasks   (count / countByTaskKindAndStatus / findByStatus)
      → fleet_artifacts (count)
    → FleetDashboardStats DTO

ATMs by Model / by Institution tables:

FleetDashboard onMount (once, not on the 60s timer)
  → GET /api/fleet/devices
    → InstitutionContext.resolveScope()  (null = unrestricted; else List<institutionKey>)
    → deviceSummaryRepository.findAll()  OR  findByInstitutionKeyIn(scope)
    → List<Map> {atmId, institution(Key), status, model, ...}
  → frontend groups by model & institution, counts operational/offline

The device rows are populated out-of-band by the Kafka consumer, so the dashboard reads a local mirror, decoupled from device-service availability.

Kafka (async, off the request path) — [platform.kafka]

Consumed by fleet (feeds this screen's device tables):

Topic Consumer Effect
hiveops.device.events DeviceEventConsumer (@KafkaListener, groupId hiveops-fleet-device-sync, auto-offset-reset=earliest) Upserts device_summary rows read by GET /api/fleet/devices

Produced by fleet (NOT read by this screen — listed for completeness):

Topic Producer Notes
hiveops.fleet.task.events FleetTaskEventPublisher via FleetTaskService created/status/archived events for downstream consumers; the dashboard reads fleet_tasks directly, not this topic

There is no reconciler — if devices stops publishing, device_summary (and therefore the ATM tables) goes stale silently. Cross-link [platform.data-architecture].

DB tables (all in hiveiq_fleet)

Table Access for this screen Notes
fleet_tasks READ (counts) active tasks (PENDING/QUEUED/RUNNING)
fleet_artifacts READ (count) uploadable/CDN-imported artifacts
device_summary READ Kafka-synced mirror of device state; the only source for the ATM tables

fleet_task_history, patch_windows, atm_captures exist in fleet but are not touched by the dashboard.

Key API endpoints (this feature)

Method Path Handler Auth
GET /api/fleet/tasks/stats (alias /api/fleet/stats) FleetApiController.getStatsFleetTaskService.getStats hasAnyRole('USER','CUSTOMER','ADMIN','MSP_ADMIN','BCOS_ADMIN')
GET /api/fleet/devices FleetApiController.listDevices same

Base default in frontend: http://localhost:8097/api/fleet; prod https://api.bcos.cloud/fleet.

Executor → Kafka → record-store pattern (context)

The broader fleet task lifecycle follows executor → hiveops.fleet.task.events → devices record-store, and terminal tasks archive to fleet_task_history. This dashboard sits outside that loop — it only aggregates current-state reads (task/artifact counts + the device mirror). Worth knowing so you don't wire the dashboard into the task-event pipeline.

Notable implementation facts (verify before relying on displayed numbers)

  • getStats currently hard-codes completedTasks/failedTasks to 0, scopes pendingTasks to AUTO_UPDATE+PENDING only, and ignores its institutionKeys argument for the global fleet_tasks/fleet_artifacts counts.
  • The FleetDashboardStats DTO has no totalModulesReporting field, so the frontend's "Modules Reporting" always renders its 0 default.
  • Device status mapping is client-side: IN_SERVICE→operational; OUT_OF_SERVICE/DOWN/INACTIVE→offline.