// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.chronicle.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "google/type/interval.proto";

option csharp_namespace = "Google.Cloud.Chronicle.V1";
option go_package = "cloud.google.com/go/chronicle/apiv1/chroniclepb;chroniclepb";
option java_multiple_files = true;
option java_outer_classname = "FindingsRefinementProto";
option java_package = "com.google.cloud.chronicle.v1";
option php_namespace = "Google\\Cloud\\Chronicle\\V1";
option ruby_package = "Google::Cloud::Chronicle::V1";
option (google.api.resource_definition) = {
  type: "chronicle.googleapis.com/CuratedRuleSet"
  pattern: "projects/{project}/locations/{location}/instances/{instance}/curatedRuleSetCategories/{category}/curatedRuleSets/{rule_set}"
};

// FindingsRefinementService provides an interface for filtering out
// findings that are unlikely to be real threats to prevent them
// from triggering alerts or notifications.
service FindingsRefinementService {
  option (google.api.default_host) = "chronicle.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/chronicle,"
      "https://www.googleapis.com/auth/chronicle.readonly,"
      "https://www.googleapis.com/auth/cloud-platform";

  // Gets a single findings refinement.
  rpc GetFindingsRefinement(GetFindingsRefinementRequest)
      returns (FindingsRefinement) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/instances/*/findingsRefinements/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists a collection of findings refinements.
  rpc ListFindingsRefinements(ListFindingsRefinementsRequest)
      returns (ListFindingsRefinementsResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/locations/*/instances/*}/findingsRefinements"
    };
    option (google.api.method_signature) = "parent";
  }

  // Creates a new findings refinement.
  rpc CreateFindingsRefinement(CreateFindingsRefinementRequest)
      returns (FindingsRefinement) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*/instances/*}/findingsRefinements"
      body: "findings_refinement"
    };
    option (google.api.method_signature) = "parent,findings_refinement";
  }

  // Updates a findings refinement.
  rpc UpdateFindingsRefinement(UpdateFindingsRefinementRequest)
      returns (FindingsRefinement) {
    option (google.api.http) = {
      patch: "/v1/{findings_refinement.name=projects/*/locations/*/instances/*/findingsRefinements/*}"
      body: "findings_refinement"
    };
    option (google.api.method_signature) = "findings_refinement,update_mask";
  }

  // Gets a findings refinement deployment.
  rpc GetFindingsRefinementDeployment(GetFindingsRefinementDeploymentRequest)
      returns (FindingsRefinementDeployment) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/instances/*/findingsRefinements/*/deployment}"
    };
    option (google.api.method_signature) = "name";
  }

  // Updates a findings refinement deployment.
  rpc UpdateFindingsRefinementDeployment(
      UpdateFindingsRefinementDeploymentRequest)
      returns (FindingsRefinementDeployment) {
    option (google.api.http) = {
      patch: "/v1/{findings_refinement_deployment.name=projects/*/locations/*/instances/*/findingsRefinements/*/deployment}"
      body: "findings_refinement_deployment"
    };
    option (google.api.method_signature) =
        "findings_refinement_deployment,update_mask";
  }

  // Lists all findings refinement deployments.
  rpc ListAllFindingsRefinementDeployments(
      ListAllFindingsRefinementDeploymentsRequest)
      returns (ListAllFindingsRefinementDeploymentsResponse) {
    option (google.api.http) = {
      get: "/v1/{instance=projects/*/locations/*/instances/*}:listAllFindingsRefinementDeployments"
    };
    option (google.api.method_signature) = "instance";
  }

  // Returns findings refinement activity for a specific findings refinement.
  rpc ComputeFindingsRefinementActivity(
      ComputeFindingsRefinementActivityRequest)
      returns (ComputeFindingsRefinementActivityResponse) {
    option (google.api.http) = {
      post: "/v1/{name=projects/*/locations/*/instances/*/findingsRefinements/*}:computeFindingsRefinementActivity"
      body: "*"
    };
    option (google.api.method_signature) = "name";
  }

  // Returns findings refinement activity for all findings refinements.
  rpc ComputeAllFindingsRefinementActivities(
      ComputeAllFindingsRefinementActivitiesRequest)
      returns (ComputeAllFindingsRefinementActivitiesResponse) {
    option (google.api.http) = {
      post: "/v1/{instance=projects/*/locations/*/instances/*}:computeAllFindingsRefinementActivities"
      body: "*"
    };
    option (google.api.method_signature) = "instance";
  }
}

// The type of findings refinement, which determines what the findings
// refinement runs over and the mechanism by which it runs.
enum FindingsRefinementType {
  // The findings refinement type is unspecified.
  FINDINGS_REFINEMENT_TYPE_UNSPECIFIED = 0;

  // Indicates that the findings refinement is a detection exclusion and
  // should exclude matching detections.
  DETECTION_EXCLUSION = 1;
}

// Represents a set of logic conditions used to refine various types of
// findings such as curated rule detections.
message FindingsRefinement {
  option (google.api.resource) = {
    type: "chronicle.googleapis.com/FindingsRefinement"
    pattern: "projects/{project}/locations/{location}/instances/{instance}/findingsRefinements/{findings_refinement}"
  };

  // Full resource name for the findings refinement.
  // Format:
  // projects/{project}/locations/{region}/instances/{instance}/findingsRefinements/{findings_refinement}
  string name = 1;

  // Display name of the findings refinement.
  string display_name = 2;

  // The type of findings refinement.
  FindingsRefinementType type = 3;

  // Output only. The timestamp of when the findings refinement was created.
  google.protobuf.Timestamp create_time = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The timestamp of when the findings refinement was last
  // updated.
  google.protobuf.Timestamp update_time = 5
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // The query for the findings refinement. Works in conjunction with the type
  // field to determine the findings refinement behavior. The syntax of this
  // query is the same as a UDM search string. See the following for more
  // information:
  // https://cloud.google.com/chronicle/docs/investigation/udm-search
  string query = 7;

  // Optional. The outcome filters for the findings refinement. These allow you
  // to specify filters that are applied to the outcome variables in the
  // detection. All filters must be true for a detection to match the findings
  // refinement.
  repeated OutcomeFilter outcome_filters = 8
      [(google.api.field_behavior) = OPTIONAL];
}

// The FindingsRefinementDeployment resource represents the deployment state of
// a findings refinement.
message FindingsRefinementDeployment {
  option (google.api.resource) = {
    type: "chronicle.googleapis.com/FindingsRefinementDeployment"
    pattern: "projects/{project}/locations/{location}/instances/{instance}/findingsRefinements/{findings_refinement}/deployment"
  };

  // The resources which the findings refinement is applied to. Corresponds to
  // the type of the findings refinement.
  oneof FindingsRefinementApplication {
    // The resources which the detection exclusion is applied to.
    DetectionExclusionApplication detection_exclusion_application = 5;
  }

  // Required. The resource name of the findings refinement deployment.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}/findingsRefinements/{findings_refinement}/deployment
  string name = 1 [(google.api.field_behavior) = REQUIRED];

  // Whether the findings refinement is currently deployed continuously against
  // incoming findings.
  bool enabled = 2;

  // The archive state of the findings refinement deployment.
  // Cannot be set to true unless enabled is set to false.
  // If currently set to true, enabled cannot be updated to true.
  bool archived = 3;

  // Output only. The timestamp when the findings refinement deployment was last
  // updated.
  google.protobuf.Timestamp update_time = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Describes the detectors a detection exclusion is applied to.
message DetectionExclusionApplication {
  // The CuratedRuleSets this detection exclusion applies to.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}/curatedRuleSetCategories/{category}/curatedRuleSets/{rule_set}
  repeated string curated_rule_sets = 1 [(google.api.resource_reference) = {
    type: "chronicle.googleapis.com/CuratedRuleSet"
  }];

  // The CuratedRules this detection exclusion applies to.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}/curatedRules/{rule}
  repeated string curated_rules = 2 [(google.api.resource_reference) = {
    type: "chronicle.googleapis.com/CuratedRule"
  }];

  // Optional. The Rules this detection exclusion applies to.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}/rules/{rule}
  repeated string rules = 3 [
    (google.api.field_behavior) = OPTIONAL,
    (google.api.resource_reference) = { type: "chronicle.googleapis.com/Rule" }
  ];

  // Output only. The deleted CuratedRuleSets this detection exclusion applies
  // to. Indicates to the customer that the detection exclusion no longer
  // applies to the rule sets, so the detection exclusion should be updated.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}/curatedRuleSetCategories/{category}/curatedRuleSets/{rule_set}
  repeated string deleted_curated_rule_sets = 4 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/CuratedRuleSet"
    }
  ];
}

// The activity for a specific findings refinement.
message FindingsRefinementActivity {
  // The activity for the findings refinement.
  oneof Activity {
    // The activity for the detection exclusion.
    DetectionExclusionActivity detection_exclusion_activity = 2;
  }

  // Required. Full resource name for the findings refinement this activity
  // corresponds to. Format:
  // projects/{project}/locations/{region}/instances/{instance}/findingsRefinements/{findings_refinement}
  string findings_refinement = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/FindingsRefinement"
    }
  ];
}

// The activity for a findings refinement that is a detection exclusion. The
// activity is broken down per detector.
message DetectionExclusionActivity {
  // The activity for a findings refinement that is a detection exclusion broken
  // down for one specific detector.
  message DetectionExclusionDetectorActivity {
    oneof detector_name {
      // Full resource name for the curated rule this activity corresponds to.
      // Format:
      // projects/{project}/locations/{location}/instances/{instance}/curatedRules/{rule}
      string curated_rule = 1 [(google.api.resource_reference) = {
        type: "chronicle.googleapis.com/CuratedRule"
      }];

      // Full resource name for the curated rule set this activity corresponds
      // to. This field will only be set if the customer has access to the
      // curated rule set the exclusion is applied to.
      // Format:
      // projects/{project}/locations/{location}/instances/{instance}/curatedRuleSetCategories/{curated_rule_set_category}/curatedRuleSets/{curated_rule_set}
      string curated_rule_set = 2 [(google.api.resource_reference) = {
        type: "chronicle.googleapis.com/CuratedRuleSet"
      }];

      // Full resource name for the rule this activity corresponds to.
      // Format:
      // projects/{project}/locations/{location}/instances/{instance}/rules/{rule}
      string rule = 5 [(google.api.resource_reference) = {
        type: "chronicle.googleapis.com/Rule"
      }];

      // Full resource name for the deleted curated rule set this activity
      // corresponds to. This field will only be set if the customer does
      // not have access to the curated rule set the exclusion is applied to.
      // Format:
      // projects/{project}/locations/{location}/instances/{instance}/curatedRuleSetCategories/{curated_rule_set_category}/curatedRuleSets/{curated_rule_set}
      string deleted_curated_rule_set = 6 [(google.api.resource_reference) = {
        type: "chronicle.googleapis.com/CuratedRuleSet"
      }];
    }

    // The number of detections for the detector that were excluded by the
    // detection exclusion.
    int64 excluded_detection_count = 3;

    // The total number of detections found by the detector. This includes both
    // excluded detections and non-excluded detections.
    int64 total_detection_count = 4;
  }

  // The activity for the detection exclusion broken down by detector.
  repeated DetectionExclusionDetectorActivity
      detection_exclusion_detector_activities = 1;
}

// Request message for GetFindingsRefinement method.
message GetFindingsRefinementRequest {
  // Required. The name of the findings refinement to retrieve.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}/findingsRefinements/{findings_refinement}
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/FindingsRefinement"
    }
  ];
}

// Request message for ListFindingsRefinements method.
message ListFindingsRefinementsRequest {
  // Required. The parent, which owns this collection of findings refinements.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "chronicle.googleapis.com/FindingsRefinement"
    }
  ];

  // The maximum number of findings refinements to return. The service may
  // return fewer than this value. If unspecified, at most 100 rules will be
  // returned. The maximum value is 1000; values above 1000 will be coerced to
  // 1000.
  int32 page_size = 2;

  // A page token, received from a previous `ListFindingsRefinements` call.
  // Provide this to retrieve the subsequent page.
  string page_token = 3;
}

// Response message for ListFindingsRefinements method.
message ListFindingsRefinementsResponse {
  // List of findings refinements.
  repeated FindingsRefinement findings_refinements = 1;

  // A token, which can be sent as `page_token` to retrieve the next page. If
  // this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

// Request message for CreateFindingsRefinement method.
message CreateFindingsRefinementRequest {
  // Required. The parent resource where this findings refinement will be
  // created. Format:
  // projects/{project}/locations/{location}/instances/{instance}
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "chronicle.googleapis.com/FindingsRefinement"
    }
  ];

  // Required. The findings refinement to create.
  FindingsRefinement findings_refinement = 2
      [(google.api.field_behavior) = REQUIRED];
}

// Request message for UpdateFindingsRefinement method.
message UpdateFindingsRefinementRequest {
  // Required. The findings refinement to update.
  //
  // The findings refinement's `name` field is used to identify the findings
  // refinement to update.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}/findingsRefinements/{findings_refinement}
  FindingsRefinement findings_refinement = 1
      [(google.api.field_behavior) = REQUIRED];

  // Optional. The list of fields to update. If `*` is provided, all fields will
  // be updated.
  google.protobuf.FieldMask update_mask = 2
      [(google.api.field_behavior) = OPTIONAL];
}

// Request message for GetFindingsRefinementDeployment method.
message GetFindingsRefinementDeploymentRequest {
  // Required. The name of the findings refinement to retrieve.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}/findingsRefinements/{findings_refinement}/deployment
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/FindingsRefinementDeployment"
    }
  ];
}

// Request message for UpdateFindingsRefinementDeployment method.
message UpdateFindingsRefinementDeploymentRequest {
  // Required. The findings refinement deployment to update.
  //
  // The findings refinement deployment's `name` field is used to identify the
  // findings refinement deployment to update.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}/findingsRefinements/{findings_refinement}/deployment
  FindingsRefinementDeployment findings_refinement_deployment = 1
      [(google.api.field_behavior) = REQUIRED];

  // Required. The list of fields to update. If `*` is provided, all fields will
  // be updated.
  google.protobuf.FieldMask update_mask = 2
      [(google.api.field_behavior) = REQUIRED];
}

// Request message for ListAllFindingsRefinementDeployments method.
message ListAllFindingsRefinementDeploymentsRequest {
  // Required. The name of the parent resource, which is the SecOps instance to
  // list all findings refinement deployments over. Format:
  // projects/{project}/locations/{location}/instances/{instance}
  string instance = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/Instance"
    }
  ];

  // The maximum number of findings refinement deployments to return. The
  // service may return fewer than this value. If unspecified, at most 100 rule
  // deployments will be returned. The maximum value is 1000; values above 1000
  // will be coerced to 1000.
  int32 page_size = 2;

  // A page token, received from a previous
  // `ListAllFindingsRefinementDeployments` call. Provide this to retrieve the
  // subsequent page.
  //
  // When paginating, all other parameters provided to
  // `ListAllFindingsRefinementDeployments` must match the call that provided
  // the page token.
  string page_token = 3;

  // A filter that can be used to retrieve specific findings refinement
  // deployments.
  // Only the following filters are allowed:
  // detection_exclusion_application.curated_rule_sets:"<curated_rule_set_name>"",
  // detection_exclusion_application.curated_rules:"<curated_rule_name>"
  string filter = 4;
}

// Response message for ListAllFindingsRefinementDeployments method.
message ListAllFindingsRefinementDeploymentsResponse {
  // List of all findings refinement deployments.
  repeated FindingsRefinementDeployment all_findings_refinement_deployments = 1;

  // A token, which can be sent as `page_token` to retrieve the next page. If
  // this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

// Outcome filter for the findings refinement. This is used to filter the
// findings refinement based on the outcome variable values.
message OutcomeFilter {
  // The operator to compare the outcome variable value with the outcome value
  // in the outcome filter.
  enum Operator {
    // The operator is unspecified.
    OPERATOR_UNSPECIFIED = 0;

    // The outcome variable value must be equal to the outcome value in the
    // outcome filter.
    EQUAL = 1;

    // The outcome variable value must contain the outcome value in the
    // outcome filter.
    CONTAINS = 2;

    // The outcome variable value must match the outcome value regex in the
    // outcome filter.
    MATCHES_REGEX = 3;

    // The outcome variable value must be a valid IP address in the outcome
    // filter value CIDR range.
    MATCHES_CIDR = 4;
  }

  // Required. The outcome variable name.
  string outcome_variable = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The value of the outcome variable to match.
  string outcome_value = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The operator to be applied to the outcome variable.
  Operator outcome_filter_operator = 3 [(google.api.field_behavior) = REQUIRED];
}

// Request message for ComputeFindingsRefinementActivity method.
message ComputeFindingsRefinementActivityRequest {
  // Required. Full resource name for the findings refinement to fetch the
  // activity for. Format:
  // projects/{project}/locations/{region}/instances/{instance}/findingsRefinements/{findings_refinement}
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/FindingsRefinement"
    }
  ];

  // The time interval the activity is measured over.
  google.type.Interval interval = 2;
}

// Response message for ComputeFindingsRefinementActivity method.
message ComputeFindingsRefinementActivityResponse {
  // The activity for the findings refinement.
  FindingsRefinementActivity activity = 1;
}

// Request message for ComputeAllFindingsRefinementActivities method.
message ComputeAllFindingsRefinementActivitiesRequest {
  // Required. The ID of the Instance to retrieve counts for.
  // Format:
  // projects/{project}/locations/{location}/instances/{instance}
  string instance = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/Instance"
    }
  ];

  // The time interval the activity is measured over.
  google.type.Interval interval = 2;
}

// Response message for ComputeAllFindingsRefinementActivities method.
message ComputeAllFindingsRefinementActivitiesResponse {
  // The activities of all findings refinements.
  repeated FindingsRefinementActivity activities = 1;
}
