syntax = "proto3"; option csharp_namespace = "ScadaLink.Communication.Grpc"; package sitestream; import "google/protobuf/timestamp.proto"; import "google/protobuf/wrappers.proto"; // Int32Value service SiteStreamService { rpc SubscribeInstance(InstanceStreamRequest) returns (stream SiteStreamEvent); rpc IngestAuditEvents(AuditEventBatch) returns (IngestAck); rpc IngestCachedTelemetry(CachedTelemetryBatch) returns (IngestAck); rpc PullAuditEvents(PullAuditEventsRequest) returns (PullAuditEventsResponse); } message InstanceStreamRequest { string correlation_id = 1; string instance_unique_name = 2; } message SiteStreamEvent { string correlation_id = 1; oneof event { AttributeValueUpdate attribute_changed = 2; AlarmStateUpdate alarm_changed = 3; } } enum Quality { QUALITY_UNSPECIFIED = 0; QUALITY_GOOD = 1; QUALITY_UNCERTAIN = 2; QUALITY_BAD = 3; } enum AlarmStateEnum { ALARM_STATE_UNSPECIFIED = 0; ALARM_STATE_NORMAL = 1; ALARM_STATE_ACTIVE = 2; } // Severity level for an active alarm. Binary trigger types (ValueMatch, // RangeViolation, RateOfChange) always emit ALARM_LEVEL_NONE. The HiLo // trigger type emits one of the directional values. enum AlarmLevelEnum { ALARM_LEVEL_NONE = 0; ALARM_LEVEL_LOW = 1; ALARM_LEVEL_LOW_LOW = 2; ALARM_LEVEL_HIGH = 3; ALARM_LEVEL_HIGH_HIGH = 4; } message AttributeValueUpdate { string instance_unique_name = 1; string attribute_path = 2; string attribute_name = 3; string value = 4; Quality quality = 5; google.protobuf.Timestamp timestamp = 6; } message AlarmStateUpdate { string instance_unique_name = 1; string alarm_name = 2; AlarmStateEnum state = 3; int32 priority = 4; google.protobuf.Timestamp timestamp = 5; AlarmLevelEnum level = 6; // ALARM_LEVEL_NONE for binary trigger types; set by HiLo. string message = 7; // Optional per-band operator message; empty when unset. } // Audit Log (#23) telemetry: single lifecycle event ferried from a site SQLite // hot-path row to central via IngestAuditEvents. Mirrors AuditEvent (Commons) // minus the site-local ForwardState and the central IngestedAtUtc (set on ingest). message AuditEventDto { string event_id = 1; google.protobuf.Timestamp occurred_at_utc = 2; string channel = 3; string kind = 4; string correlation_id = 5; // empty string represents null string source_site_id = 6; string source_instance_id = 7; string source_script = 8; string actor = 9; string target = 10; string status = 11; google.protobuf.Int32Value http_status = 12; // null when absent google.protobuf.Int32Value duration_ms = 13; string error_message = 14; string error_detail = 15; string request_summary = 16; string response_summary = 17; bool payload_truncated = 18; string extra = 19; } message AuditEventBatch { repeated AuditEventDto events = 1; } message IngestAck { repeated string accepted_event_ids = 1; } // Audit Log (#23) M3 cached-call combined telemetry: a single packet carries // both the AuditEvent row to insert and the SiteCalls operational-state upsert // for one lifecycle event of a cached outbound call. Central writes both rows // in one MS SQL transaction so the audit and operational mirrors never drift. message SiteCallOperationalDto { string tracked_operation_id = 1; // GUID string ("D" format) string channel = 2; // "ApiOutbound" | "DbOutbound" string target = 3; string source_site = 4; string status = 5; // AuditStatus name int32 retry_count = 6; string last_error = 7; // empty when null google.protobuf.Int32Value http_status = 8; google.protobuf.Timestamp created_at_utc = 9; google.protobuf.Timestamp updated_at_utc = 10; google.protobuf.Timestamp terminal_at_utc = 11; // absent when not terminal } message CachedTelemetryPacket { AuditEventDto audit_event = 1; SiteCallOperationalDto operational = 2; } message CachedTelemetryBatch { repeated CachedTelemetryPacket packets = 1; } // Audit Log (#23) M6 reconciliation pull: central→site request for any // site-local AuditLog rows with OccurredAtUtc >= since_utc that have not yet // been ingested centrally (ForwardState in {Pending, Forwarded}). The site // flips returned rows to Reconciled after the response is on the wire. // more_available signals batch_size was saturated so the caller knows to // issue a follow-up pull with an advanced since_utc cursor. message PullAuditEventsRequest { google.protobuf.Timestamp since_utc = 1; int32 batch_size = 2; } message PullAuditEventsResponse { repeated AuditEventDto events = 1; bool more_available = 2; }