syntax = "proto3";

package mxaccess_worker.v1;

option csharp_namespace = "ZB.MOM.WW.MxGateway.Contracts.Proto";

import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "mxaccess_gateway.proto";

// Wire-compatibility policy (ProtobufStyleGuide): this contract evolves
// additively only. Never renumber or repurpose an existing field number or
// enum value. When a field or enum value is removed, add a `reserved` range
// (and `reserved` name) covering it in the same change so a future editor
// cannot accidentally reuse the retired tag. There are no `reserved`
// declarations today because no field or enum value has ever been removed.

// Gateway-to-worker IPC envelope. Named-pipe framing prepends a little-endian
// uint32 payload length to this protobuf payload.
message WorkerEnvelope {
  uint32 protocol_version = 1;
  string session_id = 2;
  uint64 sequence = 3;
  string correlation_id = 4;

  oneof body {
    GatewayHello gateway_hello = 10;
    WorkerHello worker_hello = 11;
    WorkerReady worker_ready = 12;
    WorkerCommand worker_command = 13;
    WorkerCommandReply worker_command_reply = 14;
    WorkerCancel worker_cancel = 15;
    WorkerShutdown worker_shutdown = 16;
    WorkerShutdownAck worker_shutdown_ack = 17;
    WorkerEvent worker_event = 18;
    WorkerHeartbeat worker_heartbeat = 19;
    WorkerFault worker_fault = 20;
  }
}

message GatewayHello {
  uint32 supported_protocol_version = 1;
  string nonce = 2;
  string gateway_version = 3;
  // Maximum worker-frame payload size, in bytes, negotiated by the gateway from its
  // configured pipe limit. The worker adopts this as its frame-protocol MaxMessageBytes
  // instead of a hard-coded default; 0 (an older gateway that never set the field) means
  // "use the worker's built-in default". Sits above the public gRPC cap by an
  // envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
  // Every worker->gateway frame — events, heartbeats, faults, and control replies
  // including DrainEvents — must serialize within this limit; reply builders truncate
  // to fit rather than emit an oversized frame.
  uint32 max_frame_bytes = 4;
}

message WorkerHello {
  uint32 protocol_version = 1;
  string nonce = 2;
  int32 worker_process_id = 3;
  string worker_version = 4;
}

message WorkerReady {
  int32 worker_process_id = 1;
  string mxaccess_progid = 2;
  string mxaccess_clsid = 3;
  google.protobuf.Timestamp ready_timestamp = 4;
}

message WorkerCommand {
  mxaccess_gateway.v1.MxCommand command = 1;
  google.protobuf.Timestamp enqueue_timestamp = 2;
}

message WorkerCommandReply {
  mxaccess_gateway.v1.MxCommandReply reply = 1;
  google.protobuf.Timestamp completed_timestamp = 2;
}

message WorkerCancel {
  string reason = 1;
}

message WorkerShutdown {
  google.protobuf.Duration grace_period = 1;
  string reason = 2;
}

message WorkerShutdownAck {
  mxaccess_gateway.v1.ProtocolStatus status = 1;
}

message WorkerEvent {
  mxaccess_gateway.v1.MxEvent event = 1;
}

message WorkerHeartbeat {
  int32 worker_process_id = 1;
  WorkerState state = 2;
  google.protobuf.Timestamp last_sta_activity_timestamp = 3;
  uint32 pending_command_count = 4;
  uint32 outbound_event_queue_depth = 5;
  uint64 last_event_sequence = 6;
  string current_command_correlation_id = 7;
}

message WorkerFault {
  WorkerFaultCategory category = 1;
  string command_method = 2;
  optional int32 hresult = 3;
  string exception_type = 4;
  string diagnostic_message = 5;
  mxaccess_gateway.v1.ProtocolStatus protocol_status = 6;
}

enum WorkerState {
  WORKER_STATE_UNSPECIFIED = 0;
  WORKER_STATE_STARTING = 1;
  WORKER_STATE_HANDSHAKING = 2;
  WORKER_STATE_INITIALIZING_STA = 3;
  WORKER_STATE_READY = 4;
  WORKER_STATE_EXECUTING_COMMAND = 5;
  WORKER_STATE_SHUTTING_DOWN = 6;
  WORKER_STATE_STOPPED = 7;
  WORKER_STATE_FAULTED = 8;
}

enum WorkerFaultCategory {
  WORKER_FAULT_CATEGORY_UNSPECIFIED = 0;
  WORKER_FAULT_CATEGORY_INVALID_ARGUMENTS = 1;
  WORKER_FAULT_CATEGORY_GATEWAY_AUTHENTICATION_FAILED = 2;
  WORKER_FAULT_CATEGORY_PROTOCOL_MISMATCH = 3;
  WORKER_FAULT_CATEGORY_PROTOCOL_VIOLATION = 4;
  WORKER_FAULT_CATEGORY_PIPE_DISCONNECTED = 5;
  WORKER_FAULT_CATEGORY_MXACCESS_CREATION_FAILED = 6;
  WORKER_FAULT_CATEGORY_MXACCESS_COMMAND_FAILED = 7;
  WORKER_FAULT_CATEGORY_MXACCESS_EVENT_CONVERSION_FAILED = 8;
  WORKER_FAULT_CATEGORY_STA_HUNG = 9;
  WORKER_FAULT_CATEGORY_QUEUE_OVERFLOW = 10;
  WORKER_FAULT_CATEGORY_SHUTDOWN_TIMEOUT = 11;
}
