// Copyright 2025 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.bigquery.datapolicies.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/iam/v1/iam_policy.proto";
import "google/iam/v1/policy.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";

option csharp_namespace = "Google.Cloud.BigQuery.DataPolicies.V1";
option go_package = "cloud.google.com/go/bigquery/datapolicies/apiv1/datapoliciespb;datapoliciespb";
option java_multiple_files = true;
option java_outer_classname = "DataPolicyProto";
option java_package = "com.google.cloud.bigquery.datapolicies.v1";
option php_namespace = "Google\\Cloud\\BigQuery\\DataPolicies\\V1";
option ruby_package = "Google::Cloud::Bigquery::DataPolicies::V1";

// Data Policy Service provides APIs for managing the label-policy bindings.
service DataPolicyService {
  option (google.api.default_host) = "bigquerydatapolicy.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/bigquery,"
      "https://www.googleapis.com/auth/cloud-platform";

  // Creates a new data policy under a project with the given `dataPolicyId`
  // (used as the display name), policy tag, and data policy type.
  rpc CreateDataPolicy(CreateDataPolicyRequest) returns (DataPolicy) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*}/dataPolicies"
      body: "data_policy"
    };
    option (google.api.method_signature) = "parent,data_policy";
  }

  // Updates the metadata for an existing data policy. The target data policy
  // can be specified by the resource name.
  rpc UpdateDataPolicy(UpdateDataPolicyRequest) returns (DataPolicy) {
    option (google.api.http) = {
      patch: "/v1/{data_policy.name=projects/*/locations/*/dataPolicies/*}"
      body: "data_policy"
    };
    option (google.api.method_signature) = "data_policy,update_mask";
  }

  // Renames the id (display name) of the specified data policy.
  rpc RenameDataPolicy(RenameDataPolicyRequest) returns (DataPolicy) {
    option (google.api.http) = {
      post: "/v1/{name=projects/*/locations/*/dataPolicies/*}:rename"
      body: "*"
    };
    option (google.api.method_signature) = "name,new_data_policy_id";
  }

  // Deletes the data policy specified by its resource name.
  rpc DeleteDataPolicy(DeleteDataPolicyRequest)
      returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/locations/*/dataPolicies/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Gets the data policy specified by its resource name.
  rpc GetDataPolicy(GetDataPolicyRequest) returns (DataPolicy) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/dataPolicies/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // List all of the data policies in the specified parent project.
  rpc ListDataPolicies(ListDataPoliciesRequest)
      returns (ListDataPoliciesResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/locations/*}/dataPolicies"
    };
    option (google.api.method_signature) = "parent";
  }

  // Gets the IAM policy for the specified data policy.
  rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest)
      returns (google.iam.v1.Policy) {
    option (google.api.http) = {
      post: "/v1/{resource=projects/*/locations/*/dataPolicies/*}:getIamPolicy"
      body: "*"
    };
  }

  // Sets the IAM policy for the specified data policy.
  rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest)
      returns (google.iam.v1.Policy) {
    option (google.api.http) = {
      post: "/v1/{resource=projects/*/locations/*/dataPolicies/*}:setIamPolicy"
      body: "*"
    };
  }

  // Returns the caller's permission on the specified data policy resource.
  rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest)
      returns (google.iam.v1.TestIamPermissionsResponse) {
    option (google.api.http) = {
      post: "/v1/{resource=projects/*/locations/*/dataPolicies/*}:testIamPermissions"
      body: "*"
    };
  }
}

// Request message for the CreateDataPolicy method.
message CreateDataPolicyRequest {
  // Required. Resource name of the project that the data policy will belong to.
  // The format is `projects/{project_number}/locations/{location_id}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "bigquerydatapolicy.googleapis.com/DataPolicy"
    }
  ];

  // Required. The data policy to create. The `name` field does not need to be
  // provided for the data policy creation.
  DataPolicy data_policy = 2 [(google.api.field_behavior) = REQUIRED];
}

// Response message for the UpdateDataPolicy method.
message UpdateDataPolicyRequest {
  // Required. Update the data policy's metadata.
  //
  // The target data policy is determined by the `name` field.
  // Other fields are updated to the specified values based on the field masks.
  DataPolicy data_policy = 1 [(google.api.field_behavior) = REQUIRED];

  // The update mask applies to the resource. For the `FieldMask` definition,
  // see
  // https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#fieldmask
  // If not set, defaults to all of the fields that are allowed to update.
  //
  // Updates to the `name` and `dataPolicyId` fields are not allowed.
  google.protobuf.FieldMask update_mask = 2;
}

// Request message for the RenameDataPolicy method.
message RenameDataPolicyRequest {
  // Required. Resource name of the data policy to rename. The format is
  // `projects/{project_number}/locations/{location_id}/dataPolicies/{data_policy_id}`
  string name = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The new data policy id.
  string new_data_policy_id = 2 [(google.api.field_behavior) = REQUIRED];
}

// Request message for the DeleteDataPolicy method.
message DeleteDataPolicyRequest {
  // Required. Resource name of the data policy to delete. Format is
  // `projects/{project_number}/locations/{location_id}/dataPolicies/{data_policy_id}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "bigquerydatapolicy.googleapis.com/DataPolicy"
    }
  ];
}

// Request message for the GetDataPolicy method.
message GetDataPolicyRequest {
  // Required. Resource name of the requested data policy. Format is
  // `projects/{project_number}/locations/{location_id}/dataPolicies/{data_policy_id}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "bigquerydatapolicy.googleapis.com/DataPolicy"
    }
  ];
}

// Request message for the ListDataPolicies method.
message ListDataPoliciesRequest {
  // Required. Resource name of the project for which to list data policies.
  // Format is `projects/{project_number}/locations/{location_id}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "bigquerydatapolicy.googleapis.com/DataPolicy"
    }
  ];

  // The maximum number of data policies to return. Must be a value between 1
  // and 1000.
  // If not set, defaults to 50.
  int32 page_size = 2;

  // The `nextPageToken` value returned from a previous list request, if any. If
  // not set, defaults to an empty string.
  string page_token = 3;

  // Filters the data policies by policy tags that they
  // are associated with. Currently filter only supports
  // "policy<span></span>_tag" based filtering and OR based predicates. Sample
  // filter can be "policy<span></span>_tag:
  // projects/1/locations/us/taxonomies/2/policyTags/3".
  // You may also use wildcard such as "policy<span></span>_tag:
  // projects/1/locations/us/taxonomies/2*". Please note that OR predicates
  // cannot be used with wildcard filters.
  string filter = 4;
}

// Response message for the ListDataPolicies method.
message ListDataPoliciesResponse {
  // Data policies that belong to the requested project.
  repeated DataPolicy data_policies = 1;

  // Token used to retrieve the next page of results, or empty if there are no
  // more results.
  string next_page_token = 2;
}

// Represents the label-policy binding.
message DataPolicy {
  option (google.api.resource) = {
    type: "bigquerydatapolicy.googleapis.com/DataPolicy"
    pattern: "projects/{project}/locations/{location}/dataPolicies/{data_policy}"
  };

  // A list of supported data policy types.
  enum DataPolicyType {
    // Default value for the data policy type. This should not be used.
    DATA_POLICY_TYPE_UNSPECIFIED = 0;

    // Used to create a data policy for column-level security, without data
    // masking.
    COLUMN_LEVEL_SECURITY_POLICY = 3;

    // Used to create a data policy for data masking.
    DATA_MASKING_POLICY = 2;
  }

  // Label that is bound to this data policy.
  oneof matching_label {
    // Policy tag resource name, in the format of
    // `projects/{project_number}/locations/{location_id}/taxonomies/{taxonomy_id}/policyTags/{policyTag_id}`.
    string policy_tag = 4;
  }

  // The policy that is bound to this data policy.
  oneof policy {
    // The data masking policy that specifies the data masking rule to use.
    DataMaskingPolicy data_masking_policy = 5;
  }

  // Output only. Resource name of this data policy, in the format of
  // `projects/{project_number}/locations/{location_id}/dataPolicies/{data_policy_id}`.
  string name = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Type of data policy.
  DataPolicyType data_policy_type = 2;

  // User-assigned (human readable) ID of the data policy that needs to be
  // unique within a project. Used as {data_policy_id} in part of the resource
  // name.
  string data_policy_id = 3;
}

// The data masking policy that is used to specify data masking rule.
message DataMaskingPolicy {
  // The available masking rules. Learn more here:
  // https://cloud.google.com/bigquery/docs/column-data-masking-intro#masking_options.
  enum PredefinedExpression {
    // Default, unspecified predefined expression. No masking will take place
    // since no expression is specified.
    PREDEFINED_EXPRESSION_UNSPECIFIED = 0;

    // Masking expression to replace data with SHA-256 hash.
    SHA256 = 3;

    // Masking expression to replace data with NULLs.
    ALWAYS_NULL = 5;

    // Masking expression to replace data with their default masking values.
    // The default masking values for each type listed as below:
    //
    // * STRING: ""
    // * BYTES: b''
    // * INTEGER: 0
    // * FLOAT: 0.0
    // * NUMERIC: 0
    // * BOOLEAN: FALSE
    // * TIMESTAMP: 1970-01-01 00:00:00 UTC
    // * DATE: 1970-01-01
    // * TIME: 00:00:00
    // * DATETIME: 1970-01-01T00:00:00
    // * GEOGRAPHY: POINT(0 0)
    // * BIGNUMERIC: 0
    // * ARRAY: []
    // * STRUCT: NOT_APPLICABLE
    // * JSON: NULL
    DEFAULT_MASKING_VALUE = 7;

    // Masking expression shows the last four characters of text.
    // The masking behavior is as follows:
    //
    // * If text length > 4 characters: Replace text with XXXXX, append last
    // four characters of original text.
    // * If text length <= 4 characters: Apply SHA-256 hash.
    LAST_FOUR_CHARACTERS = 9;

    // Masking expression shows the first four characters of text.
    // The masking behavior is as follows:
    //
    // * If text length > 4 characters: Replace text with XXXXX, prepend first
    // four characters of original text.
    // * If text length <= 4 characters: Apply SHA-256 hash.
    FIRST_FOUR_CHARACTERS = 10;

    // Masking expression for email addresses.
    // The masking behavior is as follows:
    //
    // * Syntax-valid email address: Replace username with XXXXX. For example,
    // cloudysanfrancisco@gmail.com becomes XXXXX@gmail.com.
    // * Syntax-invalid email address: Apply SHA-256 hash.
    //
    // For more information, see [Email
    // mask](https://cloud.google.com/bigquery/docs/column-data-masking-intro#masking_options).
    EMAIL_MASK = 12;

    // Masking expression to only show the year of `Date`,
    // `DateTime` and `TimeStamp`. For example, with the
    // year 2076:
    //
    // * DATE         :  2076-01-01
    // * DATETIME     :  2076-01-01T00:00:00
    // * TIMESTAMP    :  2076-01-01 00:00:00 UTC
    //
    // Truncation occurs according to the UTC time zone. To change this, adjust
    // the default time zone using the `time_zone` system variable.
    // For more information, see the <a
    // href="https://cloud.google.com/bigquery/docs/reference/system-variables">System
    // variables reference</a>.
    DATE_YEAR_MASK = 13;
  }

  // A masking expression to bind to the data masking rule.
  oneof masking_expression {
    // A predefined masking expression.
    PredefinedExpression predefined_expression = 1;

    // The name of the BigQuery routine that contains the custom masking
    // routine, in the format of
    // `projects/{project_number}/datasets/{dataset_id}/routines/{routine_id}`.
    string routine = 3;
  }
}
