---
module: technical.mgmt
title: hiveops-mgmt — Management, licensing & internal identity service
tab: Overview
order: 10
audience: dev
---

> **DRAFT · internal.** Written 2026-07-01 from hiveops-mgmt source. Verify against code before relying on specifics.

## Responsibility

`hiveops-mgmt` is the Spring Boot 3.4.1 / Java 21 management backend. It owns **internal/admin users**, **license keys + activations**, **agent tokens**, **app modules and their per-user / per-institution allocations**, **global settings**, **billing (QuickBooks Online)**, and the server-rendered **MSP portal** (Thymeleaf). Customer-facing auth lives in `hiveops-auth`; mgmt handles the internal-admin side and shares JWT secret material with it. See [platform.service-ownership].

## Data

Database: PostgreSQL, name supplied via env var `DB_NAME` in the `prod` profile (JDBC URL built from `DB_HOST`/`DB_PORT`/`DB_NAME`; conventionally `hiveiq_mgmt`). Dev profile uses an in-memory H2 DB. Schema managed by Flyway (`db/migration`, baseline v3). See [platform.data-stores].

Key tables/entities (`@Table` names):

| Table | Purpose |
|-------|---------|
| `users` | Internal/admin user accounts (JWT auth, MFA fields added V11) |
| `refresh_tokens` | Refresh-token store for admin sessions |
| `licenses` / `license_activations` | License keys and per-device activation records |
| `agent_tokens` | Agent auth tokens (validated for ATM agents) |
| `app_modules` | Installable app modules (has `is_core` flag, V21) |
| `user_module_allocations` | Per-user module grants |
| `institution_module_allocations` | Per-institution module grants (V18) |
| `global_settings` | Key/value global config |
| `audit_logs` | Compliance audit trail |
| `customers` / `customer_institution_access` | Customer records + institution access (V16) |
| `api_keys` | API keys |
| `billing_rates` / `billing_invoices` / `qb_credentials` | Billing + QuickBooks Online integration (V22) |

## Kafka

No Kafka. No `@KafkaListener`, `KafkaTemplate`, or `StreamBridge` usage found in `src/main`.

## API surface

REST base path `/api/v1` (plus `/api/internal/*` service-to-service, and Thymeleaf `/portal/*` UI). Selected endpoints:

| Method + Path | Purpose |
|---------------|---------|
| POST `/api/v1/auth/login` | Internal admin login (returns JWT) |
| POST `/api/v1/auth/refresh` | Refresh JWT |
| POST `/api/v1/auth/logout` | Invalidate session |
| POST `/api/v1/licenses/activate` | Activate a license key for a device |
| POST `/api/v1/licenses/validate` | Validate an active license |
| POST `/api/v1/licenses/deactivate` | Deactivate a license |
| GET `/api/v1/licenses/{licenseKey}/status` | License status |
| GET/PUT `/api/v1/settings` , GET/PUT `/api/v1/settings/{key}` | Global settings |
| GET/POST `/api/v1/admin/modules` , PUT/DELETE `/api/v1/admin/modules/{id}` | Manage app modules |
| GET/PUT `/api/v1/admin/modules/users/{authUserId}` | Get/set a user's module allocations |
| GET `/api/v1/users/me/modules` | Current user's allocated modules |
| GET `/api/v1/msp/institutions` , PUT `/api/v1/msp/institutions/{institutionKey}/contact` | MSP institution list / contact |
| GET/PUT `/api/v1/msp/modules/users/{authUserId}` | MSP-scoped module allocations |
| POST/GET `/api/v1/agent-tokens` , POST `/api/v1/agent-tokens/{id}/revoke` | Manage agent tokens |
| POST `/api/internal/agent-tokens/validate` | Internal: validate an agent token |
| GET `/api/internal/customers/domain/{domain}/institution-keys` | Internal: resolve institution keys by domain |
| GET/PUT `/api/v1/billing/rates` , POST `/api/v1/billing/invoices/generate` | Billing rates + invoice generation |
| GET `/api/v1/billing/qb/connect` , GET `/api/v1/billing/qb/callback` | QuickBooks OAuth connect/callback |

Not exhaustive — see the `controller/` and `controller/portal/` packages.

## Gotchas

- **Two JWT secrets.** `jwt.secret` (`JWT_SECRET`) signs internal-admin tokens; a separate `customer-auth.jwt-secret` (`CUSTOMER_JWT_SECRET`) must match `hiveops-auth` for customer tokens. Both, plus `LICENSE_SECRET`, are **required with no defaults** — the app fails to start if unset.
- **Authorization roles are inconsistent.** Most endpoints use `hasRole('ADMIN')`, but MSP/module paths use `hasAnyRole('MSP_ADMIN','BCOS_ADMIN')` (and a few mix `ADMIN`, `MSP_ADMIN`, `BCOS_ADMIN`, `CUSTOMER`). Don't assume a single canonical role check across controllers.
- **DB name is env-driven, not literal.** Prod JDBC URL is assembled from `DB_HOST`/`DB_PORT`/`DB_NAME`; there is no hardcoded `hiveiq_mgmt` in `application.yml`.
- **Bootstrap requires the config server.** `bootstrap.yml` sets `fail-fast: true` with `CONFIG_USERNAME`/`CONFIG_PASSWORD`; mgmt will not start if `hiveops-config` is unreachable.
- **CORS is mandatory in prod.** `CORS_ALLOWED_ORIGINS` must list every frontend origin (and be mirrored in `hiveops-auth`); missing it blocks the SPAs.
- **Internal service secret is shared.** `INTERNAL_SERVICE_SECRET` is reused for both the claims service call and the incident service-to-service trust.
- **Swagger and H2 console are disabled by default** (`SWAGGER_ENABLED=false`, H2 console off in prod) — security hardening, don't expect them live.
