Skip to main content

reddb_server/application/
ports.rs

1use std::collections::BTreeMap;
2
3use crate::application::entity::{
4    apply_patch_operations_to_json, apply_patch_operations_to_storage_map,
5    apply_patch_operations_to_vector_fields, json_to_metadata_value, json_to_storage_value,
6    metadata_from_json, metadata_to_json, CreateDocumentInput, CreateEdgeInput, CreateEntityOutput,
7    CreateKvInput, CreateNodeInput, CreateRowInput, CreateRowsBatchInput,
8    CreateTimeSeriesPointInput, CreateVectorInput, DeleteEntityInput, DeleteEntityOutput,
9    PatchEntityInput, PatchEntityOperation, PatchEntityOperationType,
10};
11use crate::application::schema::{
12    CreateTableInput, CreateTimeSeriesInput, DropTableInput, DropTimeSeriesInput,
13};
14use crate::application::tree::{
15    CreateTreeInput, DeleteTreeNodeInput, DropTreeInput, InsertTreeNodeInput, MoveTreeNodeInput,
16    RebalanceTreeInput, ValidateTreeInput,
17};
18use crate::catalog::{
19    CatalogAnalyticsJobStatus, CatalogAttentionSummary, CatalogConsistencyReport,
20    CatalogGraphProjectionStatus, CatalogIndexStatus, CatalogModelSnapshot, CollectionDescriptor,
21};
22use crate::health::HealthProvider;
23use crate::physical::{ExportDescriptor, ManifestEvent, PhysicalMetadataFile, SnapshotDescriptor};
24use crate::runtime::{
25    RedDBRuntime, RuntimeFilter, RuntimeGraphCentralityAlgorithm, RuntimeGraphCentralityResult,
26    RuntimeGraphClusteringResult, RuntimeGraphCommunityResult, RuntimeGraphComponentsMode,
27    RuntimeGraphComponentsResult, RuntimeGraphCyclesResult, RuntimeGraphDirection,
28    RuntimeGraphHitsResult, RuntimeGraphNeighborhoodResult, RuntimeGraphPathAlgorithm,
29    RuntimeGraphPathResult, RuntimeGraphPattern, RuntimeGraphProjection,
30    RuntimeGraphPropertiesResult, RuntimeGraphTopologicalSortResult, RuntimeGraphTraversalResult,
31    RuntimeGraphTraversalStrategy, RuntimeIvfSearchResult, RuntimeQueryExplain, RuntimeQueryResult,
32    RuntimeQueryWeights, RuntimeStats, ScanCursor, ScanPage,
33};
34use crate::storage::engine::PhysicalFileHeader;
35use crate::storage::unified::devx::refs::{NodeRef, TableRef, VectorRef};
36use crate::storage::unified::devx::{
37    NativeVectorArtifactBatchInspection, NativeVectorArtifactInspection, PhysicalAuthorityStatus,
38    SimilarResult,
39};
40use crate::storage::unified::dsl::QueryResult as DslQueryResult;
41use crate::storage::unified::store::{
42    NativeCatalogSummary, NativeManifestSummary, NativeMetadataStateSummary, NativePhysicalState,
43    NativeRecoverySummary, NativeRegistrySummary, NativeVectorArtifactPageSummary,
44};
45use crate::RedDBResult;
46use crate::{PhysicalAnalyticsJob, PhysicalGraphProjection, PhysicalIndexState};
47
48pub trait RuntimeQueryPort {
49    fn execute_query(&self, query: &str) -> RedDBResult<RuntimeQueryResult>;
50    fn explain_query(&self, query: &str) -> RedDBResult<RuntimeQueryExplain>;
51    fn scan_collection(
52        &self,
53        collection: &str,
54        cursor: Option<ScanCursor>,
55        limit: usize,
56    ) -> RedDBResult<ScanPage>;
57    fn search_similar(
58        &self,
59        collection: &str,
60        vector: &[f32],
61        k: usize,
62        min_score: f32,
63    ) -> RedDBResult<Vec<SimilarResult>>;
64    fn search_ivf(
65        &self,
66        collection: &str,
67        vector: &[f32],
68        k: usize,
69        n_lists: usize,
70        n_probes: Option<usize>,
71    ) -> RedDBResult<RuntimeIvfSearchResult>;
72    fn search_hybrid(
73        &self,
74        vector: Option<Vec<f32>>,
75        query: Option<String>,
76        k: Option<usize>,
77        collections: Option<Vec<String>>,
78        entity_types: Option<Vec<String>>,
79        capabilities: Option<Vec<String>>,
80        graph_pattern: Option<RuntimeGraphPattern>,
81        filters: Vec<RuntimeFilter>,
82        weights: Option<RuntimeQueryWeights>,
83        min_score: Option<f32>,
84        limit: Option<usize>,
85    ) -> RedDBResult<DslQueryResult>;
86    fn search_text(
87        &self,
88        query: String,
89        collections: Option<Vec<String>>,
90        entity_types: Option<Vec<String>>,
91        capabilities: Option<Vec<String>>,
92        fields: Option<Vec<String>>,
93        limit: Option<usize>,
94        fuzzy: bool,
95    ) -> RedDBResult<DslQueryResult>;
96    fn search_multimodal(
97        &self,
98        query: String,
99        collections: Option<Vec<String>>,
100        entity_types: Option<Vec<String>>,
101        capabilities: Option<Vec<String>>,
102        limit: Option<usize>,
103    ) -> RedDBResult<DslQueryResult>;
104    fn search_index(
105        &self,
106        index: String,
107        value: String,
108        exact: bool,
109        collections: Option<Vec<String>>,
110        entity_types: Option<Vec<String>>,
111        capabilities: Option<Vec<String>>,
112        limit: Option<usize>,
113    ) -> RedDBResult<DslQueryResult>;
114    fn search_context(
115        &self,
116        input: crate::application::SearchContextInput,
117    ) -> RedDBResult<crate::runtime::ContextSearchResult>;
118    fn resolve_semantic_api_key(&self, provider: &crate::ai::AiProvider) -> RedDBResult<String>;
119}
120
121pub trait RuntimeEntityPort {
122    fn create_row(&self, input: CreateRowInput) -> RedDBResult<CreateEntityOutput>;
123    fn create_rows_batch(
124        &self,
125        input: CreateRowsBatchInput,
126    ) -> RedDBResult<Vec<CreateEntityOutput>>;
127    /// Pre-validated bulk insert — caller has already checked column
128    /// types and uniqueness. Server skips
129    /// `normalize_row_fields_for_contract`, `enforce_row_uniqueness`,
130    /// and `enforce_row_batch_uniqueness`. Returns the row count.
131    /// Used by `MSG_BULK_INSERT_PREVALIDATED`.
132    fn create_rows_batch_prevalidated(&self, input: CreateRowsBatchInput) -> RedDBResult<usize>;
133    /// Columnar pre-validated bulk insert — the wire handler
134    /// decoded straight into `Vec<Vec<Value>>` + a shared column-
135    /// name vector, no per-cell `(String, Value)` tuples allocated.
136    /// Avoids ~N×ncols String clones vs the tuple path. The schema
137    /// is shared across every row as a single `Arc<Vec<String>>`.
138    fn create_rows_batch_prevalidated_columnar(
139        &self,
140        collection: String,
141        column_names: std::sync::Arc<Vec<String>>,
142        rows: Vec<Vec<crate::storage::schema::Value>>,
143    ) -> RedDBResult<usize>;
144    /// Columnar bulk insert with full contract validation — wire
145    /// handler shape (one `Arc<Vec<String>>` schema shared across
146    /// every row, `Vec<Vec<Value>>` row payload). Equivalent to
147    /// `create_rows_batch` semantically but skips the per-row
148    /// `(String, Value)` tuple materialisation in the wire decoder.
149    /// When the collection has no contract (or no declared columns)
150    /// fast-paths to `create_rows_batch_prevalidated_columnar`;
151    /// otherwise falls back to the tuple path so contract
152    /// normalisation can run.
153    fn create_rows_batch_columnar(
154        &self,
155        collection: String,
156        column_names: std::sync::Arc<Vec<String>>,
157        rows: Vec<Vec<crate::storage::schema::Value>>,
158    ) -> RedDBResult<usize>;
159    fn create_node(&self, input: CreateNodeInput) -> RedDBResult<CreateEntityOutput>;
160    fn create_edge(&self, input: CreateEdgeInput) -> RedDBResult<CreateEntityOutput>;
161    fn create_vector(&self, input: CreateVectorInput) -> RedDBResult<CreateEntityOutput>;
162    fn create_document(&self, input: CreateDocumentInput) -> RedDBResult<CreateEntityOutput>;
163    fn create_kv(&self, input: CreateKvInput) -> RedDBResult<CreateEntityOutput>;
164    fn create_timeseries_point(
165        &self,
166        input: CreateTimeSeriesPointInput,
167    ) -> RedDBResult<CreateEntityOutput>;
168    fn get_kv(
169        &self,
170        collection: &str,
171        key: &str,
172    ) -> RedDBResult<Option<(crate::storage::schema::Value, crate::storage::EntityId)>>;
173    fn delete_kv(&self, collection: &str, key: &str) -> RedDBResult<bool>;
174    fn patch_entity(&self, input: PatchEntityInput) -> RedDBResult<CreateEntityOutput>;
175    fn delete_entity(&self, input: DeleteEntityInput) -> RedDBResult<DeleteEntityOutput>;
176}
177
178pub trait RuntimeSchemaPort {
179    fn create_table(&self, input: CreateTableInput) -> RedDBResult<RuntimeQueryResult>;
180    fn drop_table(&self, input: DropTableInput) -> RedDBResult<RuntimeQueryResult>;
181    fn create_timeseries(&self, input: CreateTimeSeriesInput) -> RedDBResult<RuntimeQueryResult>;
182    fn drop_timeseries(&self, input: DropTimeSeriesInput) -> RedDBResult<RuntimeQueryResult>;
183}
184
185pub trait RuntimeTreePort {
186    fn create_tree(&self, input: CreateTreeInput) -> RedDBResult<RuntimeQueryResult>;
187    fn drop_tree(&self, input: DropTreeInput) -> RedDBResult<RuntimeQueryResult>;
188    fn insert_tree_node(&self, input: InsertTreeNodeInput) -> RedDBResult<RuntimeQueryResult>;
189    fn move_tree_node(&self, input: MoveTreeNodeInput) -> RedDBResult<RuntimeQueryResult>;
190    fn delete_tree_node(&self, input: DeleteTreeNodeInput) -> RedDBResult<RuntimeQueryResult>;
191    fn validate_tree(&self, input: ValidateTreeInput) -> RedDBResult<RuntimeQueryResult>;
192    fn rebalance_tree(&self, input: RebalanceTreeInput) -> RedDBResult<RuntimeQueryResult>;
193}
194
195pub trait RuntimeAdminPort {
196    fn set_index_enabled(&self, name: &str, enabled: bool) -> RedDBResult<PhysicalIndexState>;
197    fn mark_index_building(&self, name: &str) -> RedDBResult<PhysicalIndexState>;
198    fn fail_index(&self, name: &str) -> RedDBResult<PhysicalIndexState>;
199    fn mark_index_stale(&self, name: &str) -> RedDBResult<PhysicalIndexState>;
200    fn mark_index_ready(&self, name: &str) -> RedDBResult<PhysicalIndexState>;
201    fn warmup_index_with_lifecycle(&self, name: &str) -> RedDBResult<PhysicalIndexState>;
202    fn rebuild_indexes_with_lifecycle(
203        &self,
204        collection: Option<&str>,
205    ) -> RedDBResult<Vec<PhysicalIndexState>>;
206    fn save_graph_projection(
207        &self,
208        name: impl Into<String>,
209        projection: RuntimeGraphProjection,
210        source: Option<String>,
211    ) -> RedDBResult<PhysicalGraphProjection>;
212    fn mark_graph_projection_materializing(
213        &self,
214        name: &str,
215    ) -> RedDBResult<PhysicalGraphProjection>;
216    fn materialize_graph_projection(&self, name: &str) -> RedDBResult<PhysicalGraphProjection>;
217    fn fail_graph_projection(&self, name: &str) -> RedDBResult<PhysicalGraphProjection>;
218    fn mark_graph_projection_stale(&self, name: &str) -> RedDBResult<PhysicalGraphProjection>;
219    fn save_analytics_job(
220        &self,
221        kind: impl Into<String>,
222        projection_name: Option<String>,
223        metadata: BTreeMap<String, String>,
224    ) -> RedDBResult<PhysicalAnalyticsJob>;
225    fn start_analytics_job(
226        &self,
227        kind: impl Into<String>,
228        projection_name: Option<String>,
229        metadata: BTreeMap<String, String>,
230    ) -> RedDBResult<PhysicalAnalyticsJob>;
231    fn queue_analytics_job(
232        &self,
233        kind: impl Into<String>,
234        projection_name: Option<String>,
235        metadata: BTreeMap<String, String>,
236    ) -> RedDBResult<PhysicalAnalyticsJob>;
237    fn fail_analytics_job(
238        &self,
239        kind: impl Into<String>,
240        projection_name: Option<String>,
241        metadata: BTreeMap<String, String>,
242    ) -> RedDBResult<PhysicalAnalyticsJob>;
243    fn mark_analytics_job_stale(
244        &self,
245        kind: impl Into<String>,
246        projection_name: Option<String>,
247        metadata: BTreeMap<String, String>,
248    ) -> RedDBResult<PhysicalAnalyticsJob>;
249    fn complete_analytics_job(
250        &self,
251        kind: impl Into<String>,
252        projection_name: Option<String>,
253        metadata: BTreeMap<String, String>,
254    ) -> RedDBResult<PhysicalAnalyticsJob>;
255}
256
257pub trait RuntimeCatalogPort {
258    fn collections(&self) -> Vec<String>;
259    fn catalog(&self) -> CatalogModelSnapshot;
260    fn catalog_consistency_report(&self) -> CatalogConsistencyReport;
261    fn catalog_attention_summary(&self) -> CatalogAttentionSummary;
262    fn collection_attention(&self) -> Vec<CollectionDescriptor>;
263    fn indexes(&self) -> Vec<PhysicalIndexState>;
264    fn declared_indexes(&self) -> Vec<PhysicalIndexState>;
265    fn indexes_for_collection(&self, collection: &str) -> Vec<PhysicalIndexState>;
266    fn declared_indexes_for_collection(&self, collection: &str) -> Vec<PhysicalIndexState>;
267    fn index_statuses(&self) -> Vec<CatalogIndexStatus>;
268    fn index_attention(&self) -> Vec<CatalogIndexStatus>;
269    fn graph_projections(&self) -> RedDBResult<Vec<PhysicalGraphProjection>>;
270    fn operational_graph_projections(&self) -> Vec<PhysicalGraphProjection>;
271    fn graph_projection_statuses(&self) -> Vec<CatalogGraphProjectionStatus>;
272    fn graph_projection_attention(&self) -> Vec<CatalogGraphProjectionStatus>;
273    fn analytics_jobs(&self) -> RedDBResult<Vec<PhysicalAnalyticsJob>>;
274    fn operational_analytics_jobs(&self) -> Vec<PhysicalAnalyticsJob>;
275    fn analytics_job_statuses(&self) -> Vec<CatalogAnalyticsJobStatus>;
276    fn analytics_job_attention(&self) -> Vec<CatalogAnalyticsJobStatus>;
277    fn stats(&self) -> RuntimeStats;
278}
279
280pub trait RuntimeNativePort {
281    fn health_report(&self) -> crate::health::HealthReport;
282    fn collection_roots(&self) -> RedDBResult<BTreeMap<String, u64>>;
283    fn snapshots(&self) -> RedDBResult<Vec<SnapshotDescriptor>>;
284    fn exports(&self) -> RedDBResult<Vec<ExportDescriptor>>;
285    fn physical_metadata(&self) -> RedDBResult<PhysicalMetadataFile>;
286    fn manifest_events_filtered(
287        &self,
288        collection: Option<&str>,
289        kind: Option<&str>,
290        since_snapshot: Option<u64>,
291    ) -> RedDBResult<Vec<ManifestEvent>>;
292    fn create_snapshot(&self) -> RedDBResult<SnapshotDescriptor>;
293    fn create_export(&self, name: String) -> RedDBResult<ExportDescriptor>;
294    fn checkpoint(&self) -> RedDBResult<()>;
295    fn apply_retention_policy(&self) -> RedDBResult<()>;
296    fn run_maintenance(&self) -> RedDBResult<()>;
297    fn native_header(&self) -> RedDBResult<PhysicalFileHeader>;
298    fn native_collection_roots(&self) -> RedDBResult<BTreeMap<String, u64>>;
299    fn native_manifest_summary(&self) -> RedDBResult<NativeManifestSummary>;
300    fn native_registry_summary(&self) -> RedDBResult<NativeRegistrySummary>;
301    fn native_recovery_summary(&self) -> RedDBResult<NativeRecoverySummary>;
302    fn native_catalog_summary(&self) -> RedDBResult<NativeCatalogSummary>;
303    fn native_physical_state(&self) -> RedDBResult<NativePhysicalState>;
304    fn native_vector_artifact_pages(&self) -> RedDBResult<Vec<NativeVectorArtifactPageSummary>>;
305    fn inspect_native_vector_artifact(
306        &self,
307        collection: &str,
308        artifact_kind: Option<&str>,
309    ) -> RedDBResult<NativeVectorArtifactInspection>;
310    fn warmup_native_vector_artifact(
311        &self,
312        collection: &str,
313        artifact_kind: Option<&str>,
314    ) -> RedDBResult<NativeVectorArtifactInspection>;
315    fn inspect_native_vector_artifacts(&self) -> RedDBResult<NativeVectorArtifactBatchInspection>;
316    fn warmup_native_vector_artifacts(&self) -> RedDBResult<NativeVectorArtifactBatchInspection>;
317    fn native_header_repair_policy(&self) -> RedDBResult<String>;
318    fn repair_native_header_from_metadata(&self) -> RedDBResult<String>;
319    fn rebuild_physical_metadata_from_native_state(&self) -> RedDBResult<bool>;
320    fn repair_native_physical_state_from_metadata(&self) -> RedDBResult<bool>;
321    fn native_metadata_state_summary(&self) -> RedDBResult<NativeMetadataStateSummary>;
322    fn physical_authority_status(&self) -> PhysicalAuthorityStatus;
323    fn readiness_for_query(&self) -> bool;
324    fn readiness_for_query_serverless(&self) -> bool;
325    fn readiness_for_write(&self) -> bool;
326    fn readiness_for_write_serverless(&self) -> bool;
327    fn readiness_for_repair(&self) -> bool;
328    fn readiness_for_repair_serverless(&self) -> bool;
329}
330
331pub trait RuntimeGraphPort {
332    fn resolve_graph_projection(
333        &self,
334        name: Option<&str>,
335        inline: Option<RuntimeGraphProjection>,
336    ) -> RedDBResult<Option<RuntimeGraphProjection>>;
337    fn graph_neighborhood(
338        &self,
339        node: &str,
340        direction: RuntimeGraphDirection,
341        max_depth: usize,
342        edge_labels: Option<Vec<String>>,
343        projection: Option<RuntimeGraphProjection>,
344    ) -> RedDBResult<RuntimeGraphNeighborhoodResult>;
345    fn graph_traverse(
346        &self,
347        source: &str,
348        direction: RuntimeGraphDirection,
349        max_depth: usize,
350        strategy: RuntimeGraphTraversalStrategy,
351        edge_labels: Option<Vec<String>>,
352        projection: Option<RuntimeGraphProjection>,
353    ) -> RedDBResult<RuntimeGraphTraversalResult>;
354    fn graph_shortest_path(
355        &self,
356        source: &str,
357        target: &str,
358        direction: RuntimeGraphDirection,
359        algorithm: RuntimeGraphPathAlgorithm,
360        edge_labels: Option<Vec<String>>,
361        projection: Option<RuntimeGraphProjection>,
362    ) -> RedDBResult<RuntimeGraphPathResult>;
363    fn graph_components(
364        &self,
365        mode: RuntimeGraphComponentsMode,
366        min_size: usize,
367        projection: Option<RuntimeGraphProjection>,
368    ) -> RedDBResult<RuntimeGraphComponentsResult>;
369    fn graph_centrality(
370        &self,
371        algorithm: RuntimeGraphCentralityAlgorithm,
372        top_k: usize,
373        normalize: bool,
374        max_iterations: Option<usize>,
375        epsilon: Option<f64>,
376        alpha: Option<f64>,
377        projection: Option<RuntimeGraphProjection>,
378    ) -> RedDBResult<RuntimeGraphCentralityResult>;
379    fn graph_communities(
380        &self,
381        algorithm: crate::runtime::RuntimeGraphCommunityAlgorithm,
382        min_size: usize,
383        max_iterations: Option<usize>,
384        resolution: Option<f64>,
385        projection: Option<RuntimeGraphProjection>,
386    ) -> RedDBResult<RuntimeGraphCommunityResult>;
387    fn graph_clustering(
388        &self,
389        top_k: usize,
390        include_triangles: bool,
391        projection: Option<RuntimeGraphProjection>,
392    ) -> RedDBResult<RuntimeGraphClusteringResult>;
393    fn graph_personalized_pagerank(
394        &self,
395        seeds: Vec<String>,
396        top_k: usize,
397        alpha: Option<f64>,
398        epsilon: Option<f64>,
399        max_iterations: Option<usize>,
400        projection: Option<RuntimeGraphProjection>,
401    ) -> RedDBResult<RuntimeGraphCentralityResult>;
402    fn graph_hits(
403        &self,
404        top_k: usize,
405        epsilon: Option<f64>,
406        max_iterations: Option<usize>,
407        projection: Option<RuntimeGraphProjection>,
408    ) -> RedDBResult<RuntimeGraphHitsResult>;
409    fn graph_cycles(
410        &self,
411        max_length: usize,
412        max_cycles: usize,
413        projection: Option<RuntimeGraphProjection>,
414    ) -> RedDBResult<RuntimeGraphCyclesResult>;
415    fn graph_topological_sort(
416        &self,
417        projection: Option<RuntimeGraphProjection>,
418    ) -> RedDBResult<RuntimeGraphTopologicalSortResult>;
419    fn graph_properties(
420        &self,
421        projection: Option<RuntimeGraphProjection>,
422    ) -> RedDBResult<RuntimeGraphPropertiesResult>;
423}
424
425pub trait RuntimeVcsPort {
426    fn vcs_commit(
427        &self,
428        input: crate::application::vcs::CreateCommitInput,
429    ) -> RedDBResult<crate::application::vcs::Commit>;
430
431    fn vcs_branch_create(
432        &self,
433        input: crate::application::vcs::CreateBranchInput,
434    ) -> RedDBResult<crate::application::vcs::Ref>;
435
436    fn vcs_branch_delete(&self, name: &str) -> RedDBResult<()>;
437
438    fn vcs_tag_create(
439        &self,
440        input: crate::application::vcs::CreateTagInput,
441    ) -> RedDBResult<crate::application::vcs::Ref>;
442
443    fn vcs_list_refs(&self, prefix: Option<&str>)
444        -> RedDBResult<Vec<crate::application::vcs::Ref>>;
445
446    fn vcs_checkout(
447        &self,
448        input: crate::application::vcs::CheckoutInput,
449    ) -> RedDBResult<crate::application::vcs::Ref>;
450
451    fn vcs_merge(
452        &self,
453        input: crate::application::vcs::MergeInput,
454    ) -> RedDBResult<crate::application::vcs::MergeOutcome>;
455
456    fn vcs_cherry_pick(
457        &self,
458        connection_id: u64,
459        commit: &str,
460        author: crate::application::vcs::Author,
461    ) -> RedDBResult<crate::application::vcs::MergeOutcome>;
462
463    fn vcs_revert(
464        &self,
465        connection_id: u64,
466        commit: &str,
467        author: crate::application::vcs::Author,
468    ) -> RedDBResult<crate::application::vcs::Commit>;
469
470    fn vcs_reset(&self, input: crate::application::vcs::ResetInput) -> RedDBResult<()>;
471
472    fn vcs_log(
473        &self,
474        input: crate::application::vcs::LogInput,
475    ) -> RedDBResult<Vec<crate::application::vcs::Commit>>;
476
477    fn vcs_diff(
478        &self,
479        input: crate::application::vcs::DiffInput,
480    ) -> RedDBResult<crate::application::vcs::Diff>;
481
482    fn vcs_status(
483        &self,
484        input: crate::application::vcs::StatusInput,
485    ) -> RedDBResult<crate::application::vcs::Status>;
486
487    fn vcs_lca(&self, a: &str, b: &str)
488        -> RedDBResult<Option<crate::application::vcs::CommitHash>>;
489
490    fn vcs_conflicts_list(
491        &self,
492        merge_state_id: &str,
493    ) -> RedDBResult<Vec<crate::application::vcs::Conflict>>;
494
495    fn vcs_conflict_resolve(
496        &self,
497        conflict_id: &str,
498        resolved: crate::json::Value,
499    ) -> RedDBResult<()>;
500
501    fn vcs_resolve_as_of(
502        &self,
503        spec: crate::application::vcs::AsOfSpec,
504    ) -> RedDBResult<crate::storage::transaction::snapshot::Xid>;
505
506    fn vcs_resolve_commitish(&self, spec: &str)
507        -> RedDBResult<crate::application::vcs::CommitHash>;
508
509    fn vcs_set_versioned(&self, collection: &str, enabled: bool) -> RedDBResult<()>;
510    fn vcs_list_versioned(&self) -> RedDBResult<Vec<String>>;
511    fn vcs_is_versioned(&self, collection: &str) -> RedDBResult<bool>;
512}
513
514/// Context-aware extension trait that mirrors `RuntimeEntityPort`
515/// with `&OperationContext` threaded through every method.
516///
517/// This is the migration runway for the `OperationContext` deepening
518/// (PLAN cluster 6). Each default implementation forwards to the
519/// existing context-less method, so today the trait is a pure
520/// pass-through — but new callers can already adopt the
521/// context-passing surface, and a future PR will replace the
522/// defaults with real impls that read `ctx.xid` / `ctx.write_consent`.
523///
524/// Hidden behind the `ctx-ports` feature flag during the migration
525/// window so the impl bloat doesn't burden default builds. Once
526/// every port is migrated, the flag goes away and these traits
527/// become the only surface.
528pub trait RuntimeEntityPortCtx: RuntimeEntityPort {
529    fn create_row_ctx(
530        &self,
531        ctx: &crate::application::OperationContext,
532        input: CreateRowInput,
533    ) -> RedDBResult<CreateEntityOutput> {
534        let _ = ctx;
535        self.create_row(input)
536    }
537    fn create_node_ctx(
538        &self,
539        ctx: &crate::application::OperationContext,
540        input: CreateNodeInput,
541    ) -> RedDBResult<CreateEntityOutput> {
542        let _ = ctx;
543        self.create_node(input)
544    }
545    fn create_edge_ctx(
546        &self,
547        ctx: &crate::application::OperationContext,
548        input: CreateEdgeInput,
549    ) -> RedDBResult<CreateEntityOutput> {
550        let _ = ctx;
551        self.create_edge(input)
552    }
553    fn create_vector_ctx(
554        &self,
555        ctx: &crate::application::OperationContext,
556        input: CreateVectorInput,
557    ) -> RedDBResult<CreateEntityOutput> {
558        let _ = ctx;
559        self.create_vector(input)
560    }
561    fn create_document_ctx(
562        &self,
563        ctx: &crate::application::OperationContext,
564        input: CreateDocumentInput,
565    ) -> RedDBResult<CreateEntityOutput> {
566        let _ = ctx;
567        self.create_document(input)
568    }
569    fn create_kv_ctx(
570        &self,
571        ctx: &crate::application::OperationContext,
572        input: CreateKvInput,
573    ) -> RedDBResult<CreateEntityOutput> {
574        let _ = ctx;
575        self.create_kv(input)
576    }
577    fn create_timeseries_point_ctx(
578        &self,
579        ctx: &crate::application::OperationContext,
580        input: CreateTimeSeriesPointInput,
581    ) -> RedDBResult<CreateEntityOutput> {
582        let _ = ctx;
583        self.create_timeseries_point(input)
584    }
585    fn get_kv_ctx(
586        &self,
587        ctx: &crate::application::OperationContext,
588        collection: &str,
589        key: &str,
590    ) -> RedDBResult<Option<(crate::storage::schema::Value, crate::storage::EntityId)>> {
591        let _ = ctx;
592        self.get_kv(collection, key)
593    }
594    fn delete_kv_ctx(
595        &self,
596        ctx: &crate::application::OperationContext,
597        collection: &str,
598        key: &str,
599    ) -> RedDBResult<bool> {
600        let _ = ctx;
601        self.delete_kv(collection, key)
602    }
603    fn patch_entity_ctx(
604        &self,
605        ctx: &crate::application::OperationContext,
606        input: PatchEntityInput,
607    ) -> RedDBResult<CreateEntityOutput> {
608        let _ = ctx;
609        self.patch_entity(input)
610    }
611    fn delete_entity_ctx(
612        &self,
613        ctx: &crate::application::OperationContext,
614        input: DeleteEntityInput,
615    ) -> RedDBResult<DeleteEntityOutput> {
616        let _ = ctx;
617        self.delete_entity(input)
618    }
619}
620
621/// Blanket impl: every concrete `RuntimeEntityPort` automatically
622/// gains the context-aware surface via the default forwards above.
623impl<T: RuntimeEntityPort + ?Sized> RuntimeEntityPortCtx for T {}
624
625// ─── ctx extension traits for the remaining mutating ports ───
626//
627// Same pattern as RuntimeEntityPortCtx: methods take
628// `&OperationContext` first, default-forward to the existing
629// context-less call. Blanket impls give every concrete port
630// the new surface for free. Future PRs replace the forwards
631// with real `ctx.write_consent` / `ctx.xid` handling.
632//
633// Read-only ports (RuntimeCatalogPort, RuntimeGraphPort) and the
634// read-only methods of mutating ports are intentionally absent —
635// `OperationContext` adds no locality there until the snapshot-
636// xid migration also lands.
637
638pub trait RuntimeQueryPortCtx: RuntimeQueryPort {
639    fn execute_query_ctx(
640        &self,
641        ctx: &crate::application::OperationContext,
642        query: &str,
643    ) -> RedDBResult<RuntimeQueryResult> {
644        let _ = ctx;
645        self.execute_query(query)
646    }
647    fn explain_query_ctx(
648        &self,
649        ctx: &crate::application::OperationContext,
650        query: &str,
651    ) -> RedDBResult<RuntimeQueryExplain> {
652        let _ = ctx;
653        self.explain_query(query)
654    }
655    fn scan_collection_ctx(
656        &self,
657        ctx: &crate::application::OperationContext,
658        collection: &str,
659        cursor: Option<ScanCursor>,
660        limit: usize,
661    ) -> RedDBResult<ScanPage> {
662        let _ = ctx;
663        self.scan_collection(collection, cursor, limit)
664    }
665}
666impl<T: RuntimeQueryPort + ?Sized> RuntimeQueryPortCtx for T {}
667
668pub trait RuntimeSchemaPortCtx: RuntimeSchemaPort {
669    fn create_table_ctx(
670        &self,
671        ctx: &crate::application::OperationContext,
672        input: CreateTableInput,
673    ) -> RedDBResult<RuntimeQueryResult> {
674        let _ = ctx;
675        self.create_table(input)
676    }
677    fn drop_table_ctx(
678        &self,
679        ctx: &crate::application::OperationContext,
680        input: DropTableInput,
681    ) -> RedDBResult<RuntimeQueryResult> {
682        let _ = ctx;
683        self.drop_table(input)
684    }
685    fn create_timeseries_ctx(
686        &self,
687        ctx: &crate::application::OperationContext,
688        input: CreateTimeSeriesInput,
689    ) -> RedDBResult<RuntimeQueryResult> {
690        let _ = ctx;
691        self.create_timeseries(input)
692    }
693    fn drop_timeseries_ctx(
694        &self,
695        ctx: &crate::application::OperationContext,
696        input: DropTimeSeriesInput,
697    ) -> RedDBResult<RuntimeQueryResult> {
698        let _ = ctx;
699        self.drop_timeseries(input)
700    }
701}
702impl<T: RuntimeSchemaPort + ?Sized> RuntimeSchemaPortCtx for T {}
703
704pub trait RuntimeTreePortCtx: RuntimeTreePort {
705    fn create_tree_ctx(
706        &self,
707        ctx: &crate::application::OperationContext,
708        input: CreateTreeInput,
709    ) -> RedDBResult<RuntimeQueryResult> {
710        let _ = ctx;
711        self.create_tree(input)
712    }
713    fn drop_tree_ctx(
714        &self,
715        ctx: &crate::application::OperationContext,
716        input: DropTreeInput,
717    ) -> RedDBResult<RuntimeQueryResult> {
718        let _ = ctx;
719        self.drop_tree(input)
720    }
721    fn insert_tree_node_ctx(
722        &self,
723        ctx: &crate::application::OperationContext,
724        input: InsertTreeNodeInput,
725    ) -> RedDBResult<RuntimeQueryResult> {
726        let _ = ctx;
727        self.insert_tree_node(input)
728    }
729    fn move_tree_node_ctx(
730        &self,
731        ctx: &crate::application::OperationContext,
732        input: MoveTreeNodeInput,
733    ) -> RedDBResult<RuntimeQueryResult> {
734        let _ = ctx;
735        self.move_tree_node(input)
736    }
737    fn delete_tree_node_ctx(
738        &self,
739        ctx: &crate::application::OperationContext,
740        input: DeleteTreeNodeInput,
741    ) -> RedDBResult<RuntimeQueryResult> {
742        let _ = ctx;
743        self.delete_tree_node(input)
744    }
745    fn rebalance_tree_ctx(
746        &self,
747        ctx: &crate::application::OperationContext,
748        input: RebalanceTreeInput,
749    ) -> RedDBResult<RuntimeQueryResult> {
750        let _ = ctx;
751        self.rebalance_tree(input)
752    }
753}
754impl<T: RuntimeTreePort + ?Sized> RuntimeTreePortCtx for T {}
755
756pub trait RuntimeNativePortCtx: RuntimeNativePort {
757    fn create_snapshot_ctx(
758        &self,
759        ctx: &crate::application::OperationContext,
760    ) -> RedDBResult<SnapshotDescriptor> {
761        let _ = ctx;
762        self.create_snapshot()
763    }
764    fn create_export_ctx(
765        &self,
766        ctx: &crate::application::OperationContext,
767        name: String,
768    ) -> RedDBResult<ExportDescriptor> {
769        let _ = ctx;
770        self.create_export(name)
771    }
772    fn checkpoint_ctx(&self, ctx: &crate::application::OperationContext) -> RedDBResult<()> {
773        let _ = ctx;
774        self.checkpoint()
775    }
776    fn apply_retention_policy_ctx(
777        &self,
778        ctx: &crate::application::OperationContext,
779    ) -> RedDBResult<()> {
780        let _ = ctx;
781        self.apply_retention_policy()
782    }
783    fn run_maintenance_ctx(&self, ctx: &crate::application::OperationContext) -> RedDBResult<()> {
784        let _ = ctx;
785        self.run_maintenance()
786    }
787    fn repair_native_header_from_metadata_ctx(
788        &self,
789        ctx: &crate::application::OperationContext,
790    ) -> RedDBResult<String> {
791        let _ = ctx;
792        self.repair_native_header_from_metadata()
793    }
794    fn rebuild_physical_metadata_from_native_state_ctx(
795        &self,
796        ctx: &crate::application::OperationContext,
797    ) -> RedDBResult<bool> {
798        let _ = ctx;
799        self.rebuild_physical_metadata_from_native_state()
800    }
801}
802impl<T: RuntimeNativePort + ?Sized> RuntimeNativePortCtx for T {}
803
804pub trait RuntimeVcsPortCtx: RuntimeVcsPort {
805    fn vcs_branch_delete_ctx(
806        &self,
807        ctx: &crate::application::OperationContext,
808        name: &str,
809    ) -> RedDBResult<()> {
810        let _ = ctx;
811        self.vcs_branch_delete(name)
812    }
813    fn vcs_reset_ctx(
814        &self,
815        ctx: &crate::application::OperationContext,
816        input: crate::application::vcs::ResetInput,
817    ) -> RedDBResult<()> {
818        let _ = ctx;
819        self.vcs_reset(input)
820    }
821    fn vcs_set_versioned_ctx(
822        &self,
823        ctx: &crate::application::OperationContext,
824        collection: &str,
825        enabled: bool,
826    ) -> RedDBResult<()> {
827        let _ = ctx;
828        self.vcs_set_versioned(collection, enabled)
829    }
830    fn vcs_conflict_resolve_ctx(
831        &self,
832        ctx: &crate::application::OperationContext,
833        conflict_id: &str,
834        resolved: crate::json::Value,
835    ) -> RedDBResult<()> {
836        let _ = ctx;
837        self.vcs_conflict_resolve(conflict_id, resolved)
838    }
839}
840impl<T: RuntimeVcsPort + ?Sized> RuntimeVcsPortCtx for T {}
841
842/// Port for native migration operations.
843///
844/// Stub methods — full implementations land in subsequent slices.
845pub trait RuntimeMigrationPort {
846    /// Register a new migration definition (status = pending).
847    fn migration_create(&self, input: MigrationCreateInput) -> RedDBResult<RuntimeQueryResult>;
848    /// Apply a named migration (or `*` for all pending).
849    fn migration_apply(&self, name: &str) -> RedDBResult<RuntimeQueryResult>;
850    /// Roll back an applied migration.
851    fn migration_rollback(&self, name: &str) -> RedDBResult<RuntimeQueryResult>;
852    /// Explain a migration without executing it.
853    fn migration_explain(&self, name: &str) -> RedDBResult<RuntimeQueryResult>;
854    /// List migrations, optionally filtered by status.
855    fn migration_list(&self, status: Option<&str>) -> RedDBResult<RuntimeQueryResult>;
856}
857
858/// Minimal input type for `migration_create`. Expanded in later slices.
859#[derive(Debug, Clone)]
860pub struct MigrationCreateInput {
861    pub name: String,
862    pub kind: MigrationKind,
863    pub body: String,
864    pub author: String,
865    pub depends_on: Vec<String>,
866    pub batch_size: Option<u64>,
867    pub no_rollback: bool,
868}
869
870#[derive(Debug, Clone, PartialEq, Eq)]
871pub enum MigrationKind {
872    Ddl,
873    Data,
874}
875
876#[path = "ports_impls.rs"]
877mod ports_impls;
878pub(crate) use ports_impls::build_row_update_contract_plan;
879pub(crate) use ports_impls::normalize_row_update_assignment_with_plan;
880pub(crate) use ports_impls::normalize_row_update_value_for_rule;