syntax = "proto3";

package akuity.io.kargo.service.v1alpha1;

import "google/protobuf/timestamp.proto";
import "v1alpha1/generated.proto";
import "k8s.io/api/core/v1/generated.proto";
import "rollouts/api/v1alpha1/generated.proto";
import "rbac/v1alpha1/generated.proto";

option go_package = "github.com/akuity/kargo/pkg/api/service/v1alpha1;svcv1alpha1";

enum RawFormat {
  RAW_FORMAT_UNSPECIFIED = 0;
  RAW_FORMAT_JSON = 1;
  RAW_FORMAT_YAML = 2;
}

service KargoService {
  rpc GetVersionInfo(GetVersionInfoRequest) returns (GetVersionInfoResponse);
  rpc GetConfig(GetConfigRequest) returns (GetConfigResponse);
  rpc GetPublicConfig(GetPublicConfigRequest) returns (GetPublicConfigResponse);

  rpc AdminLogin(AdminLoginRequest) returns (AdminLoginResponse);

  /* Kargo-related resources management API */
  // TODO(devholic): Add ApplyResource API
  // rpc ApplyResource(ApplyResourceRequest) returns (ApplyResourceRequest);
  rpc CreateResource(CreateResourceRequest) returns (CreateResourceResponse);
  rpc CreateOrUpdateResource(CreateOrUpdateResourceRequest) returns (CreateOrUpdateResourceResponse);
  rpc UpdateResource(UpdateResourceRequest) returns (UpdateResourceResponse);
  rpc DeleteResource(DeleteResourceRequest) returns (DeleteResourceResponse);

  /* Stage APIs */

  rpc ListStages(ListStagesRequest) returns (ListStagesResponse);
  rpc ListImages(ListImagesRequest) returns (ListImagesResponse);
  rpc GetStage(GetStageRequest) returns (GetStageResponse);
  rpc WatchStages(WatchStagesRequest) returns (stream WatchStagesResponse);
  rpc DeleteStage(DeleteStageRequest) returns (DeleteStageResponse);
  rpc RefreshStage(RefreshStageRequest) returns (RefreshStageResponse);

  /* Promotion APIs */

  rpc ListPromotions(ListPromotionsRequest) returns (ListPromotionsResponse);
  rpc WatchPromotions(WatchPromotionsRequest) returns (stream WatchPromotionsResponse);
  rpc GetPromotion(GetPromotionRequest) returns (GetPromotionResponse);
  rpc WatchPromotion(WatchPromotionRequest) returns (stream WatchPromotionResponse);
  rpc AbortPromotion(AbortPromotionRequest) returns (AbortPromotionResponse);

  /* Project APIs */

  rpc DeleteProject(DeleteProjectRequest) returns (DeleteProjectResponse);
  rpc GetProject(GetProjectRequest) returns (GetProjectResponse);
  rpc ListProjects(ListProjectsRequest) returns (ListProjectsResponse);

  /* Freight APIs */

  rpc ApproveFreight(ApproveFreightRequest) returns (ApproveFreightResponse);
  rpc DeleteFreight(DeleteFreightRequest) returns (DeleteFreightResponse);
  rpc GetFreight(GetFreightRequest) returns (GetFreightResponse);
  rpc PromoteToStage(PromoteToStageRequest) returns (PromoteToStageResponse);
  rpc PromoteDownstream(PromoteDownstreamRequest) returns (PromoteDownstreamResponse);
  rpc QueryFreight(QueryFreightRequest) returns (QueryFreightResponse);
  rpc UpdateFreightAlias(UpdateFreightAliasRequest) returns (UpdateFreightAliasResponse);

  /* Verification APIs */

  rpc Reverify(ReverifyRequest) returns (ReverifyResponse);
  rpc AbortVerification(AbortVerificationRequest) returns (AbortVerificationResponse);

  /* Warehouse APIs */

  rpc ListWarehouses(ListWarehousesRequest) returns (ListWarehousesResponse);
  rpc GetWarehouse(GetWarehouseRequest) returns (GetWarehouseResponse);
  rpc WatchWarehouses(WatchWarehousesRequest) returns (stream WatchWarehousesResponse);
  rpc DeleteWarehouse(DeleteWarehouseRequest) returns (DeleteWarehouseResponse);
  rpc RefreshWarehouse(RefreshWarehouseRequest) returns (RefreshWarehouseResponse);

  /* Credential APIs */

  rpc CreateCredentials(CreateCredentialsRequest) returns (CreateCredentialsResponse);
  rpc DeleteCredentials(DeleteCredentialsRequest) returns (DeleteCredentialsResponse);
  rpc GetCredentials(GetCredentialsRequest) returns (GetCredentialsResponse);
  rpc ListCredentials(ListCredentialsRequest) returns (ListCredentialsResponse);
  rpc UpdateCredentials(UpdateCredentialsRequest) returns (UpdateCredentialsResponse);

  /* Analysis APIs */

  rpc ListAnalysisTemplates(ListAnalysisTemplatesRequest) returns (ListAnalysisTemplatesResponse);
  rpc GetAnalysisTemplate(GetAnalysisTemplateRequest) returns (GetAnalysisTemplateResponse);
  rpc DeleteAnalysisTemplate(DeleteAnalysisTemplateRequest) returns (DeleteAnalysisTemplateResponse);
  rpc GetAnalysisRun(GetAnalysisRunRequest) returns (GetAnalysisRunResponse);

  rpc ListAnalysisTemplateConfigMaps(ListAnalysisTemplateConfigMapsRequest) returns (ListAnalysisTemplateConfigMapsResponse);
  rpc GetAnalysisTemplateConfigMap(GetAnalysisTemplateConfigMapRequest) returns (GetAnalysisTemplateConfigMapResponse);
  rpc ListAnalysisTemplateSecrets(ListAnalysisTemplateSecretsRequest) returns (ListAnalysisTemplateSecretsResponse);
  rpc GetAnalysisTemplateSecret(GetAnalysisTemplateSecretRequest) returns (GetAnalysisTemplateSecretResponse);

  /* Event APIs */

  rpc ListProjectEvents(ListProjectEventsRequest) returns (ListProjectEventsResponse);

  /* Role APIs */

  rpc CreateRole(CreateRoleRequest) returns (CreateRoleResponse);
  rpc DeleteRole(DeleteRoleRequest) returns (DeleteRoleResponse);
  rpc GetRole(GetRoleRequest) returns (GetRoleResponse);
  rpc Grant(GrantRequest) returns (GrantResponse);
  rpc ListRoles(ListRolesRequest) returns (ListRolesResponse);
  rpc Revoke(RevokeRequest) returns (RevokeResponse);
  rpc UpdateRole(UpdateRoleRequest) returns (UpdateRoleResponse);
}

message ComponentVersions {
  optional VersionInfo server = 1;
  optional VersionInfo cli = 2;
}

message VersionInfo {
  string version = 1;
  string git_commit = 2;
  bool git_tree_dirty = 3;
  google.protobuf.Timestamp build_time = 4;
  string go_version = 5;
  string compiler = 6;
  string platform = 7;
}

message GetVersionInfoRequest {}

message GetVersionInfoResponse {
  VersionInfo version_info = 1;
}

message GetConfigRequest {}

message ArgoCDShard {
  string url = 1;
  string namespace = 2;
}

message GetConfigResponse {
  map<string, ArgoCDShard> argocd_shards = 1;
  bool secret_management_enabled = 2;
}

message GetPublicConfigRequest {}

message GetPublicConfigResponse {
  OIDCConfig oidc_config = 1;
  bool admin_account_enabled = 2;
  bool skip_auth = 3;
}

message OIDCConfig {
  string issuer_url = 1;
  string client_id = 2;
  repeated string scopes = 3;
  string cli_client_id = 4;
}

message AdminLoginRequest {
  string password = 1;
}

message AdminLoginResponse {
  string id_token = 1;
}

message CreateResourceRequest {
  bytes manifest = 1;
}

message CreateResourceResult {
  oneof result {
    bytes created_resource_manifest = 1;
    string error = 2;
  }
}

message CreateResourceResponse {
  repeated CreateResourceResult results = 1;
}

message CreateOrUpdateResourceRequest {
  bytes manifest = 1;
}

message CreateOrUpdateResourceResult {
  oneof result {
    bytes created_resource_manifest = 1;
    bytes updated_resource_manifest = 2;
    string error = 3;
  }
}

message CreateOrUpdateResourceResponse {
  repeated CreateOrUpdateResourceResult results = 1;
}

message UpdateResourceRequest {
  bytes manifest = 1;
}

message UpdateResourceResult {
  oneof result {
    bytes updated_resource_manifest = 1;
    string error = 2;
  }
}

message UpdateResourceResponse {
  repeated UpdateResourceResult results = 1;
}

message DeleteResourceRequest {
  bytes manifest = 1;
}

message DeleteResourceResult {
  oneof result {
    bytes deleted_resource_manifest = 1;
    string error = 2;
  }
}

message DeleteResourceResponse {
  repeated DeleteResourceResult results = 1;
}

message ListStagesRequest {
  string project = 1;
}

message ListStagesResponse {
  repeated github.com.akuity.kargo.api.v1alpha1.Stage stages = 1;
}

message ListImagesRequest {
  string project = 1;
}

message ListImagesResponse {
  // images maps image repository names to their tags
  map<string, TagMap> images = 2;
}

message TagMap {
  // tags maps image tag names to stages which have previously used that tag
  map<string, ImageStageMap> tags = 1;
}

message ImageStageMap {
  // stages maps stage names to the order which an image was promoted to that stage
  map<string, int32> stages = 1;
}

message GetStageRequest {
  string project = 1;
  string name = 2;
  RawFormat format = 3;
}

message GetStageResponse {
  oneof result {
    github.com.akuity.kargo.api.v1alpha1.Stage stage = 1;
    bytes raw = 2;
  }
}

message WatchStagesRequest {
  string project = 1;
  string name = 2;
}

message WatchStagesResponse {
  github.com.akuity.kargo.api.v1alpha1.Stage stage = 1;
  string type = 2;
}

message DeleteStageRequest {
  string project = 1;
  string name = 2;
}

message DeleteStageResponse {
  /* explicitly empty */
}

message RefreshStageRequest {
  string project = 1;
  string name = 2;
}

message RefreshStageResponse {
  github.com.akuity.kargo.api.v1alpha1.Stage stage = 1;
}

message ListPromotionsRequest {
  string project = 1;
  optional string stage = 2;
}

message ListPromotionsResponse {
  repeated github.com.akuity.kargo.api.v1alpha1.Promotion promotions = 1;
}

message WatchPromotionsRequest {
  string project = 1;
  optional string stage = 2;
}

message WatchPromotionsResponse {
  github.com.akuity.kargo.api.v1alpha1.Promotion promotion = 1;
  string type = 2;
}

message GetPromotionRequest {
  string project = 1;
  string name = 2;
  RawFormat format = 3;
}

message GetPromotionResponse {
  oneof result {
    github.com.akuity.kargo.api.v1alpha1.Promotion promotion = 1;
    bytes raw = 2;
  }
}

message WatchPromotionRequest {
  string project = 1;
  string name = 2;
}

message WatchPromotionResponse {
  github.com.akuity.kargo.api.v1alpha1.Promotion promotion = 1;
  string type = 2;
}

message AbortPromotionRequest {
  string project = 1;
  string name = 2;
}

message AbortPromotionResponse {
  /* explicitly empty */
}

message DeleteProjectRequest {
  string name = 1;
}

message DeleteProjectResponse {
  /* explicitly empty */
}

message GetProjectRequest {
  string name = 1;
  RawFormat format = 2;
}

message GetProjectResponse {
  oneof result {
    github.com.akuity.kargo.api.v1alpha1.Project project = 1;
    bytes raw = 2;
  }
}

message ListProjectsRequest {
  optional int32 page_size = 1;
  optional int32 page = 2;
  optional string filter = 3;
}

message ListProjectsResponse {
  repeated github.com.akuity.kargo.api.v1alpha1.Project projects = 1;
  int32 total = 2;
}

message ApproveFreightRequest {
  string project = 1;
  string name = 2;
  string alias = 3;
  string stage = 4;
}

message ApproveFreightResponse {
  /* explicitly empty */
}

message DeleteFreightRequest {
  string project = 1;
  string name = 2;
  string alias = 3;
}

message DeleteFreightResponse {
  /* explicitly empty */
}

message GetFreightRequest {
  string project = 1;
  string name = 2;
  string alias = 3;
  RawFormat format = 4;
}

message GetFreightResponse {
  oneof result {
    github.com.akuity.kargo.api.v1alpha1.Freight freight = 1;
    bytes raw = 2;
  }
}

message PromoteToStageRequest {
  string project = 1;
  string stage = 2;
  string freight = 3;
  string freight_alias = 4 [json_name = "freightAlias"];
}

message PromoteToStageResponse {
  github.com.akuity.kargo.api.v1alpha1.Promotion promotion = 1;
}

message PromoteDownstreamRequest {
  string project = 1;
  string stage = 2;
  string freight = 3;
  string freight_alias = 4 [json_name = "freightAlias"];
}

message PromoteDownstreamResponse {
  repeated github.com.akuity.kargo.api.v1alpha1.Promotion promotions = 1;
}

message QueryFreightRequest {
  string project = 1;
  string stage = 2;
  string group_by = 3;
  string group = 4;
  string order_by = 5;
  bool reverse = 6;
  repeated string origins = 7;
}

message QueryFreightResponse {
  map<string, FreightList> groups = 1;
}

message FreightList {
  repeated github.com.akuity.kargo.api.v1alpha1.Freight freight = 1;
}

message UpdateFreightAliasRequest {
  string project = 1;
  string name = 2;
  string old_alias = 3 [json_name = "oldAlias"];
  string new_alias = 4 [json_name = "newAlias"];
}

message UpdateFreightAliasResponse {
  /* explicitly empty */
}

message ReverifyRequest {
  string project = 1;
  string stage = 2;
}

message ReverifyResponse {
  /* explicitly empty */
}

message AbortVerificationRequest {
  string project = 1;
  string stage = 2;
}

message AbortVerificationResponse {
  /* explicitly empty */
}

message ListWarehousesRequest {
  string project = 1;
}

message ListWarehousesResponse {
  repeated github.com.akuity.kargo.api.v1alpha1.Warehouse warehouses = 1;
}

message GetWarehouseRequest {
  string project = 1;
  string name = 2;
  RawFormat format = 3;
}

message GetWarehouseResponse {
  oneof result {
    github.com.akuity.kargo.api.v1alpha1.Warehouse warehouse = 1;
    bytes raw = 2;
  }
}

message WatchWarehousesRequest {
  string project = 1;
  string name = 2;
}

message WatchWarehousesResponse {
  github.com.akuity.kargo.api.v1alpha1.Warehouse warehouse = 1;
  string type = 2;
}

message DeleteWarehouseRequest {
  string project = 1;
  string name = 2;
}

message DeleteWarehouseResponse {
  /* explicitly empty */
}

message RefreshWarehouseRequest {
  string project = 1;
  string name = 2;
}

message RefreshWarehouseResponse {
  github.com.akuity.kargo.api.v1alpha1.Warehouse warehouse = 1;
}

message CreateCredentialsRequest {
  string project = 1;
  string name = 2;
  string description = 8;
  string type = 3;
  string repo_url = 4 [json_name = "repoURL"];
  bool repo_url_is_regex = 5 [json_name = "repoURLIsRegex"];
  string username = 6;
  string password = 7;
}

message CreateCredentialsResponse {
  k8s.io.api.core.v1.Secret credentials = 1;
}

message DeleteCredentialsRequest {
  string project = 1;
  string name = 2;
}

message DeleteCredentialsResponse {
  /* explicitly empty */
}

message GetCredentialsRequest {
  string project = 1;
  string name = 2;
  RawFormat format = 3;
}

message GetCredentialsResponse {
  oneof result {
    k8s.io.api.core.v1.Secret credentials = 1;
    bytes raw = 2;
  }
}

message ListCredentialsRequest {
  string project = 1;
}

message ListCredentialsResponse {
  repeated k8s.io.api.core.v1.Secret credentials = 1;
}

message UpdateCredentialsRequest {
  string project = 1;
  string name = 2;
  string description = 8;
  string type = 3;
  string repo_url = 4 [json_name = "repoURL"];
  bool repo_url_is_regex = 5 [json_name = "repoURLIsRegex"];
  string username = 6;
  string password = 7;
}

message UpdateCredentialsResponse {
  k8s.io.api.core.v1.Secret credentials = 1;
}

message ListAnalysisTemplatesRequest {
  string project = 1;
}

message ListAnalysisTemplatesResponse {
  repeated github.com.akuity.kargo.internal.controller.rollouts.api.v1alpha1.AnalysisTemplate analysis_templates = 1 [json_name = "analysisTemplates"];
}

message GetAnalysisTemplateRequest {
  string project = 1;
  string name = 2;
  RawFormat format = 3;
}

message GetAnalysisTemplateResponse {
  oneof result {
    github.com.akuity.kargo.internal.controller.rollouts.api.v1alpha1.AnalysisTemplate analysis_template = 1 [json_name = "analysisTemplate"];
    bytes raw = 2;
  }
}

message GetAnalysisRunRequest {
  string namespace = 1;
  string name = 2;
  RawFormat format = 3;
}

message GetAnalysisRunResponse {
  oneof result {
    github.com.akuity.kargo.internal.controller.rollouts.api.v1alpha1.AnalysisRun analysis_run = 1 [json_name = "analysisRun"];
    bytes raw = 2;
  }
}

message DeleteAnalysisTemplateRequest {
  string project = 1;
  string name = 2;
}

message DeleteAnalysisTemplateResponse {
  /* explicitly empty */
}

message ListProjectEventsRequest {
  string project = 1;
}

message ListProjectEventsResponse {
  repeated k8s.io.api.core.v1.Event events = 1;
}

message CreateRoleRequest {
  github.com.akuity.kargo.api.rbac.v1alpha1.Role role = 1;
}

message CreateRoleResponse {
  github.com.akuity.kargo.api.rbac.v1alpha1.Role role = 1;
}

message DeleteRoleRequest {
  string project = 1;
  string name = 2;
}

message DeleteRoleResponse {
  /* explicitly empty */
}

message GetRoleRequest {
  string project = 1;
  string name = 2;
  bool as_resources = 3;
  RawFormat format = 4;
}

message GetRoleResponse {
  oneof result {
    github.com.akuity.kargo.api.rbac.v1alpha1.Role role = 1;
    github.com.akuity.kargo.api.rbac.v1alpha1.RoleResources resources = 2;
    bytes raw = 3;
  }
}

message Claims {
  // Note: oneof and repeated do not work together
  repeated github.com.akuity.kargo.api.rbac.v1alpha1.Claim claims = 1;
}

message GrantRequest {
  string project = 1;
  string role = 2;
  oneof request {
    Claims user_claims = 3;
    github.com.akuity.kargo.api.rbac.v1alpha1.ResourceDetails resource_details = 4;
  }
}

message GrantResponse {
  github.com.akuity.kargo.api.rbac.v1alpha1.Role role = 1;
}

message ListRolesRequest {
  string project = 1;
  bool as_resources = 2;
}

message ListRolesResponse {
  // Note: oneof and repeated do not work together
  repeated github.com.akuity.kargo.api.rbac.v1alpha1.Role roles = 1;
  repeated github.com.akuity.kargo.api.rbac.v1alpha1.RoleResources resources = 2;
}

message RevokeRequest {
  string project = 1;
  string role = 2;
  oneof request {
    Claims user_claims = 3;
    github.com.akuity.kargo.api.rbac.v1alpha1.ResourceDetails resource_details = 4;
  }
}

message RevokeResponse {
  github.com.akuity.kargo.api.rbac.v1alpha1.Role role = 1;
}

message UpdateRoleRequest {
  github.com.akuity.kargo.api.rbac.v1alpha1.Role role = 1;
}

message UpdateRoleResponse {
  github.com.akuity.kargo.api.rbac.v1alpha1.Role role = 1;
}

message ListAnalysisTemplateConfigMapsRequest {
  string project = 1;
}

message ListAnalysisTemplateConfigMapsResponse {
  repeated k8s.io.api.core.v1.ConfigMap config_maps = 1;
}

message GetAnalysisTemplateConfigMapRequest {
  string project = 1;
  string name = 2;
  RawFormat format = 3;
}

message GetAnalysisTemplateConfigMapResponse {
  oneof result {
    k8s.io.api.core.v1.ConfigMap config_map = 1;
    bytes raw = 2;
  }
}

message ListAnalysisTemplateSecretsRequest {
  string project = 1;
}

message ListAnalysisTemplateSecretsResponse {
  repeated k8s.io.api.core.v1.Secret secrets = 1;
}

message GetAnalysisTemplateSecretRequest {
  string project = 1;
  string name = 2;
  RawFormat format = 3;
}

message GetAnalysisTemplateSecretResponse {
  oneof result {
    k8s.io.api.core.v1.Secret secret = 1;
    bytes raw = 2;
  }
}
