@lix-js/sdk 0.6.0-preview.3 → 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 (235) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +105 -65
  3. package/dist/engine-wasm/index.js +4 -4
  4. package/dist/engine-wasm/wasm/lix_engine.d.ts +30 -6
  5. package/dist/engine-wasm/wasm/lix_engine.js +187 -117
  6. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  7. package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +14 -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 +42 -28
  11. package/dist/open-lix.js +49 -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 +819 -124
  94. package/dist-engine-src/src/session/create_branch.rs +94 -0
  95. package/dist-engine-src/src/session/execute.rs +260 -57
  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 +19 -16
  102. package/dist-engine-src/src/session/switch_branch.rs +113 -0
  103. package/dist-engine-src/src/session/transaction.rs +557 -0
  104. package/dist-engine-src/src/sql2/bind/classify.rs +102 -0
  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} +98 -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 +4 -5
  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 +30 -24
  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 -109
  218. package/dist-engine-src/src/sql2/classify.rs +0 -182
  219. package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
  220. package/dist-engine-src/src/sql2/execute.rs +0 -3440
  221. package/dist-engine-src/src/sql2/public_bind/assignment.rs +0 -46
  222. package/dist-engine-src/src/sql2/public_bind/capability.rs +0 -41
  223. package/dist-engine-src/src/sql2/public_bind/dml.rs +0 -166
  224. package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -25
  225. package/dist-engine-src/src/sql2/public_bind/table.rs +0 -168
  226. package/dist-engine-src/src/sql2/version_scope.rs +0 -394
  227. package/dist-engine-src/src/storage/types.rs +0 -501
  228. package/dist-engine-src/src/tracked_state/by_file_index.rs +0 -98
  229. package/dist-engine-src/src/tracked_state/materializer.rs +0 -488
  230. package/dist-engine-src/src/transaction/live_state_overlay.rs +0 -35
  231. package/dist-engine-src/src/version/lifecycle.rs +0 -221
  232. package/dist-engine-src/src/version/mod.rs +0 -13
  233. package/dist-engine-src/src/version/refs.rs +0 -330
  234. package/dist-engine-src/src/version/stage_rows.rs +0 -67
  235. package/dist-engine-src/src/version/types.rs +0 -21
@@ -2,6 +2,7 @@ use std::collections::{BTreeMap, BTreeSet};
2
2
 
3
3
  use serde_json::Value as JsonValue;
4
4
 
5
+ use crate::branch::{BRANCH_DESCRIPTOR_SCHEMA_KEY, BRANCH_REF_SCHEMA_KEY};
5
6
  use crate::catalog::{
6
7
  CatalogSnapshot, ForeignKeyPlan, SchemaCatalogKey, SchemaPlan, StateDeleteReferencePlan,
7
8
  StateForeignKeyPlan,
@@ -11,7 +12,7 @@ use crate::common::format_json_pointer;
11
12
  use crate::common::parse_json_pointer;
12
13
  use crate::common::{json_pointer_get, validate_row_metadata};
13
14
  use crate::domain::{Domain, DomainFileScope, DomainRowIdentity};
14
- use crate::entity_identity::{canonical_json_text, EntityIdentity, EntityIdentityError};
15
+ use crate::entity_pk::{canonical_json_text, EntityPk, EntityPkError};
15
16
  #[cfg(test)]
16
17
  use crate::live_state::LiveStateRowIdentity;
17
18
  use crate::live_state::{
@@ -31,7 +32,6 @@ use crate::transaction::staging::{PreparedValidationRow, PreparedWriteValidation
31
32
  #[cfg(test)]
32
33
  use crate::transaction::types::PreparedStateRow;
33
34
  use crate::transaction::types::TransactionWriteOrigin;
34
- use crate::version::{VERSION_DESCRIPTOR_SCHEMA_KEY, VERSION_REF_SCHEMA_KEY};
35
35
  use crate::LixError;
36
36
 
37
37
  const REGISTERED_SCHEMA_KEY: &str = "lix_registered_schema";
@@ -83,15 +83,15 @@ async fn scan_committed_constraint_rows(
83
83
  live_state: &dyn LiveStateReader,
84
84
  domain: &Domain,
85
85
  schema_keys: Vec<String>,
86
- entity_ids: Vec<EntityIdentity>,
86
+ entity_pks: Vec<EntityPk>,
87
87
  include_tombstones: bool,
88
88
  ) -> Result<Vec<MaterializedLiveStateRow>, LixError> {
89
89
  let rows = live_state
90
90
  .scan_rows(&LiveStateScanRequest {
91
91
  filter: LiveStateFilter {
92
92
  schema_keys: schema_keys.clone(),
93
- entity_ids: entity_ids.clone(),
94
- version_ids: vec![domain.version_id().to_string()],
93
+ entity_pks: entity_pks.clone(),
94
+ branch_ids: vec![domain.branch_id().to_string()],
95
95
  file_ids: domain.file_filters(),
96
96
  untracked: Some(domain.untracked()),
97
97
  include_tombstones,
@@ -105,7 +105,7 @@ async fn scan_committed_constraint_rows(
105
105
  .filter(|row| {
106
106
  domain.contains(row)
107
107
  && (schema_keys.is_empty() || schema_keys.contains(&row.schema_key))
108
- && (entity_ids.is_empty() || entity_ids.contains(&row.entity_id))
108
+ && (entity_pks.is_empty() || entity_pks.contains(&row.entity_pk))
109
109
  })
110
110
  .collect())
111
111
  }
@@ -114,14 +114,14 @@ async fn load_committed_constraint_row(
114
114
  live_state: &dyn LiveStateReader,
115
115
  domain: &Domain,
116
116
  schema_key: &str,
117
- entity_id: EntityIdentity,
117
+ entity_pk: EntityPk,
118
118
  include_tombstones: bool,
119
119
  ) -> Result<Option<MaterializedLiveStateRow>, LixError> {
120
120
  Ok(scan_committed_constraint_rows(
121
121
  live_state,
122
122
  domain,
123
123
  vec![schema_key.to_string()],
124
- vec![entity_id],
124
+ vec![entity_pk],
125
125
  include_tombstones,
126
126
  )
127
127
  .await?
@@ -188,7 +188,7 @@ pub(crate) async fn validate_prepared_writes(
188
188
  validate_committed_delete_restrictions(&input, input.schema_catalog, &pending_constraints)
189
189
  .await?;
190
190
  validate_file_descriptor_delete_restrictions(&input, &pending_constraints).await?;
191
- validate_version_ref_delete_restrictions(&input, &pending_constraints).await?;
191
+ validate_branch_ref_delete_restrictions(&input, &pending_constraints).await?;
192
192
  validate_committed_insert_identities(&input, &pending_constraints).await?;
193
193
  validate_committed_unique_constraints(&input, &pending_constraints).await?;
194
194
  validate_directory_descriptor_parent_graph(&input, &staged_rows, &constraint_rows).await?;
@@ -245,7 +245,7 @@ async fn validate_registered_schema_identity_is_canonical(
245
245
  input.live_state,
246
246
  &pending_row.domain().with_exact_file_scope(None),
247
247
  REGISTERED_SCHEMA_KEY,
248
- pending_row.entity_id().clone(),
248
+ pending_row.entity_pk().clone(),
249
249
  false,
250
250
  )
251
251
  .await?
@@ -347,7 +347,7 @@ fn apply_staged_directory_parent_rows(
347
347
  {
348
348
  continue;
349
349
  }
350
- let id = row.entity_id().as_single_string_owned()?;
350
+ let id = row.entity_pk().as_single_string_owned()?;
351
351
  let Some(snapshot) = row.snapshot_json() else {
352
352
  parents.remove(&id);
353
353
  continue;
@@ -432,27 +432,27 @@ fn optional_snapshot_string(
432
432
  #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
433
433
  struct FilesystemNamespaceIdentity {
434
434
  schema_key: String,
435
- entity_id: EntityIdentity,
435
+ entity_pk: EntityPk,
436
436
  }
437
437
 
438
438
  #[derive(Debug, Clone, PartialEq, Eq)]
439
439
  enum FilesystemNamespaceOccupant {
440
440
  Directory {
441
- entity_id: EntityIdentity,
441
+ entity_pk: EntityPk,
442
442
  parent_id: Option<String>,
443
443
  name: String,
444
444
  },
445
445
  File {
446
- entity_id: EntityIdentity,
446
+ entity_pk: EntityPk,
447
447
  directory_id: Option<String>,
448
448
  entry_name: String,
449
449
  },
450
450
  }
451
451
 
452
452
  impl FilesystemNamespaceOccupant {
453
- fn entity_id(&self) -> &EntityIdentity {
453
+ fn entity_pk(&self) -> &EntityPk {
454
454
  match self {
455
- Self::Directory { entity_id, .. } | Self::File { entity_id, .. } => entity_id,
455
+ Self::Directory { entity_pk, .. } | Self::File { entity_pk, .. } => entity_pk,
456
456
  }
457
457
  }
458
458
 
@@ -483,8 +483,8 @@ async fn validate_filesystem_namespace(
483
483
  staged_rows: &[PreparedValidationRow<'_>],
484
484
  ) -> Result<(), LixError> {
485
485
  // Filesystem namespace constraints are storage-scope local. Global rows are
486
- // validated in the global scope and may be projected into version reads, but
487
- // projected globals do not participate in version-local constraint checks.
486
+ // validated in the global scope and may be projected into branch reads, but
487
+ // projected globals do not participate in branch-local constraint checks.
488
488
  let domains = staged_filesystem_namespace_domains(staged_rows);
489
489
  for domain in domains {
490
490
  let mut occupants =
@@ -555,7 +555,7 @@ fn apply_staged_filesystem_namespace_rows(
555
555
  }
556
556
  let identity = FilesystemNamespaceIdentity {
557
557
  schema_key: row.schema_key().to_string(),
558
- entity_id: row.entity_id().clone(),
558
+ entity_pk: row.entity_pk().clone(),
559
559
  };
560
560
  let Some(snapshot) = row.snapshot_json() else {
561
561
  occupants.remove(&identity);
@@ -577,13 +577,13 @@ fn filesystem_namespace_occupant_from_live_row(
577
577
  };
578
578
  let identity = FilesystemNamespaceIdentity {
579
579
  schema_key: row.schema_key.clone(),
580
- entity_id: row.entity_id.clone(),
580
+ entity_pk: row.entity_pk.clone(),
581
581
  };
582
582
  let occupant = match row.schema_key.as_str() {
583
583
  DIRECTORY_DESCRIPTOR_SCHEMA_KEY => {
584
- directory_namespace_occupant(&row.entity_id, snapshot_content)?
584
+ directory_namespace_occupant(&row.entity_pk, snapshot_content)?
585
585
  }
586
- FILE_DESCRIPTOR_SCHEMA_KEY => file_namespace_occupant(&row.entity_id, snapshot_content)?,
586
+ FILE_DESCRIPTOR_SCHEMA_KEY => file_namespace_occupant(&row.entity_pk, snapshot_content)?,
587
587
  _ => return Ok(None),
588
588
  };
589
589
  Ok(Some((identity, occupant)))
@@ -595,9 +595,9 @@ fn filesystem_namespace_occupant_from_staged_row(
595
595
  ) -> Result<FilesystemNamespaceOccupant, LixError> {
596
596
  match row.schema_key() {
597
597
  DIRECTORY_DESCRIPTOR_SCHEMA_KEY => {
598
- directory_namespace_occupant_from_value(row.entity_id(), snapshot)
598
+ directory_namespace_occupant_from_value(row.entity_pk(), snapshot)
599
599
  }
600
- FILE_DESCRIPTOR_SCHEMA_KEY => file_namespace_occupant_from_value(row.entity_id(), snapshot),
600
+ FILE_DESCRIPTOR_SCHEMA_KEY => file_namespace_occupant_from_value(row.entity_pk(), snapshot),
601
601
  _ => Err(LixError::new(
602
602
  LixError::CODE_SCHEMA_VALIDATION,
603
603
  format!(
@@ -609,31 +609,31 @@ fn filesystem_namespace_occupant_from_staged_row(
609
609
  }
610
610
 
611
611
  fn directory_namespace_occupant(
612
- entity_id: &EntityIdentity,
612
+ entity_pk: &EntityPk,
613
613
  snapshot_content: &str,
614
614
  ) -> Result<FilesystemNamespaceOccupant, LixError> {
615
615
  let snapshot = parse_directory_descriptor_snapshot(snapshot_content)?;
616
616
  Ok(FilesystemNamespaceOccupant::Directory {
617
- entity_id: entity_id.clone(),
617
+ entity_pk: entity_pk.clone(),
618
618
  parent_id: snapshot.parent_id,
619
619
  name: snapshot.name,
620
620
  })
621
621
  }
622
622
 
623
623
  fn directory_namespace_occupant_from_value(
624
- entity_id: &EntityIdentity,
624
+ entity_pk: &EntityPk,
625
625
  snapshot: &JsonValue,
626
626
  ) -> Result<FilesystemNamespaceOccupant, LixError> {
627
627
  let snapshot = directory_descriptor_snapshot_from_value(snapshot)?;
628
628
  Ok(FilesystemNamespaceOccupant::Directory {
629
- entity_id: entity_id.clone(),
629
+ entity_pk: entity_pk.clone(),
630
630
  parent_id: snapshot.parent_id,
631
631
  name: snapshot.name,
632
632
  })
633
633
  }
634
634
 
635
635
  fn file_namespace_occupant(
636
- entity_id: &EntityIdentity,
636
+ entity_pk: &EntityPk,
637
637
  snapshot_content: &str,
638
638
  ) -> Result<FilesystemNamespaceOccupant, LixError> {
639
639
  let snapshot =
@@ -644,19 +644,19 @@ fn file_namespace_occupant(
644
644
  )
645
645
  })?;
646
646
  Ok(FilesystemNamespaceOccupant::File {
647
- entity_id: entity_id.clone(),
647
+ entity_pk: entity_pk.clone(),
648
648
  directory_id: snapshot.directory_id,
649
649
  entry_name: snapshot.name,
650
650
  })
651
651
  }
652
652
 
653
653
  fn file_namespace_occupant_from_value(
654
- entity_id: &EntityIdentity,
654
+ entity_pk: &EntityPk,
655
655
  snapshot: &JsonValue,
656
656
  ) -> Result<FilesystemNamespaceOccupant, LixError> {
657
657
  let snapshot = file_descriptor_snapshot_from_value(snapshot)?;
658
658
  Ok(FilesystemNamespaceOccupant::File {
659
- entity_id: entity_id.clone(),
659
+ entity_pk: entity_pk.clone(),
660
660
  directory_id: snapshot.directory_id,
661
661
  entry_name: snapshot.name,
662
662
  })
@@ -693,18 +693,18 @@ fn filesystem_namespace_conflict_error(
693
693
  ) -> LixError {
694
694
  let parent = parent_id.as_deref().unwrap_or("<root>");
695
695
  let existing_id = existing
696
- .entity_id()
696
+ .entity_pk()
697
697
  .as_single_string_owned()
698
- .unwrap_or_else(|_| "<non-string-entity-id>".to_string());
698
+ .unwrap_or_else(|_| "<non-string-entity-pk>".to_string());
699
699
  let conflicting_id = conflicting
700
- .entity_id()
700
+ .entity_pk()
701
701
  .as_single_string_owned()
702
- .unwrap_or_else(|_| "<non-string-entity-id>".to_string());
702
+ .unwrap_or_else(|_| "<non-string-entity-pk>".to_string());
703
703
  LixError::new(
704
704
  LixError::CODE_UNIQUE,
705
705
  format!(
706
- "filesystem namespace conflict in version '{}' for parent {parent:?} entry {entry_name:?}: {} '{}' conflicts with {} '{}'",
707
- domain.version_id(),
706
+ "filesystem namespace conflict in branch '{}' for parent {parent:?} entry {entry_name:?}: {} '{}' conflicts with {} '{}'",
707
+ domain.branch_id(),
708
708
  existing.kind(),
709
709
  existing_id,
710
710
  conflicting.kind(),
@@ -756,8 +756,8 @@ fn directory_parent_cycle_error(
756
756
  LixError::new(
757
757
  LixError::CODE_CONSTRAINT_VIOLATION,
758
758
  format!(
759
- "lix_directory_descriptor parent_id cycle in version '{}': directory '{}' reaches ancestor '{}' twice",
760
- scope.domain.version_id(), start_id, repeated_id
759
+ "lix_directory_descriptor parent_id cycle in branch '{}': directory '{}' reaches ancestor '{}' twice",
760
+ scope.domain.branch_id(), start_id, repeated_id
761
761
  ),
762
762
  )
763
763
  .with_hint("Set parent_id to null or to an existing directory outside the directory's descendants.")
@@ -771,8 +771,8 @@ fn directory_parent_missing_error(
771
771
  LixError::new(
772
772
  LixError::CODE_FOREIGN_KEY,
773
773
  format!(
774
- "lix_directory_descriptor parent_id chain in version '{}' for directory '{}' references missing directory '{}'",
775
- scope.domain.version_id(), start_id, missing_id
774
+ "lix_directory_descriptor parent_id chain in branch '{}' for directory '{}' references missing directory '{}'",
775
+ scope.domain.branch_id(), start_id, missing_id
776
776
  ),
777
777
  )
778
778
  }
@@ -781,8 +781,8 @@ fn directory_parent_depth_error(scope: &DirectoryDescriptorScope, start_id: &str
781
781
  LixError::new(
782
782
  LixError::CODE_CONSTRAINT_VIOLATION,
783
783
  format!(
784
- "lix_directory_descriptor parent_id chain in version '{}' for directory '{}' exceeds maximum depth {}",
785
- scope.domain.version_id(), start_id, MAX_DIRECTORY_PARENT_DEPTH
784
+ "lix_directory_descriptor parent_id chain in branch '{}' for directory '{}' exceeds maximum depth {}",
785
+ scope.domain.branch_id(), start_id, MAX_DIRECTORY_PARENT_DEPTH
786
786
  ),
787
787
  )
788
788
  }
@@ -797,12 +797,12 @@ async fn validate_committed_insert_identities(
797
797
  .map(|target| target.identity.clone())
798
798
  .collect::<BTreeSet<_>>();
799
799
  let mut checks_by_domain_schema =
800
- BTreeMap::<(Domain, String), Vec<(EntityIdentity, Option<TransactionWriteOrigin>)>>::new();
800
+ BTreeMap::<(Domain, String), Vec<(EntityPk, Option<TransactionWriteOrigin>)>>::new();
801
801
  for (identity, origin) in input.staged_writes.insert_identities() {
802
802
  let pending_identity = DomainRowIdentity::in_domain(
803
803
  identity.domain(),
804
804
  identity.schema_key().to_string(),
805
- identity.entity_id().clone(),
805
+ identity.entity_pk().clone(),
806
806
  );
807
807
  if !pending_identity_targets.contains(&pending_identity) {
808
808
  continue;
@@ -813,66 +813,66 @@ async fn validate_committed_insert_identities(
813
813
  pending_identity.schema_key_owned(),
814
814
  ))
815
815
  .or_default()
816
- .push((pending_identity.entity_id_owned(), origin.cloned()));
816
+ .push((pending_identity.entity_pk_owned(), origin.cloned()));
817
817
  }
818
818
 
819
819
  for ((domain, schema_key), checks) in checks_by_domain_schema {
820
- let entity_ids = checks
820
+ let entity_pks = checks
821
821
  .iter()
822
- .map(|(entity_id, _)| entity_id.clone())
822
+ .map(|(entity_pk, _)| entity_pk.clone())
823
823
  .collect::<Vec<_>>();
824
824
  let committed_rows = scan_committed_constraint_rows(
825
825
  input.live_state,
826
826
  &domain,
827
827
  vec![schema_key.clone()],
828
- entity_ids,
828
+ entity_pks,
829
829
  false,
830
830
  )
831
831
  .await?;
832
- let committed_rows_by_entity_id = committed_rows
832
+ let committed_rows_by_entity_pk = committed_rows
833
833
  .into_iter()
834
834
  .filter(|row| {
835
835
  row.snapshot_content.is_some() && !pending_constraints.tombstones_identity(row)
836
836
  })
837
- .map(|row| (row.entity_id.clone(), row))
837
+ .map(|row| (row.entity_pk.clone(), row))
838
838
  .collect::<BTreeMap<_, _>>();
839
- for (entity_id, origin) in checks {
840
- if !committed_rows_by_entity_id.contains_key(&entity_id) {
839
+ for (entity_pk, origin) in checks {
840
+ if !committed_rows_by_entity_pk.contains_key(&entity_pk) {
841
841
  continue;
842
842
  }
843
843
  return Err(LixError::new(
844
844
  LixError::CODE_UNIQUE,
845
- duplicate_insert_identity_message(&schema_key, &entity_id, None, origin.as_ref()),
845
+ duplicate_insert_identity_message(&schema_key, &entity_pk, None, origin.as_ref()),
846
846
  ));
847
847
  }
848
848
  }
849
849
  Ok(())
850
850
  }
851
851
 
852
- async fn validate_version_ref_delete_restrictions(
852
+ async fn validate_branch_ref_delete_restrictions(
853
853
  input: &TransactionValidationInput<'_>,
854
854
  pending_constraints: &PendingConstraintIndexes,
855
855
  ) -> Result<(), LixError> {
856
856
  for tombstone in &pending_constraints.tombstones {
857
- if tombstone.identity.schema_key() != VERSION_REF_SCHEMA_KEY {
857
+ if tombstone.identity.schema_key() != BRANCH_REF_SCHEMA_KEY {
858
858
  continue;
859
859
  }
860
860
 
861
861
  for source_domain in tombstone
862
862
  .identity
863
863
  .domain()
864
- .version_descriptor_domains_for_ref_delete()
864
+ .branch_descriptor_domains_for_ref_delete()
865
865
  {
866
866
  let descriptor_identity = DomainRowIdentity::in_domain(
867
867
  source_domain,
868
- VERSION_DESCRIPTOR_SCHEMA_KEY,
869
- tombstone.identity.entity_id_owned(),
868
+ BRANCH_DESCRIPTOR_SCHEMA_KEY,
869
+ tombstone.identity.entity_pk_owned(),
870
870
  );
871
871
  if pending_constraints.tombstones_target_identity(&descriptor_identity) {
872
872
  continue;
873
873
  }
874
874
  if pending_constraints.has_identity_target(&descriptor_identity) {
875
- return Err(version_ref_delete_restriction_error(
875
+ return Err(branch_ref_delete_restriction_error(
876
876
  &tombstone.identity,
877
877
  &descriptor_identity,
878
878
  )?);
@@ -882,7 +882,7 @@ async fn validate_version_ref_delete_restrictions(
882
882
  input.live_state,
883
883
  descriptor_identity.domain(),
884
884
  descriptor_identity.schema_key(),
885
- descriptor_identity.entity_id_owned(),
885
+ descriptor_identity.entity_pk_owned(),
886
886
  false,
887
887
  )
888
888
  .await?
@@ -892,7 +892,7 @@ async fn validate_version_ref_delete_restrictions(
892
892
  if descriptor_row.snapshot_content.is_some()
893
893
  && !pending_constraints.tombstones_identity(&descriptor_row)
894
894
  {
895
- return Err(version_ref_delete_restriction_error(
895
+ return Err(branch_ref_delete_restriction_error(
896
896
  &tombstone.identity,
897
897
  &descriptor_identity,
898
898
  )?);
@@ -902,19 +902,19 @@ async fn validate_version_ref_delete_restrictions(
902
902
  Ok(())
903
903
  }
904
904
 
905
- fn version_ref_delete_restriction_error(
905
+ fn branch_ref_delete_restriction_error(
906
906
  ref_identity: &DomainRowIdentity,
907
907
  descriptor_identity: &DomainRowIdentity,
908
908
  ) -> Result<LixError, LixError> {
909
909
  Ok(LixError::new(
910
910
  LixError::CODE_FOREIGN_KEY,
911
911
  format!(
912
- "cannot delete '{}' row '{}' in version '{}' because matching '{}' row '{}' would remain without a version ref",
912
+ "cannot delete '{}' row '{}' in branch '{}' because matching '{}' row '{}' would remain without a branch ref",
913
913
  ref_identity.schema_key(),
914
- ref_identity.entity_id().as_single_string_owned()?,
915
- ref_identity.domain().version_id(),
914
+ ref_identity.entity_pk().as_single_string_owned()?,
915
+ ref_identity.domain().branch_id(),
916
916
  descriptor_identity.schema_key(),
917
- descriptor_identity.entity_id().as_single_string_owned()?,
917
+ descriptor_identity.entity_pk().as_single_string_owned()?,
918
918
  ),
919
919
  ))
920
920
  }
@@ -937,7 +937,7 @@ impl PendingFileDescriptorIndex {
937
937
  if row.schema_key() != FILE_DESCRIPTOR_SCHEMA_KEY || row.file_id().is_some() {
938
938
  continue;
939
939
  }
940
- if row.entity_id().as_single_string_owned().is_ok() {
940
+ if row.entity_pk().as_single_string_owned().is_ok() {
941
941
  let state = if (*row).snapshot_json().is_some() {
942
942
  PendingFileDescriptorState::Present
943
943
  } else {
@@ -958,7 +958,7 @@ impl PendingFileDescriptorIndex {
958
958
  .get(&DomainRowIdentity::in_domain(
959
959
  domain.with_exact_file_scope(None),
960
960
  FILE_DESCRIPTOR_SCHEMA_KEY,
961
- EntityIdentity::single(file_id),
961
+ EntityPk::single(file_id),
962
962
  ))
963
963
  .copied()
964
964
  }
@@ -1009,7 +1009,7 @@ async fn committed_file_descriptor_exists_in_domain(
1009
1009
  live_state,
1010
1010
  &domain.with_exact_file_scope(None),
1011
1011
  FILE_DESCRIPTOR_SCHEMA_KEY,
1012
- EntityIdentity::single(file_id),
1012
+ EntityPk::single(file_id),
1013
1013
  false,
1014
1014
  )
1015
1015
  .await?
@@ -1018,7 +1018,7 @@ async fn committed_file_descriptor_exists_in_domain(
1018
1018
  };
1019
1019
  Ok(row.snapshot_content.is_some()
1020
1020
  && row.schema_key == FILE_DESCRIPTOR_SCHEMA_KEY
1021
- && row.entity_id == EntityIdentity::single(file_id)
1021
+ && row.entity_pk == EntityPk::single(file_id)
1022
1022
  && row.file_id.is_none())
1023
1023
  }
1024
1024
 
@@ -1029,11 +1029,11 @@ fn missing_file_owner_reference_error(
1029
1029
  Ok(LixError::new(
1030
1030
  LixError::CODE_FILE_NOT_FOUND,
1031
1031
  format!(
1032
- "file ownership validation failed for schema '{}': entity '{}' references missing file_id '{}' in effective file scope for version '{}'",
1032
+ "file ownership validation failed for schema '{}': entity '{}' references missing file_id '{}' in effective file scope for branch '{}'",
1033
1033
  row.schema_key(),
1034
- row.entity_id().as_json_array_text()?,
1034
+ row.entity_pk().as_json_array_text()?,
1035
1035
  file_id,
1036
- row.version_id()
1036
+ row.branch_id()
1037
1037
  ),
1038
1038
  )
1039
1039
  .with_hint("Insert a row into lix_file with this id first, or use null for a global entity."))
@@ -1051,7 +1051,7 @@ fn validate_staged_row_shape(row: PreparedValidationRow<'_>) -> Result<(), LixEr
1051
1051
  LixError::CODE_SCHEMA_DEFINITION,
1052
1052
  "lix_registered_schema rows must not be scoped to a file",
1053
1053
  )
1054
- .with_hint("Schema definitions are scoped by version and durability only; write them with null file_id."));
1054
+ .with_hint("Schema definitions are scoped by branch and durability only; write them with null file_id."));
1055
1055
  }
1056
1056
  Ok(())
1057
1057
  }
@@ -1181,15 +1181,15 @@ fn validate_primary_key_identity(
1181
1181
  let Some(primary_key_paths) = schema_plan.primary_key.as_ref() else {
1182
1182
  return Ok(());
1183
1183
  };
1184
- let derived = EntityIdentity::from_primary_key_paths(snapshot, &primary_key_paths)
1184
+ let derived = EntityPk::from_primary_key_paths(snapshot, &primary_key_paths)
1185
1185
  .map_err(|error| primary_key_identity_error(row, &primary_key_paths, error))?;
1186
- if row.entity_id() != &derived {
1186
+ if row.entity_pk() != &derived {
1187
1187
  return Err(LixError::new(
1188
1188
  LixError::CODE_UNIQUE,
1189
1189
  format!(
1190
- "primary-key constraint violation on schema '{}': entity_id '{}' does not match derived primary key '{}'",
1190
+ "primary-key constraint violation on schema '{}': entity_pk '{}' does not match derived primary key '{}'",
1191
1191
  row.schema_key(),
1192
- row.entity_id().as_json_array_text()?,
1192
+ row.entity_pk().as_json_array_text()?,
1193
1193
  derived.as_json_array_text()?
1194
1194
  ),
1195
1195
  ));
@@ -1199,7 +1199,7 @@ fn validate_primary_key_identity(
1199
1199
 
1200
1200
  #[derive(Default)]
1201
1201
  struct PendingConstraintIndexes {
1202
- unique_values: BTreeMap<PendingUniqueKey, EntityIdentity>,
1202
+ unique_values: BTreeMap<PendingUniqueKey, EntityPk>,
1203
1203
  identity_targets: Vec<PendingIdentityTarget>,
1204
1204
  fk_targets: BTreeMap<PendingForeignKeyTargetKey, Vec<PendingForeignKeyTarget>>,
1205
1205
  fk_references: BTreeMap<PendingForeignKeyReferenceTarget, Vec<PendingForeignKeyReference>>,
@@ -1259,11 +1259,11 @@ impl PendingConstraintIndexes {
1259
1259
  pointer_group: unique_paths.clone(),
1260
1260
  value,
1261
1261
  };
1262
- if let Some(existing_entity_id) = self
1262
+ if let Some(existing_entity_pk) = self
1263
1263
  .unique_values
1264
- .insert(key.clone(), row.entity_id().clone())
1264
+ .insert(key.clone(), row.entity_pk().clone())
1265
1265
  {
1266
- if existing_entity_id != *row.entity_id() {
1266
+ if existing_entity_pk != *row.entity_pk() {
1267
1267
  return Err(LixError::new(
1268
1268
  LixError::CODE_UNIQUE,
1269
1269
  format!(
@@ -1271,8 +1271,8 @@ impl PendingConstraintIndexes {
1271
1271
  row.schema_key(),
1272
1272
  format_pointer_group(&key.pointer_group),
1273
1273
  key.value.display(),
1274
- existing_entity_id.as_json_array_text()?,
1275
- row.entity_id().as_json_array_text()?
1274
+ existing_entity_pk.as_json_array_text()?,
1275
+ row.entity_pk().as_json_array_text()?
1276
1276
  ),
1277
1277
  ));
1278
1278
  }
@@ -1299,7 +1299,7 @@ impl PendingConstraintIndexes {
1299
1299
  })
1300
1300
  .or_default()
1301
1301
  .push(PendingForeignKeyTarget {
1302
- entity_id: row.entity_id().clone(),
1302
+ entity_pk: row.entity_pk().clone(),
1303
1303
  });
1304
1304
  }
1305
1305
 
@@ -1412,7 +1412,7 @@ impl PendingConstraintIndexes {
1412
1412
  fn has_fk_reference_to_key(
1413
1413
  &self,
1414
1414
  schema_key: &str,
1415
- version_id: &str,
1415
+ branch_id: &str,
1416
1416
  file_id: Option<&str>,
1417
1417
  pointer_group: &[&str],
1418
1418
  value: UniqueConstraintValue,
@@ -1423,7 +1423,7 @@ impl PendingConstraintIndexes {
1423
1423
  .collect::<Result<Vec<_>, _>>()?;
1424
1424
  let key = PendingForeignKeyReferenceTarget::Key(PendingForeignKeyTargetKey {
1425
1425
  schema_key: schema_key.to_string(),
1426
- domain: Domain::exact_file(version_id.to_string(), false, file_id.map(str::to_string)),
1426
+ domain: Domain::exact_file(branch_id.to_string(), false, file_id.map(str::to_string)),
1427
1427
  pointer_group,
1428
1428
  value,
1429
1429
  });
@@ -1442,7 +1442,7 @@ impl PendingConstraintIndexes {
1442
1442
  fn has_fk_target(
1443
1443
  &self,
1444
1444
  schema_key: &str,
1445
- version_id: &str,
1445
+ branch_id: &str,
1446
1446
  file_id: Option<&str>,
1447
1447
  pointer_group: &[&str],
1448
1448
  value: UniqueConstraintValue,
@@ -1453,7 +1453,7 @@ impl PendingConstraintIndexes {
1453
1453
  .collect::<Result<Vec<_>, _>>()?;
1454
1454
  let key = PendingForeignKeyTargetKey {
1455
1455
  schema_key: schema_key.to_string(),
1456
- domain: Domain::exact_file(version_id.to_string(), false, file_id.map(str::to_string)),
1456
+ domain: Domain::exact_file(branch_id.to_string(), false, file_id.map(str::to_string)),
1457
1457
  pointer_group,
1458
1458
  value,
1459
1459
  };
@@ -1473,7 +1473,7 @@ struct PendingIdentityTarget {
1473
1473
 
1474
1474
  #[derive(Debug, Clone, PartialEq, Eq)]
1475
1475
  struct PendingForeignKeyTarget {
1476
- entity_id: EntityIdentity,
1476
+ entity_pk: EntityPk,
1477
1477
  }
1478
1478
 
1479
1479
  #[derive(Debug, Clone, PartialEq, Eq)]
@@ -1552,8 +1552,8 @@ fn validate_pending_delete_restrictions(
1552
1552
  schema_key: tombstone.identity.schema_key_owned(),
1553
1553
  domain,
1554
1554
  pointer_group: primary_key_paths.clone(),
1555
- value: UniqueConstraintValue::from_entity_identity(
1556
- tombstone.identity.entity_id(),
1555
+ value: UniqueConstraintValue::from_entity_pk(
1556
+ tombstone.identity.entity_pk(),
1557
1557
  ),
1558
1558
  })
1559
1559
  })
@@ -1582,11 +1582,11 @@ fn reject_pending_delete_references(
1582
1582
  Err(LixError::new(
1583
1583
  LixError::CODE_FOREIGN_KEY,
1584
1584
  format!(
1585
- "cannot delete '{}' row '{}' in version '{}' because pending row '{}' references it{}",
1585
+ "cannot delete '{}' row '{}' in branch '{}' because pending row '{}' references it{}",
1586
1586
  deleted_identity.schema_key(),
1587
- deleted_identity.entity_id().as_json_array_text()?,
1588
- deleted_identity.domain().version_id(),
1589
- reference.identity.entity_id().as_json_array_text()?,
1587
+ deleted_identity.entity_pk().as_json_array_text()?,
1588
+ deleted_identity.domain().branch_id(),
1589
+ reference.identity.entity_pk().as_json_array_text()?,
1590
1590
  pending_foreign_key_reference_target_description(target)?
1591
1591
  ),
1592
1592
  ))
@@ -1605,7 +1605,7 @@ fn pending_foreign_key_reference_target_description(
1605
1605
  PendingForeignKeyReferenceTarget::StateSurfaceIdentity(target) => Ok(format!(
1606
1606
  " through '{}:{}'",
1607
1607
  target.schema_key(),
1608
- target.entity_id().as_json_array_text()?
1608
+ target.entity_pk().as_json_array_text()?
1609
1609
  )),
1610
1610
  }
1611
1611
  }
@@ -1672,7 +1672,7 @@ async fn validate_file_descriptor_delete_restrictions(
1672
1672
  if !tombstone.identity.domain().is_exact_file(&None) {
1673
1673
  continue;
1674
1674
  }
1675
- let file_id = tombstone.identity.entity_id().as_single_string_owned()?;
1675
+ let file_id = tombstone.identity.entity_pk().as_single_string_owned()?;
1676
1676
  for source_domain in tombstone
1677
1677
  .identity
1678
1678
  .domain()
@@ -1694,10 +1694,10 @@ async fn validate_file_descriptor_delete_restrictions(
1694
1694
  return Err(LixError::new(
1695
1695
  LixError::CODE_FOREIGN_KEY,
1696
1696
  format!(
1697
- "cannot delete file descriptor '{}' in version '{}' because committed row '{}' in schema '{}' is still scoped to that file",
1697
+ "cannot delete file descriptor '{}' in branch '{}' because committed row '{}' in schema '{}' is still scoped to that file",
1698
1698
  file_id,
1699
- tombstone.identity.domain().version_id(),
1700
- row.entity_id.as_json_array_text()?,
1699
+ tombstone.identity.domain().branch_id(),
1700
+ row.entity_pk.as_json_array_text()?,
1701
1701
  row.schema_key,
1702
1702
  ),
1703
1703
  ));
@@ -1810,7 +1810,7 @@ async fn committed_deleted_row_value(
1810
1810
  live_state,
1811
1811
  tombstone.identity.domain(),
1812
1812
  tombstone.identity.schema_key(),
1813
- tombstone.identity.entity_id_owned(),
1813
+ tombstone.identity.entity_pk_owned(),
1814
1814
  true,
1815
1815
  )
1816
1816
  .await?
@@ -1835,11 +1835,11 @@ fn committed_delete_restriction_error(
1835
1835
  Ok(LixError::new(
1836
1836
  LixError::CODE_FOREIGN_KEY,
1837
1837
  format!(
1838
- "cannot delete '{}' row '{}' in version '{}' because committed row '{}' references it through {}",
1838
+ "cannot delete '{}' row '{}' in branch '{}' because committed row '{}' references it through {}",
1839
1839
  deleted_identity.schema_key(),
1840
- deleted_identity.entity_id().as_json_array_text()?,
1841
- deleted_identity.domain().version_id(),
1842
- referencing_row.entity_id.as_json_array_text()?,
1840
+ deleted_identity.entity_pk().as_json_array_text()?,
1841
+ deleted_identity.domain().branch_id(),
1842
+ referencing_row.entity_pk.as_json_array_text()?,
1843
1843
  format_pointer_group(local_properties)
1844
1844
  ),
1845
1845
  ))
@@ -1993,11 +1993,11 @@ fn reject_unresolved_foreign_keys(
1993
1993
  Err(LixError::new(
1994
1994
  LixError::CODE_FOREIGN_KEY,
1995
1995
  format!(
1996
- "foreign key on schema '{}' row '{}' via {} has no matching target in version '{}'{}",
1996
+ "foreign key on schema '{}' row '{}' via {} has no matching target in branch '{}'{}",
1997
1997
  check.source_schema_key,
1998
- check.source_identity.entity_id().as_json_array_text()?,
1998
+ check.source_identity.entity_pk().as_json_array_text()?,
1999
1999
  format_pointer_group(&check.source_pointer_group),
2000
- check.source_identity.domain().version_id(),
2000
+ check.source_identity.domain().branch_id(),
2001
2001
  unresolved_foreign_key_target_description(&check.target)?
2002
2002
  ),
2003
2003
  ))
@@ -2016,7 +2016,7 @@ fn unresolved_foreign_key_target_description(
2016
2016
  UnresolvedForeignKeyTarget::StateSurfaceIdentity(target) => Ok(format!(
2017
2017
  " for target '{}:{}'",
2018
2018
  target.schema_key(),
2019
- target.entity_id().as_json_array_text()?
2019
+ target.entity_pk().as_json_array_text()?
2020
2020
  )),
2021
2021
  }
2022
2022
  }
@@ -2076,7 +2076,7 @@ async fn committed_state_surface_foreign_key_target_exists(
2076
2076
  live_state,
2077
2077
  candidate.domain(),
2078
2078
  vec![candidate.schema_key_owned()],
2079
- vec![candidate.entity_id_owned()],
2079
+ vec![candidate.entity_pk_owned()],
2080
2080
  false,
2081
2081
  )
2082
2082
  .await?;
@@ -2084,7 +2084,7 @@ async fn committed_state_surface_foreign_key_target_exists(
2084
2084
  if pending_constraints.tombstones_identity(&row) {
2085
2085
  continue;
2086
2086
  }
2087
- if candidate.matches_parts(&Domain::for_live_row(&row), &row.schema_key, &row.entity_id)
2087
+ if candidate.matches_parts(&Domain::for_live_row(&row), &row.schema_key, &row.entity_pk)
2088
2088
  {
2089
2089
  return Ok(true);
2090
2090
  }
@@ -2098,8 +2098,8 @@ fn state_surface_target_identity(
2098
2098
  foreign_key: &StateForeignKeyPlan,
2099
2099
  snapshot: &JsonValue,
2100
2100
  ) -> Result<DomainRowIdentity, LixError> {
2101
- let entity_id =
2102
- state_surface_local_json_value(snapshot, &foreign_key.entity_id_property, "entity_id")?;
2101
+ let entity_pk =
2102
+ state_surface_local_json_value(snapshot, &foreign_key.entity_pk_property, "entity_pk")?;
2103
2103
  let schema_key =
2104
2104
  state_surface_local_value(snapshot, &foreign_key.schema_key_property, "schema_key")?;
2105
2105
  let file_id =
@@ -2107,10 +2107,10 @@ fn state_surface_target_identity(
2107
2107
  Ok(DomainRowIdentity::in_domain(
2108
2108
  source_domain.with_exact_file_scope(file_id),
2109
2109
  schema_key,
2110
- EntityIdentity::from_json_array_value(entity_id).map_err(|error| {
2110
+ EntityPk::from_json_array_value(entity_pk).map_err(|error| {
2111
2111
  LixError::new(
2112
2112
  LixError::CODE_FOREIGN_KEY,
2113
- format!("state-surface foreign key entity_id is invalid: {error}"),
2113
+ format!("state-surface foreign key entity_pk is invalid: {error}"),
2114
2114
  )
2115
2115
  })?,
2116
2116
  ))
@@ -2200,15 +2200,15 @@ async fn validate_committed_unique_constraints(
2200
2200
  ) -> Result<(), LixError> {
2201
2201
  let mut pending_by_scope = BTreeMap::<
2202
2202
  PendingUniqueConstraintScope,
2203
- BTreeMap<UniqueConstraintValue, Vec<&EntityIdentity>>,
2203
+ BTreeMap<UniqueConstraintValue, Vec<&EntityPk>>,
2204
2204
  >::new();
2205
- for (key, pending_entity_id) in &pending_constraints.unique_values {
2205
+ for (key, pending_entity_pk) in &pending_constraints.unique_values {
2206
2206
  pending_by_scope
2207
2207
  .entry(PendingUniqueConstraintScope::from(key))
2208
2208
  .or_default()
2209
2209
  .entry(key.value.clone())
2210
2210
  .or_default()
2211
- .push(pending_entity_id);
2211
+ .push(pending_entity_pk);
2212
2212
  }
2213
2213
 
2214
2214
  for (scope, pending_values) in pending_by_scope {
@@ -2246,11 +2246,11 @@ async fn validate_committed_unique_constraints(
2246
2246
  else {
2247
2247
  continue;
2248
2248
  };
2249
- let Some(pending_entity_ids) = pending_values.get(&committed_value) else {
2249
+ let Some(pending_entity_pks) = pending_values.get(&committed_value) else {
2250
2250
  continue;
2251
2251
  };
2252
- for pending_entity_id in pending_entity_ids {
2253
- if committed_row.entity_id == **pending_entity_id {
2252
+ for pending_entity_pk in pending_entity_pks {
2253
+ if committed_row.entity_pk == **pending_entity_pk {
2254
2254
  continue;
2255
2255
  }
2256
2256
  return Err(LixError::new(
@@ -2260,8 +2260,8 @@ async fn validate_committed_unique_constraints(
2260
2260
  scope.schema_key,
2261
2261
  format_pointer_group(&scope.pointer_group),
2262
2262
  committed_value.display(),
2263
- committed_row.entity_id.as_json_array_text()?,
2264
- pending_entity_id.as_json_array_text()?
2263
+ committed_row.entity_pk.as_json_array_text()?,
2264
+ pending_entity_pk.as_json_array_text()?
2265
2265
  ),
2266
2266
  ));
2267
2267
  }
@@ -2275,8 +2275,8 @@ fn committed_row_is_in_exact_unique_scope(
2275
2275
  scope: &PendingUniqueConstraintScope,
2276
2276
  ) -> bool {
2277
2277
  // LiveStateReader may return serving projections such as global rows
2278
- // projected into a requested version. Constraint validation is root-local:
2279
- // only rows authored in the exact version participate.
2278
+ // projected into a requested branch. Constraint validation is root-local:
2279
+ // only rows authored in the exact branch participate.
2280
2280
  scope.domain.contains(row) && row.schema_key == scope.schema_key
2281
2281
  }
2282
2282
 
@@ -2294,7 +2294,7 @@ impl UniqueConstraintValue {
2294
2294
  )
2295
2295
  }
2296
2296
 
2297
- fn from_entity_identity(identity: &EntityIdentity) -> Self {
2297
+ fn from_entity_pk(identity: &EntityPk) -> Self {
2298
2298
  Self(
2299
2299
  identity
2300
2300
  .parts
@@ -2360,31 +2360,22 @@ fn format_pointer_group(group: &[Vec<String>]) -> String {
2360
2360
  fn primary_key_identity_error(
2361
2361
  row: PreparedValidationRow<'_>,
2362
2362
  primary_key_paths: &[Vec<String>],
2363
- error: EntityIdentityError,
2363
+ error: EntityPkError,
2364
2364
  ) -> LixError {
2365
2365
  let reason = match error {
2366
- EntityIdentityError::EmptyPrimaryKey => "empty x-lix-primary-key".to_string(),
2367
- EntityIdentityError::EmptyPrimaryKeyPath { index } => {
2366
+ EntityPkError::EmptyPrimaryKey => "empty x-lix-primary-key".to_string(),
2367
+ EntityPkError::EmptyPrimaryKeyPath { index } => {
2368
2368
  format!("empty x-lix-primary-key pointer at index {index}")
2369
2369
  }
2370
- EntityIdentityError::EmptyPrimaryKeyValue { index } => {
2371
- let pointer = primary_key_paths
2372
- .get(index)
2373
- .map(|path| format_json_pointer(path))
2374
- .unwrap_or_else(|| format!("index {index}"));
2375
- format!("empty value at primary-key pointer '{pointer}'")
2376
- }
2377
- EntityIdentityError::MissingPrimaryKeyValue { index } => {
2370
+ EntityPkError::MissingPrimaryKeyValue { index } => {
2378
2371
  let pointer = format_json_pointer(&primary_key_paths[index]);
2379
2372
  format!("missing value at primary-key pointer '{pointer}'")
2380
2373
  }
2381
- EntityIdentityError::UnsupportedPrimaryKeyValue { index } => {
2374
+ EntityPkError::UnsupportedPrimaryKeyValue { index } => {
2382
2375
  let pointer = format_json_pointer(&primary_key_paths[index]);
2383
2376
  format!("non-string value at primary-key pointer '{pointer}'")
2384
2377
  }
2385
- EntityIdentityError::InvalidEncodedEntityIdentity => {
2386
- "invalid encoded entity identity".to_string()
2387
- }
2378
+ EntityPkError::InvalidEncodedEntityPk => "invalid encoded entity primary key".to_string(),
2388
2379
  };
2389
2380
  LixError::new(
2390
2381
  LixError::CODE_UNIQUE,
@@ -2418,7 +2409,7 @@ fn validate_foreign_key_definition(
2418
2409
  return Err(LixError::new(
2419
2410
  LixError::CODE_SCHEMA_DEFINITION,
2420
2411
  format!(
2421
- "foreign key on schema '{}' must not reference schemaKey 'lix_state'; use x-lix-state-foreign-keys with pointers ordered as [entity_id, schema_key, file_id]",
2412
+ "foreign key on schema '{}' must not reference schemaKey 'lix_state'; use x-lix-state-foreign-keys with pointers ordered as [entity_pk, schema_key, file_id]",
2422
2413
  source_key.schema_key
2423
2414
  ),
2424
2415
  ));
@@ -2688,8 +2679,7 @@ mod tests {
2688
2679
  visible_schemas: &[JsonValue],
2689
2680
  ) -> Result<CatalogSnapshot, LixError> {
2690
2681
  let catalog = catalog_from_transaction_parts_unchecked(staged_writes, visible_schemas)?;
2691
- let mut pending_keys =
2692
- BTreeMap::<SchemaCatalogKey, crate::entity_identity::EntityIdentity>::new();
2682
+ let mut pending_keys = BTreeMap::<SchemaCatalogKey, crate::entity_pk::EntityPk>::new();
2693
2683
  for row in staged_writes
2694
2684
  .validation_rows()
2695
2685
  .filter(|row| row.schema_key() == REGISTERED_SCHEMA_KEY)
@@ -2711,16 +2701,16 @@ mod tests {
2711
2701
  })?;
2712
2702
  let (key, _) = schema_from_registered_snapshot(&snapshot)?;
2713
2703
  let catalog_key = SchemaCatalogKey::from_schema_key(key);
2714
- if let Some(existing_entity_id) =
2715
- pending_keys.insert(catalog_key.clone(), row.entity_id().clone())
2704
+ if let Some(existing_entity_pk) =
2705
+ pending_keys.insert(catalog_key.clone(), row.entity_pk().clone())
2716
2706
  {
2717
2707
  return Err(LixError::new(
2718
2708
  LixError::CODE_SCHEMA_DEFINITION,
2719
2709
  format!(
2720
2710
  "duplicate pending registered schema '{}' in transaction: rows '{}' and '{}'",
2721
2711
  catalog_key.schema_key,
2722
- existing_entity_id.as_json_array_text()?,
2723
- row.entity_id().as_json_array_text()?
2712
+ existing_entity_pk.as_json_array_text()?,
2713
+ row.entity_pk().as_json_array_text()?
2724
2714
  ),
2725
2715
  ));
2726
2716
  }
@@ -2784,8 +2774,8 @@ mod tests {
2784
2774
  .chain(test_file_descriptor_rows())
2785
2775
  .find(|row| {
2786
2776
  row.schema_key == request.schema_key
2787
- && row.version_id == request.version_id
2788
- && row.entity_id == request.entity_id
2777
+ && row.branch_id == request.branch_id
2778
+ && row.entity_pk == request.entity_pk
2789
2779
  && request.file_id.matches(row.file_id.as_ref())
2790
2780
  }))
2791
2781
  }
@@ -2834,8 +2824,8 @@ mod tests {
2834
2824
  .scan_rows(&LiveStateScanRequest {
2835
2825
  filter: LiveStateFilter {
2836
2826
  schema_keys: vec![request.schema_key.clone()],
2837
- entity_ids: vec![request.entity_id.clone()],
2838
- version_ids: vec![request.version_id.clone()],
2827
+ entity_pks: vec![request.entity_pk.clone()],
2828
+ branch_ids: vec![request.branch_id.clone()],
2839
2829
  file_ids: vec![request.file_id.clone()],
2840
2830
  ..Default::default()
2841
2831
  },
@@ -2945,7 +2935,7 @@ mod tests {
2945
2935
  }
2946
2936
 
2947
2937
  #[test]
2948
- fn schema_catalog_indexes_visible_schemas_by_key_and_version() {
2938
+ fn schema_catalog_indexes_visible_schemas_by_key_and_branch() {
2949
2939
  let visible_schemas = vec![json!({
2950
2940
  "x-lix-key": "visible_schema",
2951
2941
  "type": "object",
@@ -2970,7 +2960,6 @@ mod tests {
2970
2960
  ];
2971
2961
  let staged_writes = PreparedWriteSet {
2972
2962
  state_rows: vec![pending_registered_schema_row("pending_schema")],
2973
- adopted_rows: Vec::new(),
2974
2963
  ..empty_staged_write_set()
2975
2964
  };
2976
2965
  let input = validation_input(&staged_writes, &visible_schemas);
@@ -2996,7 +2985,6 @@ mod tests {
2996
2985
  ];
2997
2986
  let staged_writes = PreparedWriteSet {
2998
2987
  state_rows: vec![pending_registered_schema_row("same_schema")],
2999
- adopted_rows: Vec::new(),
3000
2988
  ..empty_staged_write_set()
3001
2989
  };
3002
2990
 
@@ -3074,7 +3062,7 @@ mod tests {
3074
3062
  #[test]
3075
3063
  fn schema_catalog_rejects_duplicate_pending_registered_schema_identity() {
3076
3064
  let mut duplicate = pending_registered_schema_row("duplicate_schema");
3077
- duplicate.entity_id = registered_schema_entity_id("duplicate_schema_duplicate");
3065
+ duplicate.entity_pk = registered_schema_entity_pk("duplicate_schema_duplicate");
3078
3066
  let staged_writes = PreparedWriteSet {
3079
3067
  state_rows: vec![pending_registered_schema_row("duplicate_schema"), duplicate],
3080
3068
  ..empty_staged_write_set()
@@ -3110,7 +3098,6 @@ mod tests {
3110
3098
  fn schema_catalog_rejects_foreign_key_missing_target_schema() {
3111
3099
  let staged_writes = PreparedWriteSet {
3112
3100
  state_rows: vec![pending_registered_schema_from_definition(fk_child_schema())],
3113
- adopted_rows: Vec::new(),
3114
3101
  ..empty_staged_write_set()
3115
3102
  };
3116
3103
  let visible_schemas = vec![registered_schema()];
@@ -3203,11 +3190,10 @@ mod tests {
3203
3190
  schema["x-lix-foreign-keys"][0]["properties"] = json!(["/parent_id"]);
3204
3191
  schema["x-lix-foreign-keys"][0]["references"] = json!({
3205
3192
  "schemaKey": "lix_state",
3206
- "properties": ["/entity_id"]
3193
+ "properties": ["/entity_pk"]
3207
3194
  });
3208
3195
  let staged_writes = PreparedWriteSet {
3209
3196
  state_rows: vec![pending_registered_schema_from_definition(schema)],
3210
- adopted_rows: Vec::new(),
3211
3197
  ..empty_staged_write_set()
3212
3198
  };
3213
3199
  let visible_schemas = vec![registered_schema()];
@@ -3225,20 +3211,19 @@ mod tests {
3225
3211
  #[test]
3226
3212
  fn schema_catalog_rejects_state_surface_foreign_key_without_full_address_tuple() {
3227
3213
  let mut schema = state_surface_ref_schema();
3228
- schema["x-lix-state-foreign-keys"][0] = json!(["/target_entity_id"]);
3214
+ schema["x-lix-state-foreign-keys"][0] = json!(["/target_entity_pk"]);
3229
3215
  let staged_writes = PreparedWriteSet {
3230
3216
  state_rows: vec![pending_registered_schema_from_definition(schema)],
3231
- adopted_rows: Vec::new(),
3232
3217
  ..empty_staged_write_set()
3233
3218
  };
3234
3219
  let visible_schemas = vec![registered_schema()];
3235
3220
 
3236
3221
  let error = catalog_from_transaction_parts_unchecked(&staged_writes, &visible_schemas)
3237
- .expect_err("state FK target must include entity_id, schema_key, and file_id");
3222
+ .expect_err("state FK target must include entity_pk, schema_key, and file_id");
3238
3223
 
3239
3224
  assert_eq!(error.code, LixError::CODE_SCHEMA_DEFINITION);
3240
3225
  assert!(
3241
- error.message.contains("[entity_id, schema_key, file_id]"),
3226
+ error.message.contains("[entity_pk, schema_key, file_id]"),
3242
3227
  "unexpected error: {error:?}"
3243
3228
  );
3244
3229
  }
@@ -3263,7 +3248,6 @@ mod tests {
3263
3248
  let visible_schemas = vec![key_value_schema()];
3264
3249
  let staged_writes = PreparedWriteSet {
3265
3250
  state_rows: vec![staged_row("unknown_schema", None)],
3266
- adopted_rows: Vec::new(),
3267
3251
  ..empty_staged_write_set()
3268
3252
  };
3269
3253
 
@@ -3302,10 +3286,9 @@ mod tests {
3302
3286
  "untracked_only_schema",
3303
3287
  Some(json!({ "id": "row-1" }).to_string()),
3304
3288
  );
3305
- tracked_row.entity_id = EntityIdentity::single("row-1");
3289
+ tracked_row.entity_pk = EntityPk::single("row-1");
3306
3290
  let staged_writes = PreparedWriteSet {
3307
3291
  state_rows: vec![untracked_schema, tracked_row],
3308
- adopted_rows: Vec::new(),
3309
3292
  ..empty_staged_write_set()
3310
3293
  };
3311
3294
 
@@ -3347,7 +3330,6 @@ mod tests {
3347
3330
  let visible_schemas = vec![key_value_schema()];
3348
3331
  let staged_writes = PreparedWriteSet {
3349
3332
  state_rows: vec![staged_row("lix_key_value", None)],
3350
- adopted_rows: Vec::new(),
3351
3333
  ..empty_staged_write_set()
3352
3334
  };
3353
3335
 
@@ -3361,7 +3343,6 @@ mod tests {
3361
3343
  let visible_schemas = vec![unique_schema()];
3362
3344
  let staged_writes = PreparedWriteSet {
3363
3345
  state_rows: vec![unique_row("post-1", "hello-world", "first")],
3364
- adopted_rows: Vec::new(),
3365
3346
  ..empty_staged_write_set()
3366
3347
  };
3367
3348
 
@@ -3386,7 +3367,7 @@ mod tests {
3386
3367
  ];
3387
3368
  let staged_writes = PreparedWriteSet {
3388
3369
  state_rows: vec![
3389
- staged_file_descriptor_row("file-a", "version-a"),
3370
+ staged_file_descriptor_row("file-a", "branch-a"),
3390
3371
  unique_row("post-1", "hello-world", "first"),
3391
3372
  ],
3392
3373
  ..empty_staged_write_set()
@@ -3408,7 +3389,7 @@ mod tests {
3408
3389
  file_descriptor_schema(),
3409
3390
  directory_descriptor_schema(),
3410
3391
  ];
3411
- let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "version-a");
3392
+ let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "branch-a");
3412
3393
  mark_prepared_row_untracked(&mut untracked_file_descriptor);
3413
3394
  let staged_writes = PreparedWriteSet {
3414
3395
  state_rows: vec![
@@ -3441,7 +3422,7 @@ mod tests {
3441
3422
  mark_prepared_row_untracked(&mut untracked_row);
3442
3423
  let staged_writes = PreparedWriteSet {
3443
3424
  state_rows: vec![
3444
- staged_file_descriptor_row("file-a", "version-a"),
3425
+ staged_file_descriptor_row("file-a", "branch-a"),
3445
3426
  untracked_row,
3446
3427
  ],
3447
3428
  ..empty_staged_write_set()
@@ -3463,14 +3444,13 @@ mod tests {
3463
3444
  file_descriptor_schema(),
3464
3445
  directory_descriptor_schema(),
3465
3446
  ];
3466
- let mut file_descriptor_delete = staged_file_descriptor_row("file-a", "version-a");
3447
+ let mut file_descriptor_delete = staged_file_descriptor_row("file-a", "branch-a");
3467
3448
  file_descriptor_delete.snapshot = None;
3468
3449
  let staged_writes = PreparedWriteSet {
3469
3450
  state_rows: vec![
3470
3451
  file_descriptor_delete,
3471
3452
  unique_row("post-1", "hello-world", "first"),
3472
3453
  ],
3473
- adopted_rows: Vec::new(),
3474
3454
  ..empty_staged_write_set()
3475
3455
  };
3476
3456
 
@@ -3492,11 +3472,10 @@ mod tests {
3492
3472
  let visible_schemas = vec![unique_schema()];
3493
3473
  let staged_writes = PreparedWriteSet {
3494
3474
  state_rows: vec![unique_row("post-1", "hello-world", "first")],
3495
- adopted_rows: Vec::new(),
3496
3475
  ..empty_staged_write_set()
3497
3476
  };
3498
3477
  let live_state = StaticLiveStateReader {
3499
- rows: vec![committed_file_descriptor_row("file-a", "version-a")],
3478
+ rows: vec![committed_file_descriptor_row("file-a", "branch-a")],
3500
3479
  };
3501
3480
 
3502
3481
  validate_prepared_writes(TransactionValidationInput::from_visible_schemas_for_tests(
@@ -3513,10 +3492,9 @@ mod tests {
3513
3492
  let visible_schemas = vec![unique_schema()];
3514
3493
  let staged_writes = PreparedWriteSet {
3515
3494
  state_rows: vec![unique_row("post-1", "hello-world", "first")],
3516
- adopted_rows: Vec::new(),
3517
3495
  ..empty_staged_write_set()
3518
3496
  };
3519
- let mut untracked_file_descriptor = committed_file_descriptor_row("file-a", "version-a");
3497
+ let mut untracked_file_descriptor = committed_file_descriptor_row("file-a", "branch-a");
3520
3498
  mark_live_row_untracked(&mut untracked_file_descriptor);
3521
3499
  let live_state = StrictStaticLiveStateReader {
3522
3500
  rows: vec![untracked_file_descriptor],
@@ -3542,11 +3520,10 @@ mod tests {
3542
3520
  mark_prepared_row_untracked(&mut untracked_row);
3543
3521
  let staged_writes = PreparedWriteSet {
3544
3522
  state_rows: vec![untracked_row],
3545
- adopted_rows: Vec::new(),
3546
3523
  ..empty_staged_write_set()
3547
3524
  };
3548
3525
  let live_state = StrictStaticLiveStateReader {
3549
- rows: vec![committed_file_descriptor_row("file-a", "version-a")],
3526
+ rows: vec![committed_file_descriptor_row("file-a", "branch-a")],
3550
3527
  };
3551
3528
 
3552
3529
  validate_prepared_writes(TransactionValidationInput::from_visible_schemas_for_tests(
@@ -3563,11 +3540,10 @@ mod tests {
3563
3540
  let visible_schemas = vec![unique_schema()];
3564
3541
  let staged_writes = PreparedWriteSet {
3565
3542
  state_rows: vec![unique_row("post-1", "hello-world", "first")],
3566
- adopted_rows: Vec::new(),
3567
3543
  ..empty_staged_write_set()
3568
3544
  };
3569
- let tracked_file_descriptor = committed_file_descriptor_row("file-a", "version-a");
3570
- let mut untracked_tombstone = committed_file_descriptor_row("file-a", "version-a");
3545
+ let tracked_file_descriptor = committed_file_descriptor_row("file-a", "branch-a");
3546
+ let mut untracked_tombstone = committed_file_descriptor_row("file-a", "branch-a");
3571
3547
  untracked_tombstone.snapshot_content = None;
3572
3548
  mark_live_row_untracked(&mut untracked_tombstone);
3573
3549
  let live_state = OverlayingStaticLiveStateReader {
@@ -3590,11 +3566,10 @@ mod tests {
3590
3566
  file_descriptor_schema(),
3591
3567
  directory_descriptor_schema(),
3592
3568
  ];
3593
- let mut file_descriptor_delete = staged_file_descriptor_row("file-a", "version-a");
3569
+ let mut file_descriptor_delete = staged_file_descriptor_row("file-a", "branch-a");
3594
3570
  file_descriptor_delete.snapshot = None;
3595
3571
  let staged_writes = PreparedWriteSet {
3596
3572
  state_rows: vec![file_descriptor_delete],
3597
- adopted_rows: Vec::new(),
3598
3573
  ..empty_staged_write_set()
3599
3574
  };
3600
3575
  let live_state = StaticLiveStateReader {
@@ -3621,11 +3596,10 @@ mod tests {
3621
3596
  file_descriptor_schema(),
3622
3597
  directory_descriptor_schema(),
3623
3598
  ];
3624
- let mut file_descriptor_delete = staged_file_descriptor_row("file-a", "version-a");
3599
+ let mut file_descriptor_delete = staged_file_descriptor_row("file-a", "branch-a");
3625
3600
  file_descriptor_delete.snapshot = None;
3626
3601
  let staged_writes = PreparedWriteSet {
3627
3602
  state_rows: vec![file_descriptor_delete],
3628
- adopted_rows: Vec::new(),
3629
3603
  ..empty_staged_write_set()
3630
3604
  };
3631
3605
  let mut untracked_row =
@@ -3633,7 +3607,7 @@ mod tests {
3633
3607
  mark_live_row_untracked(&mut untracked_row);
3634
3608
  let live_state = StrictStaticLiveStateReader {
3635
3609
  rows: vec![
3636
- committed_file_descriptor_row("file-a", "version-a"),
3610
+ committed_file_descriptor_row("file-a", "branch-a"),
3637
3611
  untracked_row,
3638
3612
  ],
3639
3613
  };
@@ -3653,9 +3627,9 @@ mod tests {
3653
3627
  #[tokio::test]
3654
3628
  async fn validation_allows_untracked_directory_parent_to_tracked_directory() {
3655
3629
  let visible_schemas = vec![directory_descriptor_schema()];
3656
- let tracked_parent = directory_descriptor_row("dir-parent", None, "parent", "version-a");
3630
+ let tracked_parent = directory_descriptor_row("dir-parent", None, "parent", "branch-a");
3657
3631
  let mut untracked_child =
3658
- directory_descriptor_row("dir-child", Some("dir-parent"), "child", "version-a");
3632
+ directory_descriptor_row("dir-child", Some("dir-parent"), "child", "branch-a");
3659
3633
  mark_prepared_row_untracked(&mut untracked_child);
3660
3634
  let staged_writes = PreparedWriteSet {
3661
3635
  state_rows: vec![tracked_parent, untracked_child],
@@ -3672,13 +3646,12 @@ mod tests {
3672
3646
  let visible_schemas = vec![unique_schema()];
3673
3647
  let staged_writes = PreparedWriteSet {
3674
3648
  state_rows: vec![unique_row("post-1", "hello-world", "first")],
3675
- adopted_rows: Vec::new(),
3676
3649
  ..empty_staged_write_set()
3677
3650
  };
3678
3651
  let live_state = StrictStaticLiveStateReader {
3679
3652
  rows: vec![committed_file_descriptor_row(
3680
3653
  "file-a",
3681
- crate::GLOBAL_VERSION_ID,
3654
+ crate::GLOBAL_BRANCH_ID,
3682
3655
  )],
3683
3656
  };
3684
3657
 
@@ -3689,7 +3662,7 @@ mod tests {
3689
3662
  &live_state,
3690
3663
  ))
3691
3664
  .await
3692
- .expect_err("global file descriptor should not satisfy a version-local row");
3665
+ .expect_err("global file descriptor should not satisfy a branch-local row");
3693
3666
 
3694
3667
  assert_eq!(error.code, LixError::CODE_FILE_NOT_FOUND);
3695
3668
  }
@@ -3698,10 +3671,9 @@ mod tests {
3698
3671
  async fn validation_rejects_primary_key_duplicate_with_different_identity() {
3699
3672
  let visible_schemas = vec![unique_schema()];
3700
3673
  let mut conflicting = unique_row("post-1", "hello-world", "first");
3701
- conflicting.entity_id = crate::entity_identity::EntityIdentity::single("post-2");
3674
+ conflicting.entity_pk = crate::entity_pk::EntityPk::single("post-2");
3702
3675
  let staged_writes = PreparedWriteSet {
3703
3676
  state_rows: vec![unique_row("post-1", "hello-world", "first"), conflicting],
3704
- adopted_rows: Vec::new(),
3705
3677
  ..empty_staged_write_set()
3706
3678
  };
3707
3679
 
@@ -3749,37 +3721,35 @@ mod tests {
3749
3721
  }
3750
3722
 
3751
3723
  #[tokio::test]
3752
- async fn validation_rejects_pending_unique_same_value_in_same_version() {
3724
+ async fn validation_rejects_pending_unique_same_value_in_same_branch() {
3753
3725
  let visible_schemas = vec![unique_schema()];
3754
3726
  let mut duplicate = unique_row("post-2", "hello-world", "second");
3755
- duplicate.version_id = "version-a".to_string();
3727
+ duplicate.branch_id = "branch-a".to_string();
3756
3728
  let staged_writes = PreparedWriteSet {
3757
3729
  state_rows: vec![unique_row("post-1", "hello-world", "first"), duplicate],
3758
- adopted_rows: Vec::new(),
3759
3730
  ..empty_staged_write_set()
3760
3731
  };
3761
3732
 
3762
3733
  let error = validate_prepared_writes(validation_input(&staged_writes, &visible_schemas))
3763
3734
  .await
3764
- .expect_err("same unique value in the same version should fail");
3735
+ .expect_err("same unique value in the same branch should fail");
3765
3736
 
3766
3737
  assert_eq!(error.code, LixError::CODE_UNIQUE);
3767
3738
  }
3768
3739
 
3769
3740
  #[tokio::test]
3770
- async fn validation_allows_pending_unique_same_value_in_different_versions() {
3741
+ async fn validation_allows_pending_unique_same_value_in_different_branches() {
3771
3742
  let visible_schemas = vec![unique_schema()];
3772
- let mut version_b = unique_row("post-2", "hello-world", "second");
3773
- version_b.version_id = "version-b".to_string();
3743
+ let mut branch_b = unique_row("post-2", "hello-world", "second");
3744
+ branch_b.branch_id = "branch-b".to_string();
3774
3745
  let staged_writes = PreparedWriteSet {
3775
- state_rows: vec![unique_row("post-1", "hello-world", "first"), version_b],
3776
- adopted_rows: Vec::new(),
3746
+ state_rows: vec![unique_row("post-1", "hello-world", "first"), branch_b],
3777
3747
  ..empty_staged_write_set()
3778
3748
  };
3779
3749
 
3780
3750
  validate_prepared_writes(validation_input(&staged_writes, &visible_schemas))
3781
3751
  .await
3782
- .expect("unique values should be scoped to the exact version_id");
3752
+ .expect("unique values should be scoped to the exact branch_id");
3783
3753
  }
3784
3754
 
3785
3755
  #[tokio::test]
@@ -3805,7 +3775,6 @@ mod tests {
3805
3775
  tombstone.snapshot = None;
3806
3776
  let staged_writes = PreparedWriteSet {
3807
3777
  state_rows: vec![tombstone, unique_row("post-2", "hello-world", "second")],
3808
- adopted_rows: Vec::new(),
3809
3778
  ..empty_staged_write_set()
3810
3779
  };
3811
3780
 
@@ -3815,24 +3784,24 @@ mod tests {
3815
3784
  }
3816
3785
 
3817
3786
  #[tokio::test]
3818
- async fn validation_scopes_pending_unique_values_by_file_and_version() {
3787
+ async fn validation_scopes_pending_unique_values_by_file_and_branch() {
3819
3788
  let visible_schemas = vec![unique_schema()];
3820
3789
  let mut different_file = unique_row("post-2", "hello-world", "second");
3821
3790
  different_file.file_id = Some("file-b".to_string());
3822
- let mut different_version = unique_row("post-3", "hello-world", "third");
3823
- different_version.version_id = "version-b".to_string();
3791
+ let mut different_branch = unique_row("post-3", "hello-world", "third");
3792
+ different_branch.branch_id = "branch-b".to_string();
3824
3793
  let staged_writes = PreparedWriteSet {
3825
3794
  state_rows: vec![
3826
3795
  unique_row("post-1", "hello-world", "first"),
3827
3796
  different_file,
3828
- different_version,
3797
+ different_branch,
3829
3798
  ],
3830
3799
  ..empty_staged_write_set()
3831
3800
  };
3832
3801
 
3833
3802
  validate_prepared_writes(validation_input(&staged_writes, &visible_schemas))
3834
3803
  .await
3835
- .expect("unique values are scoped by file and version");
3804
+ .expect("unique values are scoped by file and branch");
3836
3805
  }
3837
3806
 
3838
3807
  #[tokio::test]
@@ -3840,7 +3809,6 @@ mod tests {
3840
3809
  let visible_schemas = vec![unique_schema()];
3841
3810
  let staged_writes = PreparedWriteSet {
3842
3811
  state_rows: vec![unique_row("post-2", "hello-world", "second")],
3843
- adopted_rows: Vec::new(),
3844
3812
  ..empty_staged_write_set()
3845
3813
  };
3846
3814
  let live_state = StaticLiveStateReader {
@@ -3864,7 +3832,6 @@ mod tests {
3864
3832
  let visible_schemas = vec![unique_schema()];
3865
3833
  let staged_writes = PreparedWriteSet {
3866
3834
  state_rows: vec![unique_row("post-2", "hello-world", "second")],
3867
- adopted_rows: Vec::new(),
3868
3835
  ..empty_staged_write_set()
3869
3836
  };
3870
3837
  let tracked_duplicate = committed_unique_row("post-1", "hello-world", "first");
@@ -3898,7 +3865,6 @@ mod tests {
3898
3865
  untracked_tombstone,
3899
3866
  unique_row("post-2", "hello-world", "second"),
3900
3867
  ],
3901
- adopted_rows: Vec::new(),
3902
3868
  ..empty_staged_write_set()
3903
3869
  };
3904
3870
  let live_state = StaticLiveStateReader {
@@ -3922,7 +3888,6 @@ mod tests {
3922
3888
  let visible_schemas = vec![nullable_unique_schema()];
3923
3889
  let staged_writes = PreparedWriteSet {
3924
3890
  state_rows: vec![nullable_unique_row("row-2", None, "root-name")],
3925
- adopted_rows: Vec::new(),
3926
3891
  ..empty_staged_write_set()
3927
3892
  };
3928
3893
  let live_state = StaticLiveStateReader {
@@ -3942,11 +3907,10 @@ mod tests {
3942
3907
  }
3943
3908
 
3944
3909
  #[tokio::test]
3945
- async fn validation_rejects_committed_unique_same_value_in_same_version() {
3910
+ async fn validation_rejects_committed_unique_same_value_in_same_branch() {
3946
3911
  let visible_schemas = vec![unique_schema()];
3947
3912
  let staged_writes = PreparedWriteSet {
3948
3913
  state_rows: vec![unique_row("post-2", "hello-world", "second")],
3949
- adopted_rows: Vec::new(),
3950
3914
  ..empty_staged_write_set()
3951
3915
  };
3952
3916
  let live_state = StaticLiveStateReader {
@@ -3960,19 +3924,18 @@ mod tests {
3960
3924
  &live_state,
3961
3925
  ))
3962
3926
  .await
3963
- .expect_err("same unique value in the same version should conflict");
3927
+ .expect_err("same unique value in the same branch should conflict");
3964
3928
 
3965
3929
  assert_eq!(error.code, LixError::CODE_UNIQUE);
3966
3930
  }
3967
3931
 
3968
3932
  #[tokio::test]
3969
- async fn validation_allows_committed_unique_same_value_in_different_versions() {
3933
+ async fn validation_allows_committed_unique_same_value_in_different_branches() {
3970
3934
  let visible_schemas = vec![unique_schema()];
3971
- let mut version_b = unique_row("post-2", "hello-world", "second");
3972
- version_b.version_id = "version-b".to_string();
3935
+ let mut branch_b = unique_row("post-2", "hello-world", "second");
3936
+ branch_b.branch_id = "branch-b".to_string();
3973
3937
  let staged_writes = PreparedWriteSet {
3974
- state_rows: vec![version_b],
3975
- adopted_rows: Vec::new(),
3938
+ state_rows: vec![branch_b],
3976
3939
  ..empty_staged_write_set()
3977
3940
  };
3978
3941
  let live_state = StaticLiveStateReader {
@@ -3985,7 +3948,7 @@ mod tests {
3985
3948
  &live_state,
3986
3949
  ))
3987
3950
  .await
3988
- .expect("committed unique values should be scoped to the exact version_id");
3951
+ .expect("committed unique values should be scoped to the exact branch_id");
3989
3952
  }
3990
3953
 
3991
3954
  #[tokio::test]
@@ -3993,11 +3956,10 @@ mod tests {
3993
3956
  let visible_schemas = vec![unique_schema()];
3994
3957
  let staged_writes = PreparedWriteSet {
3995
3958
  state_rows: vec![unique_row("post-2", "hello-world", "second")],
3996
- adopted_rows: Vec::new(),
3997
3959
  ..empty_staged_write_set()
3998
3960
  };
3999
3961
  let mut projected_overlay_row = committed_unique_row("post-1", "hello-world", "first");
4000
- projected_overlay_row.version_id = "version-a".to_string();
3962
+ projected_overlay_row.branch_id = "branch-a".to_string();
4001
3963
  projected_overlay_row.global = true;
4002
3964
  let live_state = StaticLiveStateReader {
4003
3965
  rows: vec![projected_overlay_row],
@@ -4017,7 +3979,6 @@ mod tests {
4017
3979
  let visible_schemas = vec![unique_schema()];
4018
3980
  let staged_writes = PreparedWriteSet {
4019
3981
  state_rows: vec![unique_row("post-1", "hello-world", "updated")],
4020
- adopted_rows: Vec::new(),
4021
3982
  ..empty_staged_write_set()
4022
3983
  };
4023
3984
  let live_state = StaticLiveStateReader {
@@ -4046,7 +4007,6 @@ mod tests {
4046
4007
  committed_two.file_id = None;
4047
4008
  let staged_writes = PreparedWriteSet {
4048
4009
  state_rows: vec![staged_one, staged_two],
4049
- adopted_rows: Vec::new(),
4050
4010
  ..empty_staged_write_set()
4051
4011
  };
4052
4012
  let live_state = CountingStaticLiveStateReader {
@@ -4072,7 +4032,6 @@ mod tests {
4072
4032
  tombstone.snapshot = None;
4073
4033
  let staged_writes = PreparedWriteSet {
4074
4034
  state_rows: vec![tombstone, unique_row("post-2", "hello-world", "second")],
4075
- adopted_rows: Vec::new(),
4076
4035
  ..empty_staged_write_set()
4077
4036
  };
4078
4037
  let live_state = StaticLiveStateReader {
@@ -4089,15 +4048,14 @@ mod tests {
4089
4048
  }
4090
4049
 
4091
4050
  #[tokio::test]
4092
- async fn validation_allows_committed_unique_same_value_in_different_file_or_version() {
4051
+ async fn validation_allows_committed_unique_same_value_in_different_file_or_branch() {
4093
4052
  let visible_schemas = vec![unique_schema()];
4094
4053
  let mut different_file = unique_row("post-2", "hello-world", "second");
4095
4054
  different_file.file_id = Some("file-b".to_string());
4096
- let mut different_version = unique_row("post-3", "hello-world", "third");
4097
- different_version.version_id = "version-b".to_string();
4055
+ let mut different_branch = unique_row("post-3", "hello-world", "third");
4056
+ different_branch.branch_id = "branch-b".to_string();
4098
4057
  let staged_writes = PreparedWriteSet {
4099
- state_rows: vec![different_file, different_version],
4100
- adopted_rows: Vec::new(),
4058
+ state_rows: vec![different_file, different_branch],
4101
4059
  ..empty_staged_write_set()
4102
4060
  };
4103
4061
  let live_state = StaticLiveStateReader {
@@ -4110,39 +4068,38 @@ mod tests {
4110
4068
  &live_state,
4111
4069
  ))
4112
4070
  .await
4113
- .expect("committed uniqueness is scoped by file and version");
4071
+ .expect("committed uniqueness is scoped by file and branch");
4114
4072
  }
4115
4073
 
4116
4074
  #[tokio::test]
4117
- async fn validation_rejects_foreign_key_target_missing_in_same_version() {
4075
+ async fn validation_rejects_foreign_key_target_missing_in_same_branch() {
4118
4076
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4119
4077
  let staged_writes = PreparedWriteSet {
4120
- state_rows: vec![fk_child_row("child-1", "parent-1", "version-a")],
4121
- adopted_rows: Vec::new(),
4078
+ state_rows: vec![fk_child_row("child-1", "parent-1", "branch-a")],
4122
4079
  ..empty_staged_write_set()
4123
4080
  };
4124
4081
 
4125
4082
  let error = validate_prepared_writes(validation_input(&staged_writes, &visible_schemas))
4126
4083
  .await
4127
- .expect_err("foreign key must resolve in the same version");
4084
+ .expect_err("foreign key must resolve in the same branch");
4128
4085
 
4129
4086
  assert_eq!(error.code, LixError::CODE_FOREIGN_KEY);
4130
4087
  }
4131
4088
 
4132
4089
  #[tokio::test]
4133
- async fn validation_allows_foreign_key_target_in_same_version() {
4090
+ async fn validation_allows_foreign_key_target_in_same_branch() {
4134
4091
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4135
4092
  let staged_writes = PreparedWriteSet {
4136
4093
  state_rows: vec![
4137
- fk_parent_row("parent-1", "version-a"),
4138
- fk_child_row("child-1", "parent-1", "version-a"),
4094
+ fk_parent_row("parent-1", "branch-a"),
4095
+ fk_child_row("child-1", "parent-1", "branch-a"),
4139
4096
  ],
4140
4097
  ..empty_staged_write_set()
4141
4098
  };
4142
4099
 
4143
4100
  validate_prepared_writes(validation_input(&staged_writes, &visible_schemas))
4144
4101
  .await
4145
- .expect("foreign key should resolve against pending rows in the same version");
4102
+ .expect("foreign key should resolve against pending rows in the same branch");
4146
4103
  }
4147
4104
 
4148
4105
  #[tokio::test]
@@ -4153,15 +4110,15 @@ mod tests {
4153
4110
  file_descriptor_schema(),
4154
4111
  directory_descriptor_schema(),
4155
4112
  ];
4156
- let mut untracked_parent = fk_parent_row("parent-1", "version-a");
4113
+ let mut untracked_parent = fk_parent_row("parent-1", "branch-a");
4157
4114
  mark_prepared_row_untracked(&mut untracked_parent);
4158
- let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "version-a");
4115
+ let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "branch-a");
4159
4116
  mark_prepared_row_untracked(&mut untracked_file_descriptor);
4160
4117
  let staged_writes = PreparedWriteSet {
4161
4118
  state_rows: vec![
4162
4119
  untracked_file_descriptor,
4163
4120
  untracked_parent,
4164
- fk_child_row("child-1", "parent-1", "version-a"),
4121
+ fk_child_row("child-1", "parent-1", "branch-a"),
4165
4122
  ],
4166
4123
  ..empty_staged_write_set()
4167
4124
  };
@@ -4181,11 +4138,11 @@ mod tests {
4181
4138
  file_descriptor_schema(),
4182
4139
  directory_descriptor_schema(),
4183
4140
  ];
4184
- let tracked_file_descriptor = staged_file_descriptor_row("file-a", "version-a");
4185
- let tracked_parent = fk_parent_row("parent-1", "version-a");
4186
- let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "version-a");
4141
+ let tracked_file_descriptor = staged_file_descriptor_row("file-a", "branch-a");
4142
+ let tracked_parent = fk_parent_row("parent-1", "branch-a");
4143
+ let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "branch-a");
4187
4144
  mark_prepared_row_untracked(&mut untracked_file_descriptor);
4188
- let mut untracked_child = fk_child_row("child-1", "parent-1", "version-a");
4145
+ let mut untracked_child = fk_child_row("child-1", "parent-1", "branch-a");
4189
4146
  mark_prepared_row_untracked(&mut untracked_child);
4190
4147
  let staged_writes = PreparedWriteSet {
4191
4148
  state_rows: vec![
@@ -4203,35 +4160,33 @@ mod tests {
4203
4160
  }
4204
4161
 
4205
4162
  #[tokio::test]
4206
- async fn validation_rejects_foreign_key_target_that_exists_only_in_different_version() {
4163
+ async fn validation_rejects_foreign_key_target_that_exists_only_in_different_branch() {
4207
4164
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4208
4165
  let staged_writes = PreparedWriteSet {
4209
4166
  state_rows: vec![
4210
- fk_parent_row("parent-1", "version-b"),
4211
- fk_child_row("child-1", "parent-1", "version-a"),
4167
+ fk_parent_row("parent-1", "branch-b"),
4168
+ fk_child_row("child-1", "parent-1", "branch-a"),
4212
4169
  ],
4213
4170
  ..empty_staged_write_set()
4214
4171
  };
4215
4172
 
4216
4173
  let error = validate_prepared_writes(validation_input(&staged_writes, &visible_schemas))
4217
4174
  .await
4218
- .expect_err("foreign key target in another version should not satisfy this version");
4175
+ .expect_err("foreign key target in another branch should not satisfy this branch");
4219
4176
 
4220
4177
  assert_eq!(error.code, LixError::CODE_FOREIGN_KEY);
4221
4178
  }
4222
4179
 
4223
4180
  #[tokio::test]
4224
- async fn validation_allows_foreign_key_target_committed_in_same_version() {
4181
+ async fn validation_allows_foreign_key_target_committed_in_same_branch() {
4225
4182
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4226
4183
  let staged_writes = PreparedWriteSet {
4227
- state_rows: vec![fk_child_row("child-1", "parent-1", "version-a")],
4228
- adopted_rows: Vec::new(),
4184
+ state_rows: vec![fk_child_row("child-1", "parent-1", "branch-a")],
4229
4185
  ..empty_staged_write_set()
4230
4186
  };
4231
4187
  let live_state = StaticLiveStateReader {
4232
4188
  rows: vec![MaterializedLiveStateRow::from(fk_parent_row(
4233
- "parent-1",
4234
- "version-a",
4189
+ "parent-1", "branch-a",
4235
4190
  ))],
4236
4191
  };
4237
4192
 
@@ -4241,19 +4196,18 @@ mod tests {
4241
4196
  &live_state,
4242
4197
  ))
4243
4198
  .await
4244
- .expect("foreign key should resolve against committed rows in the same version");
4199
+ .expect("foreign key should resolve against committed rows in the same branch");
4245
4200
  }
4246
4201
 
4247
4202
  #[tokio::test]
4248
4203
  async fn validation_rejects_tracked_foreign_key_target_committed_only_as_untracked() {
4249
4204
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4250
4205
  let staged_writes = PreparedWriteSet {
4251
- state_rows: vec![fk_child_row("child-1", "parent-1", "version-a")],
4252
- adopted_rows: Vec::new(),
4206
+ state_rows: vec![fk_child_row("child-1", "parent-1", "branch-a")],
4253
4207
  ..empty_staged_write_set()
4254
4208
  };
4255
4209
  let mut untracked_parent =
4256
- MaterializedLiveStateRow::from(fk_parent_row("parent-1", "version-a"));
4210
+ MaterializedLiveStateRow::from(fk_parent_row("parent-1", "branch-a"));
4257
4211
  mark_live_row_untracked(&mut untracked_parent);
4258
4212
  let live_state = StaticLiveStateReader {
4259
4213
  rows: vec![untracked_parent],
@@ -4279,19 +4233,18 @@ mod tests {
4279
4233
  file_descriptor_schema(),
4280
4234
  directory_descriptor_schema(),
4281
4235
  ];
4282
- let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "version-a");
4236
+ let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "branch-a");
4283
4237
  mark_prepared_row_untracked(&mut untracked_file_descriptor);
4284
- let mut untracked_child = fk_child_row("child-1", "parent-1", "version-a");
4238
+ let mut untracked_child = fk_child_row("child-1", "parent-1", "branch-a");
4285
4239
  mark_prepared_row_untracked(&mut untracked_child);
4286
4240
  let staged_writes = PreparedWriteSet {
4287
4241
  state_rows: vec![untracked_file_descriptor, untracked_child],
4288
- adopted_rows: Vec::new(),
4289
4242
  ..empty_staged_write_set()
4290
4243
  };
4291
4244
  let live_state = StaticLiveStateReader {
4292
4245
  rows: vec![
4293
- committed_file_descriptor_row("file-a", "version-a"),
4294
- MaterializedLiveStateRow::from(fk_parent_row("parent-1", "version-a")),
4246
+ committed_file_descriptor_row("file-a", "branch-a"),
4247
+ MaterializedLiveStateRow::from(fk_parent_row("parent-1", "branch-a")),
4295
4248
  ],
4296
4249
  };
4297
4250
 
@@ -4308,13 +4261,12 @@ mod tests {
4308
4261
  async fn validation_allows_tracked_foreign_key_target_committed_behind_untracked_overlay() {
4309
4262
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4310
4263
  let staged_writes = PreparedWriteSet {
4311
- state_rows: vec![fk_child_row("child-1", "parent-1", "version-a")],
4312
- adopted_rows: Vec::new(),
4264
+ state_rows: vec![fk_child_row("child-1", "parent-1", "branch-a")],
4313
4265
  ..empty_staged_write_set()
4314
4266
  };
4315
- let tracked_parent = MaterializedLiveStateRow::from(fk_parent_row("parent-1", "version-a"));
4267
+ let tracked_parent = MaterializedLiveStateRow::from(fk_parent_row("parent-1", "branch-a"));
4316
4268
  let mut untracked_overlay =
4317
- MaterializedLiveStateRow::from(fk_parent_row("parent-1", "version-a"));
4269
+ MaterializedLiveStateRow::from(fk_parent_row("parent-1", "branch-a"));
4318
4270
  mark_live_row_untracked(&mut untracked_overlay);
4319
4271
  let live_state = OverlayingStaticLiveStateReader {
4320
4272
  rows: vec![tracked_parent, untracked_overlay],
@@ -4334,18 +4286,17 @@ mod tests {
4334
4286
  #[tokio::test]
4335
4287
  async fn validation_rejects_deleting_tracked_fk_target_referenced_behind_untracked_overlay() {
4336
4288
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4337
- let mut parent_delete = fk_parent_row("parent-1", "version-a");
4289
+ let mut parent_delete = fk_parent_row("parent-1", "branch-a");
4338
4290
  parent_delete.snapshot = None;
4339
4291
  let staged_writes = PreparedWriteSet {
4340
4292
  state_rows: vec![parent_delete],
4341
- adopted_rows: Vec::new(),
4342
4293
  ..empty_staged_write_set()
4343
4294
  };
4344
- let tracked_parent = MaterializedLiveStateRow::from(fk_parent_row("parent-1", "version-a"));
4295
+ let tracked_parent = MaterializedLiveStateRow::from(fk_parent_row("parent-1", "branch-a"));
4345
4296
  let tracked_child =
4346
- MaterializedLiveStateRow::from(fk_child_row("child-1", "parent-1", "version-a"));
4297
+ MaterializedLiveStateRow::from(fk_child_row("child-1", "parent-1", "branch-a"));
4347
4298
  let mut untracked_child_overlay =
4348
- MaterializedLiveStateRow::from(fk_child_row("child-1", "other-parent", "version-a"));
4299
+ MaterializedLiveStateRow::from(fk_child_row("child-1", "other-parent", "branch-a"));
4349
4300
  mark_live_row_untracked(&mut untracked_child_overlay);
4350
4301
  let live_state = OverlayingStaticLiveStateReader {
4351
4302
  rows: vec![tracked_parent, tracked_child, untracked_child_overlay],
@@ -4366,16 +4317,15 @@ mod tests {
4366
4317
  #[tokio::test]
4367
4318
  async fn validation_rejects_deleting_tracked_fk_target_referenced_by_committed_untracked_row() {
4368
4319
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4369
- let mut parent_delete = fk_parent_row("parent-1", "version-a");
4320
+ let mut parent_delete = fk_parent_row("parent-1", "branch-a");
4370
4321
  parent_delete.snapshot = None;
4371
4322
  let staged_writes = PreparedWriteSet {
4372
4323
  state_rows: vec![parent_delete],
4373
- adopted_rows: Vec::new(),
4374
4324
  ..empty_staged_write_set()
4375
4325
  };
4376
- let tracked_parent = MaterializedLiveStateRow::from(fk_parent_row("parent-1", "version-a"));
4326
+ let tracked_parent = MaterializedLiveStateRow::from(fk_parent_row("parent-1", "branch-a"));
4377
4327
  let mut untracked_child =
4378
- MaterializedLiveStateRow::from(fk_child_row("child-1", "parent-1", "version-a"));
4328
+ MaterializedLiveStateRow::from(fk_child_row("child-1", "parent-1", "branch-a"));
4379
4329
  mark_live_row_untracked(&mut untracked_child);
4380
4330
  let live_state = StaticLiveStateReader {
4381
4331
  rows: vec![tracked_parent, untracked_child],
@@ -4394,17 +4344,15 @@ mod tests {
4394
4344
  }
4395
4345
 
4396
4346
  #[tokio::test]
4397
- async fn validation_rejects_foreign_key_target_committed_only_in_different_version() {
4347
+ async fn validation_rejects_foreign_key_target_committed_only_in_different_branch() {
4398
4348
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4399
4349
  let staged_writes = PreparedWriteSet {
4400
- state_rows: vec![fk_child_row("child-1", "parent-1", "version-a")],
4401
- adopted_rows: Vec::new(),
4350
+ state_rows: vec![fk_child_row("child-1", "parent-1", "branch-a")],
4402
4351
  ..empty_staged_write_set()
4403
4352
  };
4404
4353
  let live_state = StaticLiveStateReader {
4405
4354
  rows: vec![MaterializedLiveStateRow::from(fk_parent_row(
4406
- "parent-1",
4407
- "version-b",
4355
+ "parent-1", "branch-b",
4408
4356
  ))],
4409
4357
  };
4410
4358
 
@@ -4416,7 +4364,7 @@ mod tests {
4416
4364
  ))
4417
4365
  .await
4418
4366
  .expect_err(
4419
- "foreign key target in another committed version should not satisfy this version",
4367
+ "foreign key target in another committed branch should not satisfy this branch",
4420
4368
  );
4421
4369
 
4422
4370
  assert_eq!(error.code, LixError::CODE_FOREIGN_KEY);
@@ -4425,19 +4373,18 @@ mod tests {
4425
4373
  #[tokio::test]
4426
4374
  async fn validation_rejects_foreign_key_target_tombstoned_by_transaction() {
4427
4375
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4428
- let mut parent_delete = fk_parent_row("parent-1", "version-a");
4376
+ let mut parent_delete = fk_parent_row("parent-1", "branch-a");
4429
4377
  parent_delete.snapshot = None;
4430
4378
  let staged_writes = PreparedWriteSet {
4431
4379
  state_rows: vec![
4432
4380
  parent_delete,
4433
- fk_child_row("child-1", "parent-1", "version-a"),
4381
+ fk_child_row("child-1", "parent-1", "branch-a"),
4434
4382
  ],
4435
4383
  ..empty_staged_write_set()
4436
4384
  };
4437
4385
  let live_state = StaticLiveStateReader {
4438
4386
  rows: vec![MaterializedLiveStateRow::from(fk_parent_row(
4439
- "parent-1",
4440
- "version-a",
4387
+ "parent-1", "branch-a",
4441
4388
  ))],
4442
4389
  };
4443
4390
 
@@ -4456,21 +4403,19 @@ mod tests {
4456
4403
  #[tokio::test]
4457
4404
  async fn validation_allows_tracked_fk_target_when_untracked_tombstone_shadows_same_identity() {
4458
4405
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4459
- let mut untracked_parent_delete = fk_parent_row("parent-1", "version-a");
4406
+ let mut untracked_parent_delete = fk_parent_row("parent-1", "branch-a");
4460
4407
  untracked_parent_delete.snapshot = None;
4461
4408
  mark_prepared_row_untracked(&mut untracked_parent_delete);
4462
4409
  let staged_writes = PreparedWriteSet {
4463
4410
  state_rows: vec![
4464
4411
  untracked_parent_delete,
4465
- fk_child_row("child-1", "parent-1", "version-a"),
4412
+ fk_child_row("child-1", "parent-1", "branch-a"),
4466
4413
  ],
4467
- adopted_rows: Vec::new(),
4468
4414
  ..empty_staged_write_set()
4469
4415
  };
4470
4416
  let live_state = StaticLiveStateReader {
4471
4417
  rows: vec![MaterializedLiveStateRow::from(fk_parent_row(
4472
- "parent-1",
4473
- "version-a",
4418
+ "parent-1", "branch-a",
4474
4419
  ))],
4475
4420
  };
4476
4421
 
@@ -4486,19 +4431,18 @@ mod tests {
4486
4431
  #[tokio::test]
4487
4432
  async fn validation_rejects_pending_reference_to_deleted_identity() {
4488
4433
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4489
- let mut parent_delete = fk_parent_row("parent-1", "version-a");
4434
+ let mut parent_delete = fk_parent_row("parent-1", "branch-a");
4490
4435
  parent_delete.snapshot = None;
4491
4436
  let staged_writes = PreparedWriteSet {
4492
4437
  state_rows: vec![
4493
4438
  parent_delete,
4494
- fk_child_row("child-1", "parent-1", "version-a"),
4439
+ fk_child_row("child-1", "parent-1", "branch-a"),
4495
4440
  ],
4496
4441
  ..empty_staged_write_set()
4497
4442
  };
4498
4443
  let live_state = StaticLiveStateReader {
4499
4444
  rows: vec![MaterializedLiveStateRow::from(fk_parent_row(
4500
- "parent-1",
4501
- "version-a",
4445
+ "parent-1", "branch-a",
4502
4446
  ))],
4503
4447
  };
4504
4448
 
@@ -4515,22 +4459,22 @@ mod tests {
4515
4459
  }
4516
4460
 
4517
4461
  #[tokio::test]
4518
- async fn validation_allows_delete_with_pending_reference_in_different_version() {
4462
+ async fn validation_allows_delete_with_pending_reference_in_different_branch() {
4519
4463
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4520
- let mut parent_delete = fk_parent_row("parent-1", "version-a");
4464
+ let mut parent_delete = fk_parent_row("parent-1", "branch-a");
4521
4465
  parent_delete.snapshot = None;
4522
4466
  let staged_writes = PreparedWriteSet {
4523
4467
  state_rows: vec![
4524
4468
  parent_delete,
4525
- fk_parent_row("parent-1", "version-b"),
4526
- fk_child_row("child-1", "parent-1", "version-b"),
4469
+ fk_parent_row("parent-1", "branch-b"),
4470
+ fk_child_row("child-1", "parent-1", "branch-b"),
4527
4471
  ],
4528
4472
  ..empty_staged_write_set()
4529
4473
  };
4530
4474
 
4531
4475
  validate_prepared_writes(validation_input(&staged_writes, &visible_schemas))
4532
4476
  .await
4533
- .expect("pending references in another version should not block this delete");
4477
+ .expect("pending references in another branch should not block this delete");
4534
4478
  }
4535
4479
 
4536
4480
  #[tokio::test]
@@ -4547,8 +4491,7 @@ mod tests {
4547
4491
  };
4548
4492
  let live_state = StaticLiveStateReader {
4549
4493
  rows: vec![MaterializedLiveStateRow::from(fk_parent_row(
4550
- "target-1",
4551
- "version-a",
4494
+ "target-1", "branch-a",
4552
4495
  ))],
4553
4496
  };
4554
4497
 
@@ -4569,9 +4512,9 @@ mod tests {
4569
4512
  file_descriptor_schema(),
4570
4513
  directory_descriptor_schema(),
4571
4514
  ];
4572
- let mut untracked_target = fk_parent_row("target-1", "version-a");
4515
+ let mut untracked_target = fk_parent_row("target-1", "branch-a");
4573
4516
  mark_prepared_row_untracked(&mut untracked_target);
4574
- let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "version-a");
4517
+ let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "branch-a");
4575
4518
  mark_prepared_row_untracked(&mut untracked_file_descriptor);
4576
4519
  let staged_writes = PreparedWriteSet {
4577
4520
  state_rows: vec![
@@ -4604,7 +4547,7 @@ mod tests {
4604
4547
  ..empty_staged_write_set()
4605
4548
  };
4606
4549
  let mut untracked_target =
4607
- MaterializedLiveStateRow::from(fk_parent_row("target-1", "version-a"));
4550
+ MaterializedLiveStateRow::from(fk_parent_row("target-1", "branch-a"));
4608
4551
  mark_live_row_untracked(&mut untracked_target);
4609
4552
  let live_state = StaticLiveStateReader {
4610
4553
  rows: vec![untracked_target],
@@ -4632,7 +4575,7 @@ mod tests {
4632
4575
  file_descriptor_schema(),
4633
4576
  directory_descriptor_schema(),
4634
4577
  ];
4635
- let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "version-a");
4578
+ let mut untracked_file_descriptor = staged_file_descriptor_row("file-a", "branch-a");
4636
4579
  mark_prepared_row_untracked(&mut untracked_file_descriptor);
4637
4580
  let mut untracked_ref =
4638
4581
  state_surface_ref_row("ref-1", "target-1", "fk_parent_schema", "file-a");
@@ -4643,8 +4586,8 @@ mod tests {
4643
4586
  };
4644
4587
  let live_state = StaticLiveStateReader {
4645
4588
  rows: vec![
4646
- committed_file_descriptor_row("file-a", "version-a"),
4647
- MaterializedLiveStateRow::from(fk_parent_row("target-1", "version-a")),
4589
+ committed_file_descriptor_row("file-a", "branch-a"),
4590
+ MaterializedLiveStateRow::from(fk_parent_row("target-1", "branch-a")),
4648
4591
  ],
4649
4592
  };
4650
4593
 
@@ -4670,9 +4613,9 @@ mod tests {
4670
4613
  )],
4671
4614
  ..empty_staged_write_set()
4672
4615
  };
4673
- let tracked_target = MaterializedLiveStateRow::from(fk_parent_row("target-1", "version-a"));
4616
+ let tracked_target = MaterializedLiveStateRow::from(fk_parent_row("target-1", "branch-a"));
4674
4617
  let mut untracked_overlay =
4675
- MaterializedLiveStateRow::from(fk_parent_row("target-1", "version-a"));
4618
+ MaterializedLiveStateRow::from(fk_parent_row("target-1", "branch-a"));
4676
4619
  mark_live_row_untracked(&mut untracked_overlay);
4677
4620
  let live_state = OverlayingStaticLiveStateReader {
4678
4621
  rows: vec![tracked_target, untracked_overlay],
@@ -4690,10 +4633,10 @@ mod tests {
4690
4633
  }
4691
4634
 
4692
4635
  #[tokio::test]
4693
- async fn validation_allows_state_surface_fk_target_with_composite_entity_id() {
4636
+ async fn validation_allows_state_surface_fk_target_with_composite_entity_pk() {
4694
4637
  let visible_schemas = vec![composite_message_schema(), state_surface_ref_schema()];
4695
4638
  let staged_writes = PreparedWriteSet {
4696
- state_rows: vec![state_surface_ref_row_with_target_entity_id(
4639
+ state_rows: vec![state_surface_ref_row_with_target_entity_pk(
4697
4640
  "ref-1",
4698
4641
  json!(["welcome.title", "en"]),
4699
4642
  "composite_message_schema",
@@ -4705,7 +4648,7 @@ mod tests {
4705
4648
  rows: vec![MaterializedLiveStateRow::from(composite_message_row(
4706
4649
  "welcome.title",
4707
4650
  "en",
4708
- "version-a",
4651
+ "branch-a",
4709
4652
  ))],
4710
4653
  };
4711
4654
 
@@ -4715,23 +4658,22 @@ mod tests {
4715
4658
  &live_state,
4716
4659
  ))
4717
4660
  .await
4718
- .expect("state FK should resolve composite JSON-array entity ids");
4661
+ .expect("state FK should resolve composite JSON-array entity pks");
4719
4662
  }
4720
4663
 
4721
4664
  #[tokio::test]
4722
- async fn validation_rejects_delete_when_same_version_reference_exists() {
4665
+ async fn validation_rejects_delete_when_same_branch_reference_exists() {
4723
4666
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4724
- let mut parent_delete = fk_parent_row("parent-1", "version-a");
4667
+ let mut parent_delete = fk_parent_row("parent-1", "branch-a");
4725
4668
  parent_delete.snapshot = None;
4726
4669
  let live_state = StaticLiveStateReader {
4727
4670
  rows: vec![
4728
- MaterializedLiveStateRow::from(fk_parent_row("parent-1", "version-a")),
4729
- MaterializedLiveStateRow::from(fk_child_row("child-1", "parent-1", "version-a")),
4671
+ MaterializedLiveStateRow::from(fk_parent_row("parent-1", "branch-a")),
4672
+ MaterializedLiveStateRow::from(fk_child_row("child-1", "parent-1", "branch-a")),
4730
4673
  ],
4731
4674
  };
4732
4675
  let staged_writes = PreparedWriteSet {
4733
4676
  state_rows: vec![parent_delete],
4734
- adopted_rows: Vec::new(),
4735
4677
  ..empty_staged_write_set()
4736
4678
  };
4737
4679
 
@@ -4742,25 +4684,24 @@ mod tests {
4742
4684
  &live_state,
4743
4685
  ))
4744
4686
  .await
4745
- .expect_err("delete should be restricted by same-version references");
4687
+ .expect_err("delete should be restricted by same-branch references");
4746
4688
 
4747
4689
  assert_eq!(error.code, LixError::CODE_FOREIGN_KEY);
4748
4690
  }
4749
4691
 
4750
4692
  #[tokio::test]
4751
- async fn validation_allows_delete_when_only_different_version_reference_exists() {
4693
+ async fn validation_allows_delete_when_only_different_branch_reference_exists() {
4752
4694
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4753
- let mut parent_delete = fk_parent_row("parent-1", "version-a");
4695
+ let mut parent_delete = fk_parent_row("parent-1", "branch-a");
4754
4696
  parent_delete.snapshot = None;
4755
4697
  let live_state = StaticLiveStateReader {
4756
4698
  rows: vec![
4757
- MaterializedLiveStateRow::from(fk_parent_row("parent-1", "version-a")),
4758
- MaterializedLiveStateRow::from(fk_child_row("child-1", "parent-1", "version-b")),
4699
+ MaterializedLiveStateRow::from(fk_parent_row("parent-1", "branch-a")),
4700
+ MaterializedLiveStateRow::from(fk_child_row("child-1", "parent-1", "branch-b")),
4759
4701
  ],
4760
4702
  };
4761
4703
  let staged_writes = PreparedWriteSet {
4762
4704
  state_rows: vec![parent_delete],
4763
- adopted_rows: Vec::new(),
4764
4705
  ..empty_staged_write_set()
4765
4706
  };
4766
4707
 
@@ -4770,25 +4711,24 @@ mod tests {
4770
4711
  &live_state,
4771
4712
  ))
4772
4713
  .await
4773
- .expect("references in another version should not restrict this version");
4714
+ .expect("references in another branch should not restrict this branch");
4774
4715
  }
4775
4716
 
4776
4717
  #[tokio::test]
4777
4718
  async fn validation_allows_delete_when_committed_reference_is_also_deleted() {
4778
4719
  let visible_schemas = vec![fk_parent_schema(), fk_child_schema()];
4779
- let mut parent_delete = fk_parent_row("parent-1", "version-a");
4720
+ let mut parent_delete = fk_parent_row("parent-1", "branch-a");
4780
4721
  parent_delete.snapshot = None;
4781
- let mut child_delete = fk_child_row("child-1", "parent-1", "version-a");
4722
+ let mut child_delete = fk_child_row("child-1", "parent-1", "branch-a");
4782
4723
  child_delete.snapshot = None;
4783
4724
  let live_state = StaticLiveStateReader {
4784
4725
  rows: vec![
4785
- MaterializedLiveStateRow::from(fk_parent_row("parent-1", "version-a")),
4786
- MaterializedLiveStateRow::from(fk_child_row("child-1", "parent-1", "version-a")),
4726
+ MaterializedLiveStateRow::from(fk_parent_row("parent-1", "branch-a")),
4727
+ MaterializedLiveStateRow::from(fk_child_row("child-1", "parent-1", "branch-a")),
4787
4728
  ],
4788
4729
  };
4789
4730
  let staged_writes = PreparedWriteSet {
4790
4731
  state_rows: vec![parent_delete, child_delete],
4791
- adopted_rows: Vec::new(),
4792
4732
  ..empty_staged_write_set()
4793
4733
  };
4794
4734
 
@@ -4821,7 +4761,7 @@ mod tests {
4821
4761
  #[test]
4822
4762
  fn pending_indexes_record_primary_key_fk_targets_by_exact_scope() {
4823
4763
  let mut indexes = PendingConstraintIndexes::default();
4824
- let row = fk_parent_row("parent-1", "version-a");
4764
+ let row = fk_parent_row("parent-1", "branch-a");
4825
4765
  let snapshot = serde_json::from_str::<JsonValue>(
4826
4766
  row.snapshot
4827
4767
  .as_ref()
@@ -4841,7 +4781,7 @@ mod tests {
4841
4781
  assert!(indexes
4842
4782
  .has_fk_target(
4843
4783
  "fk_parent_schema",
4844
- "version-a",
4784
+ "branch-a",
4845
4785
  Some("file-a"),
4846
4786
  &["/id"],
4847
4787
  UniqueConstraintValue::string_values(["parent-1"]),
@@ -4850,7 +4790,7 @@ mod tests {
4850
4790
  assert!(!indexes
4851
4791
  .has_fk_target(
4852
4792
  "fk_parent_schema",
4853
- "version-b",
4793
+ "branch-b",
4854
4794
  Some("file-a"),
4855
4795
  &["/id"],
4856
4796
  UniqueConstraintValue::string_values(["parent-1"]),
@@ -4881,7 +4821,7 @@ mod tests {
4881
4821
  assert!(indexes
4882
4822
  .has_fk_target(
4883
4823
  "unique_schema",
4884
- "version-a",
4824
+ "branch-a",
4885
4825
  Some("file-a"),
4886
4826
  &["/slug"],
4887
4827
  UniqueConstraintValue::string_values(["hello-world"]),
@@ -4892,7 +4832,7 @@ mod tests {
4892
4832
  #[test]
4893
4833
  fn pending_indexes_record_normal_fk_references_by_exact_scope() {
4894
4834
  let mut indexes = PendingConstraintIndexes::default();
4895
- let row = fk_child_row("child-1", "parent-1", "version-a");
4835
+ let row = fk_child_row("child-1", "parent-1", "branch-a");
4896
4836
  let snapshot = serde_json::from_str::<JsonValue>(
4897
4837
  row.snapshot
4898
4838
  .as_ref()
@@ -4916,7 +4856,7 @@ mod tests {
4916
4856
  assert!(indexes
4917
4857
  .has_fk_reference_to_key(
4918
4858
  "fk_parent_schema",
4919
- "version-a",
4859
+ "branch-a",
4920
4860
  Some("file-a"),
4921
4861
  &["/id"],
4922
4862
  UniqueConstraintValue::string_values(["parent-1"]),
@@ -4925,7 +4865,7 @@ mod tests {
4925
4865
  assert!(!indexes
4926
4866
  .has_fk_reference_to_key(
4927
4867
  "fk_parent_schema",
4928
- "version-b",
4868
+ "branch-b",
4929
4869
  Some("file-a"),
4930
4870
  &["/id"],
4931
4871
  UniqueConstraintValue::string_values(["parent-1"]),
@@ -4959,11 +4899,11 @@ mod tests {
4959
4899
 
4960
4900
  assert!(
4961
4901
  indexes.has_fk_reference_to_identity(DomainRowIdentity::exact(
4962
- "version-a",
4902
+ "branch-a",
4963
4903
  false,
4964
4904
  Some("file-a".to_string()),
4965
4905
  "fk_parent_schema",
4966
- EntityIdentity::single("target-1"),
4906
+ EntityPk::single("target-1"),
4967
4907
  ))
4968
4908
  );
4969
4909
  }
@@ -4971,11 +4911,11 @@ mod tests {
4971
4911
  #[test]
4972
4912
  fn pending_delete_restrictions_ignore_tombstoned_referencing_rows() {
4973
4913
  let mut indexes = PendingConstraintIndexes::default();
4974
- let mut parent_delete = fk_parent_row("parent-1", "version-a");
4914
+ let mut parent_delete = fk_parent_row("parent-1", "branch-a");
4975
4915
  parent_delete.snapshot = None;
4976
4916
  indexes.remember_tombstone(PreparedValidationRow::State(&parent_delete));
4977
4917
 
4978
- let child = fk_child_row("child-1", "parent-1", "version-a");
4918
+ let child = fk_child_row("child-1", "parent-1", "branch-a");
4979
4919
  let child_snapshot = serde_json::from_str::<JsonValue>(
4980
4920
  child
4981
4921
  .snapshot
@@ -4996,7 +4936,7 @@ mod tests {
4996
4936
  )
4997
4937
  .expect("child row should index FK reference");
4998
4938
 
4999
- let mut child_delete = fk_child_row("child-1", "parent-1", "version-a");
4939
+ let mut child_delete = fk_child_row("child-1", "parent-1", "branch-a");
5000
4940
  child_delete.snapshot = None;
5001
4941
  indexes.remember_tombstone(PreparedValidationRow::State(&child_delete));
5002
4942
 
@@ -5007,7 +4947,7 @@ mod tests {
5007
4947
  #[test]
5008
4948
  fn pending_fk_validation_collects_unresolved_normal_fk_check() {
5009
4949
  let indexes = PendingConstraintIndexes::default();
5010
- let row = fk_child_row("child-1", "parent-1", "version-a");
4950
+ let row = fk_child_row("child-1", "parent-1", "branch-a");
5011
4951
  let snapshot = serde_json::from_str::<JsonValue>(
5012
4952
  row.snapshot
5013
4953
  .as_ref()
@@ -5034,11 +4974,11 @@ mod tests {
5034
4974
  assert_eq!(
5035
4975
  unresolved[0].source_identity,
5036
4976
  DomainRowIdentity::exact(
5037
- "version-a",
4977
+ "branch-a",
5038
4978
  false,
5039
4979
  Some("file-a".to_string()),
5040
4980
  "fk_child_schema",
5041
- EntityIdentity::single("child-1"),
4981
+ EntityPk::single("child-1"),
5042
4982
  )
5043
4983
  );
5044
4984
  assert_eq!(unresolved[0].source_schema_key, "fk_child_schema");
@@ -5050,7 +4990,7 @@ mod tests {
5050
4990
  panic!("normal FK should produce key target");
5051
4991
  };
5052
4992
  assert_eq!(target.schema_key, "fk_parent_schema");
5053
- assert_eq!(target.domain.version_id(), "version-a");
4993
+ assert_eq!(target.domain.branch_id(), "branch-a");
5054
4994
  assert_eq!(
5055
4995
  target.domain.file_scope(),
5056
4996
  &DomainFileScope::Exact(Some("file-a".to_string()))
@@ -5065,7 +5005,7 @@ mod tests {
5065
5005
  #[test]
5066
5006
  fn pending_fk_validation_resolves_normal_fk_against_pending_target() {
5067
5007
  let mut indexes = PendingConstraintIndexes::default();
5068
- let parent = fk_parent_row("parent-1", "version-a");
5008
+ let parent = fk_parent_row("parent-1", "branch-a");
5069
5009
  let parent_snapshot = serde_json::from_str::<JsonValue>(
5070
5010
  parent
5071
5011
  .snapshot
@@ -5082,7 +5022,7 @@ mod tests {
5082
5022
  )
5083
5023
  .expect("parent should index as pending FK target");
5084
5024
 
5085
- let child = fk_child_row("child-1", "parent-1", "version-a");
5025
+ let child = fk_child_row("child-1", "parent-1", "branch-a");
5086
5026
  let child_snapshot = serde_json::from_str::<JsonValue>(
5087
5027
  child
5088
5028
  .snapshot
@@ -5108,14 +5048,14 @@ mod tests {
5108
5048
 
5109
5049
  assert!(
5110
5050
  unresolved.is_empty(),
5111
- "same-version pending parent should satisfy the child FK"
5051
+ "same-branch pending parent should satisfy the child FK"
5112
5052
  );
5113
5053
  }
5114
5054
 
5115
5055
  #[test]
5116
- fn pending_fk_validation_keeps_normal_fk_unresolved_across_versions() {
5056
+ fn pending_fk_validation_keeps_normal_fk_unresolved_across_branches() {
5117
5057
  let mut indexes = PendingConstraintIndexes::default();
5118
- let parent = fk_parent_row("parent-1", "version-b");
5058
+ let parent = fk_parent_row("parent-1", "branch-b");
5119
5059
  let parent_snapshot = serde_json::from_str::<JsonValue>(
5120
5060
  parent
5121
5061
  .snapshot
@@ -5132,7 +5072,7 @@ mod tests {
5132
5072
  )
5133
5073
  .expect("parent should index as pending FK target");
5134
5074
 
5135
- let child = fk_child_row("child-1", "parent-1", "version-a");
5075
+ let child = fk_child_row("child-1", "parent-1", "branch-a");
5136
5076
  let child_snapshot = serde_json::from_str::<JsonValue>(
5137
5077
  child
5138
5078
  .snapshot
@@ -5161,9 +5101,9 @@ mod tests {
5161
5101
  panic!("normal FK should produce key target");
5162
5102
  };
5163
5103
  assert_eq!(
5164
- target.domain.version_id(),
5165
- "version-a",
5166
- "FK checks are exact-version scoped, not overlay scoped"
5104
+ target.domain.branch_id(),
5105
+ "branch-a",
5106
+ "FK checks are exact-branch scoped, not overlay scoped"
5167
5107
  );
5168
5108
  }
5169
5109
 
@@ -5197,18 +5137,18 @@ mod tests {
5197
5137
  assert_eq!(
5198
5138
  unresolved[0].source_identity,
5199
5139
  DomainRowIdentity::exact(
5200
- "version-a",
5140
+ "branch-a",
5201
5141
  false,
5202
5142
  Some("file-a".to_string()),
5203
5143
  "state_surface_ref_schema",
5204
- EntityIdentity::single("ref-1"),
5144
+ EntityPk::single("ref-1"),
5205
5145
  )
5206
5146
  );
5207
5147
  assert_eq!(unresolved[0].source_schema_key, "state_surface_ref_schema");
5208
5148
  assert_eq!(
5209
5149
  unresolved[0].source_pointer_group,
5210
5150
  vec![
5211
- vec!["target_entity_id".to_string()],
5151
+ vec!["target_entity_pk".to_string()],
5212
5152
  vec!["target_schema_key".to_string()],
5213
5153
  vec!["target_file_id".to_string()],
5214
5154
  ]
@@ -5216,9 +5156,9 @@ mod tests {
5216
5156
  let UnresolvedForeignKeyTarget::StateSurfaceIdentity(target) = &unresolved[0].target else {
5217
5157
  panic!("state FK should produce state-surface identity target");
5218
5158
  };
5219
- assert_eq!(target.domain().version_id(), "version-a");
5159
+ assert_eq!(target.domain().branch_id(), "branch-a");
5220
5160
  assert_eq!(target.schema_key(), "fk_parent_schema");
5221
- assert_eq!(target.entity_id(), &EntityIdentity::single("target-1"));
5161
+ assert_eq!(target.entity_pk(), &EntityPk::single("target-1"));
5222
5162
  assert_eq!(
5223
5163
  target.domain().file_scope(),
5224
5164
  &DomainFileScope::Exact(Some("file-a".to_string()))
@@ -5228,7 +5168,7 @@ mod tests {
5228
5168
  #[tokio::test]
5229
5169
  async fn committed_fk_lookup_resolves_normal_fk_in_exact_scope() {
5230
5170
  let indexes = PendingConstraintIndexes::default();
5231
- let child = fk_child_row("child-1", "parent-1", "version-a");
5171
+ let child = fk_child_row("child-1", "parent-1", "branch-a");
5232
5172
  let child_snapshot = serde_json::from_str::<JsonValue>(
5233
5173
  child
5234
5174
  .snapshot
@@ -5252,8 +5192,7 @@ mod tests {
5252
5192
  .expect("pending FK validation should collect unresolved check");
5253
5193
  let live_state = StaticLiveStateReader {
5254
5194
  rows: vec![MaterializedLiveStateRow::from(fk_parent_row(
5255
- "parent-1",
5256
- "version-a",
5195
+ "parent-1", "branch-a",
5257
5196
  ))],
5258
5197
  };
5259
5198
 
@@ -5271,14 +5210,14 @@ mod tests {
5271
5210
 
5272
5211
  assert!(
5273
5212
  still_unresolved.is_empty(),
5274
- "same-version committed parent should satisfy unresolved FK"
5213
+ "same-branch committed parent should satisfy unresolved FK"
5275
5214
  );
5276
5215
  }
5277
5216
 
5278
5217
  #[tokio::test]
5279
- async fn committed_fk_lookup_keeps_normal_fk_unresolved_across_versions() {
5218
+ async fn committed_fk_lookup_keeps_normal_fk_unresolved_across_branches() {
5280
5219
  let indexes = PendingConstraintIndexes::default();
5281
- let child = fk_child_row("child-1", "parent-1", "version-a");
5220
+ let child = fk_child_row("child-1", "parent-1", "branch-a");
5282
5221
  let child_snapshot = serde_json::from_str::<JsonValue>(
5283
5222
  child
5284
5223
  .snapshot
@@ -5302,8 +5241,7 @@ mod tests {
5302
5241
  .expect("pending FK validation should collect unresolved check");
5303
5242
  let live_state = StaticLiveStateReader {
5304
5243
  rows: vec![MaterializedLiveStateRow::from(fk_parent_row(
5305
- "parent-1",
5306
- "version-b",
5244
+ "parent-1", "branch-b",
5307
5245
  ))],
5308
5246
  };
5309
5247
 
@@ -5322,7 +5260,7 @@ mod tests {
5322
5260
  assert_eq!(
5323
5261
  still_unresolved.len(),
5324
5262
  1,
5325
- "committed FK lookup is exact-version scoped"
5263
+ "committed FK lookup is exact-branch scoped"
5326
5264
  );
5327
5265
  }
5328
5266
 
@@ -5352,8 +5290,7 @@ mod tests {
5352
5290
  .expect("pending FK validation should collect unresolved check");
5353
5291
  let live_state = StaticLiveStateReader {
5354
5292
  rows: vec![MaterializedLiveStateRow::from(fk_parent_row(
5355
- "target-1",
5356
- "version-a",
5293
+ "target-1", "branch-a",
5357
5294
  ))],
5358
5295
  };
5359
5296
 
@@ -5378,10 +5315,9 @@ mod tests {
5378
5315
  fn empty_staged_write_set() -> PreparedWriteSet {
5379
5316
  PreparedWriteSet {
5380
5317
  state_rows: Vec::new(),
5381
- adopted_rows: Vec::new(),
5382
5318
  insert_identities: BTreeMap::new(),
5383
- commit_members_by_version: BTreeMap::new(),
5384
- extra_commit_parents_by_version: BTreeMap::new(),
5319
+ commit_change_refs_by_branch: BTreeMap::new(),
5320
+ extra_commit_parents_by_branch: BTreeMap::new(),
5385
5321
  file_data_writes: Vec::new(),
5386
5322
  }
5387
5323
  }
@@ -5399,8 +5335,8 @@ mod tests {
5399
5335
  }
5400
5336
  (request.filter.schema_keys.is_empty()
5401
5337
  || request.filter.schema_keys.contains(&row.schema_key))
5402
- && (request.filter.version_ids.is_empty()
5403
- || request.filter.version_ids.contains(&row.version_id))
5338
+ && (request.filter.branch_ids.is_empty()
5339
+ || request.filter.branch_ids.contains(&row.branch_id))
5404
5340
  && (request.filter.file_ids.is_empty()
5405
5341
  || request
5406
5342
  .filter
@@ -5414,17 +5350,17 @@ mod tests {
5414
5350
  request: &LiveStateRowRequest,
5415
5351
  ) -> bool {
5416
5352
  row.schema_key == request.schema_key
5417
- && row.version_id == request.version_id
5418
- && row.entity_id == request.entity_id
5353
+ && row.branch_id == request.branch_id
5354
+ && row.entity_pk == request.entity_pk
5419
5355
  && request.file_id.matches(row.file_id.as_ref())
5420
5356
  }
5421
5357
 
5422
5358
  fn test_file_descriptor_rows() -> Vec<MaterializedLiveStateRow> {
5423
5359
  vec![
5424
- committed_file_descriptor_row("file-a", "version-a"),
5425
- committed_file_descriptor_row("file-a", "version-b"),
5426
- committed_file_descriptor_row("file-b", "version-a"),
5427
- committed_file_descriptor_row("file-b", "version-b"),
5360
+ committed_file_descriptor_row("file-a", "branch-a"),
5361
+ committed_file_descriptor_row("file-a", "branch-b"),
5362
+ committed_file_descriptor_row("file-b", "branch-a"),
5363
+ committed_file_descriptor_row("file-b", "branch-b"),
5428
5364
  ]
5429
5365
  }
5430
5366
 
@@ -5445,7 +5381,7 @@ mod tests {
5445
5381
  PreparedStateRow {
5446
5382
  schema_plan_id: crate::catalog::SchemaPlanId::for_test(0),
5447
5383
  facts: crate::transaction::types::PreparedRowFacts::default(),
5448
- entity_id: registered_schema_entity_id(&key.schema_key),
5384
+ entity_pk: registered_schema_entity_pk(&key.schema_key),
5449
5385
  schema_key: REGISTERED_SCHEMA_KEY.to_string(),
5450
5386
  file_id: None,
5451
5387
  snapshot: Some(test_stage_json(&json!({ "value": schema }).to_string())),
@@ -5457,12 +5393,12 @@ mod tests {
5457
5393
  change_id: Some("change-registered-schema".to_string()),
5458
5394
  commit_id: Some("commit-registered-schema".to_string()),
5459
5395
  untracked: false,
5460
- version_id: crate::GLOBAL_VERSION_ID.to_string(),
5396
+ branch_id: crate::GLOBAL_BRANCH_ID.to_string(),
5461
5397
  }
5462
5398
  }
5463
5399
 
5464
- fn registered_schema_entity_id(schema_key: &str) -> crate::entity_identity::EntityIdentity {
5465
- crate::entity_identity::EntityIdentity::from_primary_key_paths(
5400
+ fn registered_schema_entity_pk(schema_key: &str) -> crate::entity_pk::EntityPk {
5401
+ crate::entity_pk::EntityPk::from_primary_key_paths(
5466
5402
  &serde_json::json!({
5467
5403
  "value": {
5468
5404
  "x-lix-key": schema_key,
@@ -5583,12 +5519,12 @@ mod tests {
5583
5519
  "x-lix-key": "state_surface_ref_schema",
5584
5520
  "x-lix-primary-key": ["/id"],
5585
5521
  "x-lix-state-foreign-keys": [
5586
- ["/target_entity_id", "/target_schema_key", "/target_file_id"]
5522
+ ["/target_entity_pk", "/target_schema_key", "/target_file_id"]
5587
5523
  ],
5588
5524
  "type": "object",
5589
5525
  "properties": {
5590
5526
  "id": { "type": "string" },
5591
- "target_entity_id": {
5527
+ "target_entity_pk": {
5592
5528
  "type": "array",
5593
5529
  "items": { "type": "string" },
5594
5530
  "minItems": 1
@@ -5596,108 +5532,108 @@ mod tests {
5596
5532
  "target_schema_key": { "type": "string" },
5597
5533
  "target_file_id": { "type": ["string", "null"] }
5598
5534
  },
5599
- "required": ["id", "target_entity_id", "target_schema_key", "target_file_id"],
5535
+ "required": ["id", "target_entity_pk", "target_schema_key", "target_file_id"],
5600
5536
  "additionalProperties": false
5601
5537
  })
5602
5538
  }
5603
5539
 
5604
- fn unique_row(entity_id: &str, slug: &str, title: &str) -> PreparedStateRow {
5540
+ fn unique_row(entity_pk: &str, slug: &str, title: &str) -> PreparedStateRow {
5605
5541
  let mut row = staged_row(
5606
5542
  "unique_schema",
5607
5543
  Some(
5608
5544
  json!({
5609
- "id": entity_id,
5545
+ "id": entity_pk,
5610
5546
  "slug": slug,
5611
5547
  "title": title,
5612
5548
  })
5613
5549
  .to_string(),
5614
5550
  ),
5615
5551
  );
5616
- row.entity_id = crate::entity_identity::EntityIdentity::single(entity_id);
5552
+ row.entity_pk = crate::entity_pk::EntityPk::single(entity_pk);
5617
5553
  row.file_id = Some("file-a".to_string());
5618
- row.version_id = "version-a".to_string();
5554
+ row.branch_id = "branch-a".to_string();
5619
5555
  row.global = false;
5620
5556
  row
5621
5557
  }
5622
5558
 
5623
- fn nullable_unique_row(entity_id: &str, scope: Option<&str>, name: &str) -> PreparedStateRow {
5559
+ fn nullable_unique_row(entity_pk: &str, scope: Option<&str>, name: &str) -> PreparedStateRow {
5624
5560
  let mut row = staged_row(
5625
5561
  "nullable_unique_schema",
5626
5562
  Some(
5627
5563
  json!({
5628
- "id": entity_id,
5564
+ "id": entity_pk,
5629
5565
  "scope": scope,
5630
5566
  "name": name,
5631
5567
  })
5632
5568
  .to_string(),
5633
5569
  ),
5634
5570
  );
5635
- row.entity_id = crate::entity_identity::EntityIdentity::single(entity_id);
5571
+ row.entity_pk = crate::entity_pk::EntityPk::single(entity_pk);
5636
5572
  row.file_id = Some("file-a".to_string());
5637
- row.version_id = "version-a".to_string();
5573
+ row.branch_id = "branch-a".to_string();
5638
5574
  row.global = false;
5639
5575
  row
5640
5576
  }
5641
5577
 
5642
- fn fk_parent_row(entity_id: &str, version_id: &str) -> PreparedStateRow {
5578
+ fn fk_parent_row(entity_pk: &str, branch_id: &str) -> PreparedStateRow {
5643
5579
  let mut row = staged_row(
5644
5580
  "fk_parent_schema",
5645
- Some(json!({ "id": entity_id }).to_string()),
5581
+ Some(json!({ "id": entity_pk }).to_string()),
5646
5582
  );
5647
- row.entity_id = crate::entity_identity::EntityIdentity::single(entity_id);
5583
+ row.entity_pk = crate::entity_pk::EntityPk::single(entity_pk);
5648
5584
  row.file_id = Some("file-a".to_string());
5649
- row.version_id = version_id.to_string();
5585
+ row.branch_id = branch_id.to_string();
5650
5586
  row.global = false;
5651
5587
  row
5652
5588
  }
5653
5589
 
5654
- fn fk_child_row(entity_id: &str, parent_id: &str, version_id: &str) -> PreparedStateRow {
5590
+ fn fk_child_row(entity_pk: &str, parent_id: &str, branch_id: &str) -> PreparedStateRow {
5655
5591
  let mut row = staged_row(
5656
5592
  "fk_child_schema",
5657
- Some(json!({ "id": entity_id, "parent_id": parent_id }).to_string()),
5593
+ Some(json!({ "id": entity_pk, "parent_id": parent_id }).to_string()),
5658
5594
  );
5659
- row.entity_id = crate::entity_identity::EntityIdentity::single(entity_id);
5595
+ row.entity_pk = crate::entity_pk::EntityPk::single(entity_pk);
5660
5596
  row.file_id = Some("file-a".to_string());
5661
- row.version_id = version_id.to_string();
5597
+ row.branch_id = branch_id.to_string();
5662
5598
  row.global = false;
5663
5599
  row
5664
5600
  }
5665
5601
 
5666
- fn composite_message_row(key: &str, locale: &str, version_id: &str) -> PreparedStateRow {
5602
+ fn composite_message_row(key: &str, locale: &str, branch_id: &str) -> PreparedStateRow {
5667
5603
  let snapshot = json!({
5668
5604
  "key": key,
5669
5605
  "locale": locale,
5670
5606
  "text": "Welcome",
5671
5607
  });
5672
5608
  let mut row = staged_row("composite_message_schema", Some(snapshot.to_string()));
5673
- row.entity_id = EntityIdentity::from_primary_key_paths(
5609
+ row.entity_pk = EntityPk::from_primary_key_paths(
5674
5610
  &snapshot,
5675
5611
  &[vec!["key".to_string()], vec!["locale".to_string()]],
5676
5612
  )
5677
5613
  .expect("composite message identity should derive");
5678
5614
  row.file_id = Some("file-a".to_string());
5679
- row.version_id = version_id.to_string();
5615
+ row.branch_id = branch_id.to_string();
5680
5616
  row.global = false;
5681
5617
  row
5682
5618
  }
5683
5619
 
5684
5620
  fn state_surface_ref_row(
5685
- entity_id: &str,
5686
- target_entity_id: &str,
5621
+ entity_pk: &str,
5622
+ target_entity_pk: &str,
5687
5623
  target_schema_key: &str,
5688
5624
  target_file_id: &str,
5689
5625
  ) -> PreparedStateRow {
5690
- state_surface_ref_row_with_target_entity_id(
5691
- entity_id,
5692
- json!([target_entity_id]),
5626
+ state_surface_ref_row_with_target_entity_pk(
5627
+ entity_pk,
5628
+ json!([target_entity_pk]),
5693
5629
  target_schema_key,
5694
5630
  target_file_id,
5695
5631
  )
5696
5632
  }
5697
5633
 
5698
- fn state_surface_ref_row_with_target_entity_id(
5699
- entity_id: &str,
5700
- target_entity_id: JsonValue,
5634
+ fn state_surface_ref_row_with_target_entity_pk(
5635
+ entity_pk: &str,
5636
+ target_entity_pk: JsonValue,
5701
5637
  target_schema_key: &str,
5702
5638
  target_file_id: &str,
5703
5639
  ) -> PreparedStateRow {
@@ -5705,17 +5641,17 @@ mod tests {
5705
5641
  "state_surface_ref_schema",
5706
5642
  Some(
5707
5643
  json!({
5708
- "id": entity_id,
5709
- "target_entity_id": target_entity_id,
5644
+ "id": entity_pk,
5645
+ "target_entity_pk": target_entity_pk,
5710
5646
  "target_schema_key": target_schema_key,
5711
5647
  "target_file_id": target_file_id,
5712
5648
  })
5713
5649
  .to_string(),
5714
5650
  ),
5715
5651
  );
5716
- row.entity_id = crate::entity_identity::EntityIdentity::single(entity_id);
5652
+ row.entity_pk = crate::entity_pk::EntityPk::single(entity_pk);
5717
5653
  row.file_id = Some("file-a".to_string());
5718
- row.version_id = "version-a".to_string();
5654
+ row.branch_id = "branch-a".to_string();
5719
5655
  row.global = false;
5720
5656
  row
5721
5657
  }
@@ -5732,7 +5668,7 @@ mod tests {
5732
5668
  row.commit_id = None;
5733
5669
  }
5734
5670
 
5735
- fn staged_file_descriptor_row(file_id: &str, version_id: &str) -> PreparedStateRow {
5671
+ fn staged_file_descriptor_row(file_id: &str, branch_id: &str) -> PreparedStateRow {
5736
5672
  let mut row = staged_row(
5737
5673
  FILE_DESCRIPTOR_SCHEMA_KEY,
5738
5674
  Some(
@@ -5745,22 +5681,22 @@ mod tests {
5745
5681
  .to_string(),
5746
5682
  ),
5747
5683
  );
5748
- row.entity_id = crate::entity_identity::EntityIdentity::single(file_id);
5684
+ row.entity_pk = crate::entity_pk::EntityPk::single(file_id);
5749
5685
  row.file_id = None;
5750
- row.version_id = version_id.to_string();
5751
- row.global = version_id == crate::GLOBAL_VERSION_ID;
5686
+ row.branch_id = branch_id.to_string();
5687
+ row.global = branch_id == crate::GLOBAL_BRANCH_ID;
5752
5688
  row
5753
5689
  }
5754
5690
 
5755
- fn committed_file_descriptor_row(file_id: &str, version_id: &str) -> MaterializedLiveStateRow {
5756
- MaterializedLiveStateRow::from(staged_file_descriptor_row(file_id, version_id))
5691
+ fn committed_file_descriptor_row(file_id: &str, branch_id: &str) -> MaterializedLiveStateRow {
5692
+ MaterializedLiveStateRow::from(staged_file_descriptor_row(file_id, branch_id))
5757
5693
  }
5758
5694
 
5759
5695
  fn directory_descriptor_row(
5760
5696
  directory_id: &str,
5761
5697
  parent_id: Option<&str>,
5762
5698
  name: &str,
5763
- version_id: &str,
5699
+ branch_id: &str,
5764
5700
  ) -> PreparedStateRow {
5765
5701
  let mut row = staged_row(
5766
5702
  DIRECTORY_DESCRIPTOR_SCHEMA_KEY,
@@ -5774,17 +5710,17 @@ mod tests {
5774
5710
  .to_string(),
5775
5711
  ),
5776
5712
  );
5777
- row.entity_id = crate::entity_identity::EntityIdentity::single(directory_id);
5713
+ row.entity_pk = crate::entity_pk::EntityPk::single(directory_id);
5778
5714
  row.file_id = None;
5779
- row.version_id = version_id.to_string();
5780
- row.global = version_id == crate::GLOBAL_VERSION_ID;
5715
+ row.branch_id = branch_id.to_string();
5716
+ row.global = branch_id == crate::GLOBAL_BRANCH_ID;
5781
5717
  row
5782
5718
  }
5783
5719
 
5784
- fn committed_unique_row(entity_id: &str, slug: &str, title: &str) -> MaterializedLiveStateRow {
5785
- let row = unique_row(entity_id, slug, title);
5720
+ fn committed_unique_row(entity_pk: &str, slug: &str, title: &str) -> MaterializedLiveStateRow {
5721
+ let row = unique_row(entity_pk, slug, title);
5786
5722
  MaterializedLiveStateRow {
5787
- entity_id: row.entity_id,
5723
+ entity_pk: row.entity_pk,
5788
5724
  schema_key: row.schema_key,
5789
5725
  file_id: row.file_id,
5790
5726
  snapshot_content: row.snapshot.as_ref().map(|snapshot| snapshot.materialize()),
@@ -5796,23 +5732,23 @@ mod tests {
5796
5732
  change_id: row.change_id,
5797
5733
  commit_id: row.commit_id,
5798
5734
  untracked: row.untracked,
5799
- version_id: row.version_id,
5735
+ branch_id: row.branch_id,
5800
5736
  }
5801
5737
  }
5802
5738
 
5803
5739
  fn committed_nullable_unique_row(
5804
- entity_id: &str,
5740
+ entity_pk: &str,
5805
5741
  scope: Option<&str>,
5806
5742
  name: &str,
5807
5743
  ) -> MaterializedLiveStateRow {
5808
- MaterializedLiveStateRow::from(nullable_unique_row(entity_id, scope, name))
5744
+ MaterializedLiveStateRow::from(nullable_unique_row(entity_pk, scope, name))
5809
5745
  }
5810
5746
 
5811
5747
  fn staged_row(schema_key: &str, snapshot_content: Option<String>) -> PreparedStateRow {
5812
5748
  PreparedStateRow {
5813
5749
  schema_plan_id: crate::catalog::SchemaPlanId::for_test(0),
5814
5750
  facts: crate::transaction::types::PreparedRowFacts::default(),
5815
- entity_id: crate::entity_identity::EntityIdentity::single("entity-1"),
5751
+ entity_pk: crate::entity_pk::EntityPk::single("entity-1"),
5816
5752
  schema_key: schema_key.to_string(),
5817
5753
  file_id: None,
5818
5754
  snapshot: snapshot_content.as_deref().map(test_stage_json),
@@ -5824,7 +5760,7 @@ mod tests {
5824
5760
  change_id: Some("change-1".to_string()),
5825
5761
  commit_id: Some("commit-1".to_string()),
5826
5762
  untracked: false,
5827
- version_id: crate::GLOBAL_VERSION_ID.to_string(),
5763
+ branch_id: crate::GLOBAL_BRANCH_ID.to_string(),
5828
5764
  }
5829
5765
  }
5830
5766
  }