// In common/proto/search.proto syntax = "proto3"; package komp_ac.search; import "common.proto"; import "tables_data.proto"; service Searcher { rpc Search(SearchRequest) returns (SearchResponse); // Loads one current row at the zero-based offset using the requested filter // and ordering. Requires a table and a nonempty filter; limit is ignored. // Returns live authorized row data and one-based filtered navigation bounds. // A missing position returns NOT_FOUND. Search and row reads are not a snapshot. rpc GetFilteredRow(SearchRequest) returns (komp_ac.tables_data.GetTableDataResponse); // Up to 64 independent counts. Results preserve request order; errors are per item. rpc BatchCount(BatchCountRequest) returns (BatchCountResponse); rpc Count(SearchRequest) returns (SearchCountResponse); } service SearchHealth { rpc GetHealth(komp_ac.common.Empty) returns (SearchHealthResponse); } service SearchAdmin { rpc ReindexTableChunk(ReindexTableChunkRequest) returns (ReindexResponse); rpc ReindexTable(ReindexTableRequest) returns (ReindexResponse); rpc ReindexProfile(ReindexProfileRequest) returns (ReindexResponse); } message ReindexTableChunkRequest { string profile_name = 1; string table_name = 2; repeated int64 row_ids = 3; } message ReindexTableRequest { string profile_name = 1; string table_name = 2; } message ReindexProfileRequest { string profile_name = 1; } message ReindexResponse { uint64 row_count = 1; uint64 affected_tables = 2; } enum SearchIndexOperation { SEARCH_INDEX_OPERATION_UNSPECIFIED = 0; SEARCH_INDEX_OPERATION_UPSERT = 1; SEARCH_INDEX_OPERATION_DELETE = 2; } message SearchIndexError { int64 job_id = 1; string profile_name = 2; string table_name = 3; int64 row_id = 4; SearchIndexOperation operation = 5; int32 attempts = 6; string last_error = 7; } message SearchHealthResponse { bool enabled = 1; bool ready = 2; bool healthy = 3; uint64 pending_jobs = 4; uint64 retrying_jobs = 5; repeated SearchIndexError errors = 6; } message SearchCountResponse { uint64 count = 1; } enum MatchMode { MATCH_MODE_UNSPECIFIED = 0; MATCH_MODE_FUZZY = 1; MATCH_MODE_EXACT = 2; } message ColumnConstraint { string column = 1; string query = 2; MatchMode mode = 3; } message SearchRequest { string profile_name = 1; optional string table_name = 2; string free_query = 3; repeated ColumnConstraint must = 4; optional uint32 limit = 5; optional uint32 offset = 6; optional SearchOrder order = 7; // Current rows are the default so pickers and relationship counts never // select historical records. Callers may explicitly search immutable row // archives as well. SearchVersionScope version_scope = 8; } enum SearchVersionScope { SEARCH_VERSION_SCOPE_CURRENT = 0; SEARCH_VERSION_SCOPE_ARCHIVED = 1; SEARCH_VERSION_SCOPE_ALL = 2; } message SearchOrder { string column = 1; SearchOrderDirection direction = 2; } enum SearchOrderDirection { SEARCH_ORDER_DIRECTION_UNSPECIFIED = 0; SEARCH_ORDER_DIRECTION_ASC = 1; SEARCH_ORDER_DIRECTION_DESC = 2; } message SearchResponse { message Hit { int64 id = 1; // PostgreSQL row ID float score = 2; string content_json = 3; string table_name = 4; // Configured human-readable values for this row, in display order. repeated string row_display_values = 5; repeated string row_display_columns = 6; optional uint64 position = 7; // Version 0 means the source predates managed row versioning. New managed // rows always return a positive version. int64 version_number = 8; bool archived = 9; } repeated Hit hits = 1; } message BatchCountRequest { repeated SearchRequest requests = 1; } message BatchCountResult { oneof outcome { uint64 count = 1; string error = 2; } } message BatchCountResponse { repeated BatchCountResult results = 1; }