syntax = "proto3";

package vantage.v1;

option go_package = "github.com/mrhid6/vantage/server/internal/grpc/pb";

service Vantage {
  rpc Register(RegisterRequest)                returns (RegisterResponse);
  rpc SyncKeys(SyncRequest)                    returns (SyncResponse);
  rpc UploadGeneratedKey(UploadKeyRequest)      returns (UploadKeyResponse);
  rpc ReportUpdates(ReportUpdatesRequest)       returns (ReportUpdatesResponse);
  rpc ReportInventory(InventoryReport)          returns (InventoryReportResponse);
  rpc SyncMonitors(SyncMonitorsRequest)         returns (SyncMonitorsResponse);
  rpc ReportChecks(ReportChecksRequest)         returns (ReportChecksResponse);
  // Bidirectional stream: agent sends auth once, server pushes commands.
  rpc CommandStream(stream AgentMessage)        returns (stream ServerCommand);
}

message RegisterRequest {
  string server_id     = 1;
  string pre_reg_token = 2;
  string hostname      = 3;
  string ip_address    = 4;
  string os_info       = 5;
}

message RegisterResponse {
  string agent_token = 1;
}

message SyncRequest {
  string server_id    = 1;
  string agent_token  = 2;
  string agent_version = 3;
}

message SyncResponse {
  repeated string public_keys = 1;
}

message UploadKeyRequest {
  string server_id   = 1;
  string agent_token = 2;
  string public_key  = 3;
  string label       = 4;
  string private_key = 5;
}

message UploadKeyResponse {
  string key_id = 1;
}

// CommandStream messages

message AgentMessage {
  string server_id   = 1;
  string agent_token = 2;
  oneof payload {
    AgentReady    ready  = 3;
    CommandResult result = 4;
    StepResult step_result = 5;
    StepOutputChunk step_output = 6;
  }
}

message AgentReady {}

message CommandResult {
  string command_id = 1;
  bool   success    = 2;
  string message    = 3;
}

message PackageUpdate {
  string name            = 1;
  string current_version = 2;
  string new_version     = 3;
}

message ReportUpdatesRequest {
  string server_id   = 1;
  string agent_token = 2;
  repeated PackageUpdate updates = 3;
}

message ReportUpdatesResponse {}

message CPUReport {
  string model     = 1;
  int32  cores     = 2;
  double usage_pct = 3;
  double load1     = 4;
}

message MemReport {
  uint64 total_bytes = 1;
  uint64 used_bytes  = 2;
}

message PartitionReport {
  string device      = 1;
  string mountpoint  = 2;
  string fstype      = 3;
  uint64 total_bytes = 4;
  uint64 used_bytes  = 5;
}

message InventoryReport {
  string server_id      = 1;
  string agent_token    = 2;
  bool   include_static = 3;
  CPUReport cpu         = 4;
  MemReport memory      = 5;
  uint64 swap_total     = 6;
  uint64 swap_used      = 7;
  repeated PartitionReport partitions = 8;
  string kernel         = 9;
}

message InventoryReportResponse {}

message MonitorSpec {
  string monitor_id      = 1;
  string type            = 2;
  string url             = 3;
  string host            = 4;
  int32  port            = 5;
  string method          = 6;
  int32  expected_status = 7;
  string keyword         = 8;
  int32  tls_warn_days   = 9;
  int32  interval_sec    = 10;
  int32  retries         = 11;
  bool   insecure        = 12;
}

message SyncMonitorsRequest {
  string server_id   = 1;
  string agent_token = 2;
}

message SyncMonitorsResponse {
  repeated MonitorSpec monitors = 1;
}

message CheckResult {
  string monitor_id       = 1;
  bool   up               = 2;
  int32  latency_ms       = 3;
  string message          = 4;
  int64  cert_expiry_unix = 5;
}

message ReportChecksRequest {
  string server_id   = 1;
  string agent_token = 2;
  repeated CheckResult results = 3;
}

message ReportChecksResponse {}

message ApplyUpdatesCmd {}

message ServerCommand {
  string command_id = 1;
  oneof command {
    GenerateKeyCmd  generate_key  = 2;
    DeleteKeyCmd    delete_key    = 3;
    UpdateAgentCmd  update_agent  = 4;
    ApplyUpdatesCmd apply_updates = 5;
    RunStepCmd      run_step      = 6;
    CleanupWorkspaceCmd cleanup_workspace = 7;
  }
}

// CleanupWorkspaceCmd tells the agent to recursively remove the run's working
// directory once all steps on that server have finished.
message CleanupWorkspaceCmd {
  string workspace_id = 1;
}

message DeleteKeyCmd {
  string label = 1;
}

message UpdateAgentCmd {
  string version       = 1; // e.g. "1.2.3"
  string gitea_base_url = 2; // e.g. "https://gitea.example.com"
}

message GenerateKeyCmd {
  string label      = 1;
  string key_type   = 2; // ed25519 | rsa | ecdsa (default: ed25519)
  int32  key_size   = 3; // bits; used for rsa and ecdsa
  string passphrase = 4; // empty = no passphrase
  string comment    = 5; // embedded in public key
}

message RunStepCmd {
  string interpreter      = 1; // "bash" | "powershell"
  string script           = 2;
  map<string, string> env = 3;
  int32  timeout_seconds  = 4;
  string workspace_id     = 5; // per-run working dir the agent creates & uses as cwd
}

message StepResult {
  string command_id             = 1;
  int32  exit_code              = 2;
  string stdout                 = 3;
  string stderr                 = 4;
  map<string, string> output_env = 5;
}

message StepOutputChunk {
  string command_id = 1;
  uint64 seq        = 2;
  bytes  data       = 3;
  bool   eof        = 4;
}
