syntax = "proto3"; package forest.v1; import "forest/v1/releases.proto"; // ── Policy types ──────────────────────────────────────────────────── enum PolicyType { POLICY_TYPE_UNSPECIFIED = 0; POLICY_TYPE_SOAK_TIME = 1; POLICY_TYPE_BRANCH_RESTRICTION = 2; POLICY_TYPE_EXTERNAL_APPROVAL = 3; } message SoakTimeConfig { // Environment that must have a successful deploy before target is allowed string source_environment = 1; // Environment that is gated by this policy string target_environment = 2; // Seconds to wait after source environment succeeds int64 duration_seconds = 3; } message BranchRestrictionConfig { // Environment that is restricted string target_environment = 1; // Regex that source branch must match string branch_pattern = 2; } message ExternalApprovalConfig { string target_environment = 1; int32 required_approvals = 2; } // ── External approval state ───────────────────────────────────────── message ExternalApprovalState { int32 required_approvals = 1; int32 current_approvals = 2; repeated ExternalApprovalDecisionEntry decisions = 3; } message ExternalApprovalDecisionEntry { string user_id = 1; string username = 2; string decision = 3; string decided_at = 4; optional string comment = 5; } // ── Policy resource ───────────────────────────────────────────────── message Policy { string id = 1; string name = 2; bool enabled = 3; PolicyType policy_type = 4; oneof config { SoakTimeConfig soak_time = 10; BranchRestrictionConfig branch_restriction = 11; ExternalApprovalConfig external_approval = 12; } string created_at = 20; string updated_at = 21; } // ── Policy evaluation result ──────────────────────────────────────── message PolicyEvaluation { string policy_name = 1; PolicyType policy_type = 2; bool passed = 3; // Human-readable explanation when blocked string reason = 4; optional ExternalApprovalState approval_state = 10; } // ── CRUD messages ─────────────────────────────────────────────────── message CreatePolicyRequest { Project project = 1; string name = 2; PolicyType policy_type = 3; oneof config { SoakTimeConfig soak_time = 10; BranchRestrictionConfig branch_restriction = 11; ExternalApprovalConfig external_approval = 12; } } message CreatePolicyResponse { Policy policy = 1; } message UpdatePolicyRequest { Project project = 1; string name = 2; optional bool enabled = 3; oneof config { SoakTimeConfig soak_time = 10; BranchRestrictionConfig branch_restriction = 11; ExternalApprovalConfig external_approval = 12; } } message UpdatePolicyResponse { Policy policy = 1; } message DeletePolicyRequest { Project project = 1; string name = 2; } message DeletePolicyResponse {} message ListPoliciesRequest { Project project = 1; } message ListPoliciesResponse { repeated Policy policies = 1; } message EvaluatePoliciesRequest { Project project = 1; string target_environment = 2; // For branch restriction checks optional string branch = 3; optional string release_intent_id = 4; } message EvaluatePoliciesResponse { repeated PolicyEvaluation evaluations = 1; bool all_passed = 2; } // ── External approval RPC messages ────────────────────────────────── message ExternalApproveReleaseRequest { Project project = 1; string release_intent_id = 2; string target_environment = 3; optional string comment = 4; bool force_bypass = 5; } message ExternalApproveReleaseResponse { ExternalApprovalState state = 1; } message ExternalRejectReleaseRequest { Project project = 1; string release_intent_id = 2; string target_environment = 3; optional string comment = 4; } message ExternalRejectReleaseResponse { ExternalApprovalState state = 1; } message GetExternalApprovalStateRequest { Project project = 1; string release_intent_id = 2; string target_environment = 3; } message GetExternalApprovalStateResponse { ExternalApprovalState state = 1; } service PolicyService { rpc CreatePolicy(CreatePolicyRequest) returns (CreatePolicyResponse); rpc UpdatePolicy(UpdatePolicyRequest) returns (UpdatePolicyResponse); rpc DeletePolicy(DeletePolicyRequest) returns (DeletePolicyResponse); rpc ListPolicies(ListPoliciesRequest) returns (ListPoliciesResponse); rpc EvaluatePolicies(EvaluatePoliciesRequest) returns (EvaluatePoliciesResponse); rpc ExternalApproveRelease(ExternalApproveReleaseRequest) returns (ExternalApproveReleaseResponse); rpc ExternalRejectRelease(ExternalRejectReleaseRequest) returns (ExternalRejectReleaseResponse); rpc GetExternalApprovalState(GetExternalApprovalStateRequest) returns (GetExternalApprovalStateResponse); }