a5256e9b12
'Pattern 4: Integration Routing' — RouteIntegrationCallAsync → SiteEnvelope(IntegrationCallRequest) → SiteCommunicationActor integration handler — was plumbed end to end but connected at neither end: no producer (zero callers) and no handler (AkkaHostedService never registered LocalHandlerType.Integration). It was an early scaffold the architecture routed around — the brokered External→Central→Site→Central round-trip is served by the Inbound API's routed-site-script path (the RouteTo* verbs, driven from CommunicationServiceInstanceRouter), which is live, tested, and shares IntegrationTimeout. Decision (#32): delete. Removed the IntegrationCall{Request,Response} messages, RouteIntegrationCallAsync, the SiteCommunicationActor receive block + _integrationHandler field + LocalHandlerType.Integration, and the four tests that covered them (2 actor, 2 message-contract, 1 dispatcher- reject, 1 mapper-reject). KEPT IntegrationTimeout — it is the live timeout for the RouteTo* verbs. Updated the exclusion-narrative comments (proto/mapper/dispatcher), design §4, the components doc timeout table, and marked the known-issue RESOLVED. Full solution build clean (0/0); Communication 634 + Host 421 green. Net -172/+20 across 14 files. Not in the gRPC proto (was deliberately excluded there), so no wire-format change.
854 lines
31 KiB
Protocol Buffer
854 lines
31 KiB
Protocol Buffer
syntax = "proto3";
|
|
option csharp_namespace = "ZB.MOM.WW.ScadaBridge.Communication.Grpc";
|
|
package scadabridge.sitecommand.v1;
|
|
|
|
import "google/protobuf/timestamp.proto";
|
|
import "google/protobuf/duration.proto";
|
|
import "google/protobuf/wrappers.proto";
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Site command plane (central → site) — the gRPC replacement for the per-site
|
|
// ClusterClient command/control channel handled by SiteCommunicationActor.
|
|
//
|
|
// The 28 migrated commands are grouped into six domain RPCs rather than 28
|
|
// individual RPCs, because the grouping is what carries the DEADLINE policy:
|
|
// every command inside one group shares a timeout class today (see
|
|
// CommunicationOptions), so one RPC per group keeps the deadline choice in one
|
|
// place on the client and one dispatch switch on the server. A `oneof` request
|
|
// / reply envelope preserves per-command typing inside the group.
|
|
//
|
|
// EVOLUTION RULE (same as sitestream.proto): field numbers are never reused and
|
|
// changes are additive only. New commands take the next free oneof tag; an
|
|
// older peer simply sees an unset oneof and answers with a clean error.
|
|
//
|
|
// The generated C# is CHECKED IN under Communication/SiteCommandGrpc/ because
|
|
// protoc segfaults inside the linux_arm64 Docker build image. Regenerate with
|
|
// docker/regen-proto.sh (or by hand per the recipe in the .csproj) — never by
|
|
// leaving an active <Protobuf> item in the project file.
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
service SiteCommandService {
|
|
// Deployment + instance lifecycle (6 commands).
|
|
rpc ExecuteLifecycle(LifecycleRequest) returns (LifecycleReply);
|
|
// Interactive OPC UA / MxGateway design-time commands (8 commands).
|
|
rpc ExecuteOpcUa(OpcUaRequest) returns (OpcUaReply);
|
|
// Remote read-only queries: event log + debug view (4 commands).
|
|
rpc ExecuteQuery(QueryRequest) returns (QueryReply);
|
|
// Parked store-and-forward message + cached-operation actions (5 commands).
|
|
rpc ExecuteParked(ParkedRequest) returns (ParkedReply);
|
|
// Inbound-API Route.To() relays (4 commands).
|
|
rpc ExecuteRoute(RouteRequest) returns (RouteReply);
|
|
// Operator-initiated manual site-pair failover (1 command).
|
|
rpc TriggerFailover(TriggerSiteFailoverDto) returns (SiteFailoverAckDto);
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Shared value carrier
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
// Explicit null marker. Needed because a map<string, LooseValue> entry always
|
|
// has a value message present, so "the dictionary holds a null for this key"
|
|
// cannot be expressed by absence the way a nullable message FIELD can.
|
|
message LooseNull {}
|
|
|
|
message LooseValueList { repeated LooseValue items = 1; }
|
|
|
|
message LooseValueMap { map<string, LooseValue> entries = 1; }
|
|
|
|
// Type-tagged carrier for the `object?` members the command plane still uses
|
|
// (script parameters and return values, attribute values, tag read/write
|
|
// values). The tags cover every CLR type these fields actually carry, so those
|
|
// values round-trip with their runtime type intact; anything else falls back to
|
|
// `json_value` (see the mapper's documented lossiness note).
|
|
//
|
|
// Date/time and decimal ride as invariant round-trip STRINGS rather than
|
|
// google.protobuf.Timestamp: Timestamp normalises everything to UTC and would
|
|
// silently drop DateTime.Kind / DateTimeOffset.Offset, which for an operator's
|
|
// tag value is data loss, not normalisation.
|
|
message LooseValue {
|
|
oneof kind {
|
|
LooseNull null_value = 1;
|
|
bool bool_value = 2;
|
|
int32 int32_value = 3;
|
|
int64 int64_value = 4;
|
|
double double_value = 5;
|
|
float float_value = 6;
|
|
string string_value = 7;
|
|
string decimal_value = 8; // invariant-culture round-trip
|
|
string date_time_value = 9; // DateTime, "O" (preserves Kind)
|
|
string date_time_offset_value = 10; // DateTimeOffset, "O" (preserves Offset)
|
|
string guid_value = 11; // "D"
|
|
string time_span_value = 12; // "c" (constant/round-trip)
|
|
bytes bytes_value = 13;
|
|
LooseValueList list_value = 14;
|
|
LooseValueMap map_value = 15;
|
|
string json_value = 16; // fallback; decodes to JsonElement
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Enums. Every enum reserves 0 for _UNSPECIFIED so a value that is absent on
|
|
// the wire is never mistaken for the first CLR member. The mapper translates
|
|
// explicitly in both directions (never by ordinal), so reordering a C# enum
|
|
// cannot silently re-map the wire.
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
enum DeploymentStatusDto {
|
|
DEPLOYMENT_STATUS_DTO_UNSPECIFIED = 0;
|
|
DEPLOYMENT_STATUS_DTO_PENDING = 1;
|
|
DEPLOYMENT_STATUS_DTO_IN_PROGRESS = 2;
|
|
DEPLOYMENT_STATUS_DTO_SUCCESS = 3;
|
|
DEPLOYMENT_STATUS_DTO_FAILED = 4;
|
|
}
|
|
|
|
enum BrowseNodeClassDto {
|
|
BROWSE_NODE_CLASS_DTO_UNSPECIFIED = 0;
|
|
BROWSE_NODE_CLASS_DTO_OBJECT = 1;
|
|
BROWSE_NODE_CLASS_DTO_VARIABLE = 2;
|
|
BROWSE_NODE_CLASS_DTO_METHOD = 3;
|
|
BROWSE_NODE_CLASS_DTO_OTHER = 4;
|
|
}
|
|
|
|
enum BrowseFailureKindDto {
|
|
BROWSE_FAILURE_KIND_DTO_UNSPECIFIED = 0;
|
|
BROWSE_FAILURE_KIND_DTO_CONNECTION_NOT_FOUND = 1;
|
|
BROWSE_FAILURE_KIND_DTO_CONNECTION_NOT_CONNECTED = 2;
|
|
BROWSE_FAILURE_KIND_DTO_NOT_BROWSABLE = 3;
|
|
BROWSE_FAILURE_KIND_DTO_TIMEOUT = 4;
|
|
BROWSE_FAILURE_KIND_DTO_SERVER_ERROR = 5;
|
|
}
|
|
|
|
enum ReadTagValuesFailureKindDto {
|
|
READ_TAG_VALUES_FAILURE_KIND_DTO_UNSPECIFIED = 0;
|
|
READ_TAG_VALUES_FAILURE_KIND_DTO_CONNECTION_NOT_FOUND = 1;
|
|
READ_TAG_VALUES_FAILURE_KIND_DTO_CONNECTION_NOT_CONNECTED = 2;
|
|
READ_TAG_VALUES_FAILURE_KIND_DTO_TIMEOUT = 3;
|
|
READ_TAG_VALUES_FAILURE_KIND_DTO_SERVER_ERROR = 4;
|
|
}
|
|
|
|
enum VerifyFailureKindDto {
|
|
VERIFY_FAILURE_KIND_DTO_UNSPECIFIED = 0;
|
|
VERIFY_FAILURE_KIND_DTO_UNREACHABLE = 1;
|
|
VERIFY_FAILURE_KIND_DTO_AUTH_FAILED = 2;
|
|
VERIFY_FAILURE_KIND_DTO_UNTRUSTED_CERTIFICATE = 3;
|
|
VERIFY_FAILURE_KIND_DTO_TIMEOUT = 4;
|
|
VERIFY_FAILURE_KIND_DTO_SERVER_ERROR = 5;
|
|
}
|
|
|
|
enum StoreAndForwardCategoryDto {
|
|
STORE_AND_FORWARD_CATEGORY_DTO_UNSPECIFIED = 0;
|
|
STORE_AND_FORWARD_CATEGORY_DTO_EXTERNAL_SYSTEM = 1;
|
|
STORE_AND_FORWARD_CATEGORY_DTO_NOTIFICATION = 2;
|
|
STORE_AND_FORWARD_CATEGORY_DTO_CACHED_DB_WRITE = 3;
|
|
}
|
|
|
|
enum AlarmStateDto {
|
|
ALARM_STATE_DTO_UNSPECIFIED = 0;
|
|
ALARM_STATE_DTO_ACTIVE = 1;
|
|
ALARM_STATE_DTO_NORMAL = 2;
|
|
}
|
|
|
|
enum AlarmLevelDto {
|
|
ALARM_LEVEL_DTO_UNSPECIFIED = 0;
|
|
ALARM_LEVEL_DTO_NONE = 1;
|
|
ALARM_LEVEL_DTO_LOW = 2;
|
|
ALARM_LEVEL_DTO_LOW_LOW = 3;
|
|
ALARM_LEVEL_DTO_HIGH = 4;
|
|
ALARM_LEVEL_DTO_HIGH_HIGH = 5;
|
|
}
|
|
|
|
enum AlarmKindDto {
|
|
ALARM_KIND_DTO_UNSPECIFIED = 0;
|
|
ALARM_KIND_DTO_COMPUTED = 1;
|
|
ALARM_KIND_DTO_NATIVE_OPC_UA = 2;
|
|
ALARM_KIND_DTO_NATIVE_MX_ACCESS = 3;
|
|
}
|
|
|
|
enum AlarmShelveStateDto {
|
|
ALARM_SHELVE_STATE_DTO_UNSPECIFIED = 0;
|
|
ALARM_SHELVE_STATE_DTO_UNSHELVED = 1;
|
|
ALARM_SHELVE_STATE_DTO_ONE_SHOT_SHELVED = 2;
|
|
ALARM_SHELVE_STATE_DTO_TIMED_SHELVED = 3;
|
|
ALARM_SHELVE_STATE_DTO_PERMANENT_SHELVED = 4;
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// RPC 1 — ExecuteLifecycle
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
message RefreshDeploymentCommandDto {
|
|
string deployment_id = 1;
|
|
string instance_unique_name = 2;
|
|
string revision_hash = 3;
|
|
string deployed_by = 4;
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
string central_fetch_base_url = 6;
|
|
string fetch_token = 7;
|
|
}
|
|
|
|
message EnableInstanceCommandDto {
|
|
string command_id = 1;
|
|
string instance_unique_name = 2;
|
|
google.protobuf.Timestamp timestamp = 3;
|
|
}
|
|
|
|
message DisableInstanceCommandDto {
|
|
string command_id = 1;
|
|
string instance_unique_name = 2;
|
|
google.protobuf.Timestamp timestamp = 3;
|
|
}
|
|
|
|
message DeleteInstanceCommandDto {
|
|
string command_id = 1;
|
|
string instance_unique_name = 2;
|
|
google.protobuf.Timestamp timestamp = 3;
|
|
}
|
|
|
|
message DeploymentStateQueryRequestDto {
|
|
string correlation_id = 1;
|
|
string instance_unique_name = 2;
|
|
google.protobuf.Timestamp timestamp = 3;
|
|
}
|
|
|
|
message SharedScriptArtifactDto {
|
|
string name = 1;
|
|
string code = 2;
|
|
string parameter_definitions = 3; // empty string represents null
|
|
string return_definition = 4; // empty string represents null
|
|
}
|
|
|
|
message ExternalSystemArtifactDto {
|
|
string name = 1;
|
|
string endpoint_url = 2;
|
|
string auth_type = 3;
|
|
string auth_configuration = 4; // empty string represents null
|
|
string method_definitions_json = 5; // empty string represents null
|
|
int32 timeout_seconds = 6;
|
|
}
|
|
|
|
message DatabaseConnectionArtifactDto {
|
|
string name = 1;
|
|
string connection_string = 2;
|
|
int32 max_retries = 3;
|
|
google.protobuf.Duration retry_delay = 4;
|
|
}
|
|
|
|
message NotificationListArtifactDto {
|
|
string name = 1;
|
|
repeated string recipient_emails = 2;
|
|
}
|
|
|
|
message DataConnectionArtifactDto {
|
|
string name = 1;
|
|
string protocol = 2;
|
|
string primary_configuration_json = 3; // empty string represents null
|
|
string backup_configuration_json = 4; // empty string represents null
|
|
int32 failover_retry_count = 5;
|
|
}
|
|
|
|
message SmtpConfigurationArtifactDto {
|
|
string name = 1;
|
|
string server = 2;
|
|
int32 port = 3;
|
|
string auth_mode = 4;
|
|
string from_address = 5;
|
|
string username = 6; // empty string represents null
|
|
string password = 7; // empty string represents null
|
|
string oauth_config = 8; // empty string represents null
|
|
}
|
|
|
|
// Each artifact collection on DeployArtifactsCommand is a NULLABLE list, and
|
|
// proto3 `repeated` cannot distinguish null from empty. Wrapping each in its
|
|
// own message makes the null/empty distinction a message-presence question,
|
|
// which proto3 does model — the same silent-data-loss class the transport
|
|
// round-trip guard caught in PLAN-05 T8.
|
|
message SharedScriptArtifactListDto { repeated SharedScriptArtifactDto items = 1; }
|
|
message ExternalSystemArtifactListDto { repeated ExternalSystemArtifactDto items = 1; }
|
|
message DatabaseConnectionArtifactListDto { repeated DatabaseConnectionArtifactDto items = 1; }
|
|
message NotificationListArtifactListDto { repeated NotificationListArtifactDto items = 1; }
|
|
message DataConnectionArtifactListDto { repeated DataConnectionArtifactDto items = 1; }
|
|
message SmtpConfigurationArtifactListDto { repeated SmtpConfigurationArtifactDto items = 1; }
|
|
|
|
message DeployArtifactsCommandDto {
|
|
string deployment_id = 1;
|
|
SharedScriptArtifactListDto shared_scripts = 2; // absent => null
|
|
ExternalSystemArtifactListDto external_systems = 3; // absent => null
|
|
DatabaseConnectionArtifactListDto database_connections = 4; // absent => null
|
|
NotificationListArtifactListDto notification_lists = 5; // absent => null
|
|
DataConnectionArtifactListDto data_connections = 6; // absent => null
|
|
SmtpConfigurationArtifactListDto smtp_configurations = 7; // absent => null
|
|
google.protobuf.Timestamp timestamp = 8;
|
|
}
|
|
|
|
message DeploymentStatusResponseDto {
|
|
string deployment_id = 1;
|
|
string instance_unique_name = 2;
|
|
DeploymentStatusDto status = 3;
|
|
string error_message = 4; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
}
|
|
|
|
message InstanceLifecycleResponseDto {
|
|
string command_id = 1;
|
|
string instance_unique_name = 2;
|
|
bool success = 3;
|
|
string error_message = 4; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
}
|
|
|
|
message DeploymentStateQueryResponseDto {
|
|
string correlation_id = 1;
|
|
string instance_unique_name = 2;
|
|
bool is_deployed = 3;
|
|
string applied_deployment_id = 4; // empty string represents null
|
|
string applied_revision_hash = 5; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 6;
|
|
}
|
|
|
|
message ArtifactDeploymentResponseDto {
|
|
string deployment_id = 1;
|
|
string site_id = 2;
|
|
bool success = 3;
|
|
string error_message = 4; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
}
|
|
|
|
message LifecycleRequest {
|
|
oneof command {
|
|
RefreshDeploymentCommandDto refresh_deployment = 1;
|
|
EnableInstanceCommandDto enable_instance = 2;
|
|
DisableInstanceCommandDto disable_instance = 3;
|
|
DeleteInstanceCommandDto delete_instance = 4;
|
|
DeploymentStateQueryRequestDto deployment_state_query = 5;
|
|
DeployArtifactsCommandDto deploy_artifacts = 6;
|
|
}
|
|
}
|
|
|
|
message LifecycleReply {
|
|
oneof reply {
|
|
DeploymentStatusResponseDto deployment_status = 1;
|
|
InstanceLifecycleResponseDto instance_lifecycle = 2;
|
|
DeploymentStateQueryResponseDto deployment_state_query = 3;
|
|
ArtifactDeploymentResponseDto artifact_deployment = 4;
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// RPC 2 — ExecuteOpcUa
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
message BrowseNodeCommandDto {
|
|
string connection_name = 1;
|
|
string parent_node_id = 2; // empty string represents null (browse root)
|
|
string continuation_token = 3; // empty string represents null (first page)
|
|
string site_identifier = 4; // empty string represents null
|
|
}
|
|
|
|
message BrowseNodeDto {
|
|
string node_id = 1;
|
|
string display_name = 2;
|
|
BrowseNodeClassDto node_class = 3;
|
|
bool has_children = 4;
|
|
string data_type = 5; // empty string represents null
|
|
google.protobuf.Int32Value value_rank = 6; // absent => null
|
|
google.protobuf.BoolValue writable = 7; // absent => null
|
|
}
|
|
|
|
message BrowseFailureDto {
|
|
BrowseFailureKindDto kind = 1;
|
|
string message = 2;
|
|
}
|
|
|
|
message BrowseNodeResultDto {
|
|
repeated BrowseNodeDto children = 1;
|
|
bool truncated = 2;
|
|
BrowseFailureDto failure = 3; // absent => null (success)
|
|
string continuation_token = 4; // empty string represents null (final page)
|
|
}
|
|
|
|
message SearchAddressSpaceCommandDto {
|
|
string connection_name = 1;
|
|
string query = 2;
|
|
int32 max_depth = 3;
|
|
int32 max_results = 4;
|
|
string site_identifier = 5; // empty string represents null
|
|
}
|
|
|
|
message AddressSpaceMatchDto {
|
|
BrowseNodeDto node = 1;
|
|
string path = 2;
|
|
}
|
|
|
|
message SearchAddressSpaceResultDto {
|
|
repeated AddressSpaceMatchDto matches = 1;
|
|
bool cap_reached = 2;
|
|
BrowseFailureDto failure = 3; // absent => null (success)
|
|
}
|
|
|
|
message ReadTagValuesCommandDto {
|
|
string connection_name = 1;
|
|
repeated string tag_paths = 2;
|
|
}
|
|
|
|
message TagReadOutcomeDto {
|
|
string tag_path = 1;
|
|
bool success = 2;
|
|
LooseValue value = 3; // absent => null
|
|
string quality = 4;
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
string error_message = 6; // empty string represents null
|
|
}
|
|
|
|
message ReadTagValuesFailureDto {
|
|
ReadTagValuesFailureKindDto kind = 1;
|
|
string message = 2;
|
|
}
|
|
|
|
message ReadTagValuesResultDto {
|
|
repeated TagReadOutcomeDto outcomes = 1;
|
|
ReadTagValuesFailureDto failure = 2; // absent => null (success)
|
|
}
|
|
|
|
message VerifyEndpointCommandDto {
|
|
string connection_name = 1;
|
|
string protocol = 2;
|
|
string config_json = 3;
|
|
string site_identifier = 4; // empty string represents null
|
|
}
|
|
|
|
message ServerCertInfoDto {
|
|
string thumbprint = 1;
|
|
string subject = 2;
|
|
string issuer = 3;
|
|
google.protobuf.Timestamp not_before_utc = 4;
|
|
google.protobuf.Timestamp not_after_utc = 5;
|
|
string der_base64 = 6;
|
|
}
|
|
|
|
// failure_kind is a NULLABLE enum on the CLR side, and proto3 enums have no
|
|
// presence, so it rides inside a one-field message exactly like Int32Value.
|
|
message VerifyFailureKindValue { VerifyFailureKindDto value = 1; }
|
|
|
|
message VerifyEndpointResultDto {
|
|
bool success = 1;
|
|
VerifyFailureKindValue failure_kind = 2; // absent => null (success)
|
|
string error = 3; // empty string represents null
|
|
ServerCertInfoDto cert = 4; // absent => null
|
|
}
|
|
|
|
message TrustServerCertCommandDto {
|
|
string connection_name = 1;
|
|
string der_base64 = 2;
|
|
string thumbprint = 3;
|
|
string site_identifier = 4; // empty string represents null
|
|
}
|
|
|
|
message ListServerCertsCommandDto {
|
|
string site_identifier = 1; // empty string represents null
|
|
}
|
|
|
|
message RemoveServerCertCommandDto {
|
|
string thumbprint = 1;
|
|
string site_identifier = 2; // empty string represents null
|
|
}
|
|
|
|
message TrustedCertInfoDto {
|
|
string thumbprint = 1;
|
|
string subject = 2;
|
|
string issuer = 3;
|
|
google.protobuf.Timestamp not_before_utc = 4;
|
|
google.protobuf.Timestamp not_after_utc = 5;
|
|
bool rejected = 6;
|
|
}
|
|
|
|
// CertTrustResult.Certs is a nullable list (null for trust/remove, populated
|
|
// for list) — same null-vs-empty problem as the artifact collections.
|
|
message TrustedCertInfoListDto { repeated TrustedCertInfoDto items = 1; }
|
|
|
|
message CertTrustResultDto {
|
|
bool success = 1;
|
|
string error = 2; // empty string represents null
|
|
TrustedCertInfoListDto certs = 3; // absent => null
|
|
}
|
|
|
|
message WriteTagRequestDto {
|
|
string correlation_id = 1;
|
|
string connection_name = 2;
|
|
string tag_path = 3;
|
|
LooseValue value = 4; // absent => null
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
}
|
|
|
|
message WriteTagResponseDto {
|
|
string correlation_id = 1;
|
|
bool success = 2;
|
|
string error_message = 3; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 4;
|
|
}
|
|
|
|
message OpcUaRequest {
|
|
oneof command {
|
|
BrowseNodeCommandDto browse_node = 1;
|
|
SearchAddressSpaceCommandDto search_address_space = 2;
|
|
ReadTagValuesCommandDto read_tag_values = 3;
|
|
VerifyEndpointCommandDto verify_endpoint = 4;
|
|
TrustServerCertCommandDto trust_server_cert = 5;
|
|
ListServerCertsCommandDto list_server_certs = 6;
|
|
RemoveServerCertCommandDto remove_server_cert = 7;
|
|
WriteTagRequestDto write_tag = 8;
|
|
}
|
|
}
|
|
|
|
message OpcUaReply {
|
|
oneof reply {
|
|
BrowseNodeResultDto browse_node = 1;
|
|
SearchAddressSpaceResultDto search_address_space = 2;
|
|
ReadTagValuesResultDto read_tag_values = 3;
|
|
VerifyEndpointResultDto verify_endpoint = 4;
|
|
CertTrustResultDto cert_trust = 5;
|
|
WriteTagResponseDto write_tag = 6;
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// RPC 3 — ExecuteQuery
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
message EventLogQueryRequestDto {
|
|
string correlation_id = 1;
|
|
string site_id = 2;
|
|
google.protobuf.Timestamp from = 3; // absent => null
|
|
google.protobuf.Timestamp to = 4; // absent => null
|
|
string event_type = 5; // empty string represents null
|
|
string severity = 6; // empty string represents null
|
|
string instance_id = 7; // empty string represents null
|
|
string keyword_filter = 8; // empty string represents null
|
|
string continuation_token = 9; // empty string represents null
|
|
int32 page_size = 10;
|
|
google.protobuf.Timestamp timestamp = 11;
|
|
}
|
|
|
|
message EventLogEntryDto {
|
|
string id = 1;
|
|
google.protobuf.Timestamp timestamp = 2;
|
|
string event_type = 3;
|
|
string severity = 4;
|
|
string instance_id = 5; // empty string represents null
|
|
string source = 6;
|
|
string message = 7;
|
|
string details = 8; // empty string represents null
|
|
}
|
|
|
|
message EventLogQueryResponseDto {
|
|
string correlation_id = 1;
|
|
string site_id = 2;
|
|
repeated EventLogEntryDto entries = 3;
|
|
string continuation_token = 4; // empty string represents null
|
|
bool has_more = 5;
|
|
bool success = 6;
|
|
string error_message = 7; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 8;
|
|
}
|
|
|
|
message DebugSnapshotRequestDto {
|
|
string instance_unique_name = 1;
|
|
string correlation_id = 2;
|
|
}
|
|
|
|
message SubscribeDebugViewRequestDto {
|
|
string instance_unique_name = 1;
|
|
string correlation_id = 2;
|
|
}
|
|
|
|
message UnsubscribeDebugViewRequestDto {
|
|
string instance_unique_name = 1;
|
|
string correlation_id = 2;
|
|
}
|
|
|
|
// UnsubscribeDebugView is a Tell today (CommunicationService.UnsubscribeDebugView
|
|
// fires and forgets). A unary RPC must still answer something, so the site sends
|
|
// this empty ack; the central transport ignores it to keep the caller-visible
|
|
// fire-and-forget semantics identical.
|
|
message UnsubscribeDebugViewAckDto {}
|
|
|
|
message AlarmConditionStateDto {
|
|
bool active = 1;
|
|
bool acknowledged = 2;
|
|
google.protobuf.BoolValue confirmed = 3; // absent => null (not confirmable)
|
|
AlarmShelveStateDto shelve = 4;
|
|
bool suppressed = 5;
|
|
int32 severity = 6;
|
|
}
|
|
|
|
message DebugAttributeValueDto {
|
|
string instance_unique_name = 1;
|
|
string attribute_path = 2;
|
|
string attribute_name = 3;
|
|
LooseValue value = 4; // absent => null
|
|
string quality = 5;
|
|
google.protobuf.Timestamp timestamp = 6;
|
|
}
|
|
|
|
// Full-fidelity projection of Commons AlarmStateChanged. Deliberately NOT the
|
|
// sitestream AlarmStateUpdate: that one flattens the value to a display string
|
|
// and the shelve state to free text, which is right for a live stream but would
|
|
// lose data on a snapshot the central UI renders as authoritative state.
|
|
message DebugAlarmStateDto {
|
|
string instance_unique_name = 1;
|
|
string alarm_name = 2;
|
|
AlarmStateDto state = 3;
|
|
int32 priority = 4;
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
AlarmLevelDto level = 6;
|
|
string message = 7;
|
|
AlarmKindDto kind = 8;
|
|
// Absent means "not explicitly set" — the CLR record then derives the
|
|
// computed default from state + priority. See the mapper's note on why the
|
|
// encoder omits a condition that already equals that derived default.
|
|
AlarmConditionStateDto condition = 9;
|
|
string source_reference = 10;
|
|
string alarm_type_name = 11;
|
|
string category = 12;
|
|
string operator_user = 13;
|
|
string operator_comment = 14;
|
|
google.protobuf.Timestamp original_raise_time = 15; // absent => null
|
|
string current_value = 16;
|
|
string limit_value = 17;
|
|
string native_source_canonical_name = 18;
|
|
bool is_configured_placeholder = 19;
|
|
}
|
|
|
|
message DebugViewSnapshotDto {
|
|
string instance_unique_name = 1;
|
|
repeated DebugAttributeValueDto attribute_values = 2;
|
|
repeated DebugAlarmStateDto alarm_states = 3;
|
|
google.protobuf.Timestamp snapshot_timestamp = 4;
|
|
bool instance_not_found = 5;
|
|
}
|
|
|
|
message QueryRequest {
|
|
oneof command {
|
|
EventLogQueryRequestDto event_log_query = 1;
|
|
DebugSnapshotRequestDto debug_snapshot = 2;
|
|
SubscribeDebugViewRequestDto subscribe_debug_view = 3;
|
|
UnsubscribeDebugViewRequestDto unsubscribe_debug_view = 4;
|
|
}
|
|
}
|
|
|
|
message QueryReply {
|
|
oneof reply {
|
|
EventLogQueryResponseDto event_log_query = 1;
|
|
DebugViewSnapshotDto debug_view_snapshot = 2;
|
|
UnsubscribeDebugViewAckDto unsubscribe_debug_view = 3;
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// RPC 4 — ExecuteParked
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
message ParkedMessageQueryRequestDto {
|
|
string correlation_id = 1;
|
|
string site_id = 2;
|
|
int32 page_number = 3;
|
|
int32 page_size = 4;
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
}
|
|
|
|
message ParkedMessageEntryDto {
|
|
string message_id = 1;
|
|
string target_system = 2;
|
|
string method_name = 3;
|
|
string error_message = 4;
|
|
int32 attempt_count = 5;
|
|
google.protobuf.Timestamp original_timestamp = 6;
|
|
google.protobuf.Timestamp last_attempt_timestamp = 7;
|
|
int32 max_attempts = 8;
|
|
StoreAndForwardCategoryDto category = 9;
|
|
string origin_instance = 10; // empty string represents null
|
|
}
|
|
|
|
message ParkedMessageQueryResponseDto {
|
|
string correlation_id = 1;
|
|
string site_id = 2;
|
|
repeated ParkedMessageEntryDto messages = 3;
|
|
int32 total_count = 4;
|
|
int32 page_number = 5;
|
|
int32 page_size = 6;
|
|
bool success = 7;
|
|
string error_message = 8; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 9;
|
|
}
|
|
|
|
message ParkedMessageRetryRequestDto {
|
|
string correlation_id = 1;
|
|
string site_id = 2;
|
|
string message_id = 3;
|
|
google.protobuf.Timestamp timestamp = 4;
|
|
}
|
|
|
|
message ParkedMessageRetryResponseDto {
|
|
string correlation_id = 1;
|
|
bool success = 2;
|
|
string error_message = 3; // empty string represents null
|
|
}
|
|
|
|
message ParkedMessageDiscardRequestDto {
|
|
string correlation_id = 1;
|
|
string site_id = 2;
|
|
string message_id = 3;
|
|
google.protobuf.Timestamp timestamp = 4;
|
|
}
|
|
|
|
message ParkedMessageDiscardResponseDto {
|
|
string correlation_id = 1;
|
|
bool success = 2;
|
|
string error_message = 3; // empty string represents null
|
|
}
|
|
|
|
message RetryParkedOperationDto {
|
|
string correlation_id = 1;
|
|
string tracked_operation_id = 2; // TrackedOperationId GUID, "D" format
|
|
}
|
|
|
|
message DiscardParkedOperationDto {
|
|
string correlation_id = 1;
|
|
string tracked_operation_id = 2; // TrackedOperationId GUID, "D" format
|
|
}
|
|
|
|
message ParkedOperationActionAckDto {
|
|
string correlation_id = 1;
|
|
bool applied = 2;
|
|
string error_message = 3; // empty string represents null
|
|
}
|
|
|
|
message ParkedRequest {
|
|
oneof command {
|
|
ParkedMessageQueryRequestDto parked_message_query = 1;
|
|
ParkedMessageRetryRequestDto parked_message_retry = 2;
|
|
ParkedMessageDiscardRequestDto parked_message_discard = 3;
|
|
RetryParkedOperationDto retry_parked_operation = 4;
|
|
DiscardParkedOperationDto discard_parked_operation = 5;
|
|
}
|
|
}
|
|
|
|
message ParkedReply {
|
|
oneof reply {
|
|
ParkedMessageQueryResponseDto parked_message_query = 1;
|
|
ParkedMessageRetryResponseDto parked_message_retry = 2;
|
|
ParkedMessageDiscardResponseDto parked_message_discard = 3;
|
|
ParkedOperationActionAckDto parked_operation_action = 4;
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// RPC 5 — ExecuteRoute
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
message RouteToCallRequestDto {
|
|
string correlation_id = 1;
|
|
string instance_unique_name = 2;
|
|
string script_name = 3;
|
|
LooseValueMap parameters = 4; // absent => null (distinct from empty)
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
string parent_execution_id = 6; // empty string represents null
|
|
}
|
|
|
|
message RouteToCallResponseDto {
|
|
string correlation_id = 1;
|
|
bool success = 2;
|
|
LooseValue return_value = 3; // absent => null
|
|
string error_message = 4; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
}
|
|
|
|
message RouteToGetAttributesRequestDto {
|
|
string correlation_id = 1;
|
|
string instance_unique_name = 2;
|
|
repeated string attribute_names = 3;
|
|
google.protobuf.Timestamp timestamp = 4;
|
|
string parent_execution_id = 5; // empty string represents null
|
|
}
|
|
|
|
message RouteToGetAttributesResponseDto {
|
|
string correlation_id = 1;
|
|
LooseValueMap values = 2; // non-nullable on the CLR side; absent => empty
|
|
bool success = 3;
|
|
string error_message = 4; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 5;
|
|
}
|
|
|
|
message RouteToSetAttributesRequestDto {
|
|
string correlation_id = 1;
|
|
string instance_unique_name = 2;
|
|
map<string, string> attribute_values = 3;
|
|
google.protobuf.Timestamp timestamp = 4;
|
|
string parent_execution_id = 5; // empty string represents null
|
|
}
|
|
|
|
message RouteToSetAttributesResponseDto {
|
|
string correlation_id = 1;
|
|
bool success = 2;
|
|
string error_message = 3; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 4;
|
|
}
|
|
|
|
message RouteToWaitForAttributeRequestDto {
|
|
string correlation_id = 1;
|
|
string instance_unique_name = 2;
|
|
string attribute_name = 3;
|
|
// NOT the empty-string-means-null convention: "wait for this attribute to
|
|
// become the empty string" is a legitimate target that must stay distinct
|
|
// from "no target supplied", so this one nullable string rides a wrapper.
|
|
google.protobuf.StringValue target_value_encoded = 4;
|
|
google.protobuf.Duration timeout = 5;
|
|
google.protobuf.Timestamp timestamp = 6;
|
|
string parent_execution_id = 7; // empty string represents null
|
|
bool require_good_quality = 8;
|
|
}
|
|
|
|
message RouteToWaitForAttributeResponseDto {
|
|
string correlation_id = 1;
|
|
bool matched = 2;
|
|
LooseValue value = 3; // absent => null
|
|
string quality = 4; // empty string represents null
|
|
bool timed_out = 5;
|
|
bool success = 6;
|
|
string error_message = 7; // empty string represents null
|
|
google.protobuf.Timestamp timestamp = 8;
|
|
}
|
|
|
|
message RouteRequest {
|
|
oneof command {
|
|
RouteToCallRequestDto route_to_call = 1;
|
|
RouteToGetAttributesRequestDto route_to_get_attributes = 2;
|
|
RouteToSetAttributesRequestDto route_to_set_attributes = 3;
|
|
RouteToWaitForAttributeRequestDto route_to_wait_for_attribute = 4;
|
|
}
|
|
}
|
|
|
|
message RouteReply {
|
|
oneof reply {
|
|
RouteToCallResponseDto route_to_call = 1;
|
|
RouteToGetAttributesResponseDto route_to_get_attributes = 2;
|
|
RouteToSetAttributesResponseDto route_to_set_attributes = 3;
|
|
RouteToWaitForAttributeResponseDto route_to_wait_for_attribute = 4;
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// RPC 6 — TriggerFailover
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
message TriggerSiteFailoverDto {
|
|
string correlation_id = 1;
|
|
string site_id = 2;
|
|
}
|
|
|
|
message SiteFailoverAckDto {
|
|
string correlation_id = 1;
|
|
bool accepted = 2;
|
|
string target_address = 3; // empty string represents null
|
|
string error_message = 4; // empty string represents null
|
|
}
|