Full role-tab rollout: every customer module now has Customer/Internal/ Architect/Claude tabs, grounded per-module in real code. Backend serves 296 docs / 96 modules. Grounding surfaced ~20 real bugs across services (filed separately after verification). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.9 KiB
module, title, tab, order, audience
| module | title | tab | order | audience |
|---|---|---|---|---|
| devices.sw-deploy | Software Deployment | Architect | 30 | internal |
Internal · architecture. Written 2026-07-01 from
hiveops-devices/frontend+hiveops-fleet/backend. Verify against code before relying on specifics.
Ownership — this feature lives in Fleet, rendered by Devices
The SW Deploy tab is a Devices SPA view (DeviceSoftwareTab.svelte) but the domain — software download/install tasks — is owned entirely by hiveops-fleet. Devices contributes only the device identity and the UI shell. See [platform.service-ownership].
| Concern | Owner |
|---|---|
Tab UI / atm object |
hiveops-devices (frontend, port 5177) |
SOFTWARE / SOFTWARE_INSTALL task lifecycle, storage, dispatch |
hiveops-fleet (backend, port 8097, DB hiveiq_fleet) |
| Agent auth / device identity source of truth | hiveops-devices backend (atms) → mirrored to fleet device_summary via Kafka |
Data flow
1. Read path (rendering the tab)
DeviceSoftwareTab → fleetAPI.getTasksPaginated({ atmId, taskKind:['SOFTWARE','SOFTWARE_INSTALL'] }) → gateway /fleet/tasks/paginated → FleetApiController.getFiltered → FleetTaskService.getFilteredPaginated → FleetTaskSpecification.withFilters over the live fleet_tasks table. Frontend derives the two step cards (latestDownload, latestInstall) and the history table client-side.
2. Create path (Schedule Install)
fleetAPI.createTask({ atmIds:[id], taskKind:'SOFTWARE_INSTALL', scheduledAt? }) → POST /fleet/tasks → FleetTaskService.createTask:
- Resolves each
atmIdagainstdevice_summary(deviceSummaryRepository.findById); skips if missing, offline (>15 min sincelastHeartbeat), or out of institution scope. SOFTWARE/SOFTWARE_INSTALL(andHOTFIX/HOTFIX_INSTALL) are created with initial statusPENDING_APPROVAL.- If no
scheduledAtand kind isSOFTWARE_INSTALL, defers to the device's assigned patch window (PatchWindowService.nextOccurrence). - Persists to
fleet_tasks, thenFleetTaskEventPublisher.publishCreated→ Kafka.
3. Approval → dispatch
POST /fleet/tasks/{id}/approve (FLEET_APPROVER / BCOS_ADMIN) moves the task PENDING_APPROVAL → PENDING. The agent (via agent-proxy, role INTERNAL) polls GET /api/internal/fleet/tasks/next?atm={atmId}&kind=...; getNextPendingTaskOfKind returns the oldest PENDING task whose scheduledAt is null/past, marks it QUEUED, and returns artifact metadata (name, version, sha256, CDN url + token) for SOFTWARE. SOFTWARE_INSTALL carries no artifact — the agent runs softwareinstall.cmd against its staged software/ dir.
4. Status reporting → archival (executor → record-store)
Agent reports progress via POST /api/internal/fleet/tasks/{taskId}/status (downloadOffset, totalSize, status) → FleetTaskService.updateTaskStatus:
RUNNINGsetsstartedAt;COMPLETED/FAILEDsetcompletedAt; download progress percent is derived from offset/total.- Every update publishes
FleetTaskEventPublisher.publishStatusUpdate. - On
COMPLETED, the row is archived tofleet_task_historyand deleted fromfleet_tasks(archiveAndDelete, also emitspublishArchived). A@Scheduledsweep every 5 min archives strayCOMPLETED/CANCELLED/REJECTED; history is purged after 30 days. This is the classic live-table + archived-record-store split. See [platform.data-architecture].
Kafka
| Topic | Direction | Class | Notes |
|---|---|---|---|
hiveops.fleet.task.events |
produced by fleet | FleetTaskEventPublisher / FleetTaskKafkaConfig.FLEET_TASK_EVENTS_TOPIC |
eventTypes TASK_CREATED, TASK_STATUS, TASK_ARCHIVED; keyed per task. Consumed downstream by devices (FleetTaskEventConsumer → device_fleet_tasks mirror). |
hiveops.device.events |
consumed by fleet | DeviceEventConsumer (group hiveops-fleet-device-sync) |
Upserts/deletes device_summary from devices' DEVICE_CREATED/UPDATED/DELETED. This is how fleet knows the device exists, its institutionKey, and lastHeartbeat seed. |
See [platform.kafka].
Tables (DB hiveiq_fleet)
| Table | Entity | Role in this feature |
|---|---|---|
fleet_tasks |
FleetTask |
Live SOFTWARE/SOFTWARE_INSTALL rows — the tab's read source |
fleet_task_history |
FleetTaskHistory |
Archived terminal tasks (completed installs/downloads land here) |
device_summary |
DeviceSummary |
Fleet's mirror of devices; target resolution, online check, institution scope |
fleet_artifacts |
FleetArtifact |
Software package metadata for SOFTWARE downloads (enabled flag, CDN url, sha256) |
| patch window tables | PatchWindow / PatchWindowDevice |
Auto-schedule for SOFTWARE_INSTALL |
Key endpoints
| Method + Path | Purpose | Auth |
|---|---|---|
GET /api/fleet/tasks/paginated |
Tab read (filter taskKind, atmId) |
USER…BCOS_ADMIN |
POST /api/fleet/tasks |
Create install/download task | ADMIN/MSP_ADMIN/BCOS_ADMIN |
POST /api/fleet/tasks/{id}/approve | /reject |
Approve gate | FLEET_APPROVER / BCOS_ADMIN |
POST /api/fleet/tasks/{id}/cancel | /retry |
Lifecycle | ADMIN/MSP_ADMIN/BCOS_ADMIN |
GET /api/fleet/tasks/history |
Archived (completed) tasks | USER…BCOS_ADMIN |
GET /api/internal/fleet/tasks/next |
Agent poll/dispatch | INTERNAL |
POST /api/internal/fleet/tasks/{id}/status |
Agent status/progress | INTERNAL |
Architectural note (see uncertainties)
The tab reads the live fleet_tasks table, but COMPLETED tasks are archived+deleted immediately. Completed software history therefore lives only in fleet_task_history / the /tasks/history endpoint, which this tab does not query. Treat the tab as "in-flight + failed" state; use history for the completed record.
Cross-links: [platform.data-architecture] · [platform.kafka] · [platform.service-ownership]