@lix-js/sdk 0.6.0-preview.2 → 0.6.0-preview.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +4 -5
- package/dist/engine-wasm/wasm/lix_engine.js +1 -1
- package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
- package/dist/generated/builtin-schemas.d.ts +87 -162
- package/dist/generated/builtin-schemas.js +139 -236
- package/dist/open-lix.d.ts +1 -1
- package/dist-engine-src/src/binary_cas/types.rs +0 -6
- package/dist-engine-src/src/catalog/context.rs +412 -0
- package/dist-engine-src/src/catalog/mod.rs +10 -0
- package/dist-engine-src/src/catalog/schema.rs +4 -0
- package/dist-engine-src/src/catalog/snapshot.rs +1114 -0
- package/dist-engine-src/src/cel/mod.rs +1 -1
- package/dist-engine-src/src/cel/provider.rs +1 -1
- package/dist-engine-src/src/commit_graph/context.rs +328 -1015
- package/dist-engine-src/src/commit_graph/mod.rs +2 -3
- package/dist-engine-src/src/commit_graph/types.rs +7 -43
- package/dist-engine-src/src/commit_graph/walker.rs +57 -81
- package/dist-engine-src/src/commit_store/codec.rs +887 -0
- package/dist-engine-src/src/commit_store/context.rs +944 -0
- package/dist-engine-src/src/commit_store/materialization.rs +84 -0
- package/dist-engine-src/src/commit_store/mod.rs +16 -0
- package/dist-engine-src/src/commit_store/storage.rs +600 -0
- package/dist-engine-src/src/commit_store/types.rs +215 -0
- package/dist-engine-src/src/common/identity.rs +15 -5
- package/dist-engine-src/src/common/json_pointer.rs +67 -0
- package/dist-engine-src/src/common/metadata.rs +17 -12
- package/dist-engine-src/src/common/mod.rs +5 -5
- package/dist-engine-src/src/domain.rs +324 -0
- package/dist-engine-src/src/engine.rs +29 -43
- package/dist-engine-src/src/entity_identity.rs +238 -118
- package/dist-engine-src/src/functions/context.rs +17 -52
- package/dist-engine-src/src/functions/deterministic.rs +1 -1
- package/dist-engine-src/src/functions/mod.rs +1 -1
- package/dist-engine-src/src/functions/provider.rs +4 -4
- package/dist-engine-src/src/functions/state.rs +39 -66
- package/dist-engine-src/src/functions/types.rs +1 -1
- package/dist-engine-src/src/init.rs +204 -151
- package/dist-engine-src/src/json_store/context.rs +354 -60
- package/dist-engine-src/src/json_store/encoded.rs +6 -6
- package/dist-engine-src/src/json_store/mod.rs +4 -1
- package/dist-engine-src/src/json_store/store.rs +884 -11
- package/dist-engine-src/src/json_store/types.rs +166 -1
- package/dist-engine-src/src/lib.rs +10 -9
- package/dist-engine-src/src/live_state/context.rs +608 -830
- package/dist-engine-src/src/live_state/mod.rs +3 -3
- package/dist-engine-src/src/live_state/overlay.rs +7 -7
- package/dist-engine-src/src/live_state/reader.rs +5 -5
- package/dist-engine-src/src/live_state/types.rs +19 -36
- package/dist-engine-src/src/live_state/visibility.rs +19 -14
- package/dist-engine-src/src/plugin/archive.rs +3 -6
- package/dist-engine-src/src/plugin/install.rs +0 -18
- package/dist-engine-src/src/plugin/plugin_manifest.json +0 -1
- package/dist-engine-src/src/schema/annotations/defaults.rs +2 -7
- package/dist-engine-src/src/schema/builtin/lix_account.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_change.json +11 -10
- package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_commit.json +8 -46
- package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +29 -22
- package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_label.json +10 -3
- package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +74 -0
- package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +2 -8
- package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -1
- package/dist-engine-src/src/schema/builtin/mod.rs +10 -59
- package/dist-engine-src/src/schema/compatibility.rs +787 -0
- package/dist-engine-src/src/schema/definition.json +47 -17
- package/dist-engine-src/src/schema/definition.rs +202 -96
- package/dist-engine-src/src/schema/key.rs +9 -77
- package/dist-engine-src/src/schema/mod.rs +4 -4
- package/dist-engine-src/src/schema/tests.rs +133 -92
- package/dist-engine-src/src/session/context.rs +40 -42
- package/dist-engine-src/src/session/create_version.rs +22 -14
- package/dist-engine-src/src/session/execute.rs +45 -14
- package/dist-engine-src/src/session/merge/apply.rs +4 -4
- package/dist-engine-src/src/session/merge/conflicts.rs +3 -2
- package/dist-engine-src/src/session/merge/stats.rs +1 -1
- package/dist-engine-src/src/session/merge/version.rs +35 -45
- package/dist-engine-src/src/session/mod.rs +4 -2
- package/dist-engine-src/src/session/optimization9_sql2_bench.rs +100 -0
- package/dist-engine-src/src/session/switch_version.rs +16 -28
- package/dist-engine-src/src/sql2/change_provider.rs +14 -20
- package/dist-engine-src/src/sql2/classify.rs +61 -26
- package/dist-engine-src/src/sql2/context.rs +22 -18
- package/dist-engine-src/src/sql2/directory_history_provider.rs +28 -20
- package/dist-engine-src/src/sql2/directory_provider.rs +131 -83
- package/dist-engine-src/src/sql2/entity_history_provider.rs +10 -14
- package/dist-engine-src/src/sql2/entity_provider.rs +680 -169
- package/dist-engine-src/src/sql2/error.rs +21 -1
- package/dist-engine-src/src/sql2/execute.rs +325 -264
- package/dist-engine-src/src/sql2/file_history_provider.rs +29 -21
- package/dist-engine-src/src/sql2/file_provider.rs +533 -108
- package/dist-engine-src/src/sql2/filesystem_planner.rs +58 -94
- package/dist-engine-src/src/sql2/filesystem_visibility.rs +37 -23
- package/dist-engine-src/src/sql2/history_projection.rs +3 -27
- package/dist-engine-src/src/sql2/history_provider.rs +11 -17
- package/dist-engine-src/src/sql2/history_route.rs +22 -8
- package/dist-engine-src/src/sql2/lix_state_provider.rs +178 -96
- package/dist-engine-src/src/sql2/mod.rs +6 -3
- package/dist-engine-src/src/sql2/predicate_typecheck.rs +246 -0
- package/dist-engine-src/src/sql2/public_bind/assignment.rs +46 -0
- package/dist-engine-src/src/sql2/public_bind/capability.rs +41 -0
- package/dist-engine-src/src/sql2/public_bind/dml.rs +166 -0
- package/dist-engine-src/src/sql2/public_bind/mod.rs +25 -0
- package/dist-engine-src/src/sql2/public_bind/table.rs +168 -0
- package/dist-engine-src/src/sql2/read_only.rs +10 -12
- package/dist-engine-src/src/sql2/session.rs +7 -10
- package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +76 -0
- package/dist-engine-src/src/sql2/udfs/mod.rs +8 -1
- package/dist-engine-src/src/sql2/udfs/public_call.rs +211 -0
- package/dist-engine-src/src/sql2/version_provider.rs +46 -31
- package/dist-engine-src/src/sql2/version_scope.rs +4 -4
- package/dist-engine-src/src/storage_bench.rs +1782 -325
- package/dist-engine-src/src/test_support.rs +183 -36
- package/dist-engine-src/src/tracked_state/by_file_index.rs +20 -24
- package/dist-engine-src/src/tracked_state/codec.rs +1519 -181
- package/dist-engine-src/src/tracked_state/context.rs +1155 -271
- package/dist-engine-src/src/tracked_state/diff.rs +249 -57
- package/dist-engine-src/src/tracked_state/materialization.rs +365 -103
- package/dist-engine-src/src/tracked_state/materializer.rs +488 -0
- package/dist-engine-src/src/tracked_state/merge.rs +37 -19
- package/dist-engine-src/src/tracked_state/mod.rs +8 -7
- package/dist-engine-src/src/tracked_state/storage.rs +138 -6
- package/dist-engine-src/src/tracked_state/tree.rs +695 -252
- package/dist-engine-src/src/tracked_state/types.rs +176 -6
- package/dist-engine-src/src/transaction/commit.rs +695 -435
- package/dist-engine-src/src/transaction/context.rs +551 -310
- package/dist-engine-src/src/transaction/live_state_overlay.rs +9 -8
- package/dist-engine-src/src/transaction/mod.rs +2 -0
- package/dist-engine-src/src/transaction/normalization.rs +311 -447
- package/dist-engine-src/src/transaction/prep.rs +37 -0
- package/dist-engine-src/src/transaction/schema_resolver.rs +93 -71
- package/dist-engine-src/src/transaction/staging.rs +701 -406
- package/dist-engine-src/src/transaction/types.rs +231 -122
- package/dist-engine-src/src/transaction/validation.rs +2717 -1698
- package/dist-engine-src/src/untracked_state/codec.rs +40 -96
- package/dist-engine-src/src/untracked_state/context.rs +21 -5
- package/dist-engine-src/src/untracked_state/materialization.rs +10 -104
- package/dist-engine-src/src/untracked_state/mod.rs +3 -5
- package/dist-engine-src/src/untracked_state/storage.rs +105 -57
- package/dist-engine-src/src/untracked_state/types.rs +63 -13
- package/dist-engine-src/src/version/context.rs +1 -13
- package/dist-engine-src/src/version/lifecycle.rs +221 -0
- package/dist-engine-src/src/version/mod.rs +3 -2
- package/dist-engine-src/src/version/refs.rs +12 -103
- package/dist-engine-src/src/version/stage_rows.rs +15 -19
- package/package.json +1 -1
- package/dist-engine-src/src/changelog/codec.rs +0 -321
- package/dist-engine-src/src/changelog/context.rs +0 -92
- package/dist-engine-src/src/changelog/materialization.rs +0 -121
- package/dist-engine-src/src/changelog/mod.rs +0 -13
- package/dist-engine-src/src/changelog/reader.rs +0 -20
- package/dist-engine-src/src/changelog/storage.rs +0 -220
- package/dist-engine-src/src/changelog/types.rs +0 -38
- package/dist-engine-src/src/schema/builtin/lix_change_set.json +0 -18
- package/dist-engine-src/src/schema/builtin/lix_change_set_element.json +0 -75
- package/dist-engine-src/src/schema/builtin/lix_entity_label.json +0 -63
- package/dist-engine-src/src/schema_registry.rs +0 -294
- package/dist-engine-src/src/sql2/commit_derived_provider.rs +0 -591
- package/dist-engine-src/src/tracked_state/rebuild.rs +0 -771
- package/dist-engine-src/src/tracked_state/tree_types.rs +0 -176
|
@@ -5,11 +5,11 @@ mod types;
|
|
|
5
5
|
mod visibility;
|
|
6
6
|
|
|
7
7
|
#[allow(unused_imports)]
|
|
8
|
-
pub(crate) use context::{LiveStateContext, LiveStateStoreReader
|
|
8
|
+
pub(crate) use context::{LiveStateContext, LiveStateStoreReader};
|
|
9
9
|
#[allow(unused_imports)]
|
|
10
10
|
pub(crate) use reader::LiveStateReader;
|
|
11
11
|
#[allow(unused_imports)]
|
|
12
12
|
pub(crate) use types::{
|
|
13
|
-
Bound, LiveStateFilter, LiveStateProjection,
|
|
14
|
-
|
|
13
|
+
Bound, LiveStateFilter, LiveStateProjection, LiveStateRowIdentity, LiveStateRowRequest,
|
|
14
|
+
LiveStateScanRequest, MaterializedLiveStateRow, ScanConstraint, ScanField, ScanOperator,
|
|
15
15
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
use std::collections::BTreeMap;
|
|
2
2
|
|
|
3
|
-
use crate::live_state::{
|
|
3
|
+
use crate::live_state::{LiveStateRowIdentity, MaterializedLiveStateRow};
|
|
4
4
|
|
|
5
5
|
/// Applies the local untracked overlay to tracked live-state rows.
|
|
6
6
|
///
|
|
@@ -9,9 +9,9 @@ use crate::live_state::{LiveStateRow, LiveStateRowIdentity};
|
|
|
9
9
|
/// knowing whether a visible row came from tracked changelog projection or from
|
|
10
10
|
/// local untracked state.
|
|
11
11
|
pub(crate) fn overlay_untracked_rows(
|
|
12
|
-
tracked_rows: Vec<
|
|
13
|
-
untracked_rows: Vec<
|
|
14
|
-
) -> Vec<
|
|
12
|
+
tracked_rows: Vec<MaterializedLiveStateRow>,
|
|
13
|
+
untracked_rows: Vec<MaterializedLiveStateRow>,
|
|
14
|
+
) -> Vec<MaterializedLiveStateRow> {
|
|
15
15
|
let mut rows_by_identity = BTreeMap::new();
|
|
16
16
|
|
|
17
17
|
for row in tracked_rows {
|
|
@@ -55,14 +55,14 @@ mod tests {
|
|
|
55
55
|
assert_eq!(rows.len(), 2);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
fn live_row(value: &str, untracked: bool, change_id: Option<&str>) ->
|
|
59
|
-
|
|
58
|
+
fn live_row(value: &str, untracked: bool, change_id: Option<&str>) -> MaterializedLiveStateRow {
|
|
59
|
+
MaterializedLiveStateRow {
|
|
60
60
|
entity_id: crate::entity_identity::EntityIdentity::single("entity"),
|
|
61
61
|
schema_key: "schema".to_string(),
|
|
62
62
|
file_id: None,
|
|
63
63
|
snapshot_content: Some(format!("{{\"value\":\"{value}\"}}")),
|
|
64
64
|
metadata: None,
|
|
65
|
-
|
|
65
|
+
deleted: false,
|
|
66
66
|
created_at: "2026-01-01T00:00:00Z".to_string(),
|
|
67
67
|
updated_at: "2026-01-01T00:00:00Z".to_string(),
|
|
68
68
|
global: true,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
use async_trait::async_trait;
|
|
2
2
|
|
|
3
|
-
use crate::live_state::
|
|
3
|
+
use crate::live_state::MaterializedLiveStateRow;
|
|
4
4
|
use crate::live_state::{LiveStateRowRequest, LiveStateScanRequest};
|
|
5
5
|
use crate::LixError;
|
|
6
6
|
|
|
7
|
-
/// Minimal
|
|
7
|
+
/// Minimal engine read model for transaction planning and SQL providers.
|
|
8
8
|
///
|
|
9
|
-
///
|
|
9
|
+
/// Engine only needs visible state-row reads here. Changelog freshness/catch-up
|
|
10
10
|
/// should be added at this boundary later instead of leaking projection internals
|
|
11
11
|
/// into sessions or SQL providers.
|
|
12
12
|
#[async_trait]
|
|
@@ -14,10 +14,10 @@ pub(crate) trait LiveStateReader: Send + Sync {
|
|
|
14
14
|
async fn scan_rows(
|
|
15
15
|
&self,
|
|
16
16
|
request: &LiveStateScanRequest,
|
|
17
|
-
) -> Result<Vec<
|
|
17
|
+
) -> Result<Vec<MaterializedLiveStateRow>, LixError>;
|
|
18
18
|
|
|
19
19
|
async fn load_row(
|
|
20
20
|
&self,
|
|
21
21
|
request: &LiveStateRowRequest,
|
|
22
|
-
) -> Result<Option<
|
|
22
|
+
) -> Result<Option<MaterializedLiveStateRow>, LixError>;
|
|
23
23
|
}
|
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
use crate::changelog::MaterializedCanonicalChange;
|
|
2
1
|
use crate::entity_identity::EntityIdentity;
|
|
3
|
-
use crate::tracked_state::
|
|
2
|
+
use crate::tracked_state::MaterializedTrackedStateRow;
|
|
4
3
|
use crate::untracked_state::{
|
|
5
4
|
MaterializedUntrackedStateRow, UntrackedStateFilter, UntrackedStateRowRequest,
|
|
6
5
|
};
|
|
7
|
-
use crate::{NullableKeyFilter,
|
|
6
|
+
use crate::{NullableKeyFilter, Value};
|
|
8
7
|
|
|
9
8
|
/// Durable row visible through live_state reads.
|
|
10
9
|
///
|
|
11
10
|
/// Unlike provider write rows, live-state rows are fully hydrated facts. Missing
|
|
12
11
|
/// generated fields should be caught before this type is constructed.
|
|
13
12
|
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
|
14
|
-
pub(crate) struct
|
|
13
|
+
pub(crate) struct MaterializedLiveStateRow {
|
|
15
14
|
pub(crate) entity_id: EntityIdentity,
|
|
16
15
|
pub(crate) schema_key: String,
|
|
17
16
|
pub(crate) file_id: Option<String>,
|
|
18
17
|
pub(crate) snapshot_content: Option<String>,
|
|
19
|
-
pub(crate) metadata: Option<
|
|
20
|
-
pub(crate)
|
|
18
|
+
pub(crate) metadata: Option<String>,
|
|
19
|
+
pub(crate) deleted: bool,
|
|
21
20
|
pub(crate) created_at: String,
|
|
22
21
|
pub(crate) updated_at: String,
|
|
23
22
|
pub(crate) global: bool,
|
|
@@ -27,32 +26,15 @@ pub(crate) struct LiveStateRow {
|
|
|
27
26
|
pub(crate) version_id: String,
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
impl From<
|
|
31
|
-
fn from(row: LiveStateRow) -> Self {
|
|
32
|
-
MaterializedCanonicalChange {
|
|
33
|
-
id: row
|
|
34
|
-
.change_id
|
|
35
|
-
.expect("tracked live-state rows must carry change_id"),
|
|
36
|
-
entity_id: row.entity_id,
|
|
37
|
-
schema_key: row.schema_key,
|
|
38
|
-
schema_version: row.schema_version,
|
|
39
|
-
file_id: row.file_id,
|
|
40
|
-
snapshot_content: row.snapshot_content,
|
|
41
|
-
metadata: row.metadata,
|
|
42
|
-
created_at: row.created_at,
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
impl From<MaterializedUntrackedStateRow> for LiveStateRow {
|
|
29
|
+
impl From<MaterializedUntrackedStateRow> for MaterializedLiveStateRow {
|
|
48
30
|
fn from(row: MaterializedUntrackedStateRow) -> Self {
|
|
49
|
-
|
|
31
|
+
MaterializedLiveStateRow {
|
|
50
32
|
entity_id: row.entity_id,
|
|
51
33
|
schema_key: row.schema_key,
|
|
52
34
|
file_id: row.file_id,
|
|
53
35
|
snapshot_content: row.snapshot_content,
|
|
54
36
|
metadata: row.metadata,
|
|
55
|
-
|
|
37
|
+
deleted: row.deleted,
|
|
56
38
|
created_at: row.created_at,
|
|
57
39
|
updated_at: row.updated_at,
|
|
58
40
|
global: row.global,
|
|
@@ -64,10 +46,10 @@ impl From<MaterializedUntrackedStateRow> for LiveStateRow {
|
|
|
64
46
|
}
|
|
65
47
|
}
|
|
66
48
|
|
|
67
|
-
impl TryFrom<&
|
|
49
|
+
impl TryFrom<&MaterializedLiveStateRow> for MaterializedTrackedStateRow {
|
|
68
50
|
type Error = crate::LixError;
|
|
69
51
|
|
|
70
|
-
fn try_from(row: &
|
|
52
|
+
fn try_from(row: &MaterializedLiveStateRow) -> Result<Self, Self::Error> {
|
|
71
53
|
if row.untracked {
|
|
72
54
|
return Err(crate::LixError::new(
|
|
73
55
|
"LIX_ERROR_UNKNOWN",
|
|
@@ -87,13 +69,13 @@ impl TryFrom<&LiveStateRow> for TrackedStateRow {
|
|
|
87
69
|
));
|
|
88
70
|
};
|
|
89
71
|
|
|
90
|
-
Ok(
|
|
72
|
+
Ok(MaterializedTrackedStateRow {
|
|
91
73
|
entity_id: row.entity_id.clone(),
|
|
92
74
|
schema_key: row.schema_key.clone(),
|
|
93
75
|
file_id: row.file_id.clone(),
|
|
94
76
|
snapshot_content: row.snapshot_content.clone(),
|
|
95
77
|
metadata: row.metadata.clone(),
|
|
96
|
-
|
|
78
|
+
deleted: row.deleted,
|
|
97
79
|
created_at: row.created_at.clone(),
|
|
98
80
|
updated_at: row.updated_at.clone(),
|
|
99
81
|
change_id,
|
|
@@ -102,15 +84,15 @@ impl TryFrom<&LiveStateRow> for TrackedStateRow {
|
|
|
102
84
|
}
|
|
103
85
|
}
|
|
104
86
|
|
|
105
|
-
impl From<&
|
|
106
|
-
fn from(row: &
|
|
87
|
+
impl From<&MaterializedLiveStateRow> for MaterializedUntrackedStateRow {
|
|
88
|
+
fn from(row: &MaterializedLiveStateRow) -> Self {
|
|
107
89
|
MaterializedUntrackedStateRow {
|
|
108
90
|
entity_id: row.entity_id.clone(),
|
|
109
91
|
schema_key: row.schema_key.clone(),
|
|
110
92
|
file_id: row.file_id.clone(),
|
|
111
93
|
snapshot_content: row.snapshot_content.clone(),
|
|
112
94
|
metadata: row.metadata.clone(),
|
|
113
|
-
|
|
95
|
+
deleted: row.deleted,
|
|
114
96
|
created_at: row.created_at.clone(),
|
|
115
97
|
updated_at: row.updated_at.clone(),
|
|
116
98
|
global: row.global,
|
|
@@ -124,7 +106,6 @@ impl From<&LiveStateRow> for MaterializedUntrackedStateRow {
|
|
|
124
106
|
pub(crate) enum ScanField {
|
|
125
107
|
EntityId,
|
|
126
108
|
FileId,
|
|
127
|
-
SchemaVersion,
|
|
128
109
|
}
|
|
129
110
|
|
|
130
111
|
/// Inclusive or exclusive range bound.
|
|
@@ -164,6 +145,8 @@ pub(crate) struct LiveStateFilter {
|
|
|
164
145
|
#[serde(default)]
|
|
165
146
|
pub(crate) file_ids: Vec<NullableKeyFilter<String>>,
|
|
166
147
|
#[serde(default)]
|
|
148
|
+
pub(crate) untracked: Option<bool>,
|
|
149
|
+
#[serde(default)]
|
|
167
150
|
pub(crate) constraints: Vec<ScanConstraint>,
|
|
168
151
|
#[serde(default)]
|
|
169
152
|
pub(crate) include_tombstones: bool,
|
|
@@ -187,7 +170,7 @@ pub(crate) struct LiveStateProjection {
|
|
|
187
170
|
pub(crate) columns: Vec<String>,
|
|
188
171
|
}
|
|
189
172
|
|
|
190
|
-
/// First-principles scan request for
|
|
173
|
+
/// First-principles scan request for engine-owned reads.
|
|
191
174
|
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)]
|
|
192
175
|
pub(crate) struct LiveStateScanRequest {
|
|
193
176
|
#[serde(default)]
|
|
@@ -228,7 +211,7 @@ pub(crate) struct LiveStateRowIdentity {
|
|
|
228
211
|
}
|
|
229
212
|
|
|
230
213
|
impl LiveStateRowIdentity {
|
|
231
|
-
pub(crate) fn from_row(row: &
|
|
214
|
+
pub(crate) fn from_row(row: &MaterializedLiveStateRow) -> Self {
|
|
232
215
|
Self {
|
|
233
216
|
version_id: row.version_id.clone(),
|
|
234
217
|
schema_key: row.schema_key.clone(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
use std::collections::BTreeMap;
|
|
2
2
|
|
|
3
|
-
use crate::live_state::{
|
|
3
|
+
use crate::live_state::{LiveStateRowIdentity, MaterializedLiveStateRow};
|
|
4
4
|
use crate::GLOBAL_VERSION_ID;
|
|
5
5
|
|
|
6
6
|
/// Expands a version-scoped storage read so global candidates are available for
|
|
@@ -32,13 +32,13 @@ pub(crate) fn expanded_version_ids(version_ids: &[String]) -> Vec<String> {
|
|
|
32
32
|
/// validation remains exact storage-scope local unless a validator explicitly
|
|
33
33
|
/// opts into overlay semantics.
|
|
34
34
|
pub(crate) fn resolve_scan_rows(
|
|
35
|
-
rows: Vec<
|
|
35
|
+
rows: Vec<MaterializedLiveStateRow>,
|
|
36
36
|
requested_version_ids: &[String],
|
|
37
37
|
include_tombstones: bool,
|
|
38
|
-
) -> Vec<
|
|
38
|
+
) -> Vec<MaterializedLiveStateRow> {
|
|
39
39
|
let mut rows = project_global_rows_into_requested_versions(rows, requested_version_ids);
|
|
40
40
|
if !include_tombstones {
|
|
41
|
-
rows.retain(|row| row.
|
|
41
|
+
rows.retain(|row| !row.deleted);
|
|
42
42
|
}
|
|
43
43
|
rows
|
|
44
44
|
}
|
|
@@ -46,10 +46,10 @@ pub(crate) fn resolve_scan_rows(
|
|
|
46
46
|
/// Resolves a row loaded through a concrete storage version into the row visible
|
|
47
47
|
/// to the requested version scope.
|
|
48
48
|
pub(crate) fn project_loaded_row(
|
|
49
|
-
mut row:
|
|
49
|
+
mut row: MaterializedLiveStateRow,
|
|
50
50
|
requested_version_id: &str,
|
|
51
51
|
matched_version_id: &str,
|
|
52
|
-
) ->
|
|
52
|
+
) -> MaterializedLiveStateRow {
|
|
53
53
|
if row.global && requested_version_id != GLOBAL_VERSION_ID {
|
|
54
54
|
row.version_id = requested_version_id.to_string();
|
|
55
55
|
} else if matched_version_id == GLOBAL_VERSION_ID && requested_version_id != GLOBAL_VERSION_ID {
|
|
@@ -59,14 +59,14 @@ pub(crate) fn project_loaded_row(
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
fn project_global_rows_into_requested_versions(
|
|
62
|
-
rows: Vec<
|
|
62
|
+
rows: Vec<MaterializedLiveStateRow>,
|
|
63
63
|
requested_version_ids: &[String],
|
|
64
|
-
) -> Vec<
|
|
64
|
+
) -> Vec<MaterializedLiveStateRow> {
|
|
65
65
|
if requested_version_ids.is_empty() {
|
|
66
66
|
return rows;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
let mut rows_by_identity = BTreeMap::<LiveStateRowIdentity,
|
|
69
|
+
let mut rows_by_identity = BTreeMap::<LiveStateRowIdentity, MaterializedLiveStateRow>::new();
|
|
70
70
|
for requested_version_id in requested_version_ids {
|
|
71
71
|
for row in &rows {
|
|
72
72
|
if row.version_id == GLOBAL_VERSION_ID {
|
|
@@ -191,14 +191,14 @@ mod tests {
|
|
|
191
191
|
value: &str,
|
|
192
192
|
global: bool,
|
|
193
193
|
change_id: Option<&str>,
|
|
194
|
-
) ->
|
|
195
|
-
|
|
194
|
+
) -> MaterializedLiveStateRow {
|
|
195
|
+
MaterializedLiveStateRow {
|
|
196
196
|
entity_id: crate::entity_identity::EntityIdentity::single("entity"),
|
|
197
197
|
schema_key: "schema".to_string(),
|
|
198
198
|
file_id: None,
|
|
199
199
|
snapshot_content: Some(format!("{{\"value\":\"{value}\"}}")),
|
|
200
200
|
metadata: None,
|
|
201
|
-
|
|
201
|
+
deleted: false,
|
|
202
202
|
created_at: "2026-01-01T00:00:00Z".to_string(),
|
|
203
203
|
updated_at: "2026-01-01T00:00:00Z".to_string(),
|
|
204
204
|
global,
|
|
@@ -209,9 +209,14 @@ mod tests {
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
fn tombstone_at(
|
|
213
|
-
|
|
212
|
+
fn tombstone_at(
|
|
213
|
+
version_id: &str,
|
|
214
|
+
global: bool,
|
|
215
|
+
change_id: Option<&str>,
|
|
216
|
+
) -> MaterializedLiveStateRow {
|
|
217
|
+
MaterializedLiveStateRow {
|
|
214
218
|
snapshot_content: None,
|
|
219
|
+
deleted: true,
|
|
215
220
|
..row_at(version_id, "ignored", global, change_id)
|
|
216
221
|
}
|
|
217
222
|
}
|
|
@@ -71,15 +71,12 @@ pub(crate) fn parse_plugin_archive_for_install(
|
|
|
71
71
|
})?;
|
|
72
72
|
validate_lix_schema_definition(&schema_json)?;
|
|
73
73
|
let schema_key = schema_key_from_definition(&schema_json)?;
|
|
74
|
-
if !seen_schema_keys.insert((
|
|
75
|
-
schema_key.schema_key.clone(),
|
|
76
|
-
schema_key.schema_version.clone(),
|
|
77
|
-
)) {
|
|
74
|
+
if !seen_schema_keys.insert(schema_key.schema_key.clone()) {
|
|
78
75
|
return Err(LixError {
|
|
79
76
|
code: "LIX_ERROR_UNKNOWN".to_string(),
|
|
80
77
|
message: format!(
|
|
81
|
-
"Plugin archive declares duplicate schema '{}
|
|
82
|
-
schema_key.schema_key
|
|
78
|
+
"Plugin archive declares duplicate schema '{}'",
|
|
79
|
+
schema_key.schema_key
|
|
83
80
|
),
|
|
84
81
|
hint: None,
|
|
85
82
|
details: None,
|
|
@@ -37,11 +37,8 @@ use crate::{LixError, Value};
|
|
|
37
37
|
|
|
38
38
|
use crate::transaction::WriteCommand;
|
|
39
39
|
const REGISTERED_SCHEMA_STORAGE_SCHEMA_KEY: &str = "lix_registered_schema";
|
|
40
|
-
const REGISTERED_SCHEMA_STORAGE_SCHEMA_VERSION: &str = "1";
|
|
41
40
|
const FILESYSTEM_DESCRIPTOR_SCHEMA_KEY: &str = "lix_file_descriptor";
|
|
42
|
-
const FILESYSTEM_DESCRIPTOR_SCHEMA_VERSION: &str = "1";
|
|
43
41
|
const FILESYSTEM_BINARY_BLOB_REF_SCHEMA_KEY: &str = "lix_binary_blob_ref";
|
|
44
|
-
const FILESYSTEM_BINARY_BLOB_REF_SCHEMA_VERSION: &str = "1";
|
|
45
42
|
|
|
46
43
|
#[derive(Clone)]
|
|
47
44
|
pub(crate) struct PluginInstallWriteContext {
|
|
@@ -170,7 +167,6 @@ fn prepare_registered_schema_write_statement_from_schemas(
|
|
|
170
167
|
.map(|row| PublicChange {
|
|
171
168
|
entity_id: row.entity_id.clone(),
|
|
172
169
|
schema_key: REGISTERED_SCHEMA_STORAGE_SCHEMA_KEY.to_string(),
|
|
173
|
-
schema_version: Some(REGISTERED_SCHEMA_STORAGE_SCHEMA_VERSION.to_string()),
|
|
174
170
|
file_id: None,
|
|
175
171
|
plugin_key: None,
|
|
176
172
|
snapshot_content: Some(row.snapshot.to_string()),
|
|
@@ -289,10 +285,6 @@ fn registered_schema_planned_row(
|
|
|
289
285
|
);
|
|
290
286
|
values.insert("file_id".to_string(), Value::Null);
|
|
291
287
|
values.insert("plugin_key".to_string(), Value::Null);
|
|
292
|
-
values.insert(
|
|
293
|
-
"schema_version".to_string(),
|
|
294
|
-
Value::Text(REGISTERED_SCHEMA_STORAGE_SCHEMA_VERSION.to_string()),
|
|
295
|
-
);
|
|
296
288
|
values.insert(
|
|
297
289
|
"snapshot_content".to_string(),
|
|
298
290
|
Value::Json(row.snapshot.clone()),
|
|
@@ -331,10 +323,6 @@ fn plugin_archive_file_descriptor_row(
|
|
|
331
323
|
);
|
|
332
324
|
values.insert("file_id".to_string(), Value::Null);
|
|
333
325
|
values.insert("plugin_key".to_string(), Value::Null);
|
|
334
|
-
values.insert(
|
|
335
|
-
"schema_version".to_string(),
|
|
336
|
-
Value::Text(FILESYSTEM_DESCRIPTOR_SCHEMA_VERSION.to_string()),
|
|
337
|
-
);
|
|
338
326
|
values.insert(
|
|
339
327
|
"snapshot_content".to_string(),
|
|
340
328
|
Value::Text(snapshot_content),
|
|
@@ -381,10 +369,6 @@ fn plugin_archive_binary_blob_ref_row(
|
|
|
381
369
|
);
|
|
382
370
|
values.insert("file_id".to_string(), Value::Text(archive_id.to_string()));
|
|
383
371
|
values.insert("plugin_key".to_string(), Value::Null);
|
|
384
|
-
values.insert(
|
|
385
|
-
"schema_version".to_string(),
|
|
386
|
-
Value::Text(FILESYSTEM_BINARY_BLOB_REF_SCHEMA_VERSION.to_string()),
|
|
387
|
-
);
|
|
388
372
|
values.insert(
|
|
389
373
|
"snapshot_content".to_string(),
|
|
390
374
|
Value::Text(snapshot_content),
|
|
@@ -506,7 +490,6 @@ fn planned_row_to_public_change(row: &PlannedStateRow) -> Result<PublicChange, L
|
|
|
506
490
|
Ok(PublicChange {
|
|
507
491
|
entity_id: row.entity_id.clone(),
|
|
508
492
|
schema_key: row.schema_key.clone(),
|
|
509
|
-
schema_version: planned_row_text_value(row, "schema_version"),
|
|
510
493
|
file_id: planned_row_text_value(row, "file_id"),
|
|
511
494
|
plugin_key: planned_row_text_value(row, "plugin_key"),
|
|
512
495
|
snapshot_content: if row.tombstone {
|
|
@@ -569,7 +552,6 @@ fn summarize_change(change: &PublicChange) -> JsonValue {
|
|
|
569
552
|
json!({
|
|
570
553
|
"entity_id": change.entity_id,
|
|
571
554
|
"schema_key": change.schema_key,
|
|
572
|
-
"schema_version": change.schema_version,
|
|
573
555
|
"file_id": change.file_id,
|
|
574
556
|
"plugin_key": change.plugin_key,
|
|
575
557
|
"version_id": change.version_id,
|
|
@@ -9,7 +9,6 @@ pub(crate) fn apply_schema_defaults<P>(
|
|
|
9
9
|
evaluator: &CelEvaluator,
|
|
10
10
|
functions: P,
|
|
11
11
|
schema_key: &str,
|
|
12
|
-
schema_version: &str,
|
|
13
12
|
) -> Result<bool, LixError>
|
|
14
13
|
where
|
|
15
14
|
P: CelFunctionProvider,
|
|
@@ -21,7 +20,6 @@ where
|
|
|
21
20
|
evaluator,
|
|
22
21
|
functions,
|
|
23
22
|
schema_key,
|
|
24
|
-
schema_version,
|
|
25
23
|
)
|
|
26
24
|
}
|
|
27
25
|
|
|
@@ -30,7 +28,6 @@ pub(crate) fn apply_schema_defaults_with_shared_runtime<P>(
|
|
|
30
28
|
schema: &JsonValue,
|
|
31
29
|
functions: P,
|
|
32
30
|
schema_key: &str,
|
|
33
|
-
schema_version: &str,
|
|
34
31
|
) -> Result<bool, LixError>
|
|
35
32
|
where
|
|
36
33
|
P: CelFunctionProvider,
|
|
@@ -41,7 +38,6 @@ where
|
|
|
41
38
|
crate::cel::shared_runtime(),
|
|
42
39
|
functions,
|
|
43
40
|
schema_key,
|
|
44
|
-
schema_version,
|
|
45
41
|
)
|
|
46
42
|
}
|
|
47
43
|
|
|
@@ -52,7 +48,6 @@ pub(crate) fn apply_schema_defaults_with_context<P>(
|
|
|
52
48
|
evaluator: &CelEvaluator,
|
|
53
49
|
functions: P,
|
|
54
50
|
schema_key: &str,
|
|
55
|
-
schema_version: &str,
|
|
56
51
|
) -> Result<bool, LixError>
|
|
57
52
|
where
|
|
58
53
|
P: CelFunctionProvider,
|
|
@@ -78,8 +73,8 @@ where
|
|
|
78
73
|
.map_err(|err| LixError {
|
|
79
74
|
code: "LIX_ERROR_UNKNOWN".to_string(),
|
|
80
75
|
message: format!(
|
|
81
|
-
"failed to evaluate x-lix-default for '{}.{}'
|
|
82
|
-
schema_key, field_name,
|
|
76
|
+
"failed to evaluate x-lix-default for '{}.{}': {}",
|
|
77
|
+
schema_key, field_name, err.message
|
|
83
78
|
),
|
|
84
79
|
hint: None,
|
|
85
80
|
details: None,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"x-lix-key": "lix_change",
|
|
3
|
-
"
|
|
4
|
-
"description": "Canonical immutable change fact. This surface represents the authoritative stream of journaled change facts. Commit lineage and non-commit scope are modeled separately around these facts.",
|
|
3
|
+
"description": "A change records one edit to a Lix entity, including what changed, when it changed, and which entity was affected.",
|
|
5
4
|
"x-lix-primary-key": [
|
|
6
5
|
"/id"
|
|
7
6
|
],
|
|
@@ -10,20 +9,20 @@
|
|
|
10
9
|
"id": {
|
|
11
10
|
"type": "string",
|
|
12
11
|
"x-lix-default": "lix_uuid_v7()",
|
|
13
|
-
"description": "Stable
|
|
12
|
+
"description": "Stable identifier for this change."
|
|
14
13
|
},
|
|
15
14
|
"entity_id": {
|
|
16
|
-
"type": "
|
|
17
|
-
"description": "
|
|
15
|
+
"type": "array",
|
|
16
|
+
"description": "Canonical JSON primary-key tuple for the entity this change applies to, scoped by (`schema_key`, `file_id`). Values are ordered according to the target schema's `x-lix-primary-key`.",
|
|
17
|
+
"items": {
|
|
18
|
+
"type": "string"
|
|
19
|
+
},
|
|
20
|
+
"minItems": 1
|
|
18
21
|
},
|
|
19
22
|
"schema_key": {
|
|
20
23
|
"type": "string",
|
|
21
24
|
"description": "Schema identifier of the entity (e.g. `lix_file_descriptor`, `lix_commit`, or a user-registered key)."
|
|
22
25
|
},
|
|
23
|
-
"schema_version": {
|
|
24
|
-
"type": "string",
|
|
25
|
-
"description": "Schema version the snapshot_content was written against (matches `x-lix-version` on the schema at write time)."
|
|
26
|
-
},
|
|
27
26
|
"file_id": {
|
|
28
27
|
"type": [
|
|
29
28
|
"string",
|
|
@@ -40,6 +39,9 @@
|
|
|
40
39
|
},
|
|
41
40
|
"created_at": {
|
|
42
41
|
"type": "string",
|
|
42
|
+
"examples": [
|
|
43
|
+
"2026-05-08T17:42:31.123Z"
|
|
44
|
+
],
|
|
43
45
|
"description": "ISO-8601 timestamp at which the change was recorded (set via `lix_timestamp()` at write time)."
|
|
44
46
|
},
|
|
45
47
|
"snapshot_content": {
|
|
@@ -54,7 +56,6 @@
|
|
|
54
56
|
"id",
|
|
55
57
|
"entity_id",
|
|
56
58
|
"schema_key",
|
|
57
|
-
"schema_version",
|
|
58
59
|
"file_id",
|
|
59
60
|
"created_at"
|
|
60
61
|
],
|
|
@@ -1,62 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"x-lix-key": "lix_commit",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"x-lix-primary-key": [
|
|
6
|
-
"/id"
|
|
7
|
-
],
|
|
8
|
-
"x-lix-foreign-keys": [
|
|
3
|
+
"description": "A commit is a stable point in project history. Versions point to commits. Use lix_commit_edge to inspect parent commits.",
|
|
4
|
+
"examples": [
|
|
9
5
|
{
|
|
10
|
-
"
|
|
11
|
-
"/change_set_id"
|
|
12
|
-
],
|
|
13
|
-
"references": {
|
|
14
|
-
"schemaKey": "lix_change_set",
|
|
15
|
-
"properties": [
|
|
16
|
-
"/id"
|
|
17
|
-
]
|
|
18
|
-
}
|
|
6
|
+
"id": "commit_01jexample"
|
|
19
7
|
}
|
|
20
8
|
],
|
|
9
|
+
"x-lix-primary-key": [
|
|
10
|
+
"/id"
|
|
11
|
+
],
|
|
21
12
|
"type": "object",
|
|
22
13
|
"properties": {
|
|
23
14
|
"id": {
|
|
24
15
|
"type": "string",
|
|
25
16
|
"x-lix-default": "lix_uuid_v7()",
|
|
26
|
-
"description": "Stable commit
|
|
27
|
-
},
|
|
28
|
-
"change_set_id": {
|
|
29
|
-
"type": "string",
|
|
30
|
-
"description": "Commit-local grouping identifier used by derived relational indexes and projections such as lix_change_set_element."
|
|
31
|
-
},
|
|
32
|
-
"change_ids": {
|
|
33
|
-
"type": "array",
|
|
34
|
-
"default": [],
|
|
35
|
-
"items": {
|
|
36
|
-
"type": "string"
|
|
37
|
-
},
|
|
38
|
-
"description": "Canonical ordered membership list of non-header change IDs whose effects this commit introduces relative to its first parent. Merge commits may reference existing changes from another parent instead of minting equivalent copies. Derived indexes such as lix_change_set_element must be rebuildable from this list. This does not include lix_version_ref pointer rows."
|
|
39
|
-
},
|
|
40
|
-
"author_account_ids": {
|
|
41
|
-
"type": "array",
|
|
42
|
-
"default": [],
|
|
43
|
-
"items": {
|
|
44
|
-
"type": "string"
|
|
45
|
-
},
|
|
46
|
-
"description": "Ordered set of author account IDs associated with this commit."
|
|
47
|
-
},
|
|
48
|
-
"parent_commit_ids": {
|
|
49
|
-
"type": "array",
|
|
50
|
-
"default": [],
|
|
51
|
-
"items": {
|
|
52
|
-
"type": "string"
|
|
53
|
-
},
|
|
54
|
-
"description": "Parent commit IDs for commit graph topology."
|
|
17
|
+
"description": "Stable identifier of this commit."
|
|
55
18
|
}
|
|
56
19
|
},
|
|
57
20
|
"required": [
|
|
58
|
-
"id"
|
|
59
|
-
"change_set_id"
|
|
21
|
+
"id"
|
|
60
22
|
],
|
|
61
23
|
"additionalProperties": false
|
|
62
24
|
}
|