diff --git a/src/ScadaLink.Communication/Protos/sitestream.proto b/src/ScadaLink.Communication/Protos/sitestream.proto
index d86459c..d01852f 100644
--- a/src/ScadaLink.Communication/Protos/sitestream.proto
+++ b/src/ScadaLink.Communication/Protos/sitestream.proto
@@ -3,9 +3,11 @@ 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);
}
message InstanceStreamRequest {
@@ -63,3 +65,31 @@ message AlarmStateUpdate {
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; }
diff --git a/src/ScadaLink.Communication/SiteStreamGrpc/Sitestream.cs b/src/ScadaLink.Communication/SiteStreamGrpc/Sitestream.cs
index b1892bc..3a843eb 100644
--- a/src/ScadaLink.Communication/SiteStreamGrpc/Sitestream.cs
+++ b/src/ScadaLink.Communication/SiteStreamGrpc/Sitestream.cs
@@ -25,40 +25,59 @@ namespace ScadaLink.Communication.Grpc {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"ChdQcm90b3Mvc2l0ZXN0cmVhbS5wcm90bxIKc2l0ZXN0cmVhbRofZ29vZ2xl",
- "L3Byb3RvYnVmL3RpbWVzdGFtcC5wcm90byJNChVJbnN0YW5jZVN0cmVhbVJl",
- "cXVlc3QSFgoOY29ycmVsYXRpb25faWQYASABKAkSHAoUaW5zdGFuY2VfdW5p",
- "cXVlX25hbWUYAiABKAkiqAEKD1NpdGVTdHJlYW1FdmVudBIWCg5jb3JyZWxh",
- "dGlvbl9pZBgBIAEoCRI9ChFhdHRyaWJ1dGVfY2hhbmdlZBgCIAEoCzIgLnNp",
- "dGVzdHJlYW0uQXR0cmlidXRlVmFsdWVVcGRhdGVIABI1Cg1hbGFybV9jaGFu",
- "Z2VkGAMgASgLMhwuc2l0ZXN0cmVhbS5BbGFybVN0YXRlVXBkYXRlSABCBwoF",
- "ZXZlbnQiyAEKFEF0dHJpYnV0ZVZhbHVlVXBkYXRlEhwKFGluc3RhbmNlX3Vu",
- "aXF1ZV9uYW1lGAEgASgJEhYKDmF0dHJpYnV0ZV9wYXRoGAIgASgJEhYKDmF0",
- "dHJpYnV0ZV9uYW1lGAMgASgJEg0KBXZhbHVlGAQgASgJEiQKB3F1YWxpdHkY",
- "BSABKA4yEy5zaXRlc3RyZWFtLlF1YWxpdHkSLQoJdGltZXN0YW1wGAYgASgL",
- "MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCLsAQoQQWxhcm1TdGF0ZVVw",
- "ZGF0ZRIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgBIAEoCRISCgphbGFybV9u",
- "YW1lGAIgASgJEikKBXN0YXRlGAMgASgOMhouc2l0ZXN0cmVhbS5BbGFybVN0",
- "YXRlRW51bRIQCghwcmlvcml0eRgEIAEoBRItCgl0aW1lc3RhbXAYBSABKAsy",
- "Gi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEikKBWxldmVsGAYgASgOMhou",
- "c2l0ZXN0cmVhbS5BbGFybUxldmVsRW51bRIPCgdtZXNzYWdlGAcgASgJKlwK",
- "B1F1YWxpdHkSFwoTUVVBTElUWV9VTlNQRUNJRklFRBAAEhAKDFFVQUxJVFlf",
- "R09PRBABEhUKEVFVQUxJVFlfVU5DRVJUQUlOEAISDwoLUVVBTElUWV9CQUQQ",
- "AypdCg5BbGFybVN0YXRlRW51bRIbChdBTEFSTV9TVEFURV9VTlNQRUNJRklF",
- "RBAAEhYKEkFMQVJNX1NUQVRFX05PUk1BTBABEhYKEkFMQVJNX1NUQVRFX0FD",
- "VElWRRACKoUBCg5BbGFybUxldmVsRW51bRIUChBBTEFSTV9MRVZFTF9OT05F",
- "EAASEwoPQUxBUk1fTEVWRUxfTE9XEAESFwoTQUxBUk1fTEVWRUxfTE9XX0xP",
- "VxACEhQKEEFMQVJNX0xFVkVMX0hJR0gQAxIZChVBTEFSTV9MRVZFTF9ISUdI",
- "X0hJR0gQBDJqChFTaXRlU3RyZWFtU2VydmljZRJVChFTdWJzY3JpYmVJbnN0",
- "YW5jZRIhLnNpdGVzdHJlYW0uSW5zdGFuY2VTdHJlYW1SZXF1ZXN0Ghsuc2l0",
- "ZXN0cmVhbS5TaXRlU3RyZWFtRXZlbnQwAUIfqgIcU2NhZGFMaW5rLkNvbW11",
- "bmljYXRpb24uR3JwY2IGcHJvdG8z"));
+ "L3Byb3RvYnVmL3RpbWVzdGFtcC5wcm90bxoeZ29vZ2xlL3Byb3RvYnVmL3dy",
+ "YXBwZXJzLnByb3RvIk0KFUluc3RhbmNlU3RyZWFtUmVxdWVzdBIWCg5jb3Jy",
+ "ZWxhdGlvbl9pZBgBIAEoCRIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgCIAEo",
+ "CSKoAQoPU2l0ZVN0cmVhbUV2ZW50EhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJ",
+ "Ej0KEWF0dHJpYnV0ZV9jaGFuZ2VkGAIgASgLMiAuc2l0ZXN0cmVhbS5BdHRy",
+ "aWJ1dGVWYWx1ZVVwZGF0ZUgAEjUKDWFsYXJtX2NoYW5nZWQYAyABKAsyHC5z",
+ "aXRlc3RyZWFtLkFsYXJtU3RhdGVVcGRhdGVIAEIHCgVldmVudCLIAQoUQXR0",
+ "cmlidXRlVmFsdWVVcGRhdGUSHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYASAB",
+ "KAkSFgoOYXR0cmlidXRlX3BhdGgYAiABKAkSFgoOYXR0cmlidXRlX25hbWUY",
+ "AyABKAkSDQoFdmFsdWUYBCABKAkSJAoHcXVhbGl0eRgFIAEoDjITLnNpdGVz",
+ "dHJlYW0uUXVhbGl0eRItCgl0aW1lc3RhbXAYBiABKAsyGi5nb29nbGUucHJv",
+ "dG9idWYuVGltZXN0YW1wIuwBChBBbGFybVN0YXRlVXBkYXRlEhwKFGluc3Rh",
+ "bmNlX3VuaXF1ZV9uYW1lGAEgASgJEhIKCmFsYXJtX25hbWUYAiABKAkSKQoF",
+ "c3RhdGUYAyABKA4yGi5zaXRlc3RyZWFtLkFsYXJtU3RhdGVFbnVtEhAKCHBy",
+ "aW9yaXR5GAQgASgFEi0KCXRpbWVzdGFtcBgFIAEoCzIaLmdvb2dsZS5wcm90",
+ "b2J1Zi5UaW1lc3RhbXASKQoFbGV2ZWwYBiABKA4yGi5zaXRlc3RyZWFtLkFs",
+ "YXJtTGV2ZWxFbnVtEg8KB21lc3NhZ2UYByABKAki9QMKDUF1ZGl0RXZlbnRE",
+ "dG8SEAoIZXZlbnRfaWQYASABKAkSMwoPb2NjdXJyZWRfYXRfdXRjGAIgASgL",
+ "MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIPCgdjaGFubmVsGAMgASgJ",
+ "EgwKBGtpbmQYBCABKAkSFgoOY29ycmVsYXRpb25faWQYBSABKAkSFgoOc291",
+ "cmNlX3NpdGVfaWQYBiABKAkSGgoSc291cmNlX2luc3RhbmNlX2lkGAcgASgJ",
+ "EhUKDXNvdXJjZV9zY3JpcHQYCCABKAkSDQoFYWN0b3IYCSABKAkSDgoGdGFy",
+ "Z2V0GAogASgJEg4KBnN0YXR1cxgLIAEoCRIwCgtodHRwX3N0YXR1cxgMIAEo",
+ "CzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlEjAKC2R1cmF0aW9uX21z",
+ "GA0gASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUSFQoNZXJyb3Jf",
+ "bWVzc2FnZRgOIAEoCRIUCgxlcnJvcl9kZXRhaWwYDyABKAkSFwoPcmVxdWVz",
+ "dF9zdW1tYXJ5GBAgASgJEhgKEHJlc3BvbnNlX3N1bW1hcnkYESABKAkSGQoR",
+ "cGF5bG9hZF90cnVuY2F0ZWQYEiABKAgSDQoFZXh0cmEYEyABKAkiPAoPQXVk",
+ "aXRFdmVudEJhdGNoEikKBmV2ZW50cxgBIAMoCzIZLnNpdGVzdHJlYW0uQXVk",
+ "aXRFdmVudER0byInCglJbmdlc3RBY2sSGgoSYWNjZXB0ZWRfZXZlbnRfaWRz",
+ "GAEgAygJKlwKB1F1YWxpdHkSFwoTUVVBTElUWV9VTlNQRUNJRklFRBAAEhAK",
+ "DFFVQUxJVFlfR09PRBABEhUKEVFVQUxJVFlfVU5DRVJUQUlOEAISDwoLUVVB",
+ "TElUWV9CQUQQAypdCg5BbGFybVN0YXRlRW51bRIbChdBTEFSTV9TVEFURV9V",
+ "TlNQRUNJRklFRBAAEhYKEkFMQVJNX1NUQVRFX05PUk1BTBABEhYKEkFMQVJN",
+ "X1NUQVRFX0FDVElWRRACKoUBCg5BbGFybUxldmVsRW51bRIUChBBTEFSTV9M",
+ "RVZFTF9OT05FEAASEwoPQUxBUk1fTEVWRUxfTE9XEAESFwoTQUxBUk1fTEVW",
+ "RUxfTE9XX0xPVxACEhQKEEFMQVJNX0xFVkVMX0hJR0gQAxIZChVBTEFSTV9M",
+ "RVZFTF9ISUdIX0hJR0gQBDKzAQoRU2l0ZVN0cmVhbVNlcnZpY2USVQoRU3Vi",
+ "c2NyaWJlSW5zdGFuY2USIS5zaXRlc3RyZWFtLkluc3RhbmNlU3RyZWFtUmVx",
+ "dWVzdBobLnNpdGVzdHJlYW0uU2l0ZVN0cmVhbUV2ZW50MAESRwoRSW5nZXN0",
+ "QXVkaXRFdmVudHMSGy5zaXRlc3RyZWFtLkF1ZGl0RXZlbnRCYXRjaBoVLnNp",
+ "dGVzdHJlYW0uSW5nZXN0QWNrQh+qAhxTY2FkYUxpbmsuQ29tbXVuaWNhdGlv",
+ "bi5HcnBjYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
- new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, },
+ new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ScadaLink.Communication.Grpc.Quality), typeof(global::ScadaLink.Communication.Grpc.AlarmStateEnum), typeof(global::ScadaLink.Communication.Grpc.AlarmLevelEnum), }, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::ScadaLink.Communication.Grpc.InstanceStreamRequest), global::ScadaLink.Communication.Grpc.InstanceStreamRequest.Parser, new[]{ "CorrelationId", "InstanceUniqueName" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::ScadaLink.Communication.Grpc.SiteStreamEvent), global::ScadaLink.Communication.Grpc.SiteStreamEvent.Parser, new[]{ "CorrelationId", "AttributeChanged", "AlarmChanged" }, new[]{ "Event" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::ScadaLink.Communication.Grpc.AttributeValueUpdate), global::ScadaLink.Communication.Grpc.AttributeValueUpdate.Parser, new[]{ "InstanceUniqueName", "AttributePath", "AttributeName", "Value", "Quality", "Timestamp" }, null, null, null, null),
- new pbr::GeneratedClrTypeInfo(typeof(global::ScadaLink.Communication.Grpc.AlarmStateUpdate), global::ScadaLink.Communication.Grpc.AlarmStateUpdate.Parser, new[]{ "InstanceUniqueName", "AlarmName", "State", "Priority", "Timestamp", "Level", "Message" }, null, null, null, null)
+ new pbr::GeneratedClrTypeInfo(typeof(global::ScadaLink.Communication.Grpc.AlarmStateUpdate), global::ScadaLink.Communication.Grpc.AlarmStateUpdate.Parser, new[]{ "InstanceUniqueName", "AlarmName", "State", "Priority", "Timestamp", "Level", "Message" }, null, null, null, null),
+ new pbr::GeneratedClrTypeInfo(typeof(global::ScadaLink.Communication.Grpc.AuditEventDto), global::ScadaLink.Communication.Grpc.AuditEventDto.Parser, new[]{ "EventId", "OccurredAtUtc", "Channel", "Kind", "CorrelationId", "SourceSiteId", "SourceInstanceId", "SourceScript", "Actor", "Target", "Status", "HttpStatus", "DurationMs", "ErrorMessage", "ErrorDetail", "RequestSummary", "ResponseSummary", "PayloadTruncated", "Extra" }, null, null, null, null),
+ new pbr::GeneratedClrTypeInfo(typeof(global::ScadaLink.Communication.Grpc.AuditEventBatch), global::ScadaLink.Communication.Grpc.AuditEventBatch.Parser, new[]{ "Events" }, null, null, null, null),
+ new pbr::GeneratedClrTypeInfo(typeof(global::ScadaLink.Communication.Grpc.IngestAck), global::ScadaLink.Communication.Grpc.IngestAck.Parser, new[]{ "AcceptedEventIds" }, null, null, null, null)
}));
}
#endregion
@@ -1487,6 +1506,1280 @@ namespace ScadaLink.Communication.Grpc {
}
+ ///
+ /// 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).
+ ///
+ [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
+ public sealed partial class AuditEventDto : pb::IMessage
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ , pb::IBufferMessage
+ #endif
+ {
+ private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AuditEventDto());
+ private pb::UnknownFieldSet _unknownFields;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public static pb::MessageParser Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::ScadaLink.Communication.Grpc.SitestreamReflection.Descriptor.MessageTypes[4]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public AuditEventDto() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public AuditEventDto(AuditEventDto other) : this() {
+ eventId_ = other.eventId_;
+ occurredAtUtc_ = other.occurredAtUtc_ != null ? other.occurredAtUtc_.Clone() : null;
+ channel_ = other.channel_;
+ kind_ = other.kind_;
+ correlationId_ = other.correlationId_;
+ sourceSiteId_ = other.sourceSiteId_;
+ sourceInstanceId_ = other.sourceInstanceId_;
+ sourceScript_ = other.sourceScript_;
+ actor_ = other.actor_;
+ target_ = other.target_;
+ status_ = other.status_;
+ HttpStatus = other.HttpStatus;
+ DurationMs = other.DurationMs;
+ errorMessage_ = other.errorMessage_;
+ errorDetail_ = other.errorDetail_;
+ requestSummary_ = other.requestSummary_;
+ responseSummary_ = other.responseSummary_;
+ payloadTruncated_ = other.payloadTruncated_;
+ extra_ = other.extra_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public AuditEventDto Clone() {
+ return new AuditEventDto(this);
+ }
+
+ /// Field number for the "event_id" field.
+ public const int EventIdFieldNumber = 1;
+ private string eventId_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string EventId {
+ get { return eventId_; }
+ set {
+ eventId_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "occurred_at_utc" field.
+ public const int OccurredAtUtcFieldNumber = 2;
+ private global::Google.Protobuf.WellKnownTypes.Timestamp occurredAtUtc_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public global::Google.Protobuf.WellKnownTypes.Timestamp OccurredAtUtc {
+ get { return occurredAtUtc_; }
+ set {
+ occurredAtUtc_ = value;
+ }
+ }
+
+ /// Field number for the "channel" field.
+ public const int ChannelFieldNumber = 3;
+ private string channel_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string Channel {
+ get { return channel_; }
+ set {
+ channel_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "kind" field.
+ public const int KindFieldNumber = 4;
+ private string kind_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string Kind {
+ get { return kind_; }
+ set {
+ kind_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "correlation_id" field.
+ public const int CorrelationIdFieldNumber = 5;
+ private string correlationId_ = "";
+ ///
+ /// empty string represents null
+ ///
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string CorrelationId {
+ get { return correlationId_; }
+ set {
+ correlationId_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "source_site_id" field.
+ public const int SourceSiteIdFieldNumber = 6;
+ private string sourceSiteId_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string SourceSiteId {
+ get { return sourceSiteId_; }
+ set {
+ sourceSiteId_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "source_instance_id" field.
+ public const int SourceInstanceIdFieldNumber = 7;
+ private string sourceInstanceId_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string SourceInstanceId {
+ get { return sourceInstanceId_; }
+ set {
+ sourceInstanceId_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "source_script" field.
+ public const int SourceScriptFieldNumber = 8;
+ private string sourceScript_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string SourceScript {
+ get { return sourceScript_; }
+ set {
+ sourceScript_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "actor" field.
+ public const int ActorFieldNumber = 9;
+ private string actor_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string Actor {
+ get { return actor_; }
+ set {
+ actor_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "target" field.
+ public const int TargetFieldNumber = 10;
+ private string target_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string Target {
+ get { return target_; }
+ set {
+ target_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "status" field.
+ public const int StatusFieldNumber = 11;
+ private string status_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string Status {
+ get { return status_; }
+ set {
+ status_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "http_status" field.
+ public const int HttpStatusFieldNumber = 12;
+ private static readonly pb::FieldCodec _single_httpStatus_codec = pb::FieldCodec.ForStructWrapper(98);
+ private int? httpStatus_;
+ ///
+ /// null when absent
+ ///
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public int? HttpStatus {
+ get { return httpStatus_; }
+ set {
+ httpStatus_ = value;
+ }
+ }
+
+
+ /// Field number for the "duration_ms" field.
+ public const int DurationMsFieldNumber = 13;
+ private static readonly pb::FieldCodec _single_durationMs_codec = pb::FieldCodec.ForStructWrapper(106);
+ private int? durationMs_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public int? DurationMs {
+ get { return durationMs_; }
+ set {
+ durationMs_ = value;
+ }
+ }
+
+
+ /// Field number for the "error_message" field.
+ public const int ErrorMessageFieldNumber = 14;
+ private string errorMessage_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string ErrorMessage {
+ get { return errorMessage_; }
+ set {
+ errorMessage_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "error_detail" field.
+ public const int ErrorDetailFieldNumber = 15;
+ private string errorDetail_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string ErrorDetail {
+ get { return errorDetail_; }
+ set {
+ errorDetail_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "request_summary" field.
+ public const int RequestSummaryFieldNumber = 16;
+ private string requestSummary_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string RequestSummary {
+ get { return requestSummary_; }
+ set {
+ requestSummary_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "response_summary" field.
+ public const int ResponseSummaryFieldNumber = 17;
+ private string responseSummary_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string ResponseSummary {
+ get { return responseSummary_; }
+ set {
+ responseSummary_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "payload_truncated" field.
+ public const int PayloadTruncatedFieldNumber = 18;
+ private bool payloadTruncated_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool PayloadTruncated {
+ get { return payloadTruncated_; }
+ set {
+ payloadTruncated_ = value;
+ }
+ }
+
+ /// Field number for the "extra" field.
+ public const int ExtraFieldNumber = 19;
+ private string extra_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string Extra {
+ get { return extra_; }
+ set {
+ extra_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override bool Equals(object other) {
+ return Equals(other as AuditEventDto);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool Equals(AuditEventDto other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (EventId != other.EventId) return false;
+ if (!object.Equals(OccurredAtUtc, other.OccurredAtUtc)) return false;
+ if (Channel != other.Channel) return false;
+ if (Kind != other.Kind) return false;
+ if (CorrelationId != other.CorrelationId) return false;
+ if (SourceSiteId != other.SourceSiteId) return false;
+ if (SourceInstanceId != other.SourceInstanceId) return false;
+ if (SourceScript != other.SourceScript) return false;
+ if (Actor != other.Actor) return false;
+ if (Target != other.Target) return false;
+ if (Status != other.Status) return false;
+ if (HttpStatus != other.HttpStatus) return false;
+ if (DurationMs != other.DurationMs) return false;
+ if (ErrorMessage != other.ErrorMessage) return false;
+ if (ErrorDetail != other.ErrorDetail) return false;
+ if (RequestSummary != other.RequestSummary) return false;
+ if (ResponseSummary != other.ResponseSummary) return false;
+ if (PayloadTruncated != other.PayloadTruncated) return false;
+ if (Extra != other.Extra) return false;
+ return Equals(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (EventId.Length != 0) hash ^= EventId.GetHashCode();
+ if (occurredAtUtc_ != null) hash ^= OccurredAtUtc.GetHashCode();
+ if (Channel.Length != 0) hash ^= Channel.GetHashCode();
+ if (Kind.Length != 0) hash ^= Kind.GetHashCode();
+ if (CorrelationId.Length != 0) hash ^= CorrelationId.GetHashCode();
+ if (SourceSiteId.Length != 0) hash ^= SourceSiteId.GetHashCode();
+ if (SourceInstanceId.Length != 0) hash ^= SourceInstanceId.GetHashCode();
+ if (SourceScript.Length != 0) hash ^= SourceScript.GetHashCode();
+ if (Actor.Length != 0) hash ^= Actor.GetHashCode();
+ if (Target.Length != 0) hash ^= Target.GetHashCode();
+ if (Status.Length != 0) hash ^= Status.GetHashCode();
+ if (httpStatus_ != null) hash ^= HttpStatus.GetHashCode();
+ if (durationMs_ != null) hash ^= DurationMs.GetHashCode();
+ if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode();
+ if (ErrorDetail.Length != 0) hash ^= ErrorDetail.GetHashCode();
+ if (RequestSummary.Length != 0) hash ^= RequestSummary.GetHashCode();
+ if (ResponseSummary.Length != 0) hash ^= ResponseSummary.GetHashCode();
+ if (PayloadTruncated != false) hash ^= PayloadTruncated.GetHashCode();
+ if (Extra.Length != 0) hash ^= Extra.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void WriteTo(pb::CodedOutputStream output) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ output.WriteRawMessage(this);
+ #else
+ if (EventId.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(EventId);
+ }
+ if (occurredAtUtc_ != null) {
+ output.WriteRawTag(18);
+ output.WriteMessage(OccurredAtUtc);
+ }
+ if (Channel.Length != 0) {
+ output.WriteRawTag(26);
+ output.WriteString(Channel);
+ }
+ if (Kind.Length != 0) {
+ output.WriteRawTag(34);
+ output.WriteString(Kind);
+ }
+ if (CorrelationId.Length != 0) {
+ output.WriteRawTag(42);
+ output.WriteString(CorrelationId);
+ }
+ if (SourceSiteId.Length != 0) {
+ output.WriteRawTag(50);
+ output.WriteString(SourceSiteId);
+ }
+ if (SourceInstanceId.Length != 0) {
+ output.WriteRawTag(58);
+ output.WriteString(SourceInstanceId);
+ }
+ if (SourceScript.Length != 0) {
+ output.WriteRawTag(66);
+ output.WriteString(SourceScript);
+ }
+ if (Actor.Length != 0) {
+ output.WriteRawTag(74);
+ output.WriteString(Actor);
+ }
+ if (Target.Length != 0) {
+ output.WriteRawTag(82);
+ output.WriteString(Target);
+ }
+ if (Status.Length != 0) {
+ output.WriteRawTag(90);
+ output.WriteString(Status);
+ }
+ if (httpStatus_ != null) {
+ _single_httpStatus_codec.WriteTagAndValue(output, HttpStatus);
+ }
+ if (durationMs_ != null) {
+ _single_durationMs_codec.WriteTagAndValue(output, DurationMs);
+ }
+ if (ErrorMessage.Length != 0) {
+ output.WriteRawTag(114);
+ output.WriteString(ErrorMessage);
+ }
+ if (ErrorDetail.Length != 0) {
+ output.WriteRawTag(122);
+ output.WriteString(ErrorDetail);
+ }
+ if (RequestSummary.Length != 0) {
+ output.WriteRawTag(130, 1);
+ output.WriteString(RequestSummary);
+ }
+ if (ResponseSummary.Length != 0) {
+ output.WriteRawTag(138, 1);
+ output.WriteString(ResponseSummary);
+ }
+ if (PayloadTruncated != false) {
+ output.WriteRawTag(144, 1);
+ output.WriteBool(PayloadTruncated);
+ }
+ if (Extra.Length != 0) {
+ output.WriteRawTag(154, 1);
+ output.WriteString(Extra);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+ if (EventId.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(EventId);
+ }
+ if (occurredAtUtc_ != null) {
+ output.WriteRawTag(18);
+ output.WriteMessage(OccurredAtUtc);
+ }
+ if (Channel.Length != 0) {
+ output.WriteRawTag(26);
+ output.WriteString(Channel);
+ }
+ if (Kind.Length != 0) {
+ output.WriteRawTag(34);
+ output.WriteString(Kind);
+ }
+ if (CorrelationId.Length != 0) {
+ output.WriteRawTag(42);
+ output.WriteString(CorrelationId);
+ }
+ if (SourceSiteId.Length != 0) {
+ output.WriteRawTag(50);
+ output.WriteString(SourceSiteId);
+ }
+ if (SourceInstanceId.Length != 0) {
+ output.WriteRawTag(58);
+ output.WriteString(SourceInstanceId);
+ }
+ if (SourceScript.Length != 0) {
+ output.WriteRawTag(66);
+ output.WriteString(SourceScript);
+ }
+ if (Actor.Length != 0) {
+ output.WriteRawTag(74);
+ output.WriteString(Actor);
+ }
+ if (Target.Length != 0) {
+ output.WriteRawTag(82);
+ output.WriteString(Target);
+ }
+ if (Status.Length != 0) {
+ output.WriteRawTag(90);
+ output.WriteString(Status);
+ }
+ if (httpStatus_ != null) {
+ _single_httpStatus_codec.WriteTagAndValue(ref output, HttpStatus);
+ }
+ if (durationMs_ != null) {
+ _single_durationMs_codec.WriteTagAndValue(ref output, DurationMs);
+ }
+ if (ErrorMessage.Length != 0) {
+ output.WriteRawTag(114);
+ output.WriteString(ErrorMessage);
+ }
+ if (ErrorDetail.Length != 0) {
+ output.WriteRawTag(122);
+ output.WriteString(ErrorDetail);
+ }
+ if (RequestSummary.Length != 0) {
+ output.WriteRawTag(130, 1);
+ output.WriteString(RequestSummary);
+ }
+ if (ResponseSummary.Length != 0) {
+ output.WriteRawTag(138, 1);
+ output.WriteString(ResponseSummary);
+ }
+ if (PayloadTruncated != false) {
+ output.WriteRawTag(144, 1);
+ output.WriteBool(PayloadTruncated);
+ }
+ if (Extra.Length != 0) {
+ output.WriteRawTag(154, 1);
+ output.WriteString(Extra);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(ref output);
+ }
+ }
+ #endif
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public int CalculateSize() {
+ int size = 0;
+ if (EventId.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(EventId);
+ }
+ if (occurredAtUtc_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(OccurredAtUtc);
+ }
+ if (Channel.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Channel);
+ }
+ if (Kind.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Kind);
+ }
+ if (CorrelationId.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(CorrelationId);
+ }
+ if (SourceSiteId.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(SourceSiteId);
+ }
+ if (SourceInstanceId.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(SourceInstanceId);
+ }
+ if (SourceScript.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(SourceScript);
+ }
+ if (Actor.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Actor);
+ }
+ if (Target.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Target);
+ }
+ if (Status.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Status);
+ }
+ if (httpStatus_ != null) {
+ size += _single_httpStatus_codec.CalculateSizeWithTag(HttpStatus);
+ }
+ if (durationMs_ != null) {
+ size += _single_durationMs_codec.CalculateSizeWithTag(DurationMs);
+ }
+ if (ErrorMessage.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(ErrorMessage);
+ }
+ if (ErrorDetail.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(ErrorDetail);
+ }
+ if (RequestSummary.Length != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeStringSize(RequestSummary);
+ }
+ if (ResponseSummary.Length != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeStringSize(ResponseSummary);
+ }
+ if (PayloadTruncated != false) {
+ size += 2 + 1;
+ }
+ if (Extra.Length != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeStringSize(Extra);
+ }
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void MergeFrom(AuditEventDto other) {
+ if (other == null) {
+ return;
+ }
+ if (other.EventId.Length != 0) {
+ EventId = other.EventId;
+ }
+ if (other.occurredAtUtc_ != null) {
+ if (occurredAtUtc_ == null) {
+ OccurredAtUtc = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+ }
+ OccurredAtUtc.MergeFrom(other.OccurredAtUtc);
+ }
+ if (other.Channel.Length != 0) {
+ Channel = other.Channel;
+ }
+ if (other.Kind.Length != 0) {
+ Kind = other.Kind;
+ }
+ if (other.CorrelationId.Length != 0) {
+ CorrelationId = other.CorrelationId;
+ }
+ if (other.SourceSiteId.Length != 0) {
+ SourceSiteId = other.SourceSiteId;
+ }
+ if (other.SourceInstanceId.Length != 0) {
+ SourceInstanceId = other.SourceInstanceId;
+ }
+ if (other.SourceScript.Length != 0) {
+ SourceScript = other.SourceScript;
+ }
+ if (other.Actor.Length != 0) {
+ Actor = other.Actor;
+ }
+ if (other.Target.Length != 0) {
+ Target = other.Target;
+ }
+ if (other.Status.Length != 0) {
+ Status = other.Status;
+ }
+ if (other.httpStatus_ != null) {
+ if (httpStatus_ == null || other.HttpStatus != 0) {
+ HttpStatus = other.HttpStatus;
+ }
+ }
+ if (other.durationMs_ != null) {
+ if (durationMs_ == null || other.DurationMs != 0) {
+ DurationMs = other.DurationMs;
+ }
+ }
+ if (other.ErrorMessage.Length != 0) {
+ ErrorMessage = other.ErrorMessage;
+ }
+ if (other.ErrorDetail.Length != 0) {
+ ErrorDetail = other.ErrorDetail;
+ }
+ if (other.RequestSummary.Length != 0) {
+ RequestSummary = other.RequestSummary;
+ }
+ if (other.ResponseSummary.Length != 0) {
+ ResponseSummary = other.ResponseSummary;
+ }
+ if (other.PayloadTruncated != false) {
+ PayloadTruncated = other.PayloadTruncated;
+ }
+ if (other.Extra.Length != 0) {
+ Extra = other.Extra;
+ }
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void MergeFrom(pb::CodedInputStream input) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ input.ReadRawMessage(this);
+ #else
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ if ((tag & 7) == 4) {
+ // Abort on any end group tag.
+ return;
+ }
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+ break;
+ case 10: {
+ EventId = input.ReadString();
+ break;
+ }
+ case 18: {
+ if (occurredAtUtc_ == null) {
+ OccurredAtUtc = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+ }
+ input.ReadMessage(OccurredAtUtc);
+ break;
+ }
+ case 26: {
+ Channel = input.ReadString();
+ break;
+ }
+ case 34: {
+ Kind = input.ReadString();
+ break;
+ }
+ case 42: {
+ CorrelationId = input.ReadString();
+ break;
+ }
+ case 50: {
+ SourceSiteId = input.ReadString();
+ break;
+ }
+ case 58: {
+ SourceInstanceId = input.ReadString();
+ break;
+ }
+ case 66: {
+ SourceScript = input.ReadString();
+ break;
+ }
+ case 74: {
+ Actor = input.ReadString();
+ break;
+ }
+ case 82: {
+ Target = input.ReadString();
+ break;
+ }
+ case 90: {
+ Status = input.ReadString();
+ break;
+ }
+ case 98: {
+ int? value = _single_httpStatus_codec.Read(input);
+ if (httpStatus_ == null || value != 0) {
+ HttpStatus = value;
+ }
+ break;
+ }
+ case 106: {
+ int? value = _single_durationMs_codec.Read(input);
+ if (durationMs_ == null || value != 0) {
+ DurationMs = value;
+ }
+ break;
+ }
+ case 114: {
+ ErrorMessage = input.ReadString();
+ break;
+ }
+ case 122: {
+ ErrorDetail = input.ReadString();
+ break;
+ }
+ case 130: {
+ RequestSummary = input.ReadString();
+ break;
+ }
+ case 138: {
+ ResponseSummary = input.ReadString();
+ break;
+ }
+ case 144: {
+ PayloadTruncated = input.ReadBool();
+ break;
+ }
+ case 154: {
+ Extra = input.ReadString();
+ break;
+ }
+ }
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ if ((tag & 7) == 4) {
+ // Abort on any end group tag.
+ return;
+ }
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+ break;
+ case 10: {
+ EventId = input.ReadString();
+ break;
+ }
+ case 18: {
+ if (occurredAtUtc_ == null) {
+ OccurredAtUtc = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+ }
+ input.ReadMessage(OccurredAtUtc);
+ break;
+ }
+ case 26: {
+ Channel = input.ReadString();
+ break;
+ }
+ case 34: {
+ Kind = input.ReadString();
+ break;
+ }
+ case 42: {
+ CorrelationId = input.ReadString();
+ break;
+ }
+ case 50: {
+ SourceSiteId = input.ReadString();
+ break;
+ }
+ case 58: {
+ SourceInstanceId = input.ReadString();
+ break;
+ }
+ case 66: {
+ SourceScript = input.ReadString();
+ break;
+ }
+ case 74: {
+ Actor = input.ReadString();
+ break;
+ }
+ case 82: {
+ Target = input.ReadString();
+ break;
+ }
+ case 90: {
+ Status = input.ReadString();
+ break;
+ }
+ case 98: {
+ int? value = _single_httpStatus_codec.Read(ref input);
+ if (httpStatus_ == null || value != 0) {
+ HttpStatus = value;
+ }
+ break;
+ }
+ case 106: {
+ int? value = _single_durationMs_codec.Read(ref input);
+ if (durationMs_ == null || value != 0) {
+ DurationMs = value;
+ }
+ break;
+ }
+ case 114: {
+ ErrorMessage = input.ReadString();
+ break;
+ }
+ case 122: {
+ ErrorDetail = input.ReadString();
+ break;
+ }
+ case 130: {
+ RequestSummary = input.ReadString();
+ break;
+ }
+ case 138: {
+ ResponseSummary = input.ReadString();
+ break;
+ }
+ case 144: {
+ PayloadTruncated = input.ReadBool();
+ break;
+ }
+ case 154: {
+ Extra = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+ #endif
+
+ }
+
+ [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
+ public sealed partial class AuditEventBatch : pb::IMessage
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ , pb::IBufferMessage
+ #endif
+ {
+ private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AuditEventBatch());
+ private pb::UnknownFieldSet _unknownFields;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public static pb::MessageParser Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::ScadaLink.Communication.Grpc.SitestreamReflection.Descriptor.MessageTypes[5]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public AuditEventBatch() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public AuditEventBatch(AuditEventBatch other) : this() {
+ events_ = other.events_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public AuditEventBatch Clone() {
+ return new AuditEventBatch(this);
+ }
+
+ /// Field number for the "events" field.
+ public const int EventsFieldNumber = 1;
+ private static readonly pb::FieldCodec _repeated_events_codec
+ = pb::FieldCodec.ForMessage(10, global::ScadaLink.Communication.Grpc.AuditEventDto.Parser);
+ private readonly pbc::RepeatedField events_ = new pbc::RepeatedField();
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public pbc::RepeatedField Events {
+ get { return events_; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override bool Equals(object other) {
+ return Equals(other as AuditEventBatch);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool Equals(AuditEventBatch other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if(!events_.Equals(other.events_)) return false;
+ return Equals(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override int GetHashCode() {
+ int hash = 1;
+ hash ^= events_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void WriteTo(pb::CodedOutputStream output) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ output.WriteRawMessage(this);
+ #else
+ events_.WriteTo(output, _repeated_events_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+ events_.WriteTo(ref output, _repeated_events_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(ref output);
+ }
+ }
+ #endif
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public int CalculateSize() {
+ int size = 0;
+ size += events_.CalculateSize(_repeated_events_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void MergeFrom(AuditEventBatch other) {
+ if (other == null) {
+ return;
+ }
+ events_.Add(other.events_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void MergeFrom(pb::CodedInputStream input) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ input.ReadRawMessage(this);
+ #else
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ if ((tag & 7) == 4) {
+ // Abort on any end group tag.
+ return;
+ }
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+ break;
+ case 10: {
+ events_.AddEntriesFrom(input, _repeated_events_codec);
+ break;
+ }
+ }
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ if ((tag & 7) == 4) {
+ // Abort on any end group tag.
+ return;
+ }
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+ break;
+ case 10: {
+ events_.AddEntriesFrom(ref input, _repeated_events_codec);
+ break;
+ }
+ }
+ }
+ }
+ #endif
+
+ }
+
+ [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
+ public sealed partial class IngestAck : pb::IMessage
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ , pb::IBufferMessage
+ #endif
+ {
+ private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new IngestAck());
+ private pb::UnknownFieldSet _unknownFields;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public static pb::MessageParser Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::ScadaLink.Communication.Grpc.SitestreamReflection.Descriptor.MessageTypes[6]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public IngestAck() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public IngestAck(IngestAck other) : this() {
+ acceptedEventIds_ = other.acceptedEventIds_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public IngestAck Clone() {
+ return new IngestAck(this);
+ }
+
+ /// Field number for the "accepted_event_ids" field.
+ public const int AcceptedEventIdsFieldNumber = 1;
+ private static readonly pb::FieldCodec _repeated_acceptedEventIds_codec
+ = pb::FieldCodec.ForString(10);
+ private readonly pbc::RepeatedField acceptedEventIds_ = new pbc::RepeatedField();
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public pbc::RepeatedField AcceptedEventIds {
+ get { return acceptedEventIds_; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override bool Equals(object other) {
+ return Equals(other as IngestAck);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool Equals(IngestAck other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if(!acceptedEventIds_.Equals(other.acceptedEventIds_)) return false;
+ return Equals(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override int GetHashCode() {
+ int hash = 1;
+ hash ^= acceptedEventIds_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void WriteTo(pb::CodedOutputStream output) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ output.WriteRawMessage(this);
+ #else
+ acceptedEventIds_.WriteTo(output, _repeated_acceptedEventIds_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+ acceptedEventIds_.WriteTo(ref output, _repeated_acceptedEventIds_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(ref output);
+ }
+ }
+ #endif
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public int CalculateSize() {
+ int size = 0;
+ size += acceptedEventIds_.CalculateSize(_repeated_acceptedEventIds_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void MergeFrom(IngestAck other) {
+ if (other == null) {
+ return;
+ }
+ acceptedEventIds_.Add(other.acceptedEventIds_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void MergeFrom(pb::CodedInputStream input) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ input.ReadRawMessage(this);
+ #else
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ if ((tag & 7) == 4) {
+ // Abort on any end group tag.
+ return;
+ }
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+ break;
+ case 10: {
+ acceptedEventIds_.AddEntriesFrom(input, _repeated_acceptedEventIds_codec);
+ break;
+ }
+ }
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ if ((tag & 7) == 4) {
+ // Abort on any end group tag.
+ return;
+ }
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+ break;
+ case 10: {
+ acceptedEventIds_.AddEntriesFrom(ref input, _repeated_acceptedEventIds_codec);
+ break;
+ }
+ }
+ }
+ }
+ #endif
+
+ }
+
#endregion
}
diff --git a/src/ScadaLink.Communication/SiteStreamGrpc/SitestreamGrpc.cs b/src/ScadaLink.Communication/SiteStreamGrpc/SitestreamGrpc.cs
index 6aa6ecb..0a900cb 100644
--- a/src/ScadaLink.Communication/SiteStreamGrpc/SitestreamGrpc.cs
+++ b/src/ScadaLink.Communication/SiteStreamGrpc/SitestreamGrpc.cs
@@ -49,6 +49,10 @@ namespace ScadaLink.Communication.Grpc {
static readonly grpc::Marshaller __Marshaller_sitestream_InstanceStreamRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::ScadaLink.Communication.Grpc.InstanceStreamRequest.Parser));
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
static readonly grpc::Marshaller __Marshaller_sitestream_SiteStreamEvent = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::ScadaLink.Communication.Grpc.SiteStreamEvent.Parser));
+ [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+ static readonly grpc::Marshaller __Marshaller_sitestream_AuditEventBatch = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::ScadaLink.Communication.Grpc.AuditEventBatch.Parser));
+ [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+ static readonly grpc::Marshaller __Marshaller_sitestream_IngestAck = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::ScadaLink.Communication.Grpc.IngestAck.Parser));
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
static readonly grpc::Method __Method_SubscribeInstance = new grpc::Method(
@@ -58,6 +62,14 @@ namespace ScadaLink.Communication.Grpc {
__Marshaller_sitestream_InstanceStreamRequest,
__Marshaller_sitestream_SiteStreamEvent);
+ [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+ static readonly grpc::Method __Method_IngestAuditEvents = new grpc::Method(
+ grpc::MethodType.Unary,
+ __ServiceName,
+ "IngestAuditEvents",
+ __Marshaller_sitestream_AuditEventBatch,
+ __Marshaller_sitestream_IngestAck);
+
/// Service descriptor
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
@@ -74,6 +86,12 @@ namespace ScadaLink.Communication.Grpc {
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
+ [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+ public virtual global::System.Threading.Tasks.Task IngestAuditEvents(global::ScadaLink.Communication.Grpc.AuditEventBatch request, grpc::ServerCallContext context)
+ {
+ throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+ }
+
}
/// Client for SiteStreamService
@@ -113,6 +131,26 @@ namespace ScadaLink.Communication.Grpc {
{
return CallInvoker.AsyncServerStreamingCall(__Method_SubscribeInstance, null, options, request);
}
+ [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+ public virtual global::ScadaLink.Communication.Grpc.IngestAck IngestAuditEvents(global::ScadaLink.Communication.Grpc.AuditEventBatch request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+ {
+ return IngestAuditEvents(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+ }
+ [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+ public virtual global::ScadaLink.Communication.Grpc.IngestAck IngestAuditEvents(global::ScadaLink.Communication.Grpc.AuditEventBatch request, grpc::CallOptions options)
+ {
+ return CallInvoker.BlockingUnaryCall(__Method_IngestAuditEvents, null, options, request);
+ }
+ [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+ public virtual grpc::AsyncUnaryCall IngestAuditEventsAsync(global::ScadaLink.Communication.Grpc.AuditEventBatch request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+ {
+ return IngestAuditEventsAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+ }
+ [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
+ public virtual grpc::AsyncUnaryCall IngestAuditEventsAsync(global::ScadaLink.Communication.Grpc.AuditEventBatch request, grpc::CallOptions options)
+ {
+ return CallInvoker.AsyncUnaryCall(__Method_IngestAuditEvents, null, options, request);
+ }
/// Creates a new instance of client from given ClientBaseConfiguration.
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
protected override SiteStreamServiceClient NewInstance(ClientBaseConfiguration configuration)
@@ -127,7 +165,8 @@ namespace ScadaLink.Communication.Grpc {
public static grpc::ServerServiceDefinition BindService(SiteStreamServiceBase serviceImpl)
{
return grpc::ServerServiceDefinition.CreateBuilder()
- .AddMethod(__Method_SubscribeInstance, serviceImpl.SubscribeInstance).Build();
+ .AddMethod(__Method_SubscribeInstance, serviceImpl.SubscribeInstance)
+ .AddMethod(__Method_IngestAuditEvents, serviceImpl.IngestAuditEvents).Build();
}
/// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic.
@@ -138,6 +177,7 @@ namespace ScadaLink.Communication.Grpc {
public static void BindService(grpc::ServiceBinderBase serviceBinder, SiteStreamServiceBase serviceImpl)
{
serviceBinder.AddMethod(__Method_SubscribeInstance, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.SubscribeInstance));
+ serviceBinder.AddMethod(__Method_IngestAuditEvents, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.IngestAuditEvents));
}
}
diff --git a/tests/ScadaLink.Communication.Tests/Protos/AuditEventProtoTests.cs b/tests/ScadaLink.Communication.Tests/Protos/AuditEventProtoTests.cs
new file mode 100644
index 0000000..4cd0d48
--- /dev/null
+++ b/tests/ScadaLink.Communication.Tests/Protos/AuditEventProtoTests.cs
@@ -0,0 +1,123 @@
+using Google.Protobuf;
+using Google.Protobuf.WellKnownTypes;
+using ScadaLink.Communication.Grpc;
+
+namespace ScadaLink.Communication.Tests.Protos;
+
+///
+/// Wire-format round-trip tests for the Audit Log (#23) telemetry proto messages
+/// (, , ).
+/// Locks the additive contract the site → central audit pipeline depends on.
+///
+public class AuditEventProtoTests
+{
+ [Fact]
+ public void AuditEventDto_RoundTrip_PreservesAllFields()
+ {
+ var occurredAt = Timestamp.FromDateTimeOffset(
+ new DateTimeOffset(2026, 5, 20, 10, 15, 30, 123, TimeSpan.Zero));
+
+ var original = new AuditEventDto
+ {
+ EventId = Guid.NewGuid().ToString(),
+ OccurredAtUtc = occurredAt,
+ Channel = "ApiOutbound",
+ Kind = "ApiCall",
+ CorrelationId = Guid.NewGuid().ToString(),
+ SourceSiteId = "site-1",
+ SourceInstanceId = "Pump01",
+ SourceScript = "OnDemand",
+ Actor = "design-key",
+ Target = "weather-api",
+ Status = "Delivered",
+ HttpStatus = 200,
+ DurationMs = 42,
+ ErrorMessage = "no error",
+ ErrorDetail = "stack",
+ RequestSummary = "GET /weather?city=brisbane",
+ ResponseSummary = "{ \"temp\": 22.5 }",
+ PayloadTruncated = true,
+ Extra = "{ \"retryCount\": 0 }"
+ };
+
+ var bytes = original.ToByteArray();
+ var deserialized = AuditEventDto.Parser.ParseFrom(bytes);
+
+ Assert.Equal(original.EventId, deserialized.EventId);
+ Assert.Equal(original.OccurredAtUtc, deserialized.OccurredAtUtc);
+ Assert.Equal(original.Channel, deserialized.Channel);
+ Assert.Equal(original.Kind, deserialized.Kind);
+ Assert.Equal(original.CorrelationId, deserialized.CorrelationId);
+ Assert.Equal(original.SourceSiteId, deserialized.SourceSiteId);
+ Assert.Equal(original.SourceInstanceId, deserialized.SourceInstanceId);
+ Assert.Equal(original.SourceScript, deserialized.SourceScript);
+ Assert.Equal(original.Actor, deserialized.Actor);
+ Assert.Equal(original.Target, deserialized.Target);
+ Assert.Equal(original.Status, deserialized.Status);
+ Assert.Equal(original.HttpStatus, deserialized.HttpStatus);
+ Assert.Equal(original.DurationMs, deserialized.DurationMs);
+ Assert.Equal(original.ErrorMessage, deserialized.ErrorMessage);
+ Assert.Equal(original.ErrorDetail, deserialized.ErrorDetail);
+ Assert.Equal(original.RequestSummary, deserialized.RequestSummary);
+ Assert.Equal(original.ResponseSummary, deserialized.ResponseSummary);
+ Assert.Equal(original.PayloadTruncated, deserialized.PayloadTruncated);
+ Assert.Equal(original.Extra, deserialized.Extra);
+ }
+
+ [Fact]
+ public void AuditEventDto_NullableInt_AbsentByDefault_NotIncludedInWire()
+ {
+ // Int32Value fields (http_status, duration_ms) are wrapper-typed in proto;
+ // when unset, the wrapper is absent, not serialized, and deserializes back to null.
+ var original = new AuditEventDto
+ {
+ EventId = Guid.NewGuid().ToString(),
+ OccurredAtUtc = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow),
+ Channel = "Notification",
+ Kind = "NotifySend",
+ Status = "Submitted"
+ };
+
+ Assert.Null(original.HttpStatus);
+ Assert.Null(original.DurationMs);
+
+ var bytes = original.ToByteArray();
+ var deserialized = AuditEventDto.Parser.ParseFrom(bytes);
+
+ Assert.Null(deserialized.HttpStatus);
+ Assert.Null(deserialized.DurationMs);
+ }
+
+ [Fact]
+ public void AuditEventBatch_Empty_RoundTrip_Yields_EmptyEvents()
+ {
+ var original = new AuditEventBatch();
+ Assert.Empty(original.Events);
+
+ var bytes = original.ToByteArray();
+ var deserialized = AuditEventBatch.Parser.ParseFrom(bytes);
+
+ Assert.Empty(deserialized.Events);
+ }
+
+ [Fact]
+ public void IngestAck_PreservesAcceptedEventIds()
+ {
+ var id1 = Guid.NewGuid().ToString();
+ var id2 = Guid.NewGuid().ToString();
+ var id3 = Guid.NewGuid().ToString();
+
+ var original = new IngestAck();
+ original.AcceptedEventIds.Add(id1);
+ original.AcceptedEventIds.Add(id2);
+ original.AcceptedEventIds.Add(id3);
+
+ var bytes = original.ToByteArray();
+ var deserialized = IngestAck.Parser.ParseFrom(bytes);
+
+ Assert.Equal(3, deserialized.AcceptedEventIds.Count);
+ Assert.Equal(id1, deserialized.AcceptedEventIds[0]);
+ Assert.Equal(id2, deserialized.AcceptedEventIds[1]);
+ Assert.Equal(id3, deserialized.AcceptedEventIds[2]);
+ }
+}