// acme.example.v3alpha1.pipeline — fictional orchestration types for streaming docs.
//
// Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil
// molestiae consequatur. Pipelines compose v2 `PayloadEnvelope` chunks with alpha
// rollout metadata for cross-package link tests.
syntax = "proto3";

package acme.example.v3alpha1;

import "acme/example/v2/types.proto";
import "acme/example/v3alpha1/types.proto";
import "buf/validate/validate.proto";
import "google/protobuf/timestamp.proto";

// PipelineStatus tracks synthetic workflow execution.
enum PipelineStatus {
  PIPELINE_STATUS_UNSPECIFIED = 0;
  PIPELINE_STATUS_QUEUED = 1;
  PIPELINE_STATUS_RUNNING = 2;
  PIPELINE_STATUS_SUCCEEDED = 3;
  PIPELINE_STATUS_FAILED = 4;
  PIPELINE_STATUS_CANCELLED = 5;
}

// PipelineStepInput is one unit of work inside a pipeline run.
message PipelineStepInput {
  string step_name = 1 [
    (buf.validate.field).required = true,
    (buf.validate.field).string.min_len = 1,
    (buf.validate.field).string.max_len = 64
  ];
  acme.example.v2.PayloadEnvelope input = 2;
  RolloutStage rollout = 3;
}

// PipelineStepResult reports completion for a single step.
message PipelineStepResult {
  string step_name = 1;
  PipelineStatus status = 2;
  acme.example.v2.ErrorDetail error = 3;
  acme.example.v2.StreamCursor cursor = 4;
  google.protobuf.Timestamp finished_at = 5;
}

// PipelineStage is a oneof-heavy stage definition for doc rendering.
message PipelineStage {
  oneof stage {
    PipelineStepInput step = 1;
    RolloutStage rollout_only = 2;
    acme.example.v2.AuditBatch audit_snapshot = 3;
  }
}

// PipelineRun identifies a long-lived orchestration instance.
message PipelineRun {
  string run_id = 1 [
    (buf.validate.field).required = true,
    (buf.validate.field).string.uuid = true
  ];
  string pipeline_name = 2 [(buf.validate.field).string.min_len = 1];
  PipelineStatus status = 3;
  repeated PipelineStepResult results = 4;
  acme.example.v2.ResourceIdentity owner = 5;
  google.protobuf.Timestamp started_at = 6;
  google.protobuf.Timestamp completed_at = 7;

  option (buf.validate.message).cel = {
    id: "pipeline_run.completed_after_started"
    message: "completed_at must not precede started_at when both are set"
    expression: "!has(this.completed_at) || !has(this.started_at) || this.completed_at >= this.started_at"
  };
}

// StartPipelineRequest kicks off a pipeline from staged inputs.
message StartPipelineRequest {
  string pipeline_name = 1 [
    (buf.validate.field).required = true,
    (buf.validate.field).string.pattern = "^[a-z][a-z0-9-]*$"
  ];
  repeated PipelineStage stages = 2 [(buf.validate.field).repeated.min_items = 1];
  acme.example.v2.ResourceIdentity actor = 3;
}

// StartPipelineResponse returns the created run handle.
message StartPipelineResponse {
  PipelineRun run = 1;
}

// WatchPipelineRequest subscribes to pipeline step events.
message WatchPipelineRequest {
  string run_id = 1 [(buf.validate.field).string.uuid = true];
  acme.example.v2.TimeWindow window = 2;
  repeated acme.example.v2.FilterExpression filters = 3;
}

// WatchPipelineResponse is one event on the WatchPipeline server stream.
message WatchPipelineResponse {
  string event_id = 1;
  PipelineStepResult step = 2;
  google.protobuf.Timestamp observed_at = 3;
  acme.example.v2.StreamCursor cursor = 4;
}

// CancelPipelineRequest stops a run by id.
message CancelPipelineRequest {
  string run_id = 1 [(buf.validate.field).string.uuid = true];
  string reason = 2 [(buf.validate.field).string.max_len = 512];
}

// CancelPipelineResponse acknowledges cancellation.
message CancelPipelineResponse {
  PipelineRun run = 1;
}
