@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
@@ -14,8 +14,8 @@
14
14
  #[cfg(test)]
15
15
  mod integration_smoke_test {
16
16
  use feltdb::{
17
- StateRevision, StateStore, StateTopology, Relationship, SemanticDiff,
18
- ConflictClassification, ConflictClass, ReconciliationPlan,
17
+ ConflictClass, ConflictClassification, ReconciliationPlan, Relationship, SemanticDiff,
18
+ StateRevision, StateStore, StateTopology,
19
19
  };
20
20
  use serde_json::json;
21
21
 
@@ -25,13 +25,14 @@ mod integration_smoke_test {
25
25
  let store = StateStore::new_volatile();
26
26
  let initial_state = store
27
27
  .create(
28
+ "docs:1",
28
29
  r#"{"users":{"alice":{"balance":100},"bob":{"balance":50}}}"#.to_string(),
29
30
  "initial-authority".to_string(),
30
31
  )
31
32
  .expect("Failed to create initial state");
32
33
 
33
34
  assert!(store.exists(&initial_state.id));
34
- assert_eq!(store.current().unwrap().id, initial_state.id);
35
+ assert_eq!(store.get(&initial_state.id).unwrap().id, initial_state.id);
35
36
 
36
37
  println!("✓ Step 1: Created initial state ({})", initial_state.id);
37
38
 
@@ -44,13 +45,10 @@ mod integration_smoke_test {
44
45
  )
45
46
  .expect("Failed to create alice branch");
46
47
 
47
- store
48
- .create_branch("alice-branch".to_string(), alice_branch.id.clone())
49
- .expect("Failed to create alice-branch");
50
-
51
48
  println!(
52
49
  "✓ Step 2: Created alice branch ({}), parent: {}",
53
- alice_branch.id, alice_branch.parent().unwrap()
50
+ alice_branch.id,
51
+ alice_branch.parent().unwrap()
54
52
  );
55
53
 
56
54
  // Step 3: Create second branch from initial state (Bob's branch - modifies bob balance)
@@ -62,13 +60,10 @@ mod integration_smoke_test {
62
60
  )
63
61
  .expect("Failed to create bob branch");
64
62
 
65
- store
66
- .create_branch("bob-branch".to_string(), bob_branch.id.clone())
67
- .expect("Failed to create bob-branch");
68
-
69
63
  println!(
70
64
  "✓ Step 3: Created bob branch ({}), parent: {}",
71
- bob_branch.id, bob_branch.parent().unwrap()
65
+ bob_branch.id,
66
+ bob_branch.parent().unwrap()
72
67
  );
73
68
 
74
69
  // Step 4: Inspect topology
@@ -96,18 +91,15 @@ mod integration_smoke_test {
96
91
  );
97
92
 
98
93
  // Step 5: Compute semantic diffs
99
- let initial_json = serde_json::from_str(
100
- r#"{"users":{"alice":{"balance":100},"bob":{"balance":50}}}"#,
101
- )
102
- .unwrap();
103
- let alice_json = serde_json::from_str(
104
- r#"{"users":{"alice":{"balance":150},"bob":{"balance":50}}}"#,
105
- )
106
- .unwrap();
107
- let bob_json = serde_json::from_str(
108
- r#"{"users":{"alice":{"balance":100},"bob":{"balance":150}}}"#,
109
- )
110
- .unwrap();
94
+ let initial_json =
95
+ serde_json::from_str(r#"{"users":{"alice":{"balance":100},"bob":{"balance":50}}}"#)
96
+ .unwrap();
97
+ let alice_json =
98
+ serde_json::from_str(r#"{"users":{"alice":{"balance":150},"bob":{"balance":50}}}"#)
99
+ .unwrap();
100
+ let bob_json =
101
+ serde_json::from_str(r#"{"users":{"alice":{"balance":100},"bob":{"balance":150}}}"#)
102
+ .unwrap();
111
103
 
112
104
  let alice_diff = SemanticDiff::compute(&initial_json, &alice_json);
113
105
  let bob_diff = SemanticDiff::compute(&initial_json, &bob_json);
@@ -120,18 +112,15 @@ mod integration_smoke_test {
120
112
  println!(" - Bob's change: {:?}", bob_diff.changes[0]);
121
113
 
122
114
  // Step 6: Classify conflicts
123
- let conflict_class = ConflictClassification::classify(
124
- &initial_state,
125
- &alice_branch,
126
- &bob_branch,
127
- );
115
+ let conflict_class =
116
+ ConflictClassification::classify(&initial_state, &alice_branch, &bob_branch);
128
117
 
129
118
  // These changes are independent (different paths)
130
119
  assert_eq!(conflict_class.overall, ConflictClass::Independent);
131
- assert!(
132
- conflict_class.path_conflicts.iter()
133
- .all(|c| c.classification == ConflictClass::Independent)
134
- );
120
+ assert!(conflict_class
121
+ .path_conflicts
122
+ .iter()
123
+ .all(|c| c.classification == ConflictClass::Independent));
135
124
 
136
125
  println!("✓ Step 6: Classified conflicts as INDEPENDENT");
137
126
 
@@ -172,7 +161,10 @@ mod integration_smoke_test {
172
161
  )
173
162
  .expect("Failed to commit reconciled state");
174
163
 
175
- println!("✓ Step 8: Materialized reconciled state ({})", final_state.id);
164
+ println!(
165
+ "✓ Step 8: Materialized reconciled state ({})",
166
+ final_state.id
167
+ );
176
168
 
177
169
  // Step 9: Verify state properties
178
170
  let retrieved = store
@@ -207,6 +199,7 @@ mod integration_smoke_test {
207
199
  let store = StateStore::new_volatile();
208
200
  let initial = store
209
201
  .create(
202
+ "docs:1",
210
203
  r#"{"status":"initial"}"#.to_string(),
211
204
  "auth".to_string(),
212
205
  )
@@ -232,6 +225,7 @@ mod integration_smoke_test {
232
225
  let store = StateStore::new_volatile();
233
226
  let initial = store
234
227
  .create(
228
+ "docs:1",
235
229
  r#"{"value":"initial"}"#.to_string(),
236
230
  "auth".to_string(),
237
231
  )
@@ -262,12 +256,12 @@ mod integration_smoke_test {
262
256
  // Test that unrelated branches are detected as such
263
257
  let store1 = StateStore::new_volatile();
264
258
  let state1 = store1
265
- .create(r#"{"id":1}"#.to_string(), "auth1".to_string())
259
+ .create("docs:1", r#"{"id":1}"#.to_string(), "auth1".to_string())
266
260
  .unwrap();
267
261
 
268
262
  let store2 = StateStore::new_volatile();
269
263
  let state2 = store2
270
- .create(r#"{"id":2}"#.to_string(), "auth2".to_string())
264
+ .create("docs:1", r#"{"id":2}"#.to_string(), "auth2".to_string())
271
265
  .unwrap();
272
266
 
273
267
  let mut topology = StateTopology::new();
@@ -294,36 +288,34 @@ mod integration_smoke_test {
294
288
  let diff2 = SemanticDiff::compute(&old, &new_string);
295
289
 
296
290
  assert_eq!(diff1.changes.len(), 0, "No change for same representation");
297
- assert_eq!(diff2.changes.len(), 1, "Change detected for different representation");
291
+ assert_eq!(
292
+ diff2.changes.len(),
293
+ 1,
294
+ "Change detected for different representation"
295
+ );
298
296
 
299
297
  println!("✓ Representation sensitivity verified in diffs");
300
298
  }
301
299
 
302
300
  #[test]
303
- fn test_branching_does_not_advance_current() {
304
- // Verify that creating a branch doesn't automatically advance current pointer
301
+ fn test_committing_a_child_does_not_disturb_its_parent() {
302
+ // The store keeps no pointer that a commit could advance, so a parent
303
+ // is exactly as retrievable after its child exists as before.
305
304
  let store = StateStore::new_volatile();
306
305
  let state1 = store
307
- .create(r#"{"v":1}"#.to_string(), "auth".to_string())
306
+ .create("docs:1", r#"{"v":1}"#.to_string(), "auth".to_string())
308
307
  .unwrap();
308
+ assert_eq!(store.get(&state1.id).unwrap().content, r#"{"v":1}"#);
309
309
 
310
- let current_after_create = store.current().unwrap();
311
- assert_eq!(current_after_create.id, state1.id);
312
-
313
- // Branch from state1
314
310
  let state2 = store
315
311
  .commit(r#"{"v":2}"#.to_string(), &state1, "auth".to_string())
316
312
  .unwrap();
317
313
 
318
- store
319
- .create_branch("test-branch".to_string(), state2.id.clone())
320
- .unwrap();
321
-
322
- // Current should still be state2 (because we committed it)
323
- let current_after_branch = store.current().unwrap();
324
- assert_eq!(current_after_branch.id, state2.id);
314
+ assert_eq!(store.get(&state1.id).unwrap().content, r#"{"v":1}"#);
315
+ assert_eq!(store.get(&state2.id).unwrap().content, r#"{"v":2}"#);
316
+ assert_eq!(store.parent(&state2.id).unwrap().id, state1.id);
325
317
 
326
- println!("✓ Branch creation verified (doesn't implicitly advance current)");
318
+ println!("✓ A commit adds a revision and displaces nothing");
327
319
  }
328
320
 
329
321
  #[test]
@@ -331,11 +323,15 @@ mod integration_smoke_test {
331
323
  // Verify that reconciliation requires explicit plan
332
324
  let store = StateStore::new_volatile();
333
325
  let initial = store
334
- .create(r#"{"a":1,"b":2}"#.to_string(), "auth".to_string())
326
+ .create("docs:1", r#"{"a":1,"b":2}"#.to_string(), "auth".to_string())
335
327
  .unwrap();
336
328
 
337
329
  let left = store
338
- .commit(r#"{"a":10,"b":2}"#.to_string(), &initial, "auth".to_string())
330
+ .commit(
331
+ r#"{"a":10,"b":2}"#.to_string(),
332
+ &initial,
333
+ "auth".to_string(),
334
+ )
339
335
  .unwrap();
340
336
 
341
337
  let right = StateRevision::child(
@@ -348,12 +344,8 @@ mod integration_smoke_test {
348
344
  let classification = ConflictClassification::classify(&initial, &left, &right);
349
345
 
350
346
  // Caller must supply explicit plan
351
- let plan = ReconciliationPlan::new(
352
- left.id.clone(),
353
- right.id.clone(),
354
- initial.id.clone(),
355
- true,
356
- );
347
+ let plan =
348
+ ReconciliationPlan::new(left.id.clone(), right.id.clone(), initial.id.clone(), true);
357
349
 
358
350
  assert!(plan.validate());
359
351
  assert!(
@@ -22,8 +22,12 @@ mod state_persistence_tests {
22
22
  // Create initial state with FeltDB persistence
23
23
  let db1 = feltdb::FeltDb::open(&temp_path).expect("open db");
24
24
  let store1 = StateStore::with_feltdb(Arc::new(db1)).expect("create store");
25
- let rev1 = store1.create(r#"{"v":1}"#.to_string(), "auth".to_string()).expect("create");
26
- let rev2 = store1.commit(r#"{"v":2}"#.to_string(), &rev1, "auth".to_string()).expect("commit");
25
+ let rev1 = store1
26
+ .create("docs:1", r#"{"v":1}"#.to_string(), "auth".to_string())
27
+ .expect("create");
28
+ let rev2 = store1
29
+ .commit(r#"{"v":2}"#.to_string(), &rev1, "auth".to_string())
30
+ .expect("commit");
27
31
 
28
32
  let id1 = rev1.id.clone();
29
33
  let id2 = rev2.id.clone();
@@ -32,7 +36,10 @@ mod state_persistence_tests {
32
36
  // Verify both revisions exist
33
37
  assert!(store1.exists(&id1), "rev1 should exist");
34
38
  assert!(store1.exists(&id2), "rev2 should exist");
35
- assert_eq!(store1.current().map(|r| r.id.as_hex().to_string()), Some(id2_hex.clone()));
39
+ assert_eq!(
40
+ store1.get(&id2).map(|r| r.id.as_hex().to_string()),
41
+ Some(id2_hex.clone())
42
+ );
36
43
 
37
44
  // Drop store and database (simulate restart)
38
45
  drop(store1);
@@ -44,7 +51,11 @@ mod state_persistence_tests {
44
51
  // Verify all revisions still exist
45
52
  assert!(store2.exists(&id1), "rev1 should survive restart");
46
53
  assert!(store2.exists(&id2), "rev2 should survive restart");
47
- assert_eq!(store2.current().map(|r| r.id.as_hex().to_string()), Some(id2_hex), "current should be restored");
54
+ assert_eq!(
55
+ store2.get(&id2).map(|r| r.id.as_hex().to_string()),
56
+ Some(id2_hex),
57
+ "the revision is retrievable by identity after restart"
58
+ );
48
59
 
49
60
  // Verify content is correct
50
61
  let recovered_rev2 = store2.get(&id2).expect("get rev2");
@@ -59,7 +70,13 @@ mod state_persistence_tests {
59
70
 
60
71
  let db1 = feltdb::FeltDb::open(&temp_path).expect("open db");
61
72
  let store1 = StateStore::with_feltdb(Arc::new(db1)).expect("create store");
62
- let rev1 = store1.create(r#"{"fixed":"content"}"#.to_string(), "auth".to_string()).expect("create");
73
+ let rev1 = store1
74
+ .create(
75
+ "docs:1",
76
+ r#"{"fixed":"content"}"#.to_string(),
77
+ "auth".to_string(),
78
+ )
79
+ .expect("create");
63
80
  let id1 = rev1.id.clone();
64
81
  drop(store1);
65
82
 
@@ -67,9 +84,13 @@ mod state_persistence_tests {
67
84
  let db2 = feltdb::FeltDb::open(&temp_path).expect("open db again");
68
85
  let store2 = StateStore::with_feltdb(Arc::new(db2)).expect("recovery");
69
86
  let recovered = store2.get(&id1).expect("get");
70
-
87
+
71
88
  // Content hash must be the same for identical content
72
- assert_eq!(recovered.id.as_hex(), id1.as_hex(), "StateId should be deterministic");
89
+ assert_eq!(
90
+ recovered.id.as_hex(),
91
+ id1.as_hex(),
92
+ "StateId should be deterministic"
93
+ );
73
94
  }
74
95
 
75
96
  #[test]
@@ -80,22 +101,28 @@ mod state_persistence_tests {
80
101
  // Create store and initial state
81
102
  let db1 = feltdb::FeltDb::open(&temp_path).expect("open db");
82
103
  let store1 = StateStore::with_feltdb(Arc::new(db1)).expect("create store");
83
- let rev1 = store1.create(r#"{"v":1}"#.to_string(), "auth".to_string()).expect("create");
84
-
104
+ let rev1 = store1
105
+ .create("docs:1", r#"{"v":1}"#.to_string(), "auth".to_string())
106
+ .expect("create");
107
+
85
108
  let id1 = rev1.id.clone();
86
109
  let id1_hex = id1.as_hex().to_string();
87
-
88
- // Create a branch
89
- store1.create_branch("main".to_string(), id1.clone()).expect("branch");
90
-
91
- // Verify branch exists
92
- assert_eq!(store1.branch_head("main").map(|id| id.as_hex().to_string()), Some(id1_hex.clone()));
110
+
111
+ // There are no named branches. A revision is addressed by its own
112
+ // content-derived identity, which is what a name would have pointed at.
113
+ assert_eq!(
114
+ store1.get(&id1).map(|id| id.id.as_hex().to_string()),
115
+ Some(id1_hex.clone())
116
+ );
93
117
  drop(store1);
94
118
 
95
- // Recover and check branch
96
119
  let db2 = feltdb::FeltDb::open(&temp_path).expect("open db again");
97
- let store2 = StateStore::with_feltdb(Arc::new(db2)).expect("recovery");
98
- assert_eq!(store2.branch_head("main").map(|id| id.as_hex().to_string()), Some(id1_hex), "branch should survive restart");
120
+ let store2 = StateStore::with_feltdb(Arc::new(db2)).expect("reopen");
121
+ assert_eq!(
122
+ store2.get(&id1).map(|id| id.id.as_hex().to_string()),
123
+ Some(id1_hex),
124
+ "the revision survives restart under its own identity"
125
+ );
99
126
  }
100
127
 
101
128
  #[test]
@@ -105,14 +132,22 @@ mod state_persistence_tests {
105
132
 
106
133
  // Create volatile store
107
134
  let store1 = StateStore::new_volatile();
108
- let rev1 = store1.create(r#"{"v":1}"#.to_string(), "auth".to_string()).expect("create");
135
+ let rev1 = store1
136
+ .create("docs:1", r#"{"v":1}"#.to_string(), "auth".to_string())
137
+ .expect("create");
109
138
  drop(store1);
110
139
 
111
140
  // Try to recover from disk (should be empty)
112
141
  let db2 = feltdb::FeltDb::open(&temp_path).expect("open db");
113
142
  let store2 = StateStore::with_feltdb(Arc::new(db2)).expect("create store");
114
- assert!(!store2.exists(&rev1.id), "volatile store should not persist");
115
- assert!(store2.current().is_none(), "should have no current state");
143
+ assert!(
144
+ !store2.exists(&rev1.id),
145
+ "volatile store should not persist"
146
+ );
147
+ assert!(
148
+ store2.get(&rev1.id).is_none(),
149
+ "nothing from the volatile store reached disk"
150
+ );
116
151
  }
117
152
 
118
153
  #[test]
@@ -123,10 +158,16 @@ mod state_persistence_tests {
123
158
  // Create chain of revisions
124
159
  let db1 = feltdb::FeltDb::open(&temp_path).expect("open db");
125
160
  let store1 = StateStore::with_feltdb(Arc::new(db1)).expect("create store");
126
- let rev1 = store1.create(r#"{"v":1}"#.to_string(), "auth".to_string()).expect("create");
127
- let rev2 = store1.commit(r#"{"v":2}"#.to_string(), &rev1, "auth".to_string()).expect("commit");
128
- let rev3 = store1.commit(r#"{"v":3}"#.to_string(), &rev2, "auth".to_string()).expect("commit");
129
-
161
+ let rev1 = store1
162
+ .create("docs:1", r#"{"v":1}"#.to_string(), "auth".to_string())
163
+ .expect("create");
164
+ let rev2 = store1
165
+ .commit(r#"{"v":2}"#.to_string(), &rev1, "auth".to_string())
166
+ .expect("commit");
167
+ let rev3 = store1
168
+ .commit(r#"{"v":3}"#.to_string(), &rev2, "auth".to_string())
169
+ .expect("commit");
170
+
130
171
  let id1 = rev1.id.clone();
131
172
  let id2 = rev2.id.clone();
132
173
  let id3 = rev3.id.clone();
@@ -135,15 +176,26 @@ mod state_persistence_tests {
135
176
  // Recover and verify parent pointers
136
177
  let db2 = feltdb::FeltDb::open(&temp_path).expect("open db again");
137
178
  let store2 = StateStore::with_feltdb(Arc::new(db2)).expect("recovery");
138
-
179
+
139
180
  let recovered_rev3 = store2.get(&id3).expect("get rev3");
140
- assert_eq!(recovered_rev3.parent_id.as_ref().map(|id| id.as_hex()), Some(id2.as_hex()), "rev3 parent should be rev2");
141
-
181
+ assert_eq!(
182
+ recovered_rev3.parent_id.as_ref().map(|id| id.as_hex()),
183
+ Some(id2.as_hex()),
184
+ "rev3 parent should be rev2"
185
+ );
186
+
142
187
  let recovered_rev2 = store2.get(&id2).expect("get rev2");
143
- assert_eq!(recovered_rev2.parent_id.as_ref().map(|id| id.as_hex()), Some(id1.as_hex()), "rev2 parent should be rev1");
144
-
188
+ assert_eq!(
189
+ recovered_rev2.parent_id.as_ref().map(|id| id.as_hex()),
190
+ Some(id1.as_hex()),
191
+ "rev2 parent should be rev1"
192
+ );
193
+
145
194
  let recovered_rev1 = store2.get(&id1).expect("get rev1");
146
- assert!(recovered_rev1.parent_id.is_none(), "rev1 should have no parent");
195
+ assert!(
196
+ recovered_rev1.parent_id.is_none(),
197
+ "rev1 should have no parent"
198
+ );
147
199
  }
148
200
 
149
201
  #[test]
@@ -153,20 +205,30 @@ mod state_persistence_tests {
153
205
 
154
206
  let db = feltdb::FeltDb::open(&temp_path).expect("open db");
155
207
  let store = StateStore::with_feltdb(Arc::new(db)).expect("create store");
156
-
208
+
157
209
  // Commit sequence
158
- let rev1 = store.create(r#"{"step":1}"#.to_string(), "app".to_string()).expect("1");
159
- let rev2 = store.commit(r#"{"step":2}"#.to_string(), &rev1, "app".to_string()).expect("2");
160
- let rev3 = store.commit(r#"{"step":3}"#.to_string(), &rev2, "app".to_string()).expect("3");
161
- let rev4 = store.commit(r#"{"step":4}"#.to_string(), &rev3, "app".to_string()).expect("4");
162
- let rev5 = store.commit(r#"{"step":5}"#.to_string(), &rev4, "app".to_string()).expect("5");
163
-
210
+ let rev1 = store
211
+ .create("docs:1", r#"{"step":1}"#.to_string(), "app".to_string())
212
+ .expect("1");
213
+ let rev2 = store
214
+ .commit(r#"{"step":2}"#.to_string(), &rev1, "app".to_string())
215
+ .expect("2");
216
+ let rev3 = store
217
+ .commit(r#"{"step":3}"#.to_string(), &rev2, "app".to_string())
218
+ .expect("3");
219
+ let rev4 = store
220
+ .commit(r#"{"step":4}"#.to_string(), &rev3, "app".to_string())
221
+ .expect("4");
222
+ let rev5 = store
223
+ .commit(r#"{"step":5}"#.to_string(), &rev4, "app".to_string())
224
+ .expect("5");
225
+
164
226
  let id1 = rev1.id.clone();
165
227
  let id2 = rev2.id.clone();
166
228
  let id3 = rev3.id.clone();
167
229
  let id4 = rev4.id.clone();
168
230
  let id5 = rev5.id.clone();
169
-
231
+
170
232
  // All should exist
171
233
  assert!(store.exists(&id1));
172
234
  assert!(store.exists(&id2));
@@ -174,7 +236,10 @@ mod state_persistence_tests {
174
236
  assert!(store.exists(&id4));
175
237
  assert!(store.exists(&id5));
176
238
  let id5_hex = id5.as_hex().to_string();
177
- assert_eq!(store.current().map(|r| r.id.as_hex().to_string()), Some(id5_hex));
239
+ assert_eq!(
240
+ store.get(&id5).map(|r| r.id.as_hex().to_string()),
241
+ Some(id5_hex)
242
+ );
178
243
  }
179
244
 
180
245
  #[test]
@@ -185,10 +250,13 @@ mod state_persistence_tests {
185
250
  // Create and persist
186
251
  let db1 = feltdb::FeltDb::open(&temp_path).expect("open db");
187
252
  let store1 = StateStore::with_feltdb(Arc::new(db1)).expect("create store");
188
- let rev1 = store1.create(
189
- r#"{"complex":{"nested":{"data":[1,2,3],"unicode":"αβγ"}}}"#.to_string(),
190
- "auth".to_string()
191
- ).expect("create");
253
+ let rev1 = store1
254
+ .create(
255
+ "docs:1",
256
+ r#"{"complex":{"nested":{"data":[1,2,3],"unicode":"αβγ"}}}"#.to_string(),
257
+ "auth".to_string(),
258
+ )
259
+ .expect("create");
192
260
  let id1 = rev1.id.clone();
193
261
  drop(store1);
194
262
 
@@ -196,7 +264,10 @@ mod state_persistence_tests {
196
264
  let db2 = feltdb::FeltDb::open(&temp_path).expect("open db again");
197
265
  let store2 = StateStore::with_feltdb(Arc::new(db2)).expect("recovery");
198
266
  let recovered = store2.get(&id1).expect("get");
199
- assert_eq!(recovered.content, r#"{"complex":{"nested":{"data":[1,2,3],"unicode":"αβγ"}}}"#);
267
+ assert_eq!(
268
+ recovered.content,
269
+ r#"{"complex":{"nested":{"data":[1,2,3],"unicode":"αβγ"}}}"#
270
+ );
200
271
  }
201
272
 
202
273
  #[test]
@@ -206,7 +277,9 @@ mod state_persistence_tests {
206
277
 
207
278
  let db = feltdb::FeltDb::open(&temp_path).expect("open db");
208
279
  let store = StateStore::with_feltdb(Arc::new(db)).expect("create store");
209
- let rev1 = store.create(r#"{"v":1}"#.to_string(), "auth".to_string()).expect("create");
280
+ let rev1 = store
281
+ .create("docs:1", r#"{"v":1}"#.to_string(), "auth".to_string())
282
+ .expect("create");
210
283
  let id1 = rev1.id.clone();
211
284
 
212
285
  // Clone the store for concurrent access
@@ -216,11 +289,19 @@ mod state_persistence_tests {
216
289
  let id1_hex = id1.as_hex().to_string();
217
290
 
218
291
  // Both can read
219
- assert_eq!(store_clone1.current().map(|r| r.id.as_hex().to_string()), Some(id1_hex.clone()));
220
- assert_eq!(store_clone2.current().map(|r| r.id.as_hex().to_string()), Some(id1_hex));
292
+ assert_eq!(
293
+ store_clone1.get(&id1).map(|r| r.id.as_hex().to_string()),
294
+ Some(id1_hex.clone())
295
+ );
296
+ assert_eq!(
297
+ store_clone2.get(&id1).map(|r| r.id.as_hex().to_string()),
298
+ Some(id1_hex)
299
+ );
221
300
 
222
301
  // Commit from one
223
- let rev2 = store_clone1.commit(r#"{"v":2}"#.to_string(), &rev1, "auth".to_string()).expect("commit");
302
+ let rev2 = store_clone1
303
+ .commit(r#"{"v":2}"#.to_string(), &rev1, "auth".to_string())
304
+ .expect("commit");
224
305
  let id2 = rev2.id.clone();
225
306
 
226
307
  // Both should see the new revision
@@ -233,38 +314,52 @@ mod state_persistence_tests {
233
314
  let temp_dir = TempDir::new().unwrap();
234
315
  let temp_path = temp_dir.path().join("test.log");
235
316
 
317
+ // The caller carries the ids it cares about across restarts.
318
+ let rev2_id;
319
+ let rev3_id;
320
+
236
321
  // Cycle 1: create initial state
237
322
  {
238
323
  let db = feltdb::FeltDb::open(&temp_path).expect("open db");
239
324
  let store = StateStore::with_feltdb(Arc::new(db)).expect("create store");
240
- let rev1 = store.create(r#"{"cycle":1}"#.to_string(), "auth".to_string()).expect("create1");
241
- let _rev2 = store.commit(r#"{"cycle":1.5}"#.to_string(), &rev1, "auth".to_string()).expect("commit1");
325
+ let rev1 = store
326
+ .create("docs:1", r#"{"cycle":1}"#.to_string(), "auth".to_string())
327
+ .expect("create1");
328
+ rev2_id = store
329
+ .commit(r#"{"cycle":1.5}"#.to_string(), &rev1, "auth".to_string())
330
+ .expect("commit1")
331
+ .id;
242
332
  }
243
333
 
244
- // Cycle 2: recover and add more
334
+ // Cycle 2: reopen and add more, starting from the id we carried
245
335
  {
246
336
  let db = feltdb::FeltDb::open(&temp_path).expect("open db");
247
337
  let store = StateStore::with_feltdb(Arc::new(db)).expect("create store");
248
- let rev2 = store.current().expect("current");
249
- let _rev3 = store.commit(r#"{"cycle":2}"#.to_string(), &rev2, "auth".to_string()).expect("commit2");
338
+ let rev2 = store.get(&rev2_id).expect("rev2 survives");
339
+ rev3_id = store
340
+ .commit(r#"{"cycle":2}"#.to_string(), &rev2, "auth".to_string())
341
+ .expect("commit2")
342
+ .id;
250
343
  }
251
344
 
252
345
  // Cycle 3: verify all history
253
346
  {
254
347
  let db = feltdb::FeltDb::open(&temp_path).expect("open db");
255
348
  let store = StateStore::with_feltdb(Arc::new(db)).expect("create store");
256
- assert!(store.current().is_some(), "should have current state after 3 cycles");
257
-
349
+
258
350
  // Walk the chain backwards - count how many nodes we can reach
259
- let mut rev = store.current().expect("current");
260
- let mut count = 1; // Start with 1 for the current node
351
+ let mut rev = store.get(&rev3_id).expect("rev3 survives every cycle");
352
+ let mut count = 1; // Start with 1 for the current node
261
353
  while let Some(parent_id) = &rev.parent_id {
262
354
  rev = store.get(parent_id).expect("get parent");
263
355
  count += 1;
264
356
  }
265
-
266
- assert!(count >= 3, "should have chain of at least 3 revisions, got {}", count);
357
+
358
+ assert!(
359
+ count >= 3,
360
+ "should have chain of at least 3 revisions, got {}",
361
+ count
362
+ );
267
363
  }
268
364
  }
269
365
  }
270
-