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