# 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/ScadaLink.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. ## 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 Members - **AddTemplateAttribute** / **UpdateTemplateAttribute** / **DeleteTemplateAttribute**: Manage attributes on a template. - **AddTemplateAlarm** / **UpdateTemplateAlarm** / **DeleteTemplateAlarm**: Manage alarm definitions on a template. - **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. - **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, notification lists, SMTP config) to all sites or a specific site. - **GetDeploymentStatus**: Query deployment status. ### 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**: Query audit log entries with filtering by entity type, user, date range, etc. ### 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`. ## 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, scripts, compositions), shared scripts, external system definitions, database connection definitions, notification lists, inbound API method definitions. - **Deployment** role required for: instance management, deployments, debug view, debug snapshot, parked message queries, site event log queries. Site scoping is enforced for site-scoped Deployment users. - **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. - `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 | |---------|--------------|----------| | `ScadaLink:ManagementService` | `ManagementServiceOptions` | (Reserved for future configuration — e.g., command timeout overrides) | ## 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.