# Component: Management Service

## Purpose

The Management Service is an Akka.NET actor on the central cluster that provides programmatic access to all administrative operations. It exposes the same capabilities as the Central UI but through an actor-based interface, enabling the CLI (and potentially other tooling) to interact with the system without going through the web UI. The ManagementActor registers with ClusterClientReceptionist for cross-cluster access and is also exposed via an HTTP Management API endpoint (`POST /management`) for external tools like the CLI.

## Location

Central cluster only. The ManagementActor runs as a plain actor on **every** central node (not a cluster singleton). Because the actor is completely stateless — it holds no locks and no local state, delegating all work to repositories and services — running on all nodes improves availability without requiring coordination between instances. Either node can serve any request independently.

`src/ZB.MOM.WW.ScadaBridge.ManagementService/`

## Responsibilities

- Provide an actor-based interface to all administrative operations available in the Central UI.
- Register with Akka.NET ClusterClientReceptionist so external tools (CLI) can discover and communicate with it via ClusterClient.
- Expose an HTTP API endpoint (`POST /management`) that accepts JSON commands with Basic Auth, performs LDAP authentication and role resolution, and dispatches to the ManagementActor.
- Validate and authorize all incoming commands using the authenticated user identity carried in message envelopes.
- Delegate to the appropriate services and repositories for each operation.
- Return structured response messages for all commands and queries.
- Failover: The ManagementActor runs on all central nodes, so no actor-level failover is needed. If one node goes down, the ClusterClient transparently routes to the ManagementActor on the remaining node.

## Key Classes

### ManagementActor

The central actor that receives and processes all management commands. Registered at a well-known actor path (`/user/management`) and with ClusterClientReceptionist.

### ManagementEndpoints

Minimal API endpoint (`POST /management`) that serves as the HTTP interface to the ManagementActor. Handles Basic Auth decoding, LDAP authentication via `LdapAuthService`, role resolution via `RoleMapper`, command deserialization via `ManagementCommandRegistry`, and ManagementActor dispatch.

### ManagementActorHolder

DI-registered singleton that holds the `IActorRef` for the ManagementActor. Set during actor registration in `AkkaHostedService` and injected into the HTTP endpoint handler.

### ManagementCommandRegistry

Static registry mapping command names (e.g., `"ListSites"`) to command types (e.g., `ListSitesCommand`). Built via reflection at startup. Used by the HTTP endpoint to deserialize JSON payloads into the correct command type.

### Message Contracts

All request/response messages are defined in **Commons** under `Messages/Management/`. Messages follow the existing additive-only evolution rules for version compatibility. Every request message includes:

- **CorrelationId**: Application-level correlation ID for request/response pairing.
- **AuthenticatedUser**: The identity and roles of the user issuing the command (username, display name, roles, permitted sites). This is populated by the CLI from the user's authenticated session.

## ClusterClientReceptionist Registration

The ManagementActor registers itself with `ClusterClientReceptionist` at startup. This allows external processes using `ClusterClient` to send messages to the ManagementActor without joining the Akka.NET cluster as a full member. The receptionist advertises the actor under its well-known path.

## HTTP Management API

The Management Service also exposes a `POST /management` endpoint on the Central Host's web server. This provides an HTTP interface to the same ManagementActor, enabling the CLI (and other HTTP clients) to interact without Akka.NET dependencies.

**Request format:**
```json
POST /management
Authorization: Basic base64(username:password)
Content-Type: application/json

{
  "command": "ListSites",
  "payload": {}
}
```

**Response mapping:**
- `ManagementSuccess` → HTTP 200 with JSON body
- `ManagementError` → HTTP 400 with `{ "error": "...", "code": "..." }`
- `ManagementUnauthorized` → HTTP 403 with `{ "error": "...", "code": "UNAUTHORIZED" }`
- Authentication failure → HTTP 401
- Actor timeout → HTTP 504

The endpoint performs LDAP authentication and role resolution server-side, collapsing the CLI's previous two-step flow (ResolveRoles + actual command) into a single HTTP round-trip.

## HTTP Audit API

In addition to `/management`, the Management Service exposes a dedicated REST surface for the centralized Audit Log component (#23). These endpoints live in `AuditEndpoints.cs` and bypass the `ManagementActor` because the query/export workloads are read-only, keyset-paged, and stream large result sets:

- `GET /api/audit/query` — keyset-paged JSON query over the central `AuditLog` table. Authenticated via HTTP Basic Auth (shared with `/management`); gated on the `OperationalAudit` permission (Admin / Audit / AuditReadOnly roles).
- `GET /api/audit/export` — server-side streaming bulk export (CSV or JSONL) of the filtered rows. Gated on the `AuditExport` permission (Admin / Audit).

Both endpoints honour any site-scope rules attached to the caller's audit role by intersecting the caller-supplied `sourceSiteId` filter with the user's `PermittedSiteIds` (out-of-scope requests yield HTTP 403). Permission denial returns HTTP 403 with the same envelope shape used by `/management`.

## Message Groups

### Templates

- **ListTemplates** / **GetTemplate**: Query template definitions.
- **CreateTemplate** / **UpdateTemplate** / **DeleteTemplate**: Manage templates.
- **ValidateTemplate**: Run on-demand pre-deployment validation (flattening, naming collisions, script compilation).
- **GetTemplateDiff**: Compare deployed vs. template-derived configuration for an instance.

### Template Folders

- **ListTemplateFolders**: List all template folders (read-only; any authenticated user).
- **CreateTemplateFolder** (`Name`, `ParentFolderId?`): Create a folder, optionally nested under a parent (Design role).
- **RenameTemplateFolder** (`FolderId`, `NewName`): Rename a folder; enforces sibling uniqueness (Design role).
- **MoveTemplateFolder** (`FolderId`, `NewParentFolderId?`): Move a folder to a new parent (or root); rejects cycles (Design role).
- **DeleteTemplateFolder** (`FolderId`): Delete a folder; blocked if the folder contains any subfolders or templates (Design role).
- **MoveTemplateToFolder** (`TemplateId`, `NewFolderId?`): Move a template into a folder, or to the root when null (Design role).

### Template Members

- **AddTemplateAttribute** / **UpdateTemplateAttribute** / **DeleteTemplateAttribute**: Manage attributes on a template.
- **AddTemplateAlarm** / **UpdateTemplateAlarm** / **DeleteTemplateAlarm**: Manage alarm definitions on a template.
- **AddTemplateNativeAlarmSource** / **UpdateTemplateNativeAlarmSource** / **DeleteTemplateNativeAlarmSource**: Manage native alarm source bindings (the read-only OPC UA Alarms & Conditions / MxAccess Gateway mirror) on a template — `Name`, `ConnectionName`, `SourceReference`, optional `ConditionFilter` / `Description`, `IsLocked`. Mutations gated to the **Design** role; handlers write through `ITemplateEngineRepository` directly.
- **ListTemplateNativeAlarmSources** (`TemplateId`): List a template's native alarm source bindings (read-only; any authenticated user).
- **AddTemplateScript** / **UpdateTemplateScript** / **DeleteTemplateScript**: Manage scripts on a template.
- **AddTemplateComposition** / **DeleteTemplateComposition**: Manage feature module compositions on a template.

### Instances

- **ListInstances** / **GetInstance**: Query instances, with filtering by site and area.
- **CreateInstance**: Create a new instance from a template.
- **UpdateInstanceOverrides**: Set attribute overrides on an instance.
- **SetInstanceAlarmOverride** / **DeleteInstanceAlarmOverride** / **ListInstanceAlarmOverrides**: Manage per-instance computed-alarm overrides.
- **SetInstanceNativeAlarmSourceOverride** / **DeleteInstanceNativeAlarmSourceOverride**: Retarget or clear a per-instance native alarm source binding, keyed by `SourceCanonicalName` — `ConnectionNameOverride` / `SourceReferenceOverride` / `ConditionFilterOverride` each apply only when non-null. Gated to the **Deployment** role.
- **ListInstanceNativeAlarmSourceOverrides** (`InstanceId`): List an instance's native alarm source overrides (read-only).
- **SetInstanceBindings** / **BindDataConnections**: Bind data connections to instance attributes.
- **AssignArea**: Assign an instance to an area.
- **EnableInstance** / **DisableInstance** / **DeleteInstance**: Instance lifecycle commands.

### Sites

- **ListSites** / **GetSite**: Query site definitions.
- **CreateSite** / **UpdateSite** / **DeleteSite**: Manage site definitions.
- **ListAreas** / **CreateArea** / **UpdateArea** / **DeleteArea**: Manage area hierarchies per site.

### Data Connections

- **ListDataConnections** / **GetDataConnection**: Query data connection definitions.
- **CreateDataConnection** / **UpdateDataConnection** / **DeleteDataConnection**: Manage data connection definitions.
- **AssignDataConnectionToSite** / **UnassignDataConnectionFromSite**: Manage site assignments.

### Deployments

- **DeployInstance**: Deploy configuration to a specific instance (includes pre-deployment validation).
- **DeployArtifacts**: Deploy system-wide artifacts (shared scripts, external system definitions, DB connections, data connections) to all sites or a specific site.
- **GetDeploymentStatus**: Query deployment status.

### Secured Writes (MxGateway, two-person)

The two-person authorization workflow for writes through the MxAccess Gateway. Backed by the central `PendingSecuredWrite` table; all four lifecycle events emit a best-effort Audit Log row sharing the row id as `CorrelationId` (see Component-AuditLog.md).

- **SubmitSecuredWriteCommand** (`Operator` role): validates the target connection exists and uses the **MxGateway** protocol (rejected otherwise), then inserts a `Pending` row capturing site / connection / tag / typed value / operator + comment. Nothing is written yet.
- **ApproveSecuredWriteCommand** (`Verifier` role): enforces **no self-approval** (`VerifierUser ≠ OperatorUser`, checked **before** any state change) and a **compare-and-swap** race guard (`TryMarkApprovedAsync` — exactly one concurrent approver flips `Pending → Approved`; the loser is rejected). On winning, it validates the value type, decodes the value (guarded — a bad value fails the row deterministically rather than leaving it stuck `Approved`), and relays a `WriteTagRequest` to the site MxGateway via the Communication Layer, recording the outcome as `Executed` or `Failed`.
- **RejectSecuredWriteCommand** (`Verifier` role): marks a `Pending` row `Rejected` with the verifier's reason.
- **ListSecuredWritesCommand** (any of `Operator` / `Verifier` / `Administrator`): pending queue + terminal history, global or per-site. Although read-only, the history table exposes process-sensitive tag values, so it is **not** open to any authenticated user — it is gated to the two Secured Write roles plus `Administrator` (any-of), aligning with the `RequireSecuredWriteAccess` Central UI policy (arch-review UA1).

### External Systems

- **ListExternalSystems** / **GetExternalSystem**: Query external system definitions.
- **CreateExternalSystem** / **UpdateExternalSystem** / **DeleteExternalSystem**: Manage external system definitions.

### Notifications

- **ListNotificationLists** / **GetNotificationList**: Query notification lists.
- **CreateNotificationList** / **UpdateNotificationList** / **DeleteNotificationList**: Manage notification lists and recipients.
- **GetSmtpConfig** / **UpdateSmtpConfig**: Query and update SMTP configuration.

### Security (LDAP & API Keys)

- **ListApiKeys** / **CreateApiKey** / **UpdateApiKey** / **EnableApiKey** / **DisableApiKey** / **DeleteApiKey**: Manage API keys.
- **ListRoleMappings** / **CreateRoleMapping** / **UpdateRoleMapping** / **DeleteRoleMapping**: Manage LDAP group-to-role mappings.
- **ListScopeRules** / **AddScopeRule** / **DeleteScopeRule**: Manage site scope rules on role mappings.

### Audit Log

- **QueryAuditLog**: Legacy configuration-change audit query (filtered by entity type, user, date range, etc.) routed through `/management`. Gated to the `Admin` role; superseded for the centralized Audit Log component (#23) by the dedicated `/api/audit/*` REST endpoints described below.

### Transport (Bundle Import / Export)

- **ExportBundle**: Build an encrypted bundle (templates, system artifacts, central-only configuration). Gated to the `Design` role. Returns base64-encoded bundle bytes plus a byte count.
- **PreviewBundle**: Unlock and inspect a previously uploaded bundle session, returning the per-entity preview (adds, modifies, identicals, blockers). Gated to the `Admin` role.
- **ImportBundle**: Apply a previewed bundle with per-conflict resolutions inside a single audit-correlated session. Gated to the `Admin` role.

### Shared Scripts

- **ListSharedScripts** / **GetSharedScript**: Query shared script definitions.
- **CreateSharedScript** / **UpdateSharedScript** / **DeleteSharedScript**: Manage shared scripts.

### Database Connections

- **ListDatabaseConnections** / **GetDatabaseConnection**: Query database connection definitions.
- **CreateDatabaseConnection** / **UpdateDatabaseConnection** / **DeleteDatabaseConnection**: Manage database connections.

### Inbound API Methods

- **ListApiMethods** / **GetApiMethod**: Query inbound API method definitions.
- **CreateApiMethod** / **UpdateApiMethod** / **DeleteApiMethod**: Manage inbound API methods.

### Health

- **GetHealthSummary**: Query current health status of all sites.
- **GetSiteHealth**: Query detailed health for a specific site.

### Remote Queries

- **QuerySiteEventLog**: Query site event log entries from a remote site (routed via communication layer). Supports date range, keyword search, and pagination.
- **QueryParkedMessages**: Query parked (dead-letter) messages at a remote site (routed via communication layer). Supports pagination.
- **DebugSnapshot**: Request a one-shot snapshot of attribute values and alarm states for a running instance. Resolves the instance's site from the config DB and routes via the communication layer. Uses 30s `QueryTimeout`.
- **BrowseNodeCommand**: Browse an OPC UA / MxGateway connection's address space one level at a time; supports a `BrowseNext` continuation token (paging) and returns per-node type-info for OPC UA Variables. (`Design` role.)
- **SearchAddressSpaceCommand**: Bounded recursive address-space search (depth + result caps, case-insensitive substring) against an OPC UA connection. (`Design` role.)
- **VerifyEndpointCommand**: Ask a site to probe an OPC UA endpoint (temporary client, short timeout) and report success / typed failure / a captured-but-untrusted server cert. Read-only — never trusts. (`Design` role — runs inside the Admin-gated connection editor.)
- **TrustServerCertCommand** / **RemoveServerCertCommand** / **ListServerCertsCommand**: Manage the site's OPC UA trusted-peer PKI store; Trust/Remove broadcast to **both** site nodes (see Component-SiteRuntime.md). (`Admin` role.)

## Authorization

Every incoming message carries the authenticated user's identity and roles. The ManagementActor enforces the same role-based authorization rules as the Central UI:

- **Admin** role required for: site management, area management, API key management, role mapping management, scope rule management, system configuration.
- **Design** role required for: template authoring (including template member management: attributes, alarms, native alarm sources, scripts, compositions), shared scripts, external system definitions, database connection definitions, notification lists, inbound API method definitions.
- **Deployment** role required for: instance management (including instance alarm overrides and native alarm source overrides), deployments, debug view, debug snapshot, parked message queries, site event log queries. Site scoping is enforced for site-scoped Deployment users.
- **Operator** role required for: submitting a secured write (`SubmitSecuredWriteCommand`).
- **Verifier** role required for: approving / rejecting a secured write (`ApproveSecuredWriteCommand` / `RejectSecuredWriteCommand`). The no-self-approval rule (`Operator ≠ Verifier`) is enforced in the handler, independent of the role check.
- **Any of Operator / Verifier / Administrator** required for: listing / querying secured writes (`ListSecuredWritesCommand`). Read-only, but the history exposes process-sensitive tag values, so it is gated any-of rather than open to every authenticated user (arch-review UA1). Enforced as an any-of gate (`GetRequiredRoles` returns the permitted set; the caller must hold at least one).
- **Admin** role additionally required for: server-certificate trust/remove/list (`TrustServerCertCommand` / `RemoveServerCertCommand` / `ListServerCertsCommand`).
- **Read-only access** (any authenticated role): health summary, health site, site event log queries, parked message queries.

Unauthorized commands receive an `Unauthorized` response message. Failed authorization attempts are not audit logged (consistent with existing behavior).

## Service Dependencies (DI)

The ManagementActor receives the following services and repositories via DI (injected through the actor's constructor or via a service provider):

- `ITemplateEngineRepository` / `TemplateService` — Template operations.
- `InstanceService` — Instance lifecycle and configuration.
- `ISiteRepository` — Site definitions and area management.
- `IDeploymentManagerRepository` / `DeploymentService` — Deployment pipeline operations.
- `ArtifactDeploymentService` — System-wide artifact deployment.
- `IExternalSystemRepository` — External system definitions.
- `INotificationRepository` — Notification lists and SMTP config.
- `ISecurityRepository` — API keys and LDAP role mappings.
- `ISecuredWriteRepository` — Pending/decided secured writes (the two-person MxGateway write workflow).
- `IAuditLogRepository` — Best-effort central direct-write of secured-write lifecycle audit rows.
- `IInboundApiRepository` — Inbound API method definitions.
- `ISharedScriptRepository` / `SharedScriptService` — Shared script definitions.
- `IDatabaseConnectionRepository` — Database connection definitions.
- `ICentralHealthAggregator` — Health status aggregation.
- `CommunicationService` — Central-site communication for deployment and remote queries.

## Configuration

| Section | Options Class | Contents |
|---------|--------------|----------|
| `ScadaBridge:ManagementService` | `ManagementServiceOptions` | `CommandTimeout` (`TimeSpan`, default 30 s) — Ask timeout the HTTP endpoint applies when forwarding to the `ManagementActor`. A non-positive configured value falls back to the 30 s default. |

## Dependencies

- **Commons**: Message contracts (`Messages/Management/`), shared types, repository interfaces.
- **Configuration Database (MS SQL)**: All queries and mutations go through repositories backed by EF Core.
- **Configuration Database (via IAuditService)**: All mutating operations are audit logged through the existing transactional audit mechanism.
- **Communication Layer**: Deployment commands and remote queries (parked messages, event logs) are routed to sites via Communication.
- **Security & Auth**: Authorization rules are enforced on every command using the authenticated user identity from the message envelope.
- **Cluster Infrastructure**: ManagementActor runs on all central nodes; ClusterClientReceptionist requires cluster membership.
- **All service components**: The ManagementActor delegates to the same services used by the Central UI — Template Engine, Deployment Manager, etc.

## Interactions

- **CLI**: The primary consumer. Connects via the HTTP Management API (`POST /management`) and sends commands as JSON with Basic Auth credentials.
- **Host**: Registers the ManagementActor and ClusterClientReceptionist on central nodes during startup.
- **Central UI**: Shares the same underlying services and repositories. The ManagementActor and Central UI are parallel interfaces to the same operations.
- **Communication Layer**: Deployment commands and remote site queries flow through communication actors.
- **Configuration Database (via IAuditService)**: All configuration changes are audited.
- **Security & Auth**: The ManagementActor enforces authorization using user identity passed in messages. For HTTP API access, the Management endpoint authenticates the user via LDAP and resolves roles before dispatching to the ManagementActor.
