syntax = "proto3";

package nominal.storage.v1;

import "buf/validate/validate.proto";
import "google/api/annotations.proto";
import "nominal/protos/gen/v1/alias.proto";
import "nominal/protos/types/time/time.proto";

option java_multiple_files = true;
option java_package = "io.nominal.storage.v1";

// A retention exemption for a dataset, representing a time range that should be preserved
// regardless of the dataset's retention policy.
message DatasetRetentionExemption {
  // The dataset this exemption applies to.
  string dataset_rid = 1 [
    (buf.validate.field).required = true,
    (nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.DatasetRid"}
  ];

  // Identifier for the source of this exemption (e.g. run RID).
  string source_id = 2 [(buf.validate.field).required = true];

  // Inclusive time range to exempt from retention.
  nominal.types.time.Range bounds = 3 [(buf.validate.field).required = true];

  optional string description = 4 [(buf.validate.field).string.max_len = 1024];
}

message UpsertDatasetRetentionExemptionRequest {
  string dataset_rid = 1 [
    (buf.validate.field).required = true,
    (nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.DatasetRid"}
  ];

  string source_id = 2 [(buf.validate.field).required = true];

  // Inclusive time range to exempt from retention.
  nominal.types.time.Range bounds = 3 [(buf.validate.field).required = true];

  optional string description = 4 [(buf.validate.field).string.max_len = 1024];
}

message UpsertDatasetRetentionExemptionResponse {
  DatasetRetentionExemption exemption = 1;
}

message DeleteDatasetRetentionExemptionRequest {
  string dataset_rid = 1 [
    (buf.validate.field).required = true,
    (nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.DatasetRid"}
  ];

  string source_id = 2 [(buf.validate.field).required = true];
}

message DeleteDatasetRetentionExemptionResponse {}

message ListDatasetRetentionExemptionsRequest {
  string dataset_rid = 1 [
    (buf.validate.field).required = true,
    (nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.DatasetRid"}
  ];

  // Filter exemptions that overlap with this time range.
  nominal.types.time.Range bounds = 2 [(buf.validate.field).required = true];

  optional int32 page_size = 3 [
    (buf.validate.field).int32.gte = 1,
    (buf.validate.field).int32.lte = 1000
  ];

  optional string next_page_token = 4 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.Token"}];
}

message ListDatasetRetentionExemptionsResponse {
  repeated DatasetRetentionExemption exemptions = 1;
  optional string next_page_token = 2 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.Token"}];
}

message KeepForever {}

message KeepUntilExpiry {
  int32 expiry_days = 1 [(buf.validate.field).int32.gt = 0];
}

message RetentionPolicy {
  oneof policy {
    option (buf.validate.oneof).required = true;
    KeepForever keep_forever = 1;
    KeepUntilExpiry keep_until_expiry = 2;
  }
}

message UpdateRetentionPolicyRequest {
  string dataset_rid = 1 [
    (buf.validate.field).required = true,
    (nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.DatasetRid"}
  ];

  // If absent, the retention policy is removed (reverts to default/keep-forever).
  optional RetentionPolicy retention_policy = 2;
}

message UpdateRetentionPolicyResponse {}

// Manages retention policies and exemptions for datasets.
service DatasetRetentionService {
  // Update or remove the retention policy for a dataset. When a policy is set,
  // data older than the policy's expiry will be deleted.
  rpc UpdateRetentionPolicy(UpdateRetentionPolicyRequest) returns (UpdateRetentionPolicyResponse) {
    option (google.api.http) = {
      put: "/storage/dataset-retention/v1/policy/{dataset_rid}"
      body: "*"
    };
  }

  // Create or update a retention exemption for a dataset. The exemption is keyed by
  // (dataset_rid, source_id) — upserting with the same key updates the time range.
  rpc UpsertDatasetRetentionExemption(UpsertDatasetRetentionExemptionRequest) returns (UpsertDatasetRetentionExemptionResponse) {
    option (google.api.http) = {
      post: "/storage/dataset-retention/v1/exemptions"
      body: "*"
    };
  }

  // Delete a retention exemption for a dataset.
  rpc DeleteDatasetRetentionExemption(DeleteDatasetRetentionExemptionRequest) returns (DeleteDatasetRetentionExemptionResponse) {
    option (google.api.http) = {delete: "/storage/dataset-retention/v1/exemptions/{dataset_rid}/{source_id}"};
  }

  // List retention exemptions for a dataset, filtered to those overlapping the given time range.
  rpc ListDatasetRetentionExemptions(ListDatasetRetentionExemptionsRequest) returns (ListDatasetRetentionExemptionsResponse) {
    option (google.api.http) = {
      post: "/storage/dataset-retention/v1/exemptions/list"
      body: "*"
    };
  }
}
