// SPDX-License-Identifier: Apache-2.0
// Inventory read/write/watch.
syntax = "proto3";

package kyvernon.v1;

import "kyvernon/v1/common.proto";

// Reads, writes and watches the objects of the inventory.
service InventoryService {
  // One object by id.
  rpc GetObject(GetObjectRequest) returns (Object);
  // Objects of one kind, optionally under a parent, paginated by id.
  rpc ListObjects(ListObjectsRequest) returns (ListObjectsResponse);
  // Direct children of an object, any kind.
  rpc GetChildren(GetChildrenRequest) returns (ListObjectsResponse);
  // Change feed after a version. Yields retained history first, then live
  // changes. A Resync item means the client must re-read and resume from the
  // given version.
  rpc WatchChanges(WatchChangesRequest) returns (stream WatchItem);
  // Creates an object of `kind` under `parent` with a JSON body.
  rpc CreateObject(CreateObjectRequest) returns (Object);
  // Replaces an object's body (compare-and-set on `expected_version`).
  rpc UpdateObject(UpdateObjectRequest) returns (Object);
  // Deletes an object.
  rpc DeleteObject(DeleteObjectRequest) returns (Empty);
}

// Read consistency: linearizable through the leader, or the local copy of the controller that answers.
enum Consistency {
  CONSISTENCY_LINEARIZABLE = 0;
  CONSISTENCY_LOCAL = 1;
}

// Reads one object.
message GetObjectRequest {
  // Id of the object.
  string id = 1;
  // Read consistency.
  Consistency consistency = 2;
}

// Lists objects of one kind.
message ListObjectsRequest {
  // Object kind to list.
  string kind = 1;
  // Only the objects under this parent; empty for all.
  string parent = 2;
  // Only the objects whose name starts with this text.
  string name_prefix = 3;
  // Only the objects changed after this store version; 0 for all.
  uint64 changed_after = 4;
  // Paging.
  PageRequest page = 5;
  // Read consistency.
  Consistency consistency = 6;
}

// A page of objects.
message ListObjectsResponse {
  // The objects of the page.
  repeated Object items = 1;
  // Store version and cursor of the next page.
  PageInfo page = 2;
}

// Reads the direct children of an object.
message GetChildrenRequest {
  // Id of the parent.
  string id = 1;
  // Read consistency.
  Consistency consistency = 2;
}

// Starts the change feed.
message WatchChangesRequest {
  // Store version to continue after; 0 starts at the oldest retained change.
  uint64 since = 1;
  // Only these kinds (empty = all).
  repeated string kinds = 2;
}

// What a change did to an object.
enum ChangeKind {
  CHANGE_KIND_CREATED = 0;
  CHANGE_KIND_UPDATED = 1;
  CHANGE_KIND_DELETED = 2;
}

// One change of one object.
message Change {
  // Created, updated or deleted.
  ChangeKind kind = 1;
  // The object after the change (its last state for a deletion).
  Object object = 2;
}

// The changes of one store version.
message ChangeSet {
  // Store version of the changes.
  uint64 version = 1;
  // Time of the change, RFC 3339.
  string at = 2;
  // User or service that made the change.
  string actor = 3;
  // The changed objects.
  repeated Change changes = 4;
}

// The feed lost history: read the objects again and resume after `version`.
message Resync {
  // Store version to resume after.
  uint64 version = 1;
}

// One item of the change feed: a change set or a resync.
message WatchItem {
  oneof item {
    // Changes of one store version.
    ChangeSet changes = 1;
    // The client must read again.
    Resync resync = 2;
  }
}

// Creates an object.
message CreateObjectRequest {
  // Object kind to create.
  string kind = 1;
  // Id of the parent.
  string parent = 2;
  // Body of the object as JSON.
  string data_json = 3;
  // Key that makes a retried request create the object once.
  string idempotency_key = 4;
}

// Replaces the body of an object.
message UpdateObjectRequest {
  // Id of the object.
  string id = 1;
  // Version the change is based on; a newer version refuses it with `CONFLICT`.
  uint64 expected_version = 2;
  // New body as JSON.
  string data_json = 3;
}

// Deletes an object.
message DeleteObjectRequest {
  // Id of the object.
  string id = 1;
  // Version the deletion is based on; 0 deletes any version.
  uint64 expected_version = 2;
  // Also delete the objects under it.
  bool cascade = 3;
}
