Files
quixos-protocol/proto/camino/api.proto
T
Timothy J. Aveni 5634d3ee78 Add checked workspace-interface query roots
Implement scoped interface extents across QX, generated bindings, SDK,
Orch, Camino and browser queries. Preserve native projection, aggregation,
pagination and watch invalidation without synthetic persisted objects.
Validate exact query grants and scope freshness on execution and replay.
Add local PostgreSQL, transport, browser and code-generation coverage.

C1 implementation slice only: full-text indexes and Studio search adoption
(C2/C3) remain tracked in the implementation handoff. No publication or deployment.
2026-09-19 10:18:47 -07:00

366 lines
9.5 KiB
Protocol Buffer

syntax = "proto3";
package camino;
import "camino/schema.proto";
import "quixos/refs.proto";
service CaminoService {
rpc ExecuteQuery(QueryRequest) returns (QueryResponse);
rpc QueryChanges(QueryChangesRequest) returns (QueryChangesResponse);
rpc InstallPersistencePlan(InstallPersistencePlanRequest) returns (InstallPersistencePlanResponse);
rpc GetPersistencePlan(GetPersistencePlanRequest) returns (GetPersistencePlanResponse);
rpc CreateObject(CreateObjectRequest) returns (CreateObjectResponse);
rpc GetObject(GetObjectRequest) returns (GetObjectResponse);
rpc ListObjects(ListObjectsRequest) returns (ListObjectsResponse);
rpc ReadState(ReadStateRequest) returns (ReadStateResponse);
rpc WriteState(WriteStateRequest) returns (WriteStateResponse);
rpc ConnectEdge(ConnectEdgeRequest) returns (ConnectEdgeResponse);
rpc ResolveEdge(ResolveEdgeRequest) returns (ResolveEdgeResponse);
rpc DisconnectEdge(DisconnectEdgeRequest) returns (DisconnectEdgeResponse);
rpc ReadCollection(ResolveEdgeRequest) returns (ReadCollectionResponse);
rpc ReplaceCollection(ReplaceCollectionRequest) returns (ReadCollectionResponse);
rpc ListOps(ListOpsRequest) returns (ListOpsResponse);
rpc WatchObject(WatchObjectRequest) returns (stream WatchObjectEvent);
}
message NullValue {}
message ObjectValue {
map<string, Value> fields = 1;
}
message ListValue {
repeated Value values = 1;
}
message RefValue {
string object_id = 1;
}
message CrdtValue {
string type = 1;
string encoding = 2;
bytes payload = 3;
}
message StateValueSource {
string object_id = 1;
string slot_id = 2;
string value_type_json = 3;
string storage_policy_json = 4;
uint64 revision = 5;
// CRDT-backed state is still read as its materialized Value. The snapshot
// travels with the writable source identity so a client can retain and
// advance a local replica without exposing the document to package code.
CrdtValue crdt_snapshot = 6;
}
message ValueSource {
StateValueSource state = 1;
}
message Value {
oneof kind {
NullValue null_value = 1;
bool bool_value = 2;
double number_value = 3;
string string_value = 4;
string integer_value = 5;
bytes bytes_value = 6;
ObjectValue object_value = 7;
ListValue list_value = 8;
RefValue ref_value = 9;
CrdtValue crdt_value = 10;
}
ValueSource source = 11;
// Trusted query coordinator annotation. Travels with values through residual
// row selection, then is removed in favor of final-path hydration metadata.
QueryFieldOrigin query_origin = 12;
}
message QueryFieldOrigin {
string selection_id = 1;
string atom_id = 2;
string interface_revision_id = 3;
string member_id = 4;
StateValueSource source = 5;
}
message QueryLiveField {
repeated QueryPathPart path = 1;
string selection_id = 2;
string object_id = 3;
quixos.CapabilityRef capability = 4;
string watch_operation_id = 5;
string setter_operation_id = 6;
quixos.FieldEditing editing = 7;
StateValueSource source = 8;
}
message InstallPersistencePlanRequest {
PersistencePlan plan = 1;
}
message InstallPersistencePlanResponse {
PersistencePlan plan = 1;
}
message GetPersistencePlanRequest {}
message GetPersistencePlanResponse {
PersistencePlan plan = 1;
}
message CreateObjectRequest {
string atom_id = 1;
map<string, Value> initial_state = 2;
}
message CreateObjectResponse {
CaminoObject object = 1;
}
message GetObjectRequest {
string object_id = 1;
}
message GetObjectResponse {
CaminoObject object = 1;
}
message ListObjectsRequest {
string atom_id = 1;
}
message ListObjectsResponse {
repeated CaminoObject objects = 1;
}
message ReadStateRequest {
string object_id = 1;
string slot_id = 2;
}
message ReadStateResponse {
Value value = 1;
}
message WriteStateRequest {
string object_id = 1;
string slot_id = 2;
Value value = 3;
string client_mutation_id = 4;
}
message WriteStateResponse {
Value value = 1;
CaminoObject object = 2;
}
message ConnectEdgeRequest {
string edge_type_id = 1;
string projection_id = 2;
string object_id = 3;
string target_object_id = 4;
optional int32 ordinal = 5;
optional int32 target_ordinal = 6;
}
message ConnectEdgeResponse {
CaminoEdge edge = 1;
}
message ResolveEdgeRequest {
string object_id = 1;
string edge_type_id = 2;
string projection_id = 3;
}
message ResolveEdgeResponse {
repeated CaminoEdge edges = 1;
}
message DisconnectEdgeRequest {
string edge_id = 1;
}
message DisconnectEdgeResponse {
string edge_id = 1;
}
message CollectionEntry {
// Existing entry identity to preserve; empty allocates a new canonical edge.
string edge_id = 1;
string target_object_id = 2;
Value key = 3;
}
message ReadCollectionResponse {
uint64 revision = 1;
repeated CollectionEntry entries = 2;
}
message ReplaceCollectionRequest {
string object_id = 1;
string edge_type_id = 2;
string projection_id = 3;
uint64 expected_revision = 4;
repeated CollectionEntry entries = 5;
}
message ListOpsRequest {
string object_id = 1;
}
message ListOpsResponse {
repeated CaminoOp ops = 1;
}
message WatchObjectRequest {
string object_id = 1;
string after_op_id = 2;
bool include_snapshot = 3;
// Managed runtimes must watch only their injected attachments.
repeated string attachment_ids = 4;
}
message WatchObjectEvent {
string object_id = 1;
CaminoObject snapshot = 2;
CaminoOp op = 3;
}
message CaminoObject {
string id = 1;
string atom_id = 2;
string workspace_revision_id = 3;
string created_at = 4;
string updated_at = 5;
map<string, Value> state = 6;
map<string, uint64> state_revisions = 7;
}
message CaminoEdge {
string id = 1;
string edge_type_id = 2;
string first_object_id = 3;
string second_object_id = 4;
string first_projection_id = 5;
string second_projection_id = 6;
optional int32 first_ordinal = 7;
optional int32 second_ordinal = 8;
string created_at = 9;
string first_key_json = 10;
string second_key_json = 11;
}
message CaminoOp {
string id = 1;
string object_id = 2;
string op_kind = 3;
Value payload = 4;
string actor = 5;
string created_at = 6;
string client_mutation_id = 7;
}
message QueryRequest {
string query_id = 1;
oneof root {
string object_id = 2;
quixos.WorkspaceQueryScope workspace_scope = 5;
}
map<string, Value> variables = 3;
// Typed callers require this exact checked definition. Administrative/raw
// callers may omit it to explicitly select the currently installed definition.
string expected_definition_digest = 4;
}
message QueryPathPart {
oneof part {
string field = 1;
uint32 index = 2;
}
}
message QueryPendingField {
repeated QueryPathPart path = 1;
string object_id = 2;
string interface_revision_id = 3;
string member_id = 4;
string operation_id = 5;
string value_type_json = 6;
// Internal residual facts are separate from the authored result projection.
optional uint32 residual_window = 7;
uint32 residual_row = 8;
string residual_field = 9;
optional uint32 relational_capture = 10;
uint32 captured_object = 11;
}
message QueryStats {
uint32 sql_count = 1;
double sql_ms = 2;
uint32 rpc_count = 3;
double rpc_ms = 4;
uint32 result_bytes = 5;
double preparation_ms = 6;
double total_ms = 7;
uint32 relational_stages = 8;
uint32 captured_candidates = 9;
double relational_ms = 10;
double residual_ms = 11;
}
message QueryResponse {
Value value = 1;
string data_version = 2;
string binding_digest = 3;
repeated QueryPendingField pending = 4;
QueryStats stats = 5;
// Redeemable only through the host's private control socket, not an RPC grant.
string preparation_token = 6;
repeated QueryFieldFailure errors = 7;
repeated QueryResidualWindow residual_windows = 8;
// Native reads share one database snapshot; package enrichment does not.
string consistency = 9; // native-snapshot | mixed
repeated QueryRelationalCapture relational_captures = 10;
repeated QueryLiveField live_fields = 11;
}
// Private coordinator input, removed before publishing a result. Memberships
// and native facts share one snapshot; package reads are sampled afterwards.
message QueryCapturedMember {
string object_id = 1;
string entry_id = 2;
Value map_key = 3;
}
message QueryCapturedMembers {
repeated QueryCapturedMember entries = 1;
}
message QueryCapturedObject {
string object_id = 1;
map<string, Value> fields = 2;
map<string, string> field_types = 3;
map<string, QueryCapturedMembers> relationships = 4;
}
message QueryRelationalCapture {
repeated QueryPathPart path = 1;
QueryRelationalPlan plan = 2;
string root_object_id = 3;
repeated QueryCapturedObject objects = 4;
string variables_json = 5;
uint32 row_limit = 6;
uint32 candidate_limit = 7;
optional uint32 residual_window = 8;
repeated string result_path = 9;
}
message QueryResidualRow {
string entry_id = 1;
map<string, Value> fields = 2;
}
message QueryResidualOrder {
string field = 1;
bool descending = 2;
}
message QueryResidualWindow {
repeated QueryPathPart path = 1;
repeated QueryResidualRow rows = 2;
string predicate_json = 3;
repeated QueryResidualOrder order = 4;
uint32 limit = 5;
bool bounded_all = 6;
repeated QuerySelection selection = 7;
map<string, string> field_types = 8;
bool relational = 9;
repeated string matched_entries = 10;
}
message QueryFieldFailure {
repeated QueryPathPart path = 1;
string error = 2;
}
message QueryChangesRequest {
string query_id = 1;
oneof root {
string object_id = 2;
quixos.WorkspaceQueryScope workspace_scope = 4;
}
string data_version = 3;
}
message QueryChangesResponse {
bool changed = 1;
}