---
module: msp.module-allocations
title: Module Allocations
tab: Claude
order: 40
audience: dev
---

Terse agent reference. Frontend: `hiveops-msp/frontend` (`AllocationsView.svelte`). No dedicated backend.

## Owners
- Module catalogue + allocations → **hiveops-mgmt** (DB `hiveiq_mgmt`)
- User list → **hiveops-auth** (DB `hiveiq_auth`)
- SPA → **hiveops-msp** (frontend only, port 5186, `msp.bcos.cloud`)

## Endpoints (all require `hasAnyRole('MSP_ADMIN','BCOS_ADMIN')`)
| Method | Path | Service | Purpose |
|---|---|---|---|
| GET | `/api/v1/msp/modules` | mgmt | Allocatable catalogue (`enabled && !isDefault`) |
| GET | `/api/v1/msp/institutions` | mgmt | MSP-scoped institutions |
| GET | `/api/v1/msp/modules/users/{authUserId}` | mgmt | User's modules (defaults + allocations) |
| PUT | `/api/v1/msp/modules/users/{authUserId}` | mgmt | Replace allocation; body `{ "moduleIds": [<Long>...] }`; returns 204 |
| GET | `/auth/api/msp/users?page&size&search&role&status&institutionKey` | auth | User page (`size` capped 200, sort `name`) |
| GET | `/api/v1/users/me/modules` | mgmt | Launcher-effective modules (NOT this screen) |

Frontend prefixes: mgmt calls via `/mgmt/...`, auth via `/auth/...` (gateway strips prefix).

## Tables (`hiveiq_mgmt` unless noted)
- `app_modules` — cols incl. `enabled`, `is_default`, `is_core`, `display_order`
- `user_module_allocations` — `auth_user_id` → `module_id` (this screen writes here)
- `institution_module_allocations` — `institution_key` → `module_id` (launcher gate)
- `customer_institution_access`, `customers` — MSP scope resolution
- `users` — in `hiveiq_auth` (auth-owned)

## Topics
- **None.** No Kafka on this path.

## Gotchas
- PUT is **delete-all-then-insert** (full replace), not a delta. Send the complete desired set.
- Catalogue = `enabled=true AND is_default=false`. Defaults are always granted, never listed.
- MSP scope is derived from **email domain → `customers.domain`**, not the JWT institution-keys claim (claim goes stale).
- Allocating a module ≠ user sees it. Launcher `getEffectiveModulesForUser` also filters by `institution_module_allocations` (core modules bypass; BCOS_ADMIN bypasses all). Non-core module needs an institution allocation too.
- `setModulesForAuthUser` silently drops module ids not in `app_modules` (no error).
- SPA swallows per-user allocation GET errors (empty catch) — no toast; check network tab.
- Changes apply on **next launcher open**; no push/websocket.
- `getEffectiveModulesForUser` keys on `principal.getCustomerId()` while this screen writes by `authUserId` from `/auth/api/msp/users` — assumed identical id space (verify before assuming a mismatch is the cause of "not showing").

## Do NOT
- Do NOT expect a Kafka event, mirror table, or record-store write — none exist here.
- Do NOT send a partial `moduleIds` diff expecting a merge; you will wipe the rest.
- Do NOT add allocation write endpoints to auth or the SPA — mgmt owns allocation writes.
- Do NOT treat "user has allocation but no launcher module" as a bug before checking the institution gate.
- Do NOT rely on the JWT institution-keys claim for MSP scope; use the domain-derived path.
- Do NOT expose `is_default=true` modules in the assign list.
