syntax = "proto3";

package tikeo.worker.v1;

service WorkerTunnelService {
  rpc OpenTunnel(stream WorkerMessage) returns (stream ServerMessage);
  rpc SubscribeTaskLogs(SubscribeTaskLogsRequest) returns (stream TaskLog);
}

message WorkerMessage {
  oneof kind {
    RegisterWorker register = 1;
    Heartbeat heartbeat = 2;
    TaskResult task_result = 3;
    TaskLog task_log = 4;
    UnregisterWorker unregister = 5;
    TaskCheckpoint task_checkpoint = 6;
  }
}

message ServerMessage {
  oneof kind {
    WorkerRegistered registered = 1;
    Ping ping = 2;
    DispatchTask dispatch_task = 3;
  }
}

message RegisterWorker {
  // Optional client-side stable instance hint. The tikeo still assigns the authoritative `worker_id`.
  string client_instance_id = 1;
  string app = 2;
  string namespace = 3;
  string cluster = 4;
  string region = 5;
  // Legacy free-form labels/capabilities. New routing must use `structured_capabilities`.
  repeated string capabilities = 6;
  map<string, string> labels = 7;
  WorkerCapabilities structured_capabilities = 8;
  WorkerClusterElection election = 9;
}

message WorkerCapabilities {
  // Human/operator tags such as java or spring-boot. Not used for dispatch routing.
  repeated string tags = 1;
  repeated ProcessorCapability normal_processors = 2;
  repeated ScriptRunnerCapability script_runners = 3;
  repeated PluginProcessorCapability plugin_processors = 4;
}

message ProcessorCapability {
  string name = 1;
  string description = 2;
}

message ScriptRunnerCapability {
  string language = 1;
  string sandbox_backend = 2;
}

message PluginProcessorCapability {
  string type = 1;
  repeated string processor_names = 2;
  // Rich processor list carrying display metadata for operator UI.
  repeated ProcessorCapability processors = 3;
}

message WorkerClusterElection {
  bool enabled = 1;
  // Stable election domain. Empty means namespace/app/cluster/region.
  string domain = 2;
  // Optional deterministic priority. Lower values win ties after health checks.
  uint32 priority = 3;
}

message Heartbeat {
  string worker_id = 1;
  uint64 sequence = 2;
  uint64 generation = 3;
  string fencing_token = 4;
}

message WorkerRegistered {
  string worker_id = 1;
  uint64 lease_seconds = 2;
  uint64 generation = 3;
  string fencing_token = 4;
}

message UnregisterWorker {
  string worker_id = 1;
  uint64 generation = 2;
  string fencing_token = 3;
}

message Ping {
  uint64 sequence = 1;
}

message DispatchTask {
  string instance_id = 1;
  string job_id = 2;
  bytes payload = 3;
  // Explicit processor key used by SDK adapters. Defaults to `job_id` for backwards compatibility.
  string processor_name = 4;
  // Optional dynamic processor metadata. Empty for normal processors.
  TaskProcessorBinding processor_binding = 5;
  // Server-issued opaque assignment authority bound to worker session generation/fencing.
  string assignment_token = 6;
}

message TaskProcessorBinding {
  oneof kind {
    WasmProcessorBinding wasm = 1;
    ScriptProcessorBinding script = 2;
  }
}

message ScriptProcessorBinding {
  string script_id = 1;
  string version = 2;
  string language = 3;
  bytes content = 4;
  string version_id = 5;
  uint64 version_number = 6;
  string content_sha256 = 7;
  uint64 timeout_ms = 8;
  uint64 max_memory_bytes = 9;
  uint64 max_output_bytes = 10;
  bool allow_network = 11;
  repeated string allowed_env_vars = 12;
  repeated string read_only_paths = 13;
  repeated string writable_paths = 14;
  repeated string secret_refs = 15;
  repeated string allowed_network_hosts = 16;
  string sandbox_backend = 17;
}

message WasmProcessorBinding {
  string script_id = 1;
  string version = 2;
  bytes module = 3;
  string runtime = 4;
  string entrypoint = 5;
  uint64 timeout_ms = 6;
  uint64 max_memory_bytes = 7;
  uint64 fuel = 8;
  bool allow_network = 9;
  repeated string allowed_env_vars = 10;
  // Immutable script version snapshot identifier when available.
  string version_id = 11;
  // Monotonic script version snapshot number when available.
  uint64 version_number = 12;
  // Lowercase hex SHA-256 digest of module bytes. Workers must verify when present.
  string module_sha256 = 13;
  // Reserved signature hook for future PKI-backed module verification.
  string module_signature = 14;
}

message TaskResult {
  string worker_id = 1;
  string instance_id = 2;
  bool success = 3;
  string message = 4;
  string assignment_token = 5;
}

message TaskLog {
  string worker_id = 1;
  string instance_id = 2;
  string level = 3;
  string message = 4;
  int64 sequence = 5;
  string assignment_token = 6;
}

message TaskCheckpoint {
  string worker_id = 1;
  string instance_id = 2;
  string checkpoint_json = 3;
  int64 sequence = 4;
  string assignment_token = 5;
}

message SubscribeTaskLogsRequest {
  string instance_id = 1;
  int64 after_sequence = 2;
  bool replay_existing = 3;
}
