diff --git a/docs/requirements/Component-ManagementService.md b/docs/requirements/Component-ManagementService.md
index 1f010103..92637b25 100644
--- a/docs/requirements/Component-ManagementService.md
+++ b/docs/requirements/Component-ManagementService.md
@@ -207,9 +207,9 @@ The two-person authorization workflow for writes through the MxAccess Gateway. B
- **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.)
+- **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. Actor-dispatched — the handler requires the command's `SiteIdentifier`, enforces site-scope, then relays via `CommunicationService.BrowseNodeAsync` (arch-review C4, CLI/UI parity). (`Design` role.)
+- **SearchAddressSpaceCommand**: Bounded recursive address-space search (depth + result caps, case-insensitive substring) against an OPC UA connection. Actor-dispatched, same `SiteIdentifier`-required + site-scope pattern, relayed via `CommunicationService.SearchAddressSpaceAsync` (arch-review C4). (`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. Actor-dispatched, `SiteIdentifier`-required + site-scope, relayed via `CommunicationService.VerifyEndpointAsync` (arch-review C4). (`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
diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs
index abf693c3..115754f3 100644
--- a/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs
@@ -363,7 +363,7 @@ public class CommunicationService
/// The OPC UA browse command.
/// Cancellation token.
/// The browse result (children + truncation flag + structured failure).
- public Task BrowseNodeAsync(
+ public virtual Task BrowseNodeAsync(
string siteId,
BrowseNodeCommand command,
CancellationToken cancellationToken = default)
@@ -385,7 +385,7 @@ public class CommunicationService
/// The verify-endpoint command (connection name + protocol + serialized config).
/// Cancellation token.
/// The verification result (success or classified failure, with a captured certificate when the failure is an untrusted certificate).
- public Task VerifyEndpointAsync(
+ public virtual Task VerifyEndpointAsync(
string siteId,
VerifyEndpointCommand command,
CancellationToken cancellationToken = default)
@@ -407,7 +407,7 @@ public class CommunicationService
/// The address-space search command (connection name + query + depth/result caps).
/// Cancellation token.
/// The search result (matches + cap-reached flag + structured failure).
- public Task SearchAddressSpaceAsync(
+ public virtual Task SearchAddressSpaceAsync(
string siteId,
SearchAddressSpaceCommand command,
CancellationToken cancellationToken = default)
diff --git a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs
index 732598c4..79556338 100644
--- a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs
@@ -243,6 +243,11 @@ public class ManagementActor : ReceiveActor
or CreateTemplateFolderCommand or RenameTemplateFolderCommand
or MoveTemplateFolderCommand or ReorderTemplateFolderCommand or DeleteTemplateFolderCommand
or MoveTemplateToFolderCommand
+ // OPC UA / MxGateway design-time remote queries (arch-review C4):
+ // browse the address space, run a bounded search, and probe/verify an
+ // endpoint. Read-only against the live site server; gated Design to
+ // match the connection editor these back.
+ or BrowseNodeCommand or SearchAddressSpaceCommand or VerifyEndpointCommand
or ExportBundleCommand => DesignerOnly,
// Transport import operations (mirror the Central UI gating:
@@ -435,6 +440,9 @@ public class ManagementActor : ReceiveActor
// Remote Queries
QueryEventLogsCommand cmd => await HandleQueryEventLogs(sp, cmd, user),
+ BrowseNodeCommand cmd => await HandleBrowseNode(sp, cmd, user),
+ SearchAddressSpaceCommand cmd => await HandleSearchAddressSpace(sp, cmd, user),
+ VerifyEndpointCommand cmd => await HandleVerifyEndpoint(sp, cmd, user),
QueryParkedMessagesCommand cmd => await HandleQueryParkedMessages(sp, cmd, user),
RetryParkedMessageCommand cmd => await HandleRetryParkedMessage(sp, cmd, user),
DiscardParkedMessageCommand cmd => await HandleDiscardParkedMessage(sp, cmd, user),
@@ -2914,6 +2922,39 @@ public class ManagementActor : ReceiveActor
return await commService.QueryEventLogsAsync(cmd.SiteIdentifier, request);
}
+ // OPC UA / MxGateway design-time remote queries (arch-review C4). These
+ // handlers give the management API/CLI parity with the Central UI, which
+ // already reaches these site actors directly. SiteIdentifier is REQUIRED —
+ // the actor must know which site to route to — and site-scope is enforced
+ // before relaying, exactly like HandleQueryEventLogs.
+
+ private static async Task