1#![allow(clippy::uninlined_format_args)] #![allow(clippy::manual_let_else)] #![allow(clippy::cast_possible_truncation)] #![allow(clippy::cast_sign_loss)] #![allow(clippy::cast_precision_loss)] #![allow(clippy::ref_option)] #![allow(clippy::match_same_arms)] #![allow(clippy::trivially_copy_pass_by_ref)] #![allow(clippy::map_unwrap_or)] #![allow(clippy::enum_glob_use)] #![allow(clippy::unused_async)] #![allow(clippy::needless_for_each)] #![allow(clippy::doc_markdown)] #![allow(clippy::missing_errors_doc)] #![allow(clippy::must_use_candidate)] #![allow(clippy::similar_names)] #![allow(clippy::needless_raw_string_hashes)] #![allow(clippy::needless_pass_by_value)] #![allow(clippy::redundant_closure_for_method_calls)] #![allow(clippy::single_match_else)] #![allow(clippy::assigning_clones)]
26#![doc = include_str!("../README.md")]
35pub mod auth;
51pub mod config;
52mod handlers;
53pub mod onboarding;
54pub mod rate_limit;
55pub mod routes;
56mod security_addon;
57pub mod tls;
58mod types;
59
60use security_addon::SecurityAddon;
61use std::sync::atomic::AtomicBool;
62use std::sync::Arc;
63use utoipa::OpenApi;
64use velesdb_core::{
65 Database, DurationHistogram, OperationalMetrics, QueryLimits, TraversalMetrics,
66};
67
68pub use onboarding::OnboardingMetrics;
69pub use types::*;
70
71pub use handlers::{
72 aggregate, analyze_collection, batch_search, bulk_delete_points, collection_diagnostics,
73 collection_sanity, compact_collection, create_collection, create_index, delete_collection,
74 delete_index, delete_point, enable_streaming, explain, flush_collection, get_collection,
75 get_collection_config, get_collection_stats, get_guardrails, get_point, get_point_relations,
76 health_check, hybrid_search, is_empty, list_collections, list_indexes, match_query,
77 multi_query_search, multi_query_search_ids, query, readiness_check, rebuild_index,
78 relate_points, reorder_for_locality, scroll_points, search, search_ids, set_point_ttl,
79 stream_insert, stream_upsert_points, text_search, unrelate_points, update_guardrails,
80 upsert_points, upsert_points_raw, vacuum_collection,
81};
82
83pub use handlers::graph::{
84 add_edge, add_edges_batch, get_edge_count, get_edges, get_node_degree, get_node_edges,
85 get_node_payload, graph_search, list_nodes, remove_edge, stream_traverse, traverse_graph,
86 traverse_parallel, upsert_node_payload, DegreeResponse, EdgeCountResponse, GraphSearchRequest,
87 GraphSearchResponse, NodeEdgeQueryParams, NodeListResponse, NodePayloadResponse,
88 ParallelTraverseRequest, StreamDoneEvent, StreamNodeEvent, StreamStatsEvent,
89 StreamTraverseParams, TraversalResultItem, TraversalStats, TraverseRequest, TraverseResponse,
90 UpsertNodePayloadRequest,
91};
92
93#[cfg(feature = "prometheus")]
94pub use handlers::metrics::{health_metrics, prometheus_metrics};
95
96#[derive(OpenApi)]
106#[openapi(
107 info(
108 title = "VelesDB API",
109 version = env!("CARGO_PKG_VERSION"),
110 description = "High-performance vector database for AI applications. \
111 Supports semantic search, HNSW indexing, and multiple distance metrics. \
112 Authentication is optional — when API keys are configured via VELESDB_API_KEYS, \
113 all endpoints except /health and /ready require a valid Bearer token.",
114 license(name = "VelesDB Core License 1.0", url = "https://github.com/cyberlife-coder/VelesDB/blob/main/LICENSE"),
115 contact(name = "VelesDB Team", url = "https://github.com/cyberlife-coder/VelesDB")
116 ),
117 security(
118 ("bearer_auth" = [])
119 ),
120 modifiers(&SecurityAddon),
121 servers(
122 (url = "/", description = "Local server")
123 ),
124 tags(
125 (name = "health", description = "Health check endpoints"),
126 (name = "collections", description = "Collection management"),
127 (name = "points", description = "Vector point operations"),
128 (name = "search", description = "Vector similarity search"),
129 (name = "query", description = "VelesQL query execution"),
130 (name = "indexes", description = "Property index management (EPIC-009)"),
131 (name = "graph", description = "Graph traversal and edge operations"),
132 (name = "guardrails", description = "Query guard-rails configuration (EPIC-048)"),
133 (name = "metrics", description = "Prometheus operational metrics")
134 ),
135 paths(
136 handlers::health::health_check,
137 handlers::health::readiness_check,
138 handlers::collections::list_collections,
139 handlers::collections::create_collection,
140 handlers::collections::get_collection,
141 handlers::collections::delete_collection,
142 handlers::collections::collection_sanity,
143 handlers::collections::is_empty,
144 handlers::collections::flush_collection,
145 handlers::admin::analyze_collection,
146 handlers::admin::get_collection_stats,
147 handlers::admin::collection_diagnostics,
148 handlers::admin::get_guardrails,
149 handlers::admin::update_guardrails,
150 handlers::points::upsert_points,
151 handlers::points::raw::upsert_points_raw,
152 handlers::points::stream_upsert_points,
153 handlers::points::stream_insert,
154 handlers::points::enable_streaming,
155 handlers::points::get_point,
156 handlers::points::delete_point,
157 handlers::points::scroll_points,
158 handlers::search::search,
159 handlers::search::batch_search,
160 handlers::search::multi_query_search,
161 handlers::search::multi_query_search_ids,
162 handlers::search::text_search,
163 handlers::search::hybrid_search,
164 handlers::search::search_ids,
165 handlers::admin::get_collection_config,
166 handlers::query::query,
167 handlers::query::aggregate,
168 handlers::query::explain,
169 handlers::indexes::create_index,
170 handlers::indexes::list_indexes,
171 handlers::indexes::delete_index,
172 handlers::graph::handlers::get_edges,
173 handlers::graph::handlers::add_edge,
174 handlers::graph::handlers::add_edges_batch,
175 handlers::graph::handlers_extended::remove_edge,
176 handlers::graph::handlers_extended::get_edge_count,
177 handlers::graph::handlers_extended::list_nodes,
178 handlers::graph::handlers_extended::get_node_edges,
179 handlers::graph::handlers_extended::get_node_payload,
180 handlers::graph::handlers_extended::upsert_node_payload,
181 handlers::graph::handlers::traverse_graph,
182 handlers::graph::handlers_extended::traverse_parallel,
183 handlers::graph::handlers::get_node_degree,
184 handlers::graph::handlers_extended::graph_search,
185 handlers::graph::stream::stream_traverse,
186 handlers::match_query::match_query,
187 handlers::admin::rebuild_index,
188 handlers::admin::vacuum_collection,
189 handlers::admin::compact_collection,
190 handlers::admin::reorder_for_locality,
191 handlers::points::bulk_delete_points,
192 handlers::points::relations::relate_points,
193 handlers::points::relations::unrelate_points,
194 handlers::points::relations::get_point_relations,
195 handlers::points::relations::set_point_ttl,
196 ),
197 components(
198 schemas(
199 CreateCollectionRequest,
200 CollectionResponse,
201 UpsertPointsRequest,
202 PointRequest,
203 StreamInsertRequest,
204 EnableStreamingRequest,
205 SearchRequest,
206 BatchSearchRequest,
207 TextSearchRequest,
208 HybridSearchRequest,
209 MultiQuerySearchRequest,
210 SearchResponse,
211 BatchSearchResponse,
212 SearchResultResponse,
213 SearchIdsResponse,
214 IdScoreResult,
215 CollectionConfigResponse,
216 ErrorResponse,
217 QueryRequest,
218 QueryResponse,
219 QueryResponseMeta,
220 AggregationResponse,
221 QueryErrorResponse,
222 QueryErrorDetail,
223 VelesqlErrorResponse,
224 VelesqlErrorDetail,
225 ExplainRequest,
226 ExplainResponse,
227 ExplainStep,
228 ExplainCost,
229 ExplainFeatures,
230 ActualStatsResponse,
231 NodeStatsResponse,
232 CreateIndexRequest,
233 IndexResponse,
234 ListIndexesResponse,
235 CollectionStatsResponse,
236 ColumnStatsResponse,
237 IndexStatsResponse,
238 ScrollRequest,
239 ScrollResponse,
240 ScrollPoint,
241 GuardRailsConfigRequest,
242 GuardRailsConfigResponse,
243 CollectionDiagnosticsResponse,
244 handlers::graph::TraverseRequest,
245 handlers::graph::TraverseResponse,
246 handlers::graph::TraversalResultItem,
247 handlers::graph::TraversalStats,
248 handlers::graph::DegreeResponse,
249 handlers::graph::AddEdgeRequest,
250 handlers::graph::AddEdgesBatchRequest,
251 handlers::graph::AddEdgesBatchResponse,
252 handlers::graph::EdgesResponse,
253 handlers::graph::EdgeResponse,
254 handlers::graph::EdgeCountResponse,
255 handlers::graph::NodeListResponse,
256 handlers::graph::NodePayloadResponse,
257 handlers::graph::UpsertNodePayloadRequest,
258 handlers::graph::ParallelTraverseRequest,
259 handlers::graph::GraphSearchRequest,
260 handlers::graph::GraphSearchResponse,
261 handlers::graph::GraphSearchResultItem,
262 handlers::graph::StreamNodeEvent,
263 handlers::graph::StreamStatsEvent,
264 handlers::graph::StreamDoneEvent,
265 handlers::match_query::MatchQueryRequest,
266 handlers::match_query::MatchQueryResponse,
267 handlers::match_query::MatchQueryResultItem,
268 handlers::match_query::MatchQueryMeta,
269 handlers::points::BulkDeleteRequest,
270 handlers::points::relations::RelateRequest,
271 handlers::points::relations::RelateResponse,
272 handlers::points::relations::RelationEdge,
273 handlers::points::relations::RelationsResponse,
274 handlers::points::relations::SetTtlRequest
275 )
276 )
277)]
278struct ApiDocBase;
279
280#[cfg(feature = "prometheus")]
283#[derive(OpenApi)]
284#[openapi(paths(handlers::metrics::prometheus_metrics))]
285struct MetricsApiDoc;
286
287pub struct ApiDoc;
290
291impl ApiDoc {
292 pub fn openapi() -> utoipa::openapi::OpenApi {
293 #[allow(unused_mut)]
294 let mut doc = ApiDocBase::openapi();
295 #[cfg(feature = "prometheus")]
296 {
297 doc = doc.merge_from(MetricsApiDoc::openapi());
298 }
299 doc
300 }
301}
302
303pub struct AppState {
308 pub db: Database,
310 pub onboarding_metrics: onboarding::OnboardingMetrics,
312 pub query_limits: parking_lot::RwLock<QueryLimits>,
314 pub ready: AtomicBool,
316 pub operational_metrics: Arc<OperationalMetrics>,
318 pub traversal_metrics: Arc<TraversalMetrics>,
320 pub query_duration_histogram: Arc<DurationHistogram>,
322}
323
324#[cfg(test)]
328#[path = "lib_tests.rs"]
329mod tests;