Files
hiveops-guide/backend/src/main/resources/content/devices/device-groups/claude.md
T
johannes 2f94d62769 content(guide): role-tabs (Internal/Architect/Claude) for all 63 customer modules (DRAFT, Refs #1 #3)
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>
2026-07-01 12:14:54 -04:00

3.5 KiB

module, title, tab, order, audience
module title tab order audience
devices.device-groups Device Groups Claude 40 internal

Owner

  • Service: hiveops-devices (port 8096, DB hiveiq_devices). Groups live entirely here.
  • Controller AtmGroupController, base @RequestMapping({"/api/atm-groups","/api/device-groups"}) (Phase-2 alias — both route).
  • External via NGINX: https://api.bcos.cloud/devices/api/atm-groups.

Endpoints (METHOD path — auth)

Method Path Auth Body / returns
GET /api/atm-groups any authed list, institution-scoped
GET /api/atm-groups/{id} any authed one group
POST /api/atm-groups admin {name, description?, color?, institutionKey?, atmIds?[]}
PUT /api/atm-groups/{id} admin partial update; only non-null fields applied
DELETE /api/atm-groups/{id} admin 204
PUT /api/atm-groups/{id}/atms admin body = [atmId,...]replaces all members
POST /api/atm-groups/{id}/atms/{atmId} admin add one
DELETE /api/atm-groups/{id}/atms/{atmId} admin remove one
POST /api/atm-groups/{id}/hardware-profile admin {"profileKey":"..."}{"atmIds":[...]}
POST /fleet/tasks authed fleet svc; frontend queues CONFIG_UPDATE after profile assign
  • admin = @PreAuthorize("hasAnyRole('MSP_ADMIN','BCOS_ADMIN')").
  • GET endpoints have no @PreAuthorize (only institution scoping).

Tables

  • atm_groups — id, name (UNIQUE, global), description, color, institution_key (len 10), createdAt, updatedAt.
  • atm_group_members — join (group_id, atm_id); @ManyToMany AtmGroup↔Atm.
  • atms — written only by /hardware-profile (sets atm.hardware_profile, lowercased+trimmed).

Kafka

  • Topic: hiveops.device.events, type DEVICE_UPDATED, key = atmId.
  • Emitted only by /hardware-profile (one event per member, via DeviceEventPublisher.publishUpdated).
  • Group create/update/delete/membership changes emit nothing.

Gotchas

  • Default group is client-side only — browser localStorage key hiveops_defaultGroupId. Not in DB, not per-account. Drives groupId filter on /api/atms/paginated.
  • Group name UNIQUE is global, not per-institution → duplicate name = DB constraint error; server.error.include-message=never hides detail.
  • PUT .../atms replaces the whole set — not additive. Must send full membership.
  • Single-institution caller: create forces institution_key = scope regardless of request institutionKey.
  • verifyGroupAccess only blocks when institution_key != null; null ("All") groups are editable/deletable by any in-scope admin.
  • Profile assign = 2 effects: DB+Kafka from backend, CONFIG_UPDATE fleet task from frontend (skipped if atmIds empty). Calling /hardware-profile directly does NOT queue the fleet task.
  • configPatch key used by the push = atm.hardware.profile.

Do NOT

  • Do NOT expect Set Default to persist server-side or across browsers.
  • Do NOT assume group changes propagate via Kafka / device_summary mirrors — they don't; only per-ATM hardware-profile updates do.
  • Do NOT treat PUT .../atms as add — it overwrites membership.
  • Do NOT invent a group Kafka topic or a hiveiq_* table other than atm_groups / atm_group_members.
  • Do NOT queue a fleet task by calling only the backend /hardware-profile; the fleet push is a separate frontend call.
  • Do NOT rely on error bodies — messages are suppressed in prod.