@lix-js/sdk 0.6.0-preview.4 → 0.6.0-preview.5

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.
Files changed (234) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +65 -64
  3. package/dist/engine-wasm/index.js +4 -4
  4. package/dist/engine-wasm/wasm/lix_engine.d.ts +5 -5
  5. package/dist/engine-wasm/wasm/lix_engine.js +130 -118
  6. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  7. package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +9 -8
  8. package/dist/generated/builtin-schemas.d.ts +69 -69
  9. package/dist/generated/builtin-schemas.js +94 -94
  10. package/dist/open-lix.d.ts +33 -26
  11. package/dist/open-lix.js +10 -10
  12. package/dist/sqlite/index.js +86 -30
  13. package/dist-engine-src/README.md +3 -3
  14. package/dist-engine-src/src/backend/capabilities.rs +67 -0
  15. package/dist-engine-src/src/backend/conformance/baseline.rs +1127 -0
  16. package/dist-engine-src/src/backend/conformance/factory.rs +93 -0
  17. package/dist-engine-src/src/backend/conformance/failure_tests.rs +608 -0
  18. package/dist-engine-src/src/backend/conformance/fixtures.rs +26 -0
  19. package/dist-engine-src/src/backend/conformance/mod.rs +75 -0
  20. package/dist-engine-src/src/backend/conformance/model.rs +28 -0
  21. package/dist-engine-src/src/backend/conformance/model_based.rs +257 -0
  22. package/dist-engine-src/src/backend/conformance/persistence.rs +204 -0
  23. package/dist-engine-src/src/backend/conformance/projection.rs +21 -0
  24. package/dist-engine-src/src/backend/conformance/pushdown.rs +24 -0
  25. package/dist-engine-src/src/backend/conformance/runner.rs +90 -0
  26. package/dist-engine-src/src/backend/conformance/scan.rs +24 -0
  27. package/dist-engine-src/src/backend/conformance/write.rs +16 -0
  28. package/dist-engine-src/src/backend/error.rs +94 -0
  29. package/dist-engine-src/src/backend/in_memory.rs +670 -0
  30. package/dist-engine-src/src/backend/mod.rs +36 -9
  31. package/dist-engine-src/src/backend/predicate.rs +80 -0
  32. package/dist-engine-src/src/backend/traits.rs +260 -0
  33. package/dist-engine-src/src/backend/types.rs +224 -81
  34. package/dist-engine-src/src/binary_cas/context.rs +8 -8
  35. package/dist-engine-src/src/binary_cas/kv.rs +234 -259
  36. package/dist-engine-src/src/{version → branch}/context.rs +12 -12
  37. package/dist-engine-src/src/branch/lifecycle.rs +221 -0
  38. package/dist-engine-src/src/branch/mod.rs +13 -0
  39. package/dist-engine-src/src/branch/refs.rs +321 -0
  40. package/dist-engine-src/src/branch/stage_rows.rs +67 -0
  41. package/dist-engine-src/src/branch/types.rs +21 -0
  42. package/dist-engine-src/src/catalog/context.rs +18 -18
  43. package/dist-engine-src/src/catalog/snapshot.rs +8 -8
  44. package/dist-engine-src/src/changelog/bench_support.rs +785 -0
  45. package/dist-engine-src/src/changelog/change.rs +1 -0
  46. package/dist-engine-src/src/changelog/codec.rs +497 -0
  47. package/dist-engine-src/src/changelog/commit.rs +1 -0
  48. package/dist-engine-src/src/changelog/context.rs +1614 -0
  49. package/dist-engine-src/src/changelog/mod.rs +29 -0
  50. package/dist-engine-src/src/changelog/store.rs +163 -0
  51. package/dist-engine-src/src/changelog/test_support.rs +54 -0
  52. package/dist-engine-src/src/changelog/types.rs +213 -0
  53. package/dist-engine-src/src/commit_graph/context.rs +317 -274
  54. package/dist-engine-src/src/commit_graph/mod.rs +2 -4
  55. package/dist-engine-src/src/commit_graph/types.rs +22 -42
  56. package/dist-engine-src/src/commit_graph/walker.rs +133 -103
  57. package/dist-engine-src/src/common/error.rs +52 -18
  58. package/dist-engine-src/src/common/identity.rs +2 -2
  59. package/dist-engine-src/src/common/mod.rs +1 -1
  60. package/dist-engine-src/src/domain.rs +42 -46
  61. package/dist-engine-src/src/engine.rs +74 -96
  62. package/dist-engine-src/src/{entity_identity.rs → entity_pk.rs} +89 -92
  63. package/dist-engine-src/src/functions/context.rs +56 -52
  64. package/dist-engine-src/src/functions/state.rs +51 -52
  65. package/dist-engine-src/src/init.rs +288 -154
  66. package/dist-engine-src/src/json_store/context.rs +15 -266
  67. package/dist-engine-src/src/json_store/mod.rs +26 -0
  68. package/dist-engine-src/src/json_store/store.rs +103 -718
  69. package/dist-engine-src/src/json_store/types.rs +4 -9
  70. package/dist-engine-src/src/lib.rs +49 -19
  71. package/dist-engine-src/src/live_state/context.rs +654 -790
  72. package/dist-engine-src/src/live_state/mod.rs +9 -3
  73. package/dist-engine-src/src/live_state/overlay.rs +4 -4
  74. package/dist-engine-src/src/live_state/types.rs +30 -21
  75. package/dist-engine-src/src/live_state/visibility.rs +514 -71
  76. package/dist-engine-src/src/plugin/install.rs +48 -48
  77. package/dist-engine-src/src/plugin/manifest.rs +7 -7
  78. package/dist-engine-src/src/plugin/materializer.rs +0 -275
  79. package/dist-engine-src/src/plugin/plugin_manifest.json +4 -3
  80. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +2 -2
  81. package/dist-engine-src/src/schema/builtin/lix_branch_descriptor.json +34 -0
  82. package/dist-engine-src/src/schema/builtin/lix_branch_ref.json +48 -0
  83. package/dist-engine-src/src/schema/builtin/lix_change.json +3 -3
  84. package/dist-engine-src/src/schema/builtin/lix_commit.json +1 -1
  85. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +6 -6
  86. package/dist-engine-src/src/schema/builtin/mod.rs +18 -20
  87. package/dist-engine-src/src/schema/compatibility.rs +11 -11
  88. package/dist-engine-src/src/schema/definition.json +2 -2
  89. package/dist-engine-src/src/schema/definition.rs +5 -5
  90. package/dist-engine-src/src/schema/key.rs +3 -3
  91. package/dist-engine-src/src/schema/mod.rs +1 -1
  92. package/dist-engine-src/src/schema/tests.rs +18 -18
  93. package/dist-engine-src/src/session/context.rs +803 -148
  94. package/dist-engine-src/src/session/create_branch.rs +94 -0
  95. package/dist-engine-src/src/session/execute.rs +223 -83
  96. package/dist-engine-src/src/session/merge/analysis.rs +9 -3
  97. package/dist-engine-src/src/session/merge/{version.rs → branch.rs} +119 -129
  98. package/dist-engine-src/src/session/merge/conflicts.rs +2 -2
  99. package/dist-engine-src/src/session/merge/mod.rs +5 -6
  100. package/dist-engine-src/src/session/merge/stats.rs +7 -11
  101. package/dist-engine-src/src/session/mod.rs +15 -12
  102. package/dist-engine-src/src/session/switch_branch.rs +113 -0
  103. package/dist-engine-src/src/session/transaction.rs +495 -14
  104. package/dist-engine-src/src/sql2/{classify.rs → bind/classify.rs} +3 -75
  105. package/dist-engine-src/src/sql2/bind/error.rs +5 -0
  106. package/dist-engine-src/src/sql2/bind/expr.rs +29 -0
  107. package/dist-engine-src/src/sql2/bind/mod.rs +12 -0
  108. package/dist-engine-src/src/sql2/{udfs/public_call.rs → bind/public_udf.rs} +71 -3
  109. package/dist-engine-src/src/sql2/bind/read.rs +65 -0
  110. package/dist-engine-src/src/sql2/bind/statement.rs +2236 -0
  111. package/dist-engine-src/src/sql2/bind/table.rs +273 -0
  112. package/dist-engine-src/src/sql2/bind/write.rs +86 -0
  113. package/dist-engine-src/src/sql2/branch_scope.rs +436 -0
  114. package/dist-engine-src/src/sql2/catalog/capability.rs +20 -0
  115. package/dist-engine-src/src/sql2/catalog/entity_surface.rs +296 -0
  116. package/dist-engine-src/src/sql2/catalog/mod.rs +15 -0
  117. package/dist-engine-src/src/sql2/catalog/registry.rs +556 -0
  118. package/dist-engine-src/src/sql2/catalog/schema.rs +88 -0
  119. package/dist-engine-src/src/sql2/catalog/surface.rs +41 -0
  120. package/dist-engine-src/src/sql2/change_materialization.rs +122 -0
  121. package/dist-engine-src/src/sql2/context.rs +36 -30
  122. package/dist-engine-src/src/sql2/error.rs +1 -1
  123. package/dist-engine-src/src/sql2/exec/bound_public_write.rs +1593 -0
  124. package/dist-engine-src/src/sql2/exec/datafusion.rs +5266 -0
  125. package/dist-engine-src/src/sql2/exec/fast_write.rs +82 -0
  126. package/dist-engine-src/src/sql2/exec/mod.rs +24 -0
  127. package/dist-engine-src/src/sql2/exec/write.rs +661 -0
  128. package/dist-engine-src/src/sql2/filesystem_planner.rs +72 -77
  129. package/dist-engine-src/src/sql2/filesystem_visibility.rs +21 -21
  130. package/dist-engine-src/src/sql2/history_projection.rs +8 -8
  131. package/dist-engine-src/src/sql2/history_route.rs +35 -31
  132. package/dist-engine-src/src/sql2/mod.rs +28 -23
  133. package/dist-engine-src/src/sql2/optimize/datafusion.rs +1 -0
  134. package/dist-engine-src/src/sql2/optimize/mod.rs +2 -0
  135. package/dist-engine-src/src/sql2/optimize/simple_write.rs +116 -0
  136. package/dist-engine-src/src/sql2/parse/mod.rs +69 -0
  137. package/dist-engine-src/src/sql2/parse/normalize.rs +1 -0
  138. package/dist-engine-src/src/sql2/plan/branch_scope.rs +24 -0
  139. package/dist-engine-src/src/sql2/plan/mod.rs +5 -0
  140. package/dist-engine-src/src/sql2/plan/predicate.rs +22 -0
  141. package/dist-engine-src/src/sql2/plan/write.rs +147 -0
  142. package/dist-engine-src/src/sql2/predicate_typecheck.rs +258 -0
  143. package/dist-engine-src/src/sql2/{version_provider.rs → providers/branch.rs} +218 -214
  144. package/dist-engine-src/src/sql2/{change_provider.rs → providers/change.rs} +156 -42
  145. package/dist-engine-src/src/sql2/{directory_provider.rs → providers/directory.rs} +291 -322
  146. package/dist-engine-src/src/sql2/{directory_history_provider.rs → providers/directory_history.rs} +56 -42
  147. package/dist-engine-src/src/sql2/providers/entity.rs +1484 -0
  148. package/dist-engine-src/src/sql2/{entity_history_provider.rs → providers/entity_history.rs} +43 -31
  149. package/dist-engine-src/src/sql2/{file_provider.rs → providers/file.rs} +323 -316
  150. package/dist-engine-src/src/sql2/{file_history_provider.rs → providers/file_history.rs} +60 -46
  151. package/dist-engine-src/src/sql2/{history_provider.rs → providers/history.rs} +46 -32
  152. package/dist-engine-src/src/sql2/{lix_state_provider.rs → providers/lix_state.rs} +359 -329
  153. package/dist-engine-src/src/sql2/providers/mod.rs +508 -0
  154. package/dist-engine-src/src/sql2/read_only.rs +2 -2
  155. package/dist-engine-src/src/sql2/session.rs +47 -96
  156. package/dist-engine-src/src/sql2/storage/constraints.rs +1 -0
  157. package/dist-engine-src/src/sql2/storage/mod.rs +1 -0
  158. package/dist-engine-src/src/sql2/test_support/differential.rs +712 -0
  159. package/dist-engine-src/src/sql2/test_support/generators.rs +354 -0
  160. package/dist-engine-src/src/sql2/test_support/mod.rs +2 -0
  161. package/dist-engine-src/src/sql2/udfs/{lix_active_version_commit_id.rs → lix_active_branch_commit_id.rs} +7 -7
  162. package/dist-engine-src/src/sql2/udfs/mod.rs +3 -6
  163. package/dist-engine-src/src/sql2/write_normalization.rs +45 -22
  164. package/dist-engine-src/src/storage/conformance.rs +399 -0
  165. package/dist-engine-src/src/storage/context.rs +552 -288
  166. package/dist-engine-src/src/storage/mod.rs +48 -10
  167. package/dist-engine-src/src/storage/point.rs +440 -0
  168. package/dist-engine-src/src/storage/read_scope.rs +43 -64
  169. package/dist-engine-src/src/storage/reader.rs +867 -0
  170. package/dist-engine-src/src/storage/scan.rs +784 -0
  171. package/dist-engine-src/src/storage/spaces.rs +236 -0
  172. package/dist-engine-src/src/storage/stats.rs +80 -0
  173. package/dist-engine-src/src/storage/write_set.rs +962 -0
  174. package/dist-engine-src/src/storage_bench.rs +136 -4828
  175. package/dist-engine-src/src/test_support.rs +360 -138
  176. package/dist-engine-src/src/tracked_state/bench_support.rs +394 -0
  177. package/dist-engine-src/src/tracked_state/codec.rs +155 -1057
  178. package/dist-engine-src/src/tracked_state/commit_root_rebuild.rs +358 -0
  179. package/dist-engine-src/src/tracked_state/context.rs +1927 -993
  180. package/dist-engine-src/src/tracked_state/diff.rs +1715 -261
  181. package/dist-engine-src/src/tracked_state/merge.rs +74 -88
  182. package/dist-engine-src/src/tracked_state/mod.rs +19 -16
  183. package/dist-engine-src/src/tracked_state/{materialization.rs → row_materialization.rs} +50 -178
  184. package/dist-engine-src/src/tracked_state/storage.rs +243 -191
  185. package/dist-engine-src/src/tracked_state/tree.rs +247 -371
  186. package/dist-engine-src/src/tracked_state/types.rs +49 -42
  187. package/dist-engine-src/src/transaction/bench_support.rs +407 -0
  188. package/dist-engine-src/src/transaction/commit.rs +821 -713
  189. package/dist-engine-src/src/transaction/context.rs +705 -600
  190. package/dist-engine-src/src/transaction/mod.rs +13 -2
  191. package/dist-engine-src/src/transaction/normalization.rs +63 -76
  192. package/dist-engine-src/src/transaction/prep.rs +13 -13
  193. package/dist-engine-src/src/transaction/schema_resolver.rs +19 -5
  194. package/dist-engine-src/src/transaction/staging.rs +228 -434
  195. package/dist-engine-src/src/transaction/types.rs +41 -98
  196. package/dist-engine-src/src/transaction/validation.rs +382 -446
  197. package/dist-engine-src/src/untracked_state/codec.rs +337 -29
  198. package/dist-engine-src/src/untracked_state/context.rs +7 -7
  199. package/dist-engine-src/src/untracked_state/materialization.rs +2 -2
  200. package/dist-engine-src/src/untracked_state/mod.rs +1 -1
  201. package/dist-engine-src/src/untracked_state/storage.rs +659 -157
  202. package/dist-engine-src/src/untracked_state/types.rs +21 -21
  203. package/package.json +71 -68
  204. package/dist-engine-src/src/backend/kv.rs +0 -358
  205. package/dist-engine-src/src/backend/testing.rs +0 -658
  206. package/dist-engine-src/src/commit_store/codec.rs +0 -887
  207. package/dist-engine-src/src/commit_store/context.rs +0 -944
  208. package/dist-engine-src/src/commit_store/materialization.rs +0 -84
  209. package/dist-engine-src/src/commit_store/mod.rs +0 -16
  210. package/dist-engine-src/src/commit_store/storage.rs +0 -600
  211. package/dist-engine-src/src/commit_store/types.rs +0 -215
  212. package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -34
  213. package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -48
  214. package/dist-engine-src/src/session/create_version.rs +0 -88
  215. package/dist-engine-src/src/session/merge/apply.rs +0 -23
  216. package/dist-engine-src/src/session/optimization9_sql2_bench.rs +0 -100
  217. package/dist-engine-src/src/session/switch_version.rs +0 -110
  218. package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
  219. package/dist-engine-src/src/sql2/execute.rs +0 -3533
  220. package/dist-engine-src/src/sql2/public_bind/assignment.rs +0 -46
  221. package/dist-engine-src/src/sql2/public_bind/capability.rs +0 -41
  222. package/dist-engine-src/src/sql2/public_bind/dml.rs +0 -172
  223. package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -26
  224. package/dist-engine-src/src/sql2/public_bind/table.rs +0 -168
  225. package/dist-engine-src/src/sql2/version_scope.rs +0 -394
  226. package/dist-engine-src/src/storage/types.rs +0 -501
  227. package/dist-engine-src/src/tracked_state/by_file_index.rs +0 -98
  228. package/dist-engine-src/src/tracked_state/materializer.rs +0 -488
  229. package/dist-engine-src/src/transaction/live_state_overlay.rs +0 -35
  230. package/dist-engine-src/src/version/lifecycle.rs +0 -221
  231. package/dist-engine-src/src/version/mod.rs +0 -13
  232. package/dist-engine-src/src/version/refs.rs +0 -330
  233. package/dist-engine-src/src/version/stage_rows.rs +0 -67
  234. package/dist-engine-src/src/version/types.rs +0 -21
@@ -9,9 +9,10 @@ use crate::common::{
9
9
  directory_ancestor_paths, directory_name_from_path, normalize_directory_path,
10
10
  parent_directory_path, stable_content_fingerprint_hex, ParsedFilePath,
11
11
  };
12
- use crate::entity_identity::EntityIdentity;
12
+ use crate::entity_pk::EntityPk;
13
13
  use crate::live_state::MaterializedLiveStateRow;
14
14
  use crate::LixError;
15
+ use crate::GLOBAL_BRANCH_ID;
15
16
 
16
17
  use super::filesystem_visibility::VisibleFilesystem;
17
18
  use crate::transaction::types::{TransactionFileData, TransactionJson, TransactionWriteRow};
@@ -44,7 +45,7 @@ pub(crate) struct FilesystemDeletePlan {
44
45
  /// Common state-row lane fields shared by filesystem descriptor/blob rows.
45
46
  #[derive(Debug, Clone, PartialEq, Eq)]
46
47
  pub(crate) struct FilesystemRowContext {
47
- pub(crate) version_id: String,
48
+ pub(crate) branch_id: String,
48
49
  pub(crate) global: bool,
49
50
  pub(crate) untracked: bool,
50
51
  pub(crate) file_id: Option<String>,
@@ -52,9 +53,9 @@ pub(crate) struct FilesystemRowContext {
52
53
  }
53
54
 
54
55
  impl FilesystemRowContext {
55
- pub(crate) fn active_version(version_id: impl Into<String>) -> Self {
56
+ pub(crate) fn active_branch(branch_id: impl Into<String>) -> Self {
56
57
  Self {
57
- version_id: version_id.into(),
58
+ branch_id: branch_id.into(),
58
59
  global: false,
59
60
  untracked: false,
60
61
  file_id: None,
@@ -478,8 +479,8 @@ pub(crate) fn blob_ref_row(input: BlobRefRowInput) -> Result<TransactionWriteRow
478
479
  LixError::new(
479
480
  "LIX_ERROR_UNKNOWN",
480
481
  format!(
481
- "binary blob size exceeds supported range for file '{}' version '{}'",
482
- input.file_id, input.context.version_id
482
+ "binary blob size exceeds supported range for file '{}' branch '{}'",
483
+ input.file_id, input.context.branch_id
483
484
  ),
484
485
  )
485
486
  })?;
@@ -546,7 +547,7 @@ pub(crate) fn plan_file_path_write(
546
547
  })?);
547
548
  file_data.push(TransactionFileData {
548
549
  file_id,
549
- version_id: input.context.version_id,
550
+ branch_id: input.context.branch_id,
550
551
  untracked: input.context.untracked,
551
552
  data,
552
553
  });
@@ -675,8 +676,13 @@ pub(crate) fn directory_path_resolvers_from_state_rows(
675
676
  let Some(snapshot_content) = row.snapshot_content.as_deref() else {
676
677
  continue;
677
678
  };
679
+ let storage_branch_id = if row.global {
680
+ GLOBAL_BRANCH_ID
681
+ } else {
682
+ row.branch_id.as_str()
683
+ };
678
684
  let resolver_key = filesystem_storage_scope_key(
679
- &row.version_id,
685
+ storage_branch_id,
680
686
  row.global,
681
687
  row.untracked,
682
688
  row.file_id.as_deref(),
@@ -718,7 +724,7 @@ pub(crate) fn directory_path_resolvers_from_state_rows(
718
724
  }
719
725
 
720
726
  let mut resolvers = BTreeMap::new();
721
- for (version_id, records) in directory_rows {
727
+ for (branch_id, records) in directory_rows {
722
728
  let mut paths = BTreeMap::<String, String>::new();
723
729
  for directory_id in records.keys() {
724
730
  resolve_directory_seed_path(directory_id, &records, &mut paths, &mut BTreeSet::new())?;
@@ -727,15 +733,15 @@ pub(crate) fn directory_path_resolvers_from_state_rows(
727
733
  .into_iter()
728
734
  .map(|(directory_id, path)| (path, directory_id))
729
735
  .collect::<Vec<_>>();
730
- let files = file_rows.remove(&version_id).unwrap_or_default();
736
+ let files = file_rows.remove(&branch_id).unwrap_or_default();
731
737
  resolvers.insert(
732
- version_id,
738
+ branch_id,
733
739
  DirectoryPathResolver::from_existing_filesystem(seeds, files)?,
734
740
  );
735
741
  }
736
- for (version_id, files) in file_rows {
742
+ for (branch_id, files) in file_rows {
737
743
  resolvers.insert(
738
- version_id,
744
+ branch_id,
739
745
  DirectoryPathResolver::from_existing_filesystem(std::iter::empty(), files)?,
740
746
  );
741
747
  }
@@ -743,13 +749,13 @@ pub(crate) fn directory_path_resolvers_from_state_rows(
743
749
  }
744
750
 
745
751
  pub(crate) fn filesystem_storage_scope_key(
746
- version_id: &str,
752
+ branch_id: &str,
747
753
  global: bool,
748
754
  untracked: bool,
749
755
  file_id: Option<&str>,
750
756
  ) -> String {
751
757
  format!(
752
- "version={version_id}\0global={global}\0untracked={untracked}\0file_id={}",
758
+ "branch={branch_id}\0global={global}\0untracked={untracked}\0file_id={}",
753
759
  file_id.unwrap_or("<null>")
754
760
  )
755
761
  }
@@ -804,23 +810,23 @@ fn directory_parent_cycle_error(directory_id: &str) -> LixError {
804
810
  }
805
811
 
806
812
  fn state_row(
807
- entity_id: String,
813
+ entity_pk: String,
808
814
  schema_key: &str,
809
815
  snapshot: Option<JsonValue>,
810
816
  context: FilesystemRowContext,
811
817
  ) -> TransactionWriteRow {
812
- partial_state_row(Some(entity_id), schema_key, snapshot, context)
818
+ partial_state_row(Some(entity_pk), schema_key, snapshot, context)
813
819
  }
814
820
 
815
821
  fn partial_state_row(
816
- entity_id: Option<String>,
822
+ entity_pk: Option<String>,
817
823
  schema_key: &str,
818
824
  snapshot: Option<JsonValue>,
819
825
  context: FilesystemRowContext,
820
826
  ) -> TransactionWriteRow {
821
827
  let snapshot = snapshot.map(TransactionJson::from_value_unchecked);
822
828
  TransactionWriteRow {
823
- entity_id: entity_id.map(EntityIdentity::single),
829
+ entity_pk: entity_pk.map(EntityPk::single),
824
830
  schema_key: schema_key.to_string(),
825
831
  file_id: context.file_id,
826
832
  snapshot,
@@ -832,16 +838,16 @@ fn partial_state_row(
832
838
  change_id: None,
833
839
  commit_id: None,
834
840
  untracked: context.untracked,
835
- version_id: context.version_id,
841
+ branch_id: context.branch_id,
836
842
  }
837
843
  }
838
844
 
839
845
  fn tombstone_row(
840
- entity_id: String,
846
+ entity_pk: String,
841
847
  schema_key: &str,
842
848
  context: FilesystemRowContext,
843
849
  ) -> TransactionWriteRow {
844
- state_row(entity_id, schema_key, None, context)
850
+ state_row(entity_pk, schema_key, None, context)
845
851
  }
846
852
 
847
853
  fn collect_recursive_directory_delete(
@@ -900,7 +906,7 @@ mod tests {
900
906
  use crate::sql2::filesystem_visibility::{
901
907
  VisibleBlobRef, VisibleDirectory, VisibleFile, VisibleFilesystem,
902
908
  };
903
- use crate::{entity_identity::EntityIdentity, live_state::MaterializedLiveStateRow};
909
+ use crate::{entity_pk::EntityPk, live_state::MaterializedLiveStateRow};
904
910
 
905
911
  fn test_id_generator(ids: &'static [&'static str]) -> impl FnMut() -> String {
906
912
  let mut ids = ids.iter();
@@ -914,15 +920,15 @@ mod tests {
914
920
  parent_id: None,
915
921
  name: "docs".to_string(),
916
922
  hidden: false,
917
- context: FilesystemRowContext::active_version("version-a"),
923
+ context: FilesystemRowContext::active_branch("branch-a"),
918
924
  });
919
925
 
920
926
  assert_eq!(
921
- row.entity_id.as_ref(),
922
- Some(&crate::entity_identity::EntityIdentity::single("dir-docs"))
927
+ row.entity_pk.as_ref(),
928
+ Some(&crate::entity_pk::EntityPk::single("dir-docs"))
923
929
  );
924
930
  assert_eq!(row.schema_key, "lix_directory_descriptor");
925
- assert_eq!(row.version_id, "version-a");
931
+ assert_eq!(row.branch_id, "branch-a");
926
932
  let snapshot: JsonValue = row.snapshot.as_ref().unwrap().value().clone();
927
933
  assert_eq!(snapshot["id"], "dir-docs");
928
934
  assert_eq!(snapshot["parent_id"], JsonValue::Null);
@@ -937,14 +943,12 @@ mod tests {
937
943
  directory_id: Some("dir-docs".to_string()),
938
944
  name: "readme.md".to_string(),
939
945
  hidden: false,
940
- context: FilesystemRowContext::active_version("version-a"),
946
+ context: FilesystemRowContext::active_branch("branch-a"),
941
947
  });
942
948
 
943
949
  assert_eq!(
944
- row.entity_id.as_ref(),
945
- Some(&crate::entity_identity::EntityIdentity::single(
946
- "file-readme"
947
- ))
950
+ row.entity_pk.as_ref(),
951
+ Some(&crate::entity_pk::EntityPk::single("file-readme"))
948
952
  );
949
953
  assert_eq!(row.schema_key, "lix_file_descriptor");
950
954
  let snapshot: JsonValue = row.snapshot.as_ref().unwrap().value().clone();
@@ -957,15 +961,13 @@ mod tests {
957
961
  let row = blob_ref_row(BlobRefRowInput {
958
962
  file_id: "file-readme".to_string(),
959
963
  data: b"Hello".to_vec(),
960
- context: FilesystemRowContext::active_version("version-a"),
964
+ context: FilesystemRowContext::active_branch("branch-a"),
961
965
  })
962
966
  .expect("blob ref row should build");
963
967
 
964
968
  assert_eq!(
965
- row.entity_id.as_ref(),
966
- Some(&crate::entity_identity::EntityIdentity::single(
967
- "file-readme"
968
- ))
969
+ row.entity_pk.as_ref(),
970
+ Some(&crate::entity_pk::EntityPk::single("file-readme"))
969
971
  );
970
972
  assert_eq!(row.file_id.as_deref(), Some("file-readme"));
971
973
  assert_eq!(row.schema_key, "lix_binary_blob_ref");
@@ -986,7 +988,7 @@ mod tests {
986
988
  let rows = resolver
987
989
  .ensure_directory_path(
988
990
  "/docs/nested/",
989
- FilesystemRowContext::active_version("version-a"),
991
+ FilesystemRowContext::active_branch("branch-a"),
990
992
  false,
991
993
  &mut test_id_generator(&["dir-generated-nested"]),
992
994
  )
@@ -1013,7 +1015,7 @@ mod tests {
1013
1015
  let docs_rows = resolver
1014
1016
  .ensure_directory_path(
1015
1017
  "/docs/",
1016
- FilesystemRowContext::active_version("version-a"),
1018
+ FilesystemRowContext::active_branch("branch-a"),
1017
1019
  false,
1018
1020
  &mut test_id_generator(&["dir-generated-docs"]),
1019
1021
  )
@@ -1023,7 +1025,7 @@ mod tests {
1023
1025
  let nested_rows = resolver
1024
1026
  .ensure_directory_path(
1025
1027
  "/docs/nested/",
1026
- FilesystemRowContext::active_version("version-a"),
1028
+ FilesystemRowContext::active_branch("branch-a"),
1027
1029
  false,
1028
1030
  &mut test_id_generator(&["dir-generated-nested"]),
1029
1031
  )
@@ -1045,7 +1047,7 @@ mod tests {
1045
1047
  .ensure_directory_path_with_leaf_id(
1046
1048
  "/docs/nested/",
1047
1049
  Some("dir-nested".to_string()),
1048
- FilesystemRowContext::active_version("version-a"),
1050
+ FilesystemRowContext::active_branch("branch-a"),
1049
1051
  false,
1050
1052
  &mut test_id_generator(&["dir-generated-docs"]),
1051
1053
  )
@@ -1075,7 +1077,7 @@ mod tests {
1075
1077
  let rows = resolver
1076
1078
  .ensure_directory_path(
1077
1079
  "/docs/nested/",
1078
- FilesystemRowContext::active_version("version-a"),
1080
+ FilesystemRowContext::active_branch("branch-a"),
1079
1081
  false,
1080
1082
  &mut test_id_generator(&["dir-generated-docs", "dir-generated-nested"]),
1081
1083
  )
@@ -1085,7 +1087,7 @@ mod tests {
1085
1087
  let rows = resolver
1086
1088
  .ensure_directory_path(
1087
1089
  "/docs/nested/",
1088
- FilesystemRowContext::active_version("version-a"),
1090
+ FilesystemRowContext::active_branch("branch-a"),
1089
1091
  false,
1090
1092
  &mut test_id_generator(&["should-not-be-used"]),
1091
1093
  )
@@ -1105,7 +1107,7 @@ mod tests {
1105
1107
  path: "/docs/guides/readme.md".to_string(),
1106
1108
  data: Some(b"hello".to_vec()),
1107
1109
  hidden: Some(false),
1108
- context: FilesystemRowContext::active_version("version-a"),
1110
+ context: FilesystemRowContext::active_branch("branch-a"),
1109
1111
  },
1110
1112
  &mut test_id_generator(&["dir-generated-docs", "dir-generated-guides"]),
1111
1113
  )
@@ -1114,7 +1116,7 @@ mod tests {
1114
1116
  assert_eq!(plan.count, 1);
1115
1117
  assert_eq!(plan.file_data.len(), 1);
1116
1118
  assert_eq!(plan.file_data[0].file_id, "file-readme");
1117
- assert_eq!(plan.file_data[0].version_id, "version-a");
1119
+ assert_eq!(plan.file_data[0].branch_id, "branch-a");
1118
1120
  assert_eq!(plan.file_data[0].data, b"hello");
1119
1121
  assert_eq!(plan.rows.len(), 4);
1120
1122
  assert_eq!(
@@ -1155,7 +1157,7 @@ mod tests {
1155
1157
  path: "/docs/guides/readme.md".to_string(),
1156
1158
  data: Some(b"hello".to_vec()),
1157
1159
  hidden: Some(false),
1158
- context: FilesystemRowContext::active_version("version-a"),
1160
+ context: FilesystemRowContext::active_branch("branch-a"),
1159
1161
  },
1160
1162
  &mut test_id_generator(&["should-not-be-used"]),
1161
1163
  )
@@ -1190,7 +1192,7 @@ mod tests {
1190
1192
  "/docs/renamed.md".to_string(),
1191
1193
  false,
1192
1194
  Some(b"hello".to_vec()),
1193
- FilesystemRowContext::active_version("version-a"),
1195
+ FilesystemRowContext::active_branch("branch-a"),
1194
1196
  &mut test_id_generator(&["should-not-be-used"]),
1195
1197
  )
1196
1198
  .expect("file path update should plan");
@@ -1221,7 +1223,7 @@ mod tests {
1221
1223
  "/docs/guides/readme.md".to_string(),
1222
1224
  true,
1223
1225
  Some(b"hello".to_vec()),
1224
- FilesystemRowContext::active_version("version-a"),
1226
+ FilesystemRowContext::active_branch("branch-a"),
1225
1227
  &mut test_id_generator(&["dir-generated-docs", "dir-generated-guides"]),
1226
1228
  )
1227
1229
  .expect("file path update should plan");
@@ -1257,12 +1259,12 @@ mod tests {
1257
1259
  let resolvers = super::directory_path_resolvers_from_state_rows(vec![
1258
1260
  live_directory_row(
1259
1261
  "dir-docs",
1260
- "version-a",
1262
+ "branch-a",
1261
1263
  "{\"id\":\"dir-docs\",\"parent_id\":null,\"name\":\"docs\"}",
1262
1264
  ),
1263
1265
  live_directory_row(
1264
1266
  "dir-guides",
1265
- "version-a",
1267
+ "branch-a",
1266
1268
  "{\"id\":\"dir-guides\",\"parent_id\":\"dir-docs\",\"name\":\"guides\"}",
1267
1269
  ),
1268
1270
  ])
@@ -1270,10 +1272,7 @@ mod tests {
1270
1272
 
1271
1273
  let resolver = resolvers
1272
1274
  .get(&super::filesystem_storage_scope_key(
1273
- "version-a",
1274
- false,
1275
- false,
1276
- None,
1275
+ "branch-a", false, false, None,
1277
1276
  ))
1278
1277
  .expect("storage-scope resolver should exist");
1279
1278
  assert_eq!(resolver.directory_id("/docs/").unwrap(), Some("dir-docs"));
@@ -1288,7 +1287,7 @@ mod tests {
1288
1287
  let plan = super::plan_file_delete(FileDeleteInput {
1289
1288
  file_id: "file-readme".to_string(),
1290
1289
  has_blob_ref: true,
1291
- context: FilesystemRowContext::active_version("version-a"),
1290
+ context: FilesystemRowContext::active_branch("branch-a"),
1292
1291
  });
1293
1292
 
1294
1293
  assert_eq!(plan.count, 1);
@@ -1299,10 +1298,8 @@ mod tests {
1299
1298
  .find(|row| row.schema_key == "lix_file_descriptor")
1300
1299
  .expect("file descriptor tombstone should be planned");
1301
1300
  assert_eq!(
1302
- descriptor.entity_id.as_ref(),
1303
- Some(&crate::entity_identity::EntityIdentity::single(
1304
- "file-readme"
1305
- ))
1301
+ descriptor.entity_pk.as_ref(),
1302
+ Some(&crate::entity_pk::EntityPk::single("file-readme"))
1306
1303
  );
1307
1304
  assert_eq!(descriptor.file_id, None);
1308
1305
  assert_eq!(descriptor.snapshot, None);
@@ -1313,10 +1310,8 @@ mod tests {
1313
1310
  .find(|row| row.schema_key == "lix_binary_blob_ref")
1314
1311
  .expect("blob ref tombstone should be planned");
1315
1312
  assert_eq!(
1316
- blob_ref.entity_id.as_ref(),
1317
- Some(&crate::entity_identity::EntityIdentity::single(
1318
- "file-readme"
1319
- ))
1313
+ blob_ref.entity_pk.as_ref(),
1314
+ Some(&crate::entity_pk::EntityPk::single("file-readme"))
1320
1315
  );
1321
1316
  assert_eq!(blob_ref.file_id.as_deref(), Some("file-readme"));
1322
1317
  assert_eq!(blob_ref.snapshot, None);
@@ -1327,7 +1322,7 @@ mod tests {
1327
1322
  let plan = super::plan_file_delete(FileDeleteInput {
1328
1323
  file_id: "file-readme".to_string(),
1329
1324
  has_blob_ref: false,
1330
- context: FilesystemRowContext::active_version("version-a"),
1325
+ context: FilesystemRowContext::active_branch("branch-a"),
1331
1326
  });
1332
1327
 
1333
1328
  assert_eq!(plan.count, 1);
@@ -1340,14 +1335,14 @@ mod tests {
1340
1335
  fn directory_delete_plans_descriptor_tombstone() {
1341
1336
  let plan = super::plan_directory_delete(DirectoryDeleteInput {
1342
1337
  directory_id: "dir-docs".to_string(),
1343
- context: FilesystemRowContext::active_version("version-a"),
1338
+ context: FilesystemRowContext::active_branch("branch-a"),
1344
1339
  });
1345
1340
 
1346
1341
  assert_eq!(plan.count, 1);
1347
1342
  assert_eq!(plan.rows.len(), 1);
1348
1343
  assert_eq!(
1349
- plan.rows[0].entity_id.as_ref(),
1350
- Some(&crate::entity_identity::EntityIdentity::single("dir-docs"))
1344
+ plan.rows[0].entity_pk.as_ref(),
1345
+ Some(&crate::entity_pk::EntityPk::single("dir-docs"))
1351
1346
  );
1352
1347
  assert_eq!(plan.rows[0].schema_key, "lix_directory_descriptor");
1353
1348
  assert_eq!(plan.rows[0].file_id, None);
@@ -1356,7 +1351,7 @@ mod tests {
1356
1351
 
1357
1352
  #[test]
1358
1353
  fn recursive_directory_delete_plans_files_blobs_and_deepest_directories_first() {
1359
- let context = FilesystemRowContext::active_version("version-a");
1354
+ let context = FilesystemRowContext::active_branch("branch-a");
1360
1355
  let mut directories_by_id = BTreeMap::new();
1361
1356
  directories_by_id.insert(
1362
1357
  "dir-docs".to_string(),
@@ -1408,11 +1403,11 @@ mod tests {
1408
1403
  .map(|row| {
1409
1404
  (
1410
1405
  row.schema_key.as_str(),
1411
- row.entity_id
1406
+ row.entity_pk
1412
1407
  .as_ref()
1413
- .expect("planned recursive delete row should carry entity_id")
1408
+ .expect("planned recursive delete row should carry entity_pk")
1414
1409
  .as_single_string_owned()
1415
- .expect("planned recursive delete row should project entity_id"),
1410
+ .expect("planned recursive delete row should project entity_pk"),
1416
1411
  )
1417
1412
  })
1418
1413
  .collect::<Vec<_>>(),
@@ -1467,20 +1462,20 @@ mod tests {
1467
1462
  }
1468
1463
 
1469
1464
  fn live_directory_row(
1470
- entity_id: &str,
1471
- version_id: &str,
1465
+ entity_pk: &str,
1466
+ branch_id: &str,
1472
1467
  snapshot_content: &str,
1473
1468
  ) -> MaterializedLiveStateRow {
1474
1469
  MaterializedLiveStateRow {
1475
- entity_id: EntityIdentity::single(entity_id),
1470
+ entity_pk: EntityPk::single(entity_pk),
1476
1471
  schema_key: "lix_directory_descriptor".to_string(),
1477
1472
  file_id: None,
1478
1473
  snapshot_content: Some(snapshot_content.to_string()),
1479
1474
  metadata: None,
1480
1475
  deleted: false,
1481
- version_id: version_id.to_string(),
1482
- change_id: Some(format!("change-{entity_id}")),
1483
- commit_id: Some(format!("commit-{entity_id}")),
1476
+ branch_id: branch_id.to_string(),
1477
+ change_id: Some(format!("change-{entity_pk}")),
1478
+ commit_id: Some(format!("commit-{entity_pk}")),
1484
1479
  global: false,
1485
1480
  untracked: false,
1486
1481
  created_at: "2026-04-23T00:00:00Z".to_string(),
@@ -28,11 +28,11 @@ pub(crate) struct VisibleFilesystem {
28
28
  }
29
29
 
30
30
  impl VisibleFilesystem {
31
- /// Loads filesystem rows for a single version from execution-visible live
31
+ /// Loads filesystem rows for a single branch from execution-visible live
32
32
  /// state and builds lookup indexes used by filesystem write planning.
33
33
  pub(crate) async fn load(
34
34
  live_state: Arc<dyn LiveStateReader>,
35
- version_id: &str,
35
+ branch_id: &str,
36
36
  ) -> Result<Self, LixError> {
37
37
  let rows = live_state
38
38
  .scan_rows(&LiveStateScanRequest {
@@ -42,7 +42,7 @@ impl VisibleFilesystem {
42
42
  FILE_DESCRIPTOR_SCHEMA_KEY.to_string(),
43
43
  BLOB_REF_SCHEMA_KEY.to_string(),
44
44
  ],
45
- version_ids: vec![version_id.to_string()],
45
+ branch_ids: vec![branch_id.to_string()],
46
46
  ..LiveStateFilter::default()
47
47
  },
48
48
  ..LiveStateScanRequest::default()
@@ -185,7 +185,7 @@ fn filesystem_row_context(
185
185
  row: &MaterializedLiveStateRow,
186
186
  ) -> Result<FilesystemRowContext, LixError> {
187
187
  Ok(FilesystemRowContext {
188
- version_id: row.version_id.clone(),
188
+ branch_id: row.branch_id.clone(),
189
189
  global: row.global,
190
190
  untracked: row.untracked,
191
191
  file_id: row.file_id.clone(),
@@ -232,7 +232,7 @@ mod tests {
232
232
  r#"{"id":"dir-guides","parent_id":"dir-docs","name":"guides","hidden":false}"#,
233
233
  ),
234
234
  ]),
235
- "version-a",
235
+ "branch-a",
236
236
  )
237
237
  .await
238
238
  .expect("visible filesystem should load");
@@ -261,7 +261,7 @@ mod tests {
261
261
  "file-readme",
262
262
  r#"{"id":"file-readme","directory_id":"dir-guides","name":"readme.md","hidden":false}"#,
263
263
  )]),
264
- "version-a",
264
+ "branch-a",
265
265
  )
266
266
  .await
267
267
  .expect("visible filesystem should load");
@@ -283,7 +283,7 @@ mod tests {
283
283
  "file-readme",
284
284
  r#"{"id":"file-readme","blob_hash":"abc123","size_bytes":5}"#,
285
285
  )]),
286
- "version-a",
286
+ "branch-a",
287
287
  )
288
288
  .await
289
289
  .expect("visible filesystem should load");
@@ -316,8 +316,8 @@ mod tests {
316
316
  .filter(|row| {
317
317
  (request.filter.schema_keys.is_empty()
318
318
  || request.filter.schema_keys.contains(&row.schema_key))
319
- && (request.filter.version_ids.is_empty()
320
- || request.filter.version_ids.contains(&row.version_id))
319
+ && (request.filter.branch_ids.is_empty()
320
+ || request.filter.branch_ids.contains(&row.branch_id))
321
321
  })
322
322
  .cloned()
323
323
  .collect())
@@ -331,49 +331,49 @@ mod tests {
331
331
  }
332
332
  }
333
333
 
334
- fn directory_row(entity_id: &str, snapshot_content: &str) -> MaterializedLiveStateRow {
334
+ fn directory_row(entity_pk: &str, snapshot_content: &str) -> MaterializedLiveStateRow {
335
335
  live_row(
336
- entity_id,
336
+ entity_pk,
337
337
  DIRECTORY_DESCRIPTOR_SCHEMA_KEY,
338
338
  None,
339
339
  snapshot_content,
340
340
  )
341
341
  }
342
342
 
343
- fn file_row(entity_id: &str, snapshot_content: &str) -> MaterializedLiveStateRow {
343
+ fn file_row(entity_pk: &str, snapshot_content: &str) -> MaterializedLiveStateRow {
344
344
  live_row(
345
- entity_id,
345
+ entity_pk,
346
346
  FILE_DESCRIPTOR_SCHEMA_KEY,
347
347
  None,
348
348
  snapshot_content,
349
349
  )
350
350
  }
351
351
 
352
- fn blob_ref_row(entity_id: &str, snapshot_content: &str) -> MaterializedLiveStateRow {
352
+ fn blob_ref_row(entity_pk: &str, snapshot_content: &str) -> MaterializedLiveStateRow {
353
353
  live_row(
354
- entity_id,
354
+ entity_pk,
355
355
  BLOB_REF_SCHEMA_KEY,
356
- Some(entity_id.to_string()),
356
+ Some(entity_pk.to_string()),
357
357
  snapshot_content,
358
358
  )
359
359
  }
360
360
 
361
361
  fn live_row(
362
- entity_id: &str,
362
+ entity_pk: &str,
363
363
  schema_key: &str,
364
364
  file_id: Option<String>,
365
365
  snapshot_content: &str,
366
366
  ) -> MaterializedLiveStateRow {
367
367
  MaterializedLiveStateRow {
368
- entity_id: crate::entity_identity::EntityIdentity::single(entity_id),
368
+ entity_pk: crate::entity_pk::EntityPk::single(entity_pk),
369
369
  schema_key: schema_key.to_string(),
370
370
  file_id,
371
371
  snapshot_content: Some(snapshot_content.to_string()),
372
372
  metadata: None,
373
373
  deleted: false,
374
- version_id: "version-a".to_string(),
375
- change_id: Some(format!("change-{entity_id}")),
376
- commit_id: Some(format!("commit-{entity_id}")),
374
+ branch_id: "branch-a".to_string(),
375
+ change_id: Some(format!("change-{entity_pk}")),
376
+ commit_id: Some(format!("commit-{entity_pk}")),
377
377
  global: false,
378
378
  untracked: false,
379
379
  created_at: "2026-04-23T00:00:00Z".to_string(),
@@ -1,12 +1,12 @@
1
1
  use serde_json::Value as JsonValue;
2
2
 
3
- use crate::entity_identity::EntityIdentity;
3
+ use crate::entity_pk::EntityPk;
4
4
  use crate::LixError;
5
5
 
6
6
  /// Shared projection contract for typed history views.
7
7
  ///
8
8
  /// On tombstone rows (`snapshot_content IS NULL`), identity columns survive by
9
- /// projecting from canonical entity identity. Non-identity columns must remain
9
+ /// projecting from canonical entity primary key. Non-identity columns must remain
10
10
  /// NULL because there is no snapshot to project payload from.
11
11
  pub(crate) enum HistoryIdentityProjection<'a> {
12
12
  PrimaryKeyPaths(&'a [Vec<String>]),
@@ -15,26 +15,26 @@ pub(crate) enum HistoryIdentityProjection<'a> {
15
15
 
16
16
  pub(crate) fn tombstone_identity_column_value(
17
17
  column_name: &str,
18
- entity_id: &str,
18
+ entity_pk: &str,
19
19
  projection: HistoryIdentityProjection<'_>,
20
20
  ) -> Result<Option<JsonValue>, LixError> {
21
21
  match projection {
22
22
  HistoryIdentityProjection::SingleColumn { column } => {
23
23
  if column_name == column {
24
- Ok(Some(JsonValue::String(entity_id.to_string())))
24
+ Ok(Some(JsonValue::String(entity_pk.to_string())))
25
25
  } else {
26
26
  Ok(None)
27
27
  }
28
28
  }
29
29
  HistoryIdentityProjection::PrimaryKeyPaths(primary_key_paths) => {
30
- primary_key_tombstone_value(column_name, entity_id, primary_key_paths)
30
+ primary_key_tombstone_value(column_name, entity_pk, primary_key_paths)
31
31
  }
32
32
  }
33
33
  }
34
34
 
35
35
  fn primary_key_tombstone_value(
36
36
  column_name: &str,
37
- entity_id: &str,
37
+ entity_pk: &str,
38
38
  primary_key_paths: &[Vec<String>],
39
39
  ) -> Result<Option<JsonValue>, LixError> {
40
40
  let Some(part_index) = primary_key_paths
@@ -44,9 +44,9 @@ fn primary_key_tombstone_value(
44
44
  return Ok(None);
45
45
  };
46
46
 
47
- let identity = EntityIdentity::from_json_array_text(entity_id).map_err(|error| {
47
+ let identity = EntityPk::from_json_array_text(entity_pk).map_err(|error| {
48
48
  LixError::unknown(format!(
49
- "failed to decode history tombstone entity identity: {error}"
49
+ "failed to decode history tombstone entity primary key: {error}"
50
50
  ))
51
51
  })?;
52
52
  Ok(identity