2f94d62769
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>
3.5 KiB
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(setsatm.hardware_profile, lowercased+trimmed).
Kafka
- Topic:
hiveops.device.events, typeDEVICE_UPDATED, key = atmId. - Emitted only by
/hardware-profile(one event per member, viaDeviceEventPublisher.publishUpdated). - Group create/update/delete/membership changes emit nothing.
Gotchas
- Default group is client-side only — browser
localStoragekeyhiveops_defaultGroupId. Not in DB, not per-account. DrivesgroupIdfilter on/api/atms/paginated. - Group name UNIQUE is global, not per-institution → duplicate name = DB constraint error;
server.error.include-message=neverhides detail. PUT .../atmsreplaces the whole set — not additive. Must send full membership.- Single-institution caller: create forces
institution_key = scoperegardless of requestinstitutionKey. verifyGroupAccessonly blocks wheninstitution_key != null; null ("All") groups are editable/deletable by any in-scope admin.- Profile assign = 2 effects: DB+Kafka from backend,
CONFIG_UPDATEfleet task from frontend (skipped ifatmIdsempty). Calling/hardware-profiledirectly does NOT queue the fleet task. configPatchkey used by the push =atm.hardware.profile.
Do NOT
- Do NOT expect
Set Defaultto 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 .../atmsas add — it overwrites membership. - Do NOT invent a group Kafka topic or a
hiveiq_*table other thanatm_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.