syntax = "proto3"; package forest.v1; message AnnotateReleaseRequest { string artifact_id = 1; map metadata = 2; Source source = 3; ArtifactContext context = 4; Project project = 5; Ref ref = 6; } message AnnotateReleaseResponse { Artifact artifact = 1; } message GetArtifactBySlugRequest { string slug = 1; } message GetArtifactBySlugResponse { Artifact artifact = 1; } message GetArtifactsByProjectRequest { Project project = 1; } message GetArtifactsByProjectResponse { repeated Artifact artifact = 1; } message ReleaseRequest { string artifact_id = 1; repeated string destinations = 2; repeated string environments = 3; bool force = 4; // When true, use the project's release pipeline (DAG) instead of // deploying directly to the specified destinations/environments. bool use_pipeline = 5; // When true, create a plan-only pipeline (single Plan stage, no deploy). bool prepare_only = 6; } message ReleaseResponse { // List of release intents created (one per destination) repeated ReleaseIntent intents = 1; } message ReleaseIntent { string release_intent_id = 1; string destination = 2; string environment = 3; } message WaitReleaseRequest { string release_intent_id = 1; } message WaitReleaseEvent { oneof event { ReleaseStatusUpdate status_update = 1; ReleaseLogLine log_line = 2; PipelineStageUpdate stage_update = 3; } } // Streamed in WaitRelease for pipeline releases: reports stage status changes. message PipelineStageUpdate { string stage_id = 1; string stage_type = 2; // "deploy", "wait" string status = 3; // PENDING, ACTIVE, SUCCEEDED, FAILED, CANCELLED optional string queued_at = 4; optional string started_at = 5; optional string completed_at = 6; optional string wait_until = 7; optional string error_message = 8; optional string approval_status = 9; } message ReleaseStatusUpdate { string destination = 1; string status = 2; } message ReleaseLogLine { string destination = 1; string line = 2; string timestamp = 3; LogChannel channel = 4; } enum LogChannel { LOG_CHANNEL_UNSPECIFIED = 0; LOG_CHANNEL_STDOUT = 1; LOG_CHANNEL_STDERR = 2; } message GetOrganisationsRequest {} message GetOrganisationsResponse { repeated OrganisationRef organisations = 1; } message GetProjectsRequest { oneof query { OrganisationRef organisation = 1; } } message GetProjectsResponse { repeated string projects = 1; } message CreateProjectRequest { string organisation = 1; string project = 2; } message CreateProjectResponse { Project project = 1; } message GetReleasesByActorRequest { string actor_id = 1; // user_id or app_id string actor_type = 2; // "user" or "app" int32 page_size = 3; string page_token = 4; } message GetReleasesByActorResponse { repeated ReleaseIntentSummary releases = 1; string next_page_token = 2; } message ReleaseIntentSummary { string release_intent_id = 1; string artifact_id = 2; Project project = 3; repeated ReleaseDestinationStatus destinations = 4; string created_at = 5; } message ReleaseDestinationStatus { string destination = 1; string environment = 2; string status = 3; } message GetDestinationStatesRequest { string organisation = 1; optional string project = 2; } message GetDestinationStatesResponse { repeated DestinationState destinations = 1; // Active pipeline runs affecting these destinations (if any). repeated PipelineRunState pipeline_runs = 2; } // ── Release intent states (release-centric view) ───────────────────── message GetReleaseIntentStatesRequest { string organisation = 1; optional string project = 2; // When true, also include recently completed release intents. bool include_completed = 3; } message GetReleaseIntentStatesResponse { repeated ReleaseIntentState release_intents = 1; } // Full state of a release intent: pipeline stages + individual release steps. message ReleaseIntentState { string release_intent_id = 1; string artifact_id = 2; string project = 3; string created_at = 4; // Pipeline stages (empty for non-pipeline releases). repeated PipelineStageState stages = 5; // All release_states rows for this intent (deploy steps). repeated ReleaseStepState steps = 6; } // Status of a single pipeline stage (saga coordinator view). message PipelineStageState { string stage_id = 1; repeated string depends_on = 2; PipelineRunStageType stage_type = 3; PipelineRunStageStatus status = 4; // Consistent timestamps for all stage types. optional string queued_at = 5; optional string started_at = 6; optional string completed_at = 7; optional string error_message = 8; // Type-specific context. optional string environment = 9; // deploy/plan stages optional int64 duration_seconds = 10; // wait stages optional string wait_until = 11; // wait stages repeated string release_ids = 12; // deploy/plan stages: individual release IDs optional string approval_status = 13; // plan stages: AWAITING_APPROVAL, APPROVED, REJECTED optional bool auto_approve = 14; // plan stages } // Status of a single release step (release_states row). message ReleaseStepState { string release_id = 1; optional string stage_id = 2; string destination_name = 3; string environment = 4; string status = 5; optional string queued_at = 6; optional string assigned_at = 7; optional string started_at = 8; optional string completed_at = 9; optional string error_message = 10; } message DestinationState { string destination_id = 1; string destination_name = 2; string environment = 3; optional string release_id = 4; optional string artifact_id = 5; optional string status = 6; optional string error_message = 7; optional string queued_at = 8; optional string completed_at = 9; optional int32 queue_position = 10; // Pipeline context: set when this release was created by a pipeline stage. optional string release_intent_id = 11; optional string stage_id = 12; // When a runner was assigned to this release. optional string assigned_at = 13; // When the runner actually started executing. optional string started_at = 14; } // ── Pipeline run progress ──────────────────────────────────────────── // Snapshot of an active (or recently completed) pipeline run. message PipelineRunState { string release_intent_id = 1; string artifact_id = 2; string created_at = 3; repeated PipelineRunStage stages = 4; } // Status of a single stage within a pipeline run. message PipelineRunStage { string stage_id = 1; repeated string depends_on = 2; PipelineRunStageType stage_type = 3; PipelineRunStageStatus status = 4; // Type-specific context optional string environment = 5; // deploy stages optional int64 duration_seconds = 6; // wait stages optional string queued_at = 7; // when dependencies were met optional string started_at = 8; optional string completed_at = 9; optional string error_message = 10; optional string wait_until = 11; repeated string release_ids = 12; // deploy stages: individual release IDs optional string approval_status = 13; // plan stages: AWAITING_APPROVAL, APPROVED, REJECTED optional bool auto_approve = 14; // plan stages } enum PipelineRunStageType { PIPELINE_RUN_STAGE_TYPE_UNSPECIFIED = 0; PIPELINE_RUN_STAGE_TYPE_DEPLOY = 1; PIPELINE_RUN_STAGE_TYPE_WAIT = 2; PIPELINE_RUN_STAGE_TYPE_PLAN = 3; } enum PipelineRunStageStatus { PIPELINE_RUN_STAGE_STATUS_UNSPECIFIED = 0; PIPELINE_RUN_STAGE_STATUS_PENDING = 1; PIPELINE_RUN_STAGE_STATUS_ACTIVE = 2; PIPELINE_RUN_STAGE_STATUS_SUCCEEDED = 3; PIPELINE_RUN_STAGE_STATUS_FAILED = 4; PIPELINE_RUN_STAGE_STATUS_CANCELLED = 5; PIPELINE_RUN_STAGE_STATUS_AWAITING_APPROVAL = 6; } // ── Plan stage approval ────────────────────────────────────────────── message ApprovePlanStageRequest { string release_intent_id = 1; string stage_id = 2; } message ApprovePlanStageResponse {} message RejectPlanStageRequest { string release_intent_id = 1; string stage_id = 2; optional string reason = 3; } message RejectPlanStageResponse {} message GetPlanOutputRequest { string release_intent_id = 1; string stage_id = 2; } message GetPlanOutputResponse { string plan_output = 1; // deprecated: use outputs string status = 2; // RUNNING, AWAITING_APPROVAL, APPROVED, REJECTED repeated PlanDestinationOutput outputs = 3; } message PlanDestinationOutput { string destination_id = 1; string destination_name = 2; string plan_output = 3; string status = 4; // SUCCEEDED, FAILED, RUNNING, etc. } service ReleaseService { rpc AnnotateRelease(AnnotateReleaseRequest) returns (AnnotateReleaseResponse); rpc Release(ReleaseRequest) returns (ReleaseResponse); rpc WaitRelease(WaitReleaseRequest) returns (stream WaitReleaseEvent); rpc GetArtifactBySlug(GetArtifactBySlugRequest) returns (GetArtifactBySlugResponse); rpc GetArtifactsByProject(GetArtifactsByProjectRequest) returns (GetArtifactsByProjectResponse); rpc GetReleasesByActor(GetReleasesByActorRequest) returns (GetReleasesByActorResponse); rpc GetOrganisations(GetOrganisationsRequest) returns (GetOrganisationsResponse); rpc GetProjects(GetProjectsRequest) returns (GetProjectsResponse); rpc CreateProject(CreateProjectRequest) returns (CreateProjectResponse); rpc GetDestinationStates(GetDestinationStatesRequest) returns (GetDestinationStatesResponse); rpc GetReleaseIntentStates(GetReleaseIntentStatesRequest) returns (GetReleaseIntentStatesResponse); rpc ApprovePlanStage(ApprovePlanStageRequest) returns (ApprovePlanStageResponse); rpc RejectPlanStage(RejectPlanStageRequest) returns (RejectPlanStageResponse); rpc GetPlanOutput(GetPlanOutputRequest) returns (GetPlanOutputResponse); } message Source { optional string user = 1; optional string email = 2; optional string source_type = 3; optional string run_url = 4; // The actor ID (user, app, or service account UUID) that created this annotation. optional string user_id = 5; } message ArtifactContext { string title = 1; optional string description = 2; optional string web = 3; optional string pr = 4; } message Artifact { string id = 1; string artifact_id = 2; string slug = 3; map metadata = 4; Source source = 5; ArtifactContext context = 6; Project project = 7; repeated ArtifactDestination destinations = 8; string created_at = 9; Ref ref = 10; } message ArtifactDestination { string name = 1; string environment = 2; string type_organisation = 3; string type_name = 4; uint64 type_version = 5; string status = 6; } message Project { string organisation = 1; string project = 2; } message Ref { string commit_sha = 1; optional string branch = 2; optional string commit_message = 3; optional string version = 4; optional string repo_url = 5; } message OrganisationRef { string organisation = 1; }