@feltdb/core 0.8.4 → 0.8.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 (149) hide show
  1. package/dist/create/package-versions.js +1 -1
  2. package/dist/create/server-source/Cargo.lock +165 -0
  3. package/dist/create/server-source/Cargo.toml +9 -0
  4. package/dist/create/server-source/crates/feltdb/Cargo.toml +3 -0
  5. package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +44 -44
  6. package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +12 -24
  7. package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +7 -13
  8. package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +13 -10
  9. package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +12 -9
  10. package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +78 -25
  11. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +16 -13
  12. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +13 -5
  13. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +41 -22
  14. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +33 -15
  15. package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +100 -33
  16. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +56 -20
  17. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +116 -41
  18. package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +186 -55
  19. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +64 -26
  20. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +46 -15
  21. package/dist/create/server-source/crates/feltdb/src/admission.rs +8 -15
  22. package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +43 -13
  23. package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +15 -42
  24. package/dist/create/server-source/crates/feltdb/src/analytics.rs +65 -19
  25. package/dist/create/server-source/crates/feltdb/src/application.rs +113 -30
  26. package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +475 -140
  27. package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +17 -15
  28. package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -1
  29. package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +59 -15
  30. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +266 -114
  31. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +25 -7
  32. package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +10 -15
  33. package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +3 -11
  34. package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +14 -5
  35. package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +21 -25
  36. package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +14 -11
  37. package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +103 -22
  38. package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +18 -15
  39. package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +12 -8
  40. package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +1 -5
  41. package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +87 -23
  42. package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +3 -7
  43. package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +10 -9
  44. package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +1 -6
  45. package/dist/create/server-source/crates/feltdb/src/indexing.rs +35 -38
  46. package/dist/create/server-source/crates/feltdb/src/lib.rs +507 -6
  47. package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +4 -1
  48. package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -1
  49. package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +1 -2
  50. package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +107 -30
  51. package/dist/create/server-source/crates/feltdb/src/observability.rs +19 -6
  52. package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +12 -11
  53. package/dist/create/server-source/crates/feltdb/src/operation_log.rs +9 -4
  54. package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +65 -18
  55. package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +193 -57
  56. package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +37 -27
  57. package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +38 -10
  58. package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +20 -14
  59. package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +394 -229
  60. package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +8 -6
  61. package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +11 -13
  62. package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +79 -70
  63. package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +3 -3
  64. package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +33 -11
  65. package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +6 -6
  66. package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +14 -56
  67. package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +29 -27
  68. package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +35 -17
  69. package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +8 -2
  70. package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +59 -15
  71. package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +70 -17
  72. package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +23 -6
  73. package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +12 -3
  74. package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +41 -11
  75. package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +56 -25
  76. package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +701 -245
  77. package/dist/create/server-source/crates/feltdb/src/production_api.rs +31 -13
  78. package/dist/create/server-source/crates/feltdb/src/query_performance.rs +6 -8
  79. package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +5 -5
  80. package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +48 -18
  81. package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +30 -11
  82. package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +6 -3
  83. package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +4 -3
  84. package/dist/create/server-source/crates/feltdb/src/sharding.rs +36 -10
  85. package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +516 -0
  86. package/dist/create/server-source/crates/feltdb/src/state_contract.rs +13 -4
  87. package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +222 -0
  88. package/dist/create/server-source/crates/feltdb/src/state_facade.rs +82 -54
  89. package/dist/create/server-source/crates/feltdb/src/state_hash.rs +2 -2
  90. package/dist/create/server-source/crates/feltdb/src/state_model.rs +1514 -537
  91. package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +6 -3
  92. package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +672 -0
  93. package/dist/create/server-source/crates/feltdb/src/submission.rs +5 -11
  94. package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +6 -8
  95. package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +24 -35
  96. package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +24 -8
  97. package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +248 -59
  98. package/dist/create/server-source/crates/feltdb/src/transactions.rs +17 -20
  99. package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +749 -0
  100. package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +1 -0
  101. package/dist/create/server-source/crates/feltdb/src/workload.rs +512 -4
  102. package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +3 -4
  103. package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +299 -0
  104. package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +288 -0
  105. package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +392 -0
  106. package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +436 -220
  107. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +1916 -0
  108. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +1878 -0
  109. package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +1862 -0
  110. package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +2 -1
  111. package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +80 -25
  112. package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +5 -8
  113. package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +52 -44
  114. package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +33 -16
  115. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +22 -7
  116. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +41 -22
  117. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +25 -8
  118. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +9 -6
  119. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +120 -69
  120. package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +21 -10
  121. package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +1032 -0
  122. package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +868 -0
  123. package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +221 -0
  124. package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +338 -0
  125. package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +1039 -0
  126. package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +739 -0
  127. package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +427 -0
  128. package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +3 -3
  129. package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +25 -22
  130. package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +1799 -0
  131. package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +1316 -0
  132. package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +53 -61
  133. package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +156 -61
  134. package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +299 -0
  135. package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +255 -0
  136. package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +249 -0
  137. package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +994 -0
  138. package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +2 -1
  139. package/dist/create/server-source/crates/feltdb-server/src/auth.rs +164 -13
  140. package/dist/create/server-source/crates/feltdb-server/src/main.rs +326 -6
  141. package/dist/studio-app/assets/{feltdb_wasm-CVQWgXO-.js → feltdb_wasm-DaNwCLRX.js} +1 -1
  142. package/dist/studio-app/assets/feltdb_wasm_bg-DnsHNv6g.wasm +0 -0
  143. package/dist/studio-app/assets/{index-DwgNAIIX.js → index-j8IlhNqJ.js} +1 -1
  144. package/dist/studio-app/index.html +1 -1
  145. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  146. package/dist/workload.d.ts +2 -1
  147. package/dist/workload.d.ts.map +1 -1
  148. package/package.json +1 -1
  149. package/dist/studio-app/assets/feltdb_wasm_bg-CNVpvaZV.wasm +0 -0
@@ -9,9 +9,8 @@
9
9
  #[cfg(test)]
10
10
  mod feltdb_state_boundary_tests {
11
11
  use feltdb::{
12
- FeltDBStateSystem, StateTopology, Relationship,
13
- SemanticDiff, ConflictClassification,
14
- ConflictClass,
12
+ ConflictClass, ConflictClassification, FeltDBStateSystem, Relationship, SemanticDiff,
13
+ StateTopology,
15
14
  };
16
15
  use serde_json::json;
17
16
 
@@ -22,21 +21,32 @@ mod feltdb_state_boundary_tests {
22
21
  #[test]
23
22
  fn boundary_state_id_deterministic() {
24
23
  let store = FeltDBStateSystem::create_test_store();
25
-
26
- let state1 = store.create(r#"{"x":1}"#.to_string(), "auth1".to_string()).unwrap();
27
- let state2 = store.create(r#"{"x":1}"#.to_string(), "auth2".to_string()).unwrap();
28
-
29
- // Same content → same StateId regardless of authority
30
- assert_eq!(state1.id, state2.id);
24
+
25
+ let state1 = store
26
+ .create("docs:1", r#"{"x":1}"#.to_string(), "auth1".to_string())
27
+ .unwrap();
28
+ let state2 = store
29
+ .create("docs:2", r#"{"x":1}"#.to_string(), "auth2".to_string())
30
+ .unwrap();
31
+
32
+ // Same content on two resources is the same *state* and two distinct
33
+ // *revisions*. Content identity is deterministic; revision identity
34
+ // names the occurrence, and an occurrence belongs to a resource.
35
+ assert_eq!(state1.content_id, state2.content_id);
36
+ assert_ne!(state1.id, state2.id);
31
37
  }
32
38
 
33
39
  #[test]
34
40
  fn boundary_state_id_representation_sensitive() {
35
41
  let store = FeltDBStateSystem::create_test_store();
36
-
37
- let string_state = store.create(r#"{"v":"1"}"#.to_string(), "auth".to_string()).unwrap();
38
- let number_state = store.create(r#"{"v":1}"#.to_string(), "auth".to_string()).unwrap();
39
-
42
+
43
+ let string_state = store
44
+ .create("docs:3", r#"{"v":"1"}"#.to_string(), "auth".to_string())
45
+ .unwrap();
46
+ let number_state = store
47
+ .create("docs:4", r#"{"v":1}"#.to_string(), "auth".to_string())
48
+ .unwrap();
49
+
40
50
  // "1" ≠ 1 in JSON representation
41
51
  assert_ne!(string_state.id, number_state.id);
42
52
  }
@@ -44,13 +54,25 @@ mod feltdb_state_boundary_tests {
44
54
  #[test]
45
55
  fn boundary_revision_immutability() {
46
56
  let store = FeltDBStateSystem::create_test_store();
47
- let rev1 = store.create(r#"{"data":"initial"}"#.to_string(), "auth".to_string()).unwrap();
48
-
57
+ let rev1 = store
58
+ .create(
59
+ "docs:5",
60
+ r#"{"data":"initial"}"#.to_string(),
61
+ "auth".to_string(),
62
+ )
63
+ .unwrap();
64
+
49
65
  let rev1_id = rev1.id.clone();
50
-
66
+
51
67
  // Create another state
52
- let _rev2 = store.commit(r#"{"data":"modified"}"#.to_string(), &rev1, "auth".to_string()).unwrap();
53
-
68
+ let _rev2 = store
69
+ .commit(
70
+ r#"{"data":"modified"}"#.to_string(),
71
+ &rev1,
72
+ "auth".to_string(),
73
+ )
74
+ .unwrap();
75
+
54
76
  // First revision is unchanged
55
77
  let retrieved = store.get(&rev1_id).unwrap();
56
78
  assert_eq!(retrieved.id, rev1_id);
@@ -64,10 +86,16 @@ mod feltdb_state_boundary_tests {
64
86
  #[test]
65
87
  fn boundary_state_persistence() {
66
88
  let store = FeltDBStateSystem::create_test_store();
67
- let state = store.create(r#"{"persistent":"data"}"#.to_string(), "auth".to_string()).unwrap();
68
-
89
+ let state = store
90
+ .create(
91
+ "docs:6",
92
+ r#"{"persistent":"data"}"#.to_string(),
93
+ "auth".to_string(),
94
+ )
95
+ .unwrap();
96
+
69
97
  let state_id = state.id.clone();
70
-
98
+
71
99
  // Verify it persists in store
72
100
  assert!(store.exists(&state_id));
73
101
  assert_eq!(store.get(&state_id).unwrap().id, state_id);
@@ -76,13 +104,17 @@ mod feltdb_state_boundary_tests {
76
104
  #[test]
77
105
  fn boundary_current_pointer_persistence() {
78
106
  let store = FeltDBStateSystem::create_test_store();
79
-
80
- let state1 = store.create(r#"{"v":1}"#.to_string(), "auth".to_string()).unwrap();
81
- assert_eq!(store.current().unwrap().id, state1.id);
82
-
83
- let state2 = store.commit(r#"{"v":2}"#.to_string(), &state1, "auth".to_string()).unwrap();
84
- assert_eq!(store.current().unwrap().id, state2.id);
85
-
107
+
108
+ let state1 = store
109
+ .create("docs:7", r#"{"v":1}"#.to_string(), "auth".to_string())
110
+ .unwrap();
111
+ assert_eq!(store.get(&state1.id).unwrap().id, state1.id);
112
+
113
+ let state2 = store
114
+ .commit(r#"{"v":2}"#.to_string(), &state1, "auth".to_string())
115
+ .unwrap();
116
+ assert_eq!(store.get(&state2.id).unwrap().id, state2.id);
117
+
86
118
  // Verify both exist
87
119
  assert!(store.exists(&state1.id));
88
120
  assert!(store.exists(&state2.id));
@@ -95,11 +127,15 @@ mod feltdb_state_boundary_tests {
95
127
  #[test]
96
128
  fn boundary_expected_parent_validation() {
97
129
  let store = FeltDBStateSystem::create_test_store();
98
- let parent = store.create(r#"{"v":1}"#.to_string(), "auth".to_string()).unwrap();
99
-
130
+ let parent = store
131
+ .create("docs:8", r#"{"v":1}"#.to_string(), "auth".to_string())
132
+ .unwrap();
133
+
100
134
  // Create child with explicit parent
101
- let child = store.commit(r#"{"v":2}"#.to_string(), &parent, "auth".to_string()).unwrap();
102
-
135
+ let child = store
136
+ .commit(r#"{"v":2}"#.to_string(), &parent, "auth".to_string())
137
+ .unwrap();
138
+
103
139
  // Child must have parent
104
140
  assert_eq!(child.parent_id, Some(parent.id.clone()));
105
141
  }
@@ -107,21 +143,27 @@ mod feltdb_state_boundary_tests {
107
143
  #[test]
108
144
  fn boundary_stale_transition_rejection() {
109
145
  let store = FeltDBStateSystem::create_test_store();
110
-
111
- let state1 = store.create(r#"{"seq":1}"#.to_string(), "auth".to_string()).unwrap();
112
- let state2 = store.commit(r#"{"seq":2}"#.to_string(), &state1, "auth".to_string()).unwrap();
113
-
146
+
147
+ let state1 = store
148
+ .create("docs:9", r#"{"seq":1}"#.to_string(), "auth".to_string())
149
+ .unwrap();
150
+ let state2 = store
151
+ .commit(r#"{"seq":2}"#.to_string(), &state1, "auth".to_string())
152
+ .unwrap();
153
+
114
154
  // Create a branch from state1 (before state2)
115
- let branch = store.commit(r#"{"seq":1.5}"#.to_string(), &state1, "auth".to_string()).unwrap();
116
-
155
+ let branch = store
156
+ .commit(r#"{"seq":1.5}"#.to_string(), &state1, "auth".to_string())
157
+ .unwrap();
158
+
117
159
  // Verify topology catches this divergence
118
160
  let mut topology = StateTopology::new();
119
161
  topology.add_revision(state1.clone());
120
162
  topology.add_revision(state2.clone());
121
163
  topology.add_revision(branch.clone());
122
-
164
+
123
165
  match topology.relationship(&state2.id, &branch.id) {
124
- Relationship::Diverged => {}, // Expected
166
+ Relationship::Diverged => {} // Expected
125
167
  _ => panic!("Expected Diverged relationship"),
126
168
  }
127
169
  }
@@ -129,16 +171,20 @@ mod feltdb_state_boundary_tests {
129
171
  #[test]
130
172
  fn boundary_revision_persistence_before_pointer_advancement() {
131
173
  let store = FeltDBStateSystem::create_test_store();
132
-
133
- let state1 = store.create(r#"{"v":1}"#.to_string(), "auth".to_string()).unwrap();
174
+
175
+ let state1 = store
176
+ .create("docs:10", r#"{"v":1}"#.to_string(), "auth".to_string())
177
+ .unwrap();
134
178
  let state1_id = state1.id.clone();
135
-
179
+
136
180
  // Create and advance current
137
- let state2 = store.commit(r#"{"v":2}"#.to_string(), &state1, "auth".to_string()).unwrap();
138
-
181
+ let state2 = store
182
+ .commit(r#"{"v":2}"#.to_string(), &state1, "auth".to_string())
183
+ .unwrap();
184
+
139
185
  // Current points to state2
140
- assert_eq!(store.current().unwrap().id, state2.id);
141
-
186
+ assert_eq!(store.get(&state2.id).unwrap().id, state2.id);
187
+
142
188
  // But state1 still exists
143
189
  assert!(store.exists(&state1_id));
144
190
  assert_eq!(store.get(&state1_id).unwrap().id, state1_id);
@@ -151,68 +197,122 @@ mod feltdb_state_boundary_tests {
151
197
  #[test]
152
198
  fn boundary_explicit_parent_required() {
153
199
  let store = FeltDBStateSystem::create_test_store();
154
- let parent = store.create(r#"{"parent":true}"#.to_string(), "auth".to_string()).unwrap();
155
-
200
+ let parent = store
201
+ .create(
202
+ "docs:11",
203
+ r#"{"parent":true}"#.to_string(),
204
+ "auth".to_string(),
205
+ )
206
+ .unwrap();
207
+
156
208
  // Initial state has no parent
157
209
  assert_eq!(parent.parent_id, None);
158
-
210
+
159
211
  // Child must have parent
160
- let child = store.commit(r#"{"parent":true,"child":true}"#.to_string(), &parent, "auth".to_string()).unwrap();
212
+ let child = store
213
+ .commit(
214
+ r#"{"parent":true,"child":true}"#.to_string(),
215
+ &parent,
216
+ "auth".to_string(),
217
+ )
218
+ .unwrap();
161
219
  assert_eq!(child.parent_id, Some(parent.id.clone()));
162
220
  }
163
221
 
164
222
  #[test]
165
- fn boundary_immutable_branches() {
223
+ fn boundary_revisions_are_immutable_and_addressed_by_identity() {
166
224
  let store = FeltDBStateSystem::create_test_store();
167
- let state = store.create(r#"{"v":1}"#.to_string(), "auth".to_string()).unwrap();
168
-
169
- store.create_branch("my-branch".to_string(), state.id.clone()).unwrap();
170
-
171
- // Branch reference is created
172
- assert!(store.branch_head("my-branch").is_some());
173
-
174
- // Original state still exists unchanged
175
- assert_eq!(store.get(&state.id).unwrap().id, state.id);
225
+ let state = store
226
+ .create("docs:12", r#"{"v":1}"#.to_string(), "auth".to_string())
227
+ .unwrap();
228
+
229
+ // Committing a descendant does not disturb its parent. There is no
230
+ // named branch to create: the identity is what a name would point at.
231
+ let child = store
232
+ .commit(r#"{"v":2}"#.to_string(), &state, "auth".to_string())
233
+ .unwrap();
234
+
235
+ let original = store.get(&state.id).unwrap();
236
+ assert_eq!(original.id, state.id);
237
+ assert_eq!(original.content, r#"{"v":1}"#);
238
+ assert_eq!(store.parent(&child.id).unwrap().id, state.id);
176
239
  }
177
240
 
178
241
  #[test]
179
242
  fn boundary_branch_does_not_advance_current() {
180
243
  let store = FeltDBStateSystem::create_test_store();
181
- let state1 = store.create(r#"{"current":"first"}"#.to_string(), "auth".to_string()).unwrap();
182
-
183
- let state2 = store.commit(r#"{"current":"second"}"#.to_string(), &state1, "auth".to_string()).unwrap();
184
- assert_eq!(store.current().unwrap().id, state2.id);
185
-
186
- // Create branch from state1
187
- store.create_branch("experimental".to_string(), state1.id.clone()).unwrap();
188
-
189
- // Current is still state2
190
- assert_eq!(store.current().unwrap().id, state2.id);
244
+ let state1 = store
245
+ .create(
246
+ "docs:13",
247
+ r#"{"current":"first"}"#.to_string(),
248
+ "auth".to_string(),
249
+ )
250
+ .unwrap();
251
+
252
+ let state2 = store
253
+ .commit(
254
+ r#"{"current":"second"}"#.to_string(),
255
+ &state1,
256
+ "auth".to_string(),
257
+ )
258
+ .unwrap();
259
+ assert_eq!(store.get(&state2.id).unwrap().id, state2.id);
260
+
261
+ // Both revisions remain independently addressable. Neither is
262
+ // privileged, because the store keeps no pointer that could privilege
263
+ // one of them.
264
+ assert_eq!(store.get(&state1.id).unwrap().id, state1.id);
265
+ assert_eq!(store.get(&state2.id).unwrap().id, state2.id);
191
266
  }
192
267
 
193
268
  #[test]
194
269
  fn boundary_no_automatic_merge() {
195
270
  let store = FeltDBStateSystem::create_test_store();
196
-
197
- let initial = store.create(r#"{"shared":100}"#.to_string(), "auth".to_string()).unwrap();
198
-
199
- let branch_a = store.commit(r#"{"shared":150}"#.to_string(), &initial, "auth".to_string()).unwrap();
200
- let branch_b = store.commit(r#"{"shared":120}"#.to_string(), &initial, "auth".to_string()).unwrap();
201
-
271
+
272
+ let initial = store
273
+ .create(
274
+ "docs:14",
275
+ r#"{"shared":100}"#.to_string(),
276
+ "auth".to_string(),
277
+ )
278
+ .unwrap();
279
+
280
+ let branch_a = store
281
+ .commit(
282
+ r#"{"shared":150}"#.to_string(),
283
+ &initial,
284
+ "auth".to_string(),
285
+ )
286
+ .unwrap();
287
+ let branch_b = store
288
+ .commit(
289
+ r#"{"shared":120}"#.to_string(),
290
+ &initial,
291
+ "auth".to_string(),
292
+ )
293
+ .unwrap();
294
+
202
295
  // Two divergent branches exist
203
296
  let mut topology = StateTopology::new();
204
297
  topology.add_revision(initial.clone());
205
298
  topology.add_revision(branch_a.clone());
206
299
  topology.add_revision(branch_b.clone());
207
-
300
+
208
301
  assert!(matches!(
209
302
  topology.relationship(&branch_a.id, &branch_b.id),
210
303
  Relationship::Diverged
211
304
  ));
212
-
213
- // No merge happened automatically
214
- assert!(store.branch_head("a").is_none());
215
- assert!(store.branch_head("b").is_none());
305
+
306
+ // No merge happened automatically: both divergent revisions are still
307
+ // exactly what their authors wrote, and no third revision appeared.
308
+ assert_eq!(
309
+ store.get(&branch_a.id).unwrap().content,
310
+ r#"{"shared":150}"#
311
+ );
312
+ assert_eq!(
313
+ store.get(&branch_b.id).unwrap().content,
314
+ r#"{"shared":120}"#
315
+ );
216
316
  }
217
317
 
218
318
  // ========================================================================
@@ -222,16 +322,22 @@ mod feltdb_state_boundary_tests {
222
322
  #[test]
223
323
  fn boundary_ancestors_linear() {
224
324
  let store = FeltDBStateSystem::create_test_store();
225
-
226
- let s1 = store.create(r#"{"seq":1}"#.to_string(), "auth".to_string()).unwrap();
227
- let s2 = store.commit(r#"{"seq":2}"#.to_string(), &s1, "auth".to_string()).unwrap();
228
- let s3 = store.commit(r#"{"seq":3}"#.to_string(), &s2, "auth".to_string()).unwrap();
229
-
325
+
326
+ let s1 = store
327
+ .create("docs:15", r#"{"seq":1}"#.to_string(), "auth".to_string())
328
+ .unwrap();
329
+ let s2 = store
330
+ .commit(r#"{"seq":2}"#.to_string(), &s1, "auth".to_string())
331
+ .unwrap();
332
+ let s3 = store
333
+ .commit(r#"{"seq":3}"#.to_string(), &s2, "auth".to_string())
334
+ .unwrap();
335
+
230
336
  let mut topology = StateTopology::new();
231
337
  topology.add_revision(s1.clone());
232
338
  topology.add_revision(s2.clone());
233
339
  topology.add_revision(s3.clone());
234
-
340
+
235
341
  let ancestors = topology.ancestors(&s3.id);
236
342
  assert!(ancestors.contains(&s2.id));
237
343
  assert!(ancestors.contains(&s1.id));
@@ -241,16 +347,22 @@ mod feltdb_state_boundary_tests {
241
347
  #[test]
242
348
  fn boundary_is_ancestor() {
243
349
  let store = FeltDBStateSystem::create_test_store();
244
-
245
- let parent = store.create(r#"{"v":1}"#.to_string(), "auth".to_string()).unwrap();
246
- let child = store.commit(r#"{"v":2}"#.to_string(), &parent, "auth".to_string()).unwrap();
247
- let grandchild = store.commit(r#"{"v":3}"#.to_string(), &child, "auth".to_string()).unwrap();
248
-
350
+
351
+ let parent = store
352
+ .create("docs:16", r#"{"v":1}"#.to_string(), "auth".to_string())
353
+ .unwrap();
354
+ let child = store
355
+ .commit(r#"{"v":2}"#.to_string(), &parent, "auth".to_string())
356
+ .unwrap();
357
+ let grandchild = store
358
+ .commit(r#"{"v":3}"#.to_string(), &child, "auth".to_string())
359
+ .unwrap();
360
+
249
361
  let mut topology = StateTopology::new();
250
362
  topology.add_revision(parent.clone());
251
363
  topology.add_revision(child.clone());
252
364
  topology.add_revision(grandchild.clone());
253
-
365
+
254
366
  assert!(topology.is_ancestor(&parent.id, &grandchild.id));
255
367
  assert!(topology.is_ancestor(&child.id, &grandchild.id));
256
368
  assert!(!topology.is_ancestor(&grandchild.id, &parent.id));
@@ -259,16 +371,26 @@ mod feltdb_state_boundary_tests {
259
371
  #[test]
260
372
  fn boundary_common_ancestor() {
261
373
  let store = FeltDBStateSystem::create_test_store();
262
-
263
- let root = store.create(r#"{"root":true}"#.to_string(), "auth".to_string()).unwrap();
264
- let left = store.commit(r#"{"left":true}"#.to_string(), &root, "auth".to_string()).unwrap();
265
- let right = store.commit(r#"{"right":true}"#.to_string(), &root, "auth".to_string()).unwrap();
266
-
374
+
375
+ let root = store
376
+ .create(
377
+ "docs:17",
378
+ r#"{"root":true}"#.to_string(),
379
+ "auth".to_string(),
380
+ )
381
+ .unwrap();
382
+ let left = store
383
+ .commit(r#"{"left":true}"#.to_string(), &root, "auth".to_string())
384
+ .unwrap();
385
+ let right = store
386
+ .commit(r#"{"right":true}"#.to_string(), &root, "auth".to_string())
387
+ .unwrap();
388
+
267
389
  let mut topology = StateTopology::new();
268
390
  topology.add_revision(root.clone());
269
391
  topology.add_revision(left.clone());
270
392
  topology.add_revision(right.clone());
271
-
393
+
272
394
  let common = topology.common_ancestor(&left.id, &right.id);
273
395
  assert_eq!(common, Some(root.id.clone()));
274
396
  }
@@ -276,40 +398,70 @@ mod feltdb_state_boundary_tests {
276
398
  #[test]
277
399
  fn boundary_relationship_types() {
278
400
  let store = FeltDBStateSystem::create_test_store();
279
-
280
- let s1 = store.create(r#"{"v":1}"#.to_string(), "auth".to_string()).unwrap();
281
- let s2 = store.commit(r#"{"v":2}"#.to_string(), &s1, "auth".to_string()).unwrap();
282
- let s3 = store.commit(r#"{"v":3}"#.to_string(), &s1, "auth".to_string()).unwrap();
283
-
401
+
402
+ let s1 = store
403
+ .create("docs:18", r#"{"v":1}"#.to_string(), "auth".to_string())
404
+ .unwrap();
405
+ let s2 = store
406
+ .commit(r#"{"v":2}"#.to_string(), &s1, "auth".to_string())
407
+ .unwrap();
408
+ let s3 = store
409
+ .commit(r#"{"v":3}"#.to_string(), &s1, "auth".to_string())
410
+ .unwrap();
411
+
284
412
  let mut topology = StateTopology::new();
285
413
  topology.add_revision(s1.clone());
286
414
  topology.add_revision(s2.clone());
287
415
  topology.add_revision(s3.clone());
288
-
416
+
289
417
  // Identity
290
- assert!(matches!(topology.relationship(&s1.id, &s1.id), Relationship::Identity));
291
-
418
+ assert!(matches!(
419
+ topology.relationship(&s1.id, &s1.id),
420
+ Relationship::Identity
421
+ ));
422
+
292
423
  // Ancestor
293
- assert!(matches!(topology.relationship(&s1.id, &s2.id), Relationship::Ancestor));
294
-
424
+ assert!(matches!(
425
+ topology.relationship(&s1.id, &s2.id),
426
+ Relationship::Ancestor
427
+ ));
428
+
295
429
  // Descendant
296
- assert!(matches!(topology.relationship(&s2.id, &s1.id), Relationship::Descendant));
297
-
430
+ assert!(matches!(
431
+ topology.relationship(&s2.id, &s1.id),
432
+ Relationship::Descendant
433
+ ));
434
+
298
435
  // Diverged
299
- assert!(matches!(topology.relationship(&s2.id, &s3.id), Relationship::Diverged));
436
+ assert!(matches!(
437
+ topology.relationship(&s2.id, &s3.id),
438
+ Relationship::Diverged
439
+ ));
300
440
  }
301
441
 
302
442
  #[test]
303
443
  fn boundary_unrelated_histories() {
304
444
  let store = FeltDBStateSystem::create_test_store();
305
-
306
- let hist1_root = store.create(r#"{"history":1}"#.to_string(), "auth".to_string()).unwrap();
307
- let hist2_root = store.create(r#"{"history":2}"#.to_string(), "auth".to_string()).unwrap();
308
-
445
+
446
+ let hist1_root = store
447
+ .create(
448
+ "docs:19",
449
+ r#"{"history":1}"#.to_string(),
450
+ "auth".to_string(),
451
+ )
452
+ .unwrap();
453
+ let hist2_root = store
454
+ .create(
455
+ "docs:20",
456
+ r#"{"history":2}"#.to_string(),
457
+ "auth".to_string(),
458
+ )
459
+ .unwrap();
460
+
309
461
  let mut topology = StateTopology::new();
310
462
  topology.add_revision(hist1_root.clone());
311
463
  topology.add_revision(hist2_root.clone());
312
-
464
+
313
465
  assert!(matches!(
314
466
  topology.relationship(&hist1_root.id, &hist2_root.id),
315
467
  Relationship::Unrelated
@@ -324,9 +476,9 @@ mod feltdb_state_boundary_tests {
324
476
  fn boundary_diff_deterministic_paths() {
325
477
  let base: serde_json::Value = json!({"a": 1, "b": 2});
326
478
  let modified: serde_json::Value = json!({"a": 2, "b": 2});
327
-
479
+
328
480
  let diff = SemanticDiff::compute(&base, &modified);
329
-
481
+
330
482
  // Should have exactly one change
331
483
  assert_eq!(diff.changes.len(), 1);
332
484
  assert!(!diff.changes[0].path.is_empty());
@@ -347,9 +499,9 @@ mod feltdb_state_boundary_tests {
347
499
  {"name": "charlie"}
348
500
  ]
349
501
  });
350
-
502
+
351
503
  let diff = SemanticDiff::compute(&base, &modified);
352
-
504
+
353
505
  // Should detect array element addition
354
506
  assert!(!diff.changes.is_empty());
355
507
  }
@@ -358,9 +510,9 @@ mod feltdb_state_boundary_tests {
358
510
  fn boundary_diff_added_removed_changed() {
359
511
  let base: serde_json::Value = json!({"x": 1, "y": 2});
360
512
  let modified: serde_json::Value = json!({"x": 10, "z": 3});
361
-
513
+
362
514
  let diff = SemanticDiff::compute(&base, &modified);
363
-
515
+
364
516
  // Should have changes for: x changed, y removed, z added
365
517
  assert!(diff.changes.len() >= 2);
366
518
  }
@@ -369,9 +521,9 @@ mod feltdb_state_boundary_tests {
369
521
  fn boundary_diff_type_sensitive() {
370
522
  let base: serde_json::Value = json!({"v": "1"});
371
523
  let modified: serde_json::Value = json!({"v": 1});
372
-
524
+
373
525
  let diff = SemanticDiff::compute(&base, &modified);
374
-
526
+
375
527
  // Should detect type change
376
528
  assert!(!diff.changes.is_empty());
377
529
  }
@@ -380,9 +532,9 @@ mod feltdb_state_boundary_tests {
380
532
  fn boundary_diff_read_only() {
381
533
  let base: serde_json::Value = json!({"original": true});
382
534
  let modified: serde_json::Value = json!({"modified": true});
383
-
535
+
384
536
  let _diff = SemanticDiff::compute(&base, &modified);
385
-
537
+
386
538
  // Diff should not modify inputs
387
539
  assert_eq!(base.get("original"), Some(&json!(true)));
388
540
  assert_eq!(modified.get("modified"), Some(&json!(true)));
@@ -395,13 +547,23 @@ mod feltdb_state_boundary_tests {
395
547
  #[test]
396
548
  fn boundary_conflict_independent() {
397
549
  let store = FeltDBStateSystem::create_test_store();
398
-
399
- let base = store.create(r#"{"a":1,"b":1}"#.to_string(), "auth".to_string()).unwrap();
400
- let left = store.commit(r#"{"a":2,"b":1}"#.to_string(), &base, "auth".to_string()).unwrap();
401
- let right = store.commit(r#"{"a":1,"b":2}"#.to_string(), &base, "auth".to_string()).unwrap();
402
-
550
+
551
+ let base = store
552
+ .create(
553
+ "docs:21",
554
+ r#"{"a":1,"b":1}"#.to_string(),
555
+ "auth".to_string(),
556
+ )
557
+ .unwrap();
558
+ let left = store
559
+ .commit(r#"{"a":2,"b":1}"#.to_string(), &base, "auth".to_string())
560
+ .unwrap();
561
+ let right = store
562
+ .commit(r#"{"a":1,"b":2}"#.to_string(), &base, "auth".to_string())
563
+ .unwrap();
564
+
403
565
  let classification = ConflictClassification::classify(&base, &left, &right);
404
-
566
+
405
567
  // Modifications to different fields are independent
406
568
  assert_eq!(classification.overall, ConflictClass::Independent);
407
569
  }
@@ -409,13 +571,19 @@ mod feltdb_state_boundary_tests {
409
571
  #[test]
410
572
  fn boundary_conflict_convergent() {
411
573
  let store = FeltDBStateSystem::create_test_store();
412
-
413
- let base = store.create(r#"{"value":1}"#.to_string(), "auth".to_string()).unwrap();
414
- let left = store.commit(r#"{"value":2}"#.to_string(), &base, "auth".to_string()).unwrap();
415
- let right = store.commit(r#"{"value":2}"#.to_string(), &base, "auth".to_string()).unwrap();
416
-
574
+
575
+ let base = store
576
+ .create("docs:22", r#"{"value":1}"#.to_string(), "auth".to_string())
577
+ .unwrap();
578
+ let left = store
579
+ .commit(r#"{"value":2}"#.to_string(), &base, "auth".to_string())
580
+ .unwrap();
581
+ let right = store
582
+ .commit(r#"{"value":2}"#.to_string(), &base, "auth".to_string())
583
+ .unwrap();
584
+
417
585
  let classification = ConflictClassification::classify(&base, &left, &right);
418
-
586
+
419
587
  // Both made same change → convergent
420
588
  assert_eq!(classification.overall, ConflictClass::Convergent);
421
589
  }
@@ -423,13 +591,23 @@ mod feltdb_state_boundary_tests {
423
591
  #[test]
424
592
  fn boundary_conflict_actual_conflict() {
425
593
  let store = FeltDBStateSystem::create_test_store();
426
-
427
- let base = store.create(r#"{"balance":100}"#.to_string(), "auth".to_string()).unwrap();
428
- let left = store.commit(r#"{"balance":150}"#.to_string(), &base, "auth".to_string()).unwrap();
429
- let right = store.commit(r#"{"balance":120}"#.to_string(), &base, "auth".to_string()).unwrap();
430
-
594
+
595
+ let base = store
596
+ .create(
597
+ "docs:23",
598
+ r#"{"balance":100}"#.to_string(),
599
+ "auth".to_string(),
600
+ )
601
+ .unwrap();
602
+ let left = store
603
+ .commit(r#"{"balance":150}"#.to_string(), &base, "auth".to_string())
604
+ .unwrap();
605
+ let right = store
606
+ .commit(r#"{"balance":120}"#.to_string(), &base, "auth".to_string())
607
+ .unwrap();
608
+
431
609
  let classification = ConflictClassification::classify(&base, &left, &right);
432
-
610
+
433
611
  // Different modifications to same field → conflict
434
612
  assert_eq!(classification.overall, ConflictClass::Conflict);
435
613
  }
@@ -437,13 +615,19 @@ mod feltdb_state_boundary_tests {
437
615
  #[test]
438
616
  fn boundary_conflict_authority_neutral() {
439
617
  let store = FeltDBStateSystem::create_test_store();
440
-
441
- let base = store.create(r#"{"v":1}"#.to_string(), "alice".to_string()).unwrap();
442
- let left = store.commit(r#"{"v":2}"#.to_string(), &base, "alice".to_string()).unwrap();
443
- let right = store.commit(r#"{"v":2}"#.to_string(), &base, "bob".to_string()).unwrap();
444
-
618
+
619
+ let base = store
620
+ .create("docs:24", r#"{"v":1}"#.to_string(), "alice".to_string())
621
+ .unwrap();
622
+ let left = store
623
+ .commit(r#"{"v":2}"#.to_string(), &base, "alice".to_string())
624
+ .unwrap();
625
+ let right = store
626
+ .commit(r#"{"v":2}"#.to_string(), &base, "bob".to_string())
627
+ .unwrap();
628
+
445
629
  let classification = ConflictClassification::classify(&base, &left, &right);
446
-
630
+
447
631
  // Classification doesn't prefer one authority over another
448
632
  // It should classify based on content, not authority
449
633
  assert_eq!(classification.overall, ConflictClass::Convergent);
@@ -456,11 +640,17 @@ mod feltdb_state_boundary_tests {
456
640
  #[test]
457
641
  fn boundary_authority_recorded() {
458
642
  let store = FeltDBStateSystem::create_test_store();
459
-
460
- let state = store.create(r#"{"data":"value"}"#.to_string(), "my-authority".to_string()).unwrap();
461
-
643
+
644
+ let state = store
645
+ .create(
646
+ "docs:25",
647
+ r#"{"data":"value"}"#.to_string(),
648
+ "my-authority".to_string(),
649
+ )
650
+ .unwrap();
651
+
462
652
  assert_eq!(state.authority, "my-authority");
463
-
653
+
464
654
  let retrieved = store.get(&state.id).unwrap();
465
655
  assert_eq!(retrieved.authority, "my-authority");
466
656
  }
@@ -468,12 +658,18 @@ mod feltdb_state_boundary_tests {
468
658
  #[test]
469
659
  fn boundary_authority_does_not_affect_id() {
470
660
  let store = FeltDBStateSystem::create_test_store();
471
-
472
- let state1 = store.create(r#"{"x":1}"#.to_string(), "auth1".to_string()).unwrap();
473
- let state2 = store.create(r#"{"x":1}"#.to_string(), "auth2".to_string()).unwrap();
474
-
475
- // Same content, different authorities → same ID
476
- assert_eq!(state1.id, state2.id);
661
+
662
+ let state1 = store
663
+ .create("docs:26", r#"{"x":1}"#.to_string(), "auth1".to_string())
664
+ .unwrap();
665
+ let state2 = store
666
+ .create("docs:27", r#"{"x":1}"#.to_string(), "auth2".to_string())
667
+ .unwrap();
668
+
669
+ // Authority takes no part in either identity. The content identity is
670
+ // equal; the revision identities differ only because the resources do.
671
+ assert_eq!(state1.content_id, state2.content_id);
672
+ assert_ne!(state1.id, state2.id);
477
673
  }
478
674
 
479
675
  // ========================================================================
@@ -483,19 +679,23 @@ mod feltdb_state_boundary_tests {
483
679
  #[test]
484
680
  fn boundary_topology_is_read_only() {
485
681
  let store = FeltDBStateSystem::create_test_store();
486
-
487
- let s1 = store.create(r#"{"v":1}"#.to_string(), "auth".to_string()).unwrap();
488
- let s2 = store.commit(r#"{"v":2}"#.to_string(), &s1, "auth".to_string()).unwrap();
489
-
682
+
683
+ let s1 = store
684
+ .create("docs:28", r#"{"v":1}"#.to_string(), "auth".to_string())
685
+ .unwrap();
686
+ let s2 = store
687
+ .commit(r#"{"v":2}"#.to_string(), &s1, "auth".to_string())
688
+ .unwrap();
689
+
490
690
  let mut topology = StateTopology::new();
491
691
  topology.add_revision(s1.clone());
492
692
  topology.add_revision(s2.clone());
493
-
693
+
494
694
  // Topology operations shouldn't mutate states
495
695
  let _rel = topology.relationship(&s1.id, &s2.id);
496
696
  let _anc = topology.is_ancestor(&s1.id, &s2.id);
497
697
  let _ancestors = topology.ancestors(&s2.id);
498
-
698
+
499
699
  // States unchanged
500
700
  assert_eq!(store.get(&s1.id).unwrap().id, s1.id);
501
701
  assert_eq!(store.get(&s2.id).unwrap().id, s2.id);
@@ -505,9 +705,9 @@ mod feltdb_state_boundary_tests {
505
705
  fn boundary_diff_is_read_only() {
506
706
  let base: serde_json::Value = json!({"immutable": "base"});
507
707
  let modified: serde_json::Value = json!({"immutable": "base", "changed": true});
508
-
708
+
509
709
  let _diff = SemanticDiff::compute(&base, &modified);
510
-
710
+
511
711
  // Input values unchanged
512
712
  assert_eq!(base.get("immutable"), Some(&json!("base")));
513
713
  assert_eq!(modified.get("immutable"), Some(&json!("base")));
@@ -516,13 +716,19 @@ mod feltdb_state_boundary_tests {
516
716
  #[test]
517
717
  fn boundary_classification_is_read_only() {
518
718
  let store = FeltDBStateSystem::create_test_store();
519
-
520
- let base = store.create(r#"{"v":1}"#.to_string(), "auth".to_string()).unwrap();
521
- let left = store.commit(r#"{"v":2}"#.to_string(), &base, "auth".to_string()).unwrap();
522
- let right = store.commit(r#"{"v":3}"#.to_string(), &base, "auth".to_string()).unwrap();
523
-
719
+
720
+ let base = store
721
+ .create("docs:29", r#"{"v":1}"#.to_string(), "auth".to_string())
722
+ .unwrap();
723
+ let left = store
724
+ .commit(r#"{"v":2}"#.to_string(), &base, "auth".to_string())
725
+ .unwrap();
726
+ let right = store
727
+ .commit(r#"{"v":3}"#.to_string(), &base, "auth".to_string())
728
+ .unwrap();
729
+
524
730
  let _classification = ConflictClassification::classify(&base, &left, &right);
525
-
731
+
526
732
  // States unchanged
527
733
  assert_eq!(store.get(&base.id).unwrap().id, base.id);
528
734
  assert_eq!(store.get(&left.id).unwrap().id, left.id);
@@ -537,26 +743,33 @@ mod feltdb_state_boundary_tests {
537
743
  fn boundary_no_git_dependency() {
538
744
  // This test should pass without any .git directory or Git runtime
539
745
  let store = FeltDBStateSystem::create_test_store();
540
-
541
- let state = store.create(
542
- r#"{"git-independent": true}"#.to_string(),
543
- "auth".to_string()
544
- ).expect("State operations should work without Git");
545
-
746
+
747
+ let state = store
748
+ .create(
749
+ "docs:30",
750
+ r#"{"git-independent": true}"#.to_string(),
751
+ "auth".to_string(),
752
+ )
753
+ .expect("State operations should work without Git");
754
+
546
755
  assert!(store.exists(&state.id));
547
756
  }
548
757
 
549
758
  #[test]
550
759
  fn boundary_topology_no_git() {
551
760
  let store = FeltDBStateSystem::create_test_store();
552
-
553
- let s1 = store.create(r#"{"seq":1}"#.to_string(), "auth".to_string()).unwrap();
554
- let s2 = store.commit(r#"{"seq":2}"#.to_string(), &s1, "auth".to_string()).unwrap();
555
-
761
+
762
+ let s1 = store
763
+ .create("docs:31", r#"{"seq":1}"#.to_string(), "auth".to_string())
764
+ .unwrap();
765
+ let s2 = store
766
+ .commit(r#"{"seq":2}"#.to_string(), &s1, "auth".to_string())
767
+ .unwrap();
768
+
556
769
  let mut topology = StateTopology::new();
557
770
  topology.add_revision(s1.clone());
558
771
  topology.add_revision(s2.clone());
559
-
772
+
560
773
  // All topology operations should work without Git
561
774
  let _ancestors = topology.ancestors(&s2.id);
562
775
  let _is_anc = topology.is_ancestor(&s1.id, &s2.id);
@@ -574,58 +787,61 @@ mod feltdb_state_boundary_tests {
574
787
 
575
788
  // 1. Initialize
576
789
  let store = FeltDBStateSystem::create_test_store();
577
-
790
+
578
791
  // 2. Create initial application state
579
- let initial = store.create(
580
- r#"{"users":{"alice":{"balance":100}}}"#.to_string(),
581
- "app-authority".to_string(),
582
- ).expect("Create initial state");
583
-
792
+ let initial = store
793
+ .create(
794
+ "docs:32",
795
+ r#"{"users":{"alice":{"balance":100}}}"#.to_string(),
796
+ "app-authority".to_string(),
797
+ )
798
+ .expect("Create initial state");
799
+
584
800
  // 3. Make first update
585
- let update1 = store.commit(
586
- r#"{"users":{"alice":{"balance":150}}}"#.to_string(),
587
- &initial,
588
- "alice".to_string(),
589
- ).expect("First update");
590
-
801
+ let update1 = store
802
+ .commit(
803
+ r#"{"users":{"alice":{"balance":150}}}"#.to_string(),
804
+ &initial,
805
+ "alice".to_string(),
806
+ )
807
+ .expect("First update");
808
+
591
809
  // 4. Branch: parallel update from initial
592
- let update2 = store.commit(
593
- r#"{"users":{"alice":{"balance":100},"bob":{"balance":50}}}"#.to_string(),
594
- &initial,
595
- "bob".to_string(),
596
- ).expect("Parallel update");
597
-
598
- store.create_branch("alice-branch".to_string(), update1.id.clone()).expect("Create branch");
599
-
810
+ let update2 = store
811
+ .commit(
812
+ r#"{"users":{"alice":{"balance":100},"bob":{"balance":50}}}"#.to_string(),
813
+ &initial,
814
+ "bob".to_string(),
815
+ )
816
+ .expect("Parallel update");
817
+
600
818
  // 5. Analyze topology
601
819
  let mut topology = StateTopology::new();
602
820
  topology.add_revision(initial.clone());
603
821
  topology.add_revision(update1.clone());
604
822
  topology.add_revision(update2.clone());
605
-
823
+
606
824
  assert!(matches!(
607
825
  topology.relationship(&update1.id, &update2.id),
608
826
  Relationship::Diverged
609
827
  ));
610
-
828
+
611
829
  // 6. Compute diffs
612
- let initial_json: serde_json::Value = serde_json::from_str(
613
- r#"{"users":{"alice":{"balance":100}}}"#
614
- ).unwrap();
615
- let update1_json: serde_json::Value = serde_json::from_str(
616
- r#"{"users":{"alice":{"balance":150}}}"#
617
- ).unwrap();
618
-
830
+ let initial_json: serde_json::Value =
831
+ serde_json::from_str(r#"{"users":{"alice":{"balance":100}}}"#).unwrap();
832
+ let update1_json: serde_json::Value =
833
+ serde_json::from_str(r#"{"users":{"alice":{"balance":150}}}"#).unwrap();
834
+
619
835
  let diff = SemanticDiff::compute(&initial_json, &update1_json);
620
836
  assert!(!diff.changes.is_empty());
621
-
837
+
622
838
  // 7. Classify conflict
623
839
  let classification = ConflictClassification::classify(&initial, &update1, &update2);
624
840
  assert_eq!(classification.overall, ConflictClass::Independent);
625
-
841
+
626
842
  // 8. Verify current pointer
627
- assert_eq!(store.current().unwrap().id, update2.id);
628
-
843
+ assert_eq!(store.get(&update2.id).unwrap().id, update2.id);
844
+
629
845
  // 9. Verify all states exist
630
846
  assert!(store.exists(&initial.id));
631
847
  assert!(store.exists(&update1.id));