@feltdb/core 0.8.3 → 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 (193) hide show
  1. package/dist/cli/commands.js +4 -1
  2. package/dist/cli/provisioning-neutrality.js +79 -0
  3. package/dist/collection.d.ts +43 -1
  4. package/dist/collection.d.ts.map +1 -1
  5. package/dist/collection.js +192 -22
  6. package/dist/create/create.js +25 -21
  7. package/dist/create/managed-account.js +11 -0
  8. package/dist/create/package-versions.js +1 -1
  9. package/dist/create/server-source/Cargo.lock +165 -0
  10. package/dist/create/server-source/Cargo.toml +9 -0
  11. package/dist/create/server-source/crates/feltdb/Cargo.toml +3 -0
  12. package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +44 -44
  13. package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +12 -24
  14. package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +7 -13
  15. package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +13 -10
  16. package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +12 -9
  17. package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +78 -25
  18. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +16 -13
  19. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +13 -5
  20. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +41 -22
  21. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +33 -15
  22. package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +100 -33
  23. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +56 -20
  24. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +116 -41
  25. package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +186 -55
  26. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +64 -26
  27. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +46 -15
  28. package/dist/create/server-source/crates/feltdb/src/admission.rs +8 -15
  29. package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +43 -13
  30. package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +15 -42
  31. package/dist/create/server-source/crates/feltdb/src/analytics.rs +65 -19
  32. package/dist/create/server-source/crates/feltdb/src/application.rs +113 -30
  33. package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +475 -140
  34. package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +17 -15
  35. package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -1
  36. package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +59 -15
  37. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +266 -114
  38. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +25 -7
  39. package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +10 -15
  40. package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +3 -11
  41. package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +14 -5
  42. package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +21 -25
  43. package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +14 -11
  44. package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +103 -22
  45. package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +18 -15
  46. package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +12 -8
  47. package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +1 -5
  48. package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +87 -23
  49. package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +3 -7
  50. package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +10 -9
  51. package/dist/create/server-source/crates/feltdb/src/equality_index.rs +595 -0
  52. package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +1 -6
  53. package/dist/create/server-source/crates/feltdb/src/indexing.rs +35 -38
  54. package/dist/create/server-source/crates/feltdb/src/lib.rs +1050 -117
  55. package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +4 -1
  56. package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -1
  57. package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +1 -2
  58. package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +107 -30
  59. package/dist/create/server-source/crates/feltdb/src/observability.rs +19 -6
  60. package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +12 -11
  61. package/dist/create/server-source/crates/feltdb/src/operation_log.rs +9 -4
  62. package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +65 -18
  63. package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +193 -57
  64. package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +37 -27
  65. package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +38 -10
  66. package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +20 -14
  67. package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +394 -229
  68. package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +8 -6
  69. package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +11 -13
  70. package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +90 -72
  71. package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +3 -3
  72. package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +33 -11
  73. package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +6 -6
  74. package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +14 -56
  75. package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +29 -27
  76. package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +35 -17
  77. package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +8 -2
  78. package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +59 -15
  79. package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +70 -17
  80. package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +23 -6
  81. package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +12 -3
  82. package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +41 -11
  83. package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +56 -25
  84. package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +701 -245
  85. package/dist/create/server-source/crates/feltdb/src/production_api.rs +31 -13
  86. package/dist/create/server-source/crates/feltdb/src/query_execution_diagnostics.rs +126 -0
  87. package/dist/create/server-source/crates/feltdb/src/query_performance.rs +6 -8
  88. package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +5 -5
  89. package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +48 -18
  90. package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +30 -11
  91. package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +6 -3
  92. package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +4 -3
  93. package/dist/create/server-source/crates/feltdb/src/sharding.rs +36 -10
  94. package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +516 -0
  95. package/dist/create/server-source/crates/feltdb/src/state_contract.rs +305 -6
  96. package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +222 -0
  97. package/dist/create/server-source/crates/feltdb/src/state_facade.rs +82 -54
  98. package/dist/create/server-source/crates/feltdb/src/state_hash.rs +2 -2
  99. package/dist/create/server-source/crates/feltdb/src/state_model.rs +1514 -537
  100. package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +6 -3
  101. package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +672 -0
  102. package/dist/create/server-source/crates/feltdb/src/submission.rs +5 -11
  103. package/dist/create/server-source/crates/feltdb/src/sync.rs +12 -0
  104. package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +6 -8
  105. package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +24 -35
  106. package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +24 -8
  107. package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +248 -59
  108. package/dist/create/server-source/crates/feltdb/src/transactions.rs +17 -20
  109. package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +749 -0
  110. package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +1 -0
  111. package/dist/create/server-source/crates/feltdb/src/workload.rs +512 -4
  112. package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +442 -0
  113. package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +299 -0
  114. package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +288 -0
  115. package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +392 -0
  116. package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +436 -220
  117. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +1916 -0
  118. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +1878 -0
  119. package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +1862 -0
  120. package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +234 -0
  121. package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +947 -0
  122. package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +5 -8
  123. package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +52 -44
  124. package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +33 -16
  125. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +22 -7
  126. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +41 -22
  127. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +25 -8
  128. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +9 -6
  129. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +120 -69
  130. package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +21 -10
  131. package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +1032 -0
  132. package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +868 -0
  133. package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +221 -0
  134. package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +338 -0
  135. package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +1039 -0
  136. package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +739 -0
  137. package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +427 -0
  138. package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +3 -3
  139. package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +25 -22
  140. package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +1799 -0
  141. package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +1316 -0
  142. package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +53 -61
  143. package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +156 -61
  144. package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +299 -0
  145. package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +255 -0
  146. package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +249 -0
  147. package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +994 -0
  148. package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +2 -1
  149. package/dist/create/server-source/crates/feltdb-server/src/audit.rs +1137 -29
  150. package/dist/create/server-source/crates/feltdb-server/src/auth.rs +164 -13
  151. package/dist/create/server-source/crates/feltdb-server/src/main.rs +800 -34
  152. package/dist/db.d.ts +33 -34
  153. package/dist/db.d.ts.map +1 -1
  154. package/dist/db.js +74 -20
  155. package/dist/deployment.d.ts +30 -0
  156. package/dist/deployment.d.ts.map +1 -0
  157. package/dist/deployment.js +130 -0
  158. package/dist/embedded-transaction.d.ts +22 -4
  159. package/dist/embedded-transaction.d.ts.map +1 -1
  160. package/dist/embedded-transaction.js +51 -5
  161. package/dist/feltdb.d.ts +14 -2
  162. package/dist/feltdb.d.ts.map +1 -1
  163. package/dist/file-db.js +1 -1
  164. package/dist/http-client.d.ts +14 -0
  165. package/dist/http-client.d.ts.map +1 -1
  166. package/dist/http-client.js +23 -5
  167. package/dist/http-db.d.ts +119 -1
  168. package/dist/http-db.d.ts.map +1 -1
  169. package/dist/http-db.js +346 -31
  170. package/dist/index-core.d.ts +2 -0
  171. package/dist/index-core.d.ts.map +1 -1
  172. package/dist/index-core.js +2 -0
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.js +9 -0
  175. package/dist/indexeddb-db.d.ts.map +1 -1
  176. package/dist/indexeddb-db.js +35 -21
  177. package/dist/managed-recovery.d.ts +192 -0
  178. package/dist/managed-recovery.d.ts.map +1 -0
  179. package/dist/managed-recovery.js +242 -0
  180. package/dist/memory-db.js +1 -1
  181. package/dist/studio-app/assets/{feltdb_wasm-DB8cX151.js → feltdb_wasm-DaNwCLRX.js} +1 -1
  182. package/dist/studio-app/assets/feltdb_wasm_bg-DnsHNv6g.wasm +0 -0
  183. package/dist/studio-app/assets/index-j8IlhNqJ.js +29 -0
  184. package/dist/studio-app/index.html +1 -1
  185. package/dist/transaction.d.ts +30 -0
  186. package/dist/transaction.d.ts.map +1 -1
  187. package/dist/transaction.js +41 -0
  188. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  189. package/dist/workload.d.ts +2 -1
  190. package/dist/workload.d.ts.map +1 -1
  191. package/package.json +1 -1
  192. package/dist/studio-app/assets/feltdb_wasm_bg-ClhDHp0S.wasm +0 -0
  193. package/dist/studio-app/assets/index-B0k4UAlI.js +0 -29
@@ -33,11 +33,11 @@
33
33
  /// - Resource usage (memory, CPU)
34
34
  /// - Rejection behavior
35
35
  /// - Correctness verification
36
-
37
36
  use criterion::{criterion_group, criterion_main, Criterion};
38
37
  use feltdb::{
39
38
  causal_dependency_barrier::CausalDependencyBarrier,
40
- convergence::VectorClock, submission::{SubmissionManager, SubmissionMetrics},
39
+ convergence::VectorClock,
40
+ submission::{SubmissionManager, SubmissionMetrics},
41
41
  transactions::{Operation, OperationCommand, OperationId, StateVersion},
42
42
  };
43
43
  use std::collections::HashMap;
@@ -78,7 +78,13 @@ impl SeededRng {
78
78
  }
79
79
  }
80
80
 
81
- fn generate_operation(rng: &mut SeededRng, op_id: u64, seq: u64, node: &str, client_id: usize) -> Operation {
81
+ fn generate_operation(
82
+ rng: &mut SeededRng,
83
+ op_id: u64,
84
+ seq: u64,
85
+ node: &str,
86
+ client_id: usize,
87
+ ) -> Operation {
82
88
  let record_id = format!("rec_{}", rng.next_range(0, 99));
83
89
  let _is_write = rng.next_f64() >= 0.7; // 70% reads, 30% writes
84
90
 
@@ -163,10 +169,7 @@ struct BacklogMetrics {
163
169
  // MEASUREMENT
164
170
  // ============================================================================
165
171
 
166
- async fn measure_backlog_level(
167
- writers: usize,
168
- backlog_depth: usize,
169
- ) -> BacklogMetrics {
172
+ async fn measure_backlog_level(writers: usize, backlog_depth: usize) -> BacklogMetrics {
170
173
  // Create causal dependency barrier for this measurement
171
174
  let mut barrier = CausalDependencyBarrier::new();
172
175
  let mut frontier = VectorClock::new();
@@ -180,7 +183,9 @@ async fn measure_backlog_level(
180
183
  let mut required_deps = VectorClock::new();
181
184
  // Create dependencies on future state (far beyond current frontier)
182
185
  // This ensures the operation will be causally blocked
183
- required_deps.clocks.insert("backlog_producer".to_string(), (10000 + i) as u64);
186
+ required_deps
187
+ .clocks
188
+ .insert("backlog_producer".to_string(), (10000 + i) as u64);
184
189
  let op_id = format!("pending_backlog_{}", i);
185
190
  let _ = barrier.receive_operation(op_id, required_deps);
186
191
  }
@@ -198,8 +203,10 @@ async fn measure_backlog_level(
198
203
 
199
204
  // Now measure submission performance while backlog exists
200
205
  let tx_manager = Arc::new(Mutex::new(
201
- feltdb::transaction_api::TransactionManager::new("node1".to_string(),
202
- StateVersion::new(frontier.clone(), "hash0".to_string())),
206
+ feltdb::transaction_api::TransactionManager::new(
207
+ "node1".to_string(),
208
+ StateVersion::new(frontier.clone(), "hash0".to_string()),
209
+ ),
203
210
  ));
204
211
 
205
212
  let submission_manager = SubmissionManager::new(Arc::clone(&tx_manager));
@@ -238,11 +245,13 @@ async fn measure_backlog_level(
238
245
  let outcomes = outcomes.lock().unwrap().clone();
239
246
 
240
247
  let initial_attempted = outcomes.len();
241
- let initial_accepted = outcomes.iter()
248
+ let initial_accepted = outcomes
249
+ .iter()
242
250
  .filter(|(eventually, first_lat, _)| *first_lat > 0 && *eventually)
243
251
  .count();
244
252
  let initial_rejected = initial_attempted - initial_accepted;
245
- let final_accepted = outcomes.iter()
253
+ let final_accepted = outcomes
254
+ .iter()
246
255
  .filter(|(eventually, _, _)| *eventually)
247
256
  .count();
248
257
  let final_permanently_rejected = initial_attempted - final_accepted;
@@ -287,7 +296,10 @@ async fn measure_backlog_level(
287
296
  // State hash: for causal barrier measurement, hash reflects frontier state
288
297
  let frontier_hash = format!("{:?}", frontier.clocks);
289
298
  let expected_hash = format!("{:08x}", frontier_hash.len() as u32);
290
- let actual_hash = format!("{:08x}", (backlog_depth ^ writers ^ final_accepted as usize) as u32);
299
+ let actual_hash = format!(
300
+ "{:08x}",
301
+ (backlog_depth ^ writers ^ final_accepted as usize) as u32
302
+ );
291
303
 
292
304
  let correctness_verified = actual_pending_count == backlog_depth;
293
305
  BacklogMetrics {
@@ -333,28 +345,51 @@ fn gate_14b_causal_backlog_scaling(c: &mut Criterion) {
333
345
  println!("\nTEST MATRIX:");
334
346
  println!(" Writers: {:?}", WRITERS);
335
347
  println!(" Backlog levels: {:?}", BACKLOG_LEVELS);
336
- println!(" Total combinations: {}\n", WRITERS.len() * BACKLOG_LEVELS.len());
348
+ println!(
349
+ " Total combinations: {}\n",
350
+ WRITERS.len() * BACKLOG_LEVELS.len()
351
+ );
337
352
 
338
353
  for &writer_count in WRITERS {
339
354
  println!("\n--- Writers: {} ---", writer_count);
340
355
  for &backlog_level in BACKLOG_LEVELS {
341
356
  let result = rt.block_on(measure_backlog_level(writer_count, backlog_level));
342
357
 
343
- println!("\n=== Writers={} Backlog={} ===", writer_count, backlog_level);
358
+ println!(
359
+ "\n=== Writers={} Backlog={} ===",
360
+ writer_count, backlog_level
361
+ );
344
362
  println!("\nADMISSION SEMANTICS (14A preserved):");
345
- println!(" initial_admission_attempted: {}", result.initial_attempted);
346
- println!(" initial_admission_accepted: {}", result.initial_accepted);
347
- println!(" initial_admission_rejected: {}", result.initial_rejected);
348
- println!(" initial_acceptance_rate_percent: {:.1}%",
363
+ println!(
364
+ " initial_admission_attempted: {}",
365
+ result.initial_attempted
366
+ );
367
+ println!(
368
+ " initial_admission_accepted: {}",
369
+ result.initial_accepted
370
+ );
371
+ println!(
372
+ " initial_admission_rejected: {}",
373
+ result.initial_rejected
374
+ );
375
+ println!(
376
+ " initial_acceptance_rate_percent: {:.1}%",
349
377
  if result.initial_attempted > 0 {
350
378
  (result.initial_accepted as f64 / result.initial_attempted as f64) * 100.0
351
379
  } else {
352
380
  0.0
353
381
  }
354
382
  );
355
- println!(" final_outcome_accepted: {}", result.final_accepted);
356
- println!(" final_outcome_permanently_rejected: {}", result.final_permanently_rejected);
357
- println!(" eventual_acceptance_rate_percent: {:.1}%",
383
+ println!(
384
+ " final_outcome_accepted: {}",
385
+ result.final_accepted
386
+ );
387
+ println!(
388
+ " final_outcome_permanently_rejected: {}",
389
+ result.final_permanently_rejected
390
+ );
391
+ println!(
392
+ " eventual_acceptance_rate_percent: {:.1}%",
358
393
  if result.initial_attempted > 0 {
359
394
  (result.final_accepted as f64 / result.initial_attempted as f64) * 100.0
360
395
  } else {
@@ -363,21 +398,53 @@ fn gate_14b_causal_backlog_scaling(c: &mut Criterion) {
363
398
  );
364
399
 
365
400
  println!("\nPERFORMANCE:");
366
- println!(" throughput_ops_sec: {:.3}", result.throughput_ops_sec);
367
- println!(" admission_rate_ops_sec: {:.3}", result.admission_rate_ops_sec);
368
- println!(" backlog_drain_rate_ops_sec: {:.3}", result.backlog_drain_rate_ops_sec);
369
- println!(" causal_readiness_p50_us: {}", result.p50_causal_readiness_us);
370
- println!(" causal_readiness_p95_us: {}", result.p95_causal_readiness_us);
371
- println!(" causal_readiness_p99_us: {}", result.p99_causal_readiness_us);
401
+ println!(
402
+ " throughput_ops_sec: {:.3}",
403
+ result.throughput_ops_sec
404
+ );
405
+ println!(
406
+ " admission_rate_ops_sec: {:.3}",
407
+ result.admission_rate_ops_sec
408
+ );
409
+ println!(
410
+ " backlog_drain_rate_ops_sec: {:.3}",
411
+ result.backlog_drain_rate_ops_sec
412
+ );
413
+ println!(
414
+ " causal_readiness_p50_us: {}",
415
+ result.p50_causal_readiness_us
416
+ );
417
+ println!(
418
+ " causal_readiness_p95_us: {}",
419
+ result.p95_causal_readiness_us
420
+ );
421
+ println!(
422
+ " causal_readiness_p99_us: {}",
423
+ result.p99_causal_readiness_us
424
+ );
372
425
 
373
426
  println!("\nRESOURCES:");
374
- println!(" peak_total_heap_kb: {}", result.peak_heap_kb);
427
+ println!(
428
+ " peak_total_heap_kb: {}",
429
+ result.peak_heap_kb
430
+ );
375
431
 
376
432
  println!("\nCORRECTNESS:");
377
- println!(" expected_state_hash: {}", result.expected_state_hash);
378
- println!(" actual_state_hash: {}", result.actual_state_hash);
379
- println!(" match: {}",
380
- if result.correctness_verified { "PASS" } else { "FAIL" }
433
+ println!(
434
+ " expected_state_hash: {}",
435
+ result.expected_state_hash
436
+ );
437
+ println!(
438
+ " actual_state_hash: {}",
439
+ result.actual_state_hash
440
+ );
441
+ println!(
442
+ " match: {}",
443
+ if result.correctness_verified {
444
+ "PASS"
445
+ } else {
446
+ "FAIL"
447
+ }
381
448
  );
382
449
  }
383
450
  }
@@ -14,7 +14,6 @@
14
14
  /// 4. Delayed: Messages arrive late → eventual convergence ✓
15
15
  /// 5. Dropped + Retx: Message lost then resent → reconciliation recovers it
16
16
  /// 6. Causal dependency: Operation depends on prior → waiting/ready state correct
17
-
18
17
  use feltdb::{
19
18
  convergence::VectorClock,
20
19
  distributed_transactions::{DistributedTransactionExecutor, ReplicationMessage},
@@ -116,7 +115,8 @@ fn main() {
116
115
  async fn test_basic_2replica_convergence() {
117
116
  // Setup: 1 leader + 1 replica
118
117
  let initial_hash = StateHash::from_hex("hash0".to_string());
119
- let mut leader = DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
118
+ let mut leader =
119
+ DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
120
120
  leader.register_replica("replica_1".to_string(), initial_hash.clone());
121
121
  let mut replica = DistributedTransactionExecutor::new("replica_1".to_string(), initial_hash);
122
122
 
@@ -155,7 +155,10 @@ async fn test_basic_2replica_convergence() {
155
155
 
156
156
  match result {
157
157
  Ok(envelope) => {
158
- leader_hashes.push(format!("{:?}", leader.get_replica_state("leader").map(|s| s.state_hash)));
158
+ leader_hashes.push(format!(
159
+ "{:?}",
160
+ leader.get_replica_state("leader").map(|s| s.state_hash)
161
+ ));
159
162
  println!(" ✓ Leader applied operation {}", seq);
160
163
 
161
164
  // Replicate to follower
@@ -203,7 +206,8 @@ async fn test_basic_2replica_convergence() {
203
206
 
204
207
  async fn test_duplicate_message_handling() {
205
208
  let initial_hash = StateHash::from_hex("hash0".to_string());
206
- let mut leader = DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
209
+ let mut leader =
210
+ DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
207
211
  leader.register_replica("replica_1".to_string(), initial_hash.clone());
208
212
  let mut replica = DistributedTransactionExecutor::new("replica_1".to_string(), initial_hash);
209
213
 
@@ -247,14 +251,28 @@ async fn test_duplicate_message_handling() {
247
251
  msg.clone(),
248
252
  StateVersion::new(VectorClock::new(), "hash0".to_string()),
249
253
  );
250
- println!(" First delivery: {}", if result1.is_ok() { "✓ OK" } else { "✗ Failed" });
254
+ println!(
255
+ " First delivery: {}",
256
+ if result1.is_ok() {
257
+ "✓ OK"
258
+ } else {
259
+ "✗ Failed"
260
+ }
261
+ );
251
262
 
252
263
  // Deliver same message again (duplicate)
253
264
  let result2 = replica.receive_replicated_transaction(
254
265
  msg,
255
266
  StateVersion::new(VectorClock::new(), "hash0".to_string()),
256
267
  );
257
- println!(" Duplicate delivery: {}", if result2.is_err() { "✓ Rejected (correct)" } else { "✗ Accepted (wrong!)" });
268
+ println!(
269
+ " Duplicate delivery: {}",
270
+ if result2.is_err() {
271
+ "✓ Rejected (correct)"
272
+ } else {
273
+ "✗ Accepted (wrong!)"
274
+ }
275
+ );
258
276
 
259
277
  // Verify only applied once
260
278
  if let Some(state) = replica.get_replica_state("replica_1") {
@@ -264,7 +282,8 @@ async fn test_duplicate_message_handling() {
264
282
 
265
283
  async fn test_out_of_order_delivery() {
266
284
  let initial_hash = StateHash::from_hex("hash0".to_string());
267
- let mut leader = DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
285
+ let mut leader =
286
+ DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
268
287
  leader.register_replica("replica_1".to_string(), initial_hash.clone());
269
288
  let mut replica = DistributedTransactionExecutor::new("replica_1".to_string(), initial_hash);
270
289
 
@@ -317,19 +336,27 @@ async fn test_out_of_order_delivery() {
317
336
  msg,
318
337
  StateVersion::new(VectorClock::new(), "hash0".to_string()),
319
338
  );
320
- println!(" Operation {} delivered: {}", seq, if result.is_ok() { "✓" } else { "✗" });
339
+ println!(
340
+ " Operation {} delivered: {}",
341
+ seq,
342
+ if result.is_ok() { "✓" } else { "✗" }
343
+ );
321
344
  }
322
345
  }
323
346
 
324
347
  // Verify replica eventually has all operations
325
348
  if let Some(state) = replica.get_replica_state("replica_1") {
326
- println!(" Replica has {} operations (expected 3)", state.operations_applied);
349
+ println!(
350
+ " Replica has {} operations (expected 3)",
351
+ state.operations_applied
352
+ );
327
353
  }
328
354
  }
329
355
 
330
356
  async fn test_delayed_delivery() {
331
357
  let initial_hash = StateHash::from_hex("hash0".to_string());
332
- let mut leader = DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
358
+ let mut leader =
359
+ DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
333
360
  leader.register_replica("replica_1".to_string(), initial_hash.clone());
334
361
  let mut replica = DistributedTransactionExecutor::new("replica_1".to_string(), initial_hash);
335
362
 
@@ -361,12 +388,7 @@ async fn test_delayed_delivery() {
361
388
  )
362
389
  .expect("Leader execution failed");
363
390
 
364
- let msg = ReplicationMessage::new(
365
- envelope,
366
- "leader".to_string(),
367
- "replica_1".to_string(),
368
- 0,
369
- );
391
+ let msg = ReplicationMessage::new(envelope, "leader".to_string(), "replica_1".to_string(), 0);
370
392
 
371
393
  println!(" Simulating delay...");
372
394
  // In a real test, this would use tokio::time::sleep, but for now just immediate delivery
@@ -374,7 +396,14 @@ async fn test_delayed_delivery() {
374
396
  msg,
375
397
  StateVersion::new(VectorClock::new(), "hash0".to_string()),
376
398
  );
377
- println!(" After delay delivery: {}", if result.is_ok() { "✓ OK" } else { "✗ Failed" });
399
+ println!(
400
+ " After delay delivery: {}",
401
+ if result.is_ok() {
402
+ "✓ OK"
403
+ } else {
404
+ "✗ Failed"
405
+ }
406
+ );
378
407
 
379
408
  // Verify convergence
380
409
  let leader_state = leader.get_replica_state("leader");
@@ -398,7 +427,8 @@ async fn test_delayed_delivery() {
398
427
 
399
428
  async fn test_drop_and_retransmission() {
400
429
  let initial_hash = StateHash::from_hex("hash0".to_string());
401
- let mut leader = DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
430
+ let mut leader =
431
+ DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone());
402
432
  leader.register_replica("replica_1".to_string(), initial_hash.clone());
403
433
  let mut replica = DistributedTransactionExecutor::new("replica_1".to_string(), initial_hash);
404
434
 
@@ -445,7 +475,14 @@ async fn test_drop_and_retransmission() {
445
475
  msg,
446
476
  StateVersion::new(VectorClock::new(), "hash0".to_string()),
447
477
  );
448
- println!(" Message retransmitted: {}", if result.is_ok() { "✓ OK" } else { "✗ Failed" });
478
+ println!(
479
+ " Message retransmitted: {}",
480
+ if result.is_ok() {
481
+ "✓ OK"
482
+ } else {
483
+ "✗ Failed"
484
+ }
485
+ );
449
486
 
450
487
  // Verify convergence
451
488
  let leader_state = leader.get_replica_state("leader");
@@ -466,4 +503,3 @@ async fn test_drop_and_retransmission() {
466
503
  _ => println!(" ✗ State retrieval failed"),
467
504
  }
468
505
  }
469
-
@@ -26,14 +26,15 @@
26
26
  /// - Convergence time
27
27
  /// - Peak heap per replica
28
28
  /// - State hash correctness across all replicas
29
-
30
29
  use feltdb::{
31
- convergence::VectorClock, distributed_transactions::{
30
+ convergence::VectorClock,
31
+ distributed_transactions::{
32
32
  DistributedTransactionExecutor, ReplicationMessage, TransactionEnvelope,
33
33
  },
34
- state_hash::StateHash, submission::{SubmissionManager},
34
+ state_hash::StateHash,
35
+ submission::SubmissionManager,
35
36
  transaction_api::TransactionManager,
36
- transactions::{Operation, OperationCommand, OperationId, StateVersion, ConsistencyContract},
37
+ transactions::{ConsistencyContract, Operation, OperationCommand, OperationId, StateVersion},
37
38
  };
38
39
  use std::collections::HashMap;
39
40
  use std::sync::{Arc, Mutex};
@@ -73,7 +74,13 @@ impl SeededRng {
73
74
  }
74
75
  }
75
76
 
76
- fn generate_operation(rng: &mut SeededRng, op_id: u64, seq: u64, node: &str, client_id: usize) -> Operation {
77
+ fn generate_operation(
78
+ rng: &mut SeededRng,
79
+ op_id: u64,
80
+ seq: u64,
81
+ node: &str,
82
+ client_id: usize,
83
+ ) -> Operation {
77
84
  let record_id = format!("rec_{}", rng.next_range(0, 99));
78
85
  let _is_write = rng.next_f64() >= 0.7; // 70% reads, 30% writes
79
86
 
@@ -155,15 +162,13 @@ struct ReplicationMetrics {
155
162
  // MEASUREMENT
156
163
  // ============================================================================
157
164
 
158
- async fn measure_replication_level(
159
- writers: usize,
160
- replica_count: usize,
161
- ) -> ReplicationMetrics {
165
+ async fn measure_replication_level(writers: usize, replica_count: usize) -> ReplicationMetrics {
162
166
  // Initialize distributed system with N replicas
163
167
  let initial_hash = StateHash::from_hex("hash0".to_string());
164
- let leader_executor = Arc::new(Mutex::new(
165
- DistributedTransactionExecutor::new("leader".to_string(), initial_hash.clone()),
166
- ));
168
+ let leader_executor = Arc::new(Mutex::new(DistributedTransactionExecutor::new(
169
+ "leader".to_string(),
170
+ initial_hash.clone(),
171
+ )));
167
172
 
168
173
  // Create follower replicas
169
174
  let mut follower_executors = Vec::new();
@@ -173,9 +178,10 @@ async fn measure_replication_level(
173
178
  let replica_id = format!("replica_{}", i);
174
179
  leader.register_replica(replica_id.clone(), initial_hash.clone());
175
180
 
176
- let replica_executor = Arc::new(Mutex::new(
177
- DistributedTransactionExecutor::new(replica_id, initial_hash.clone()),
178
- ));
181
+ let replica_executor = Arc::new(Mutex::new(DistributedTransactionExecutor::new(
182
+ replica_id,
183
+ initial_hash.clone(),
184
+ )));
179
185
  follower_executors.push(replica_executor);
180
186
  }
181
187
  }
@@ -188,7 +194,10 @@ async fn measure_replication_level(
188
194
  for client_id in 0..writers {
189
195
  let outcomes = Arc::clone(&outcomes);
190
196
  let leader = Arc::clone(&leader_executor);
191
- let followers = follower_executors.iter().map(Arc::clone).collect::<Vec<_>>();
197
+ let followers = follower_executors
198
+ .iter()
199
+ .map(Arc::clone)
200
+ .collect::<Vec<_>>();
192
201
  let global_seq = Arc::clone(&global_seq);
193
202
 
194
203
  let handle = tokio::spawn(async move {
@@ -279,13 +288,16 @@ async fn measure_replication_level(
279
288
  }
280
289
 
281
290
  let avg_applied = if !operations_applied_per_replica.is_empty() {
282
- operations_applied_per_replica.iter().sum::<usize>() as f64 / operations_applied_per_replica.len() as f64
291
+ operations_applied_per_replica.iter().sum::<usize>() as f64
292
+ / operations_applied_per_replica.len() as f64
283
293
  } else {
284
294
  0.0
285
295
  };
286
296
 
287
297
  // Check convergence: all replicas should have applied same operations
288
- let all_same = operations_applied_per_replica.iter().all(|&c| c == operations_accepted);
298
+ let all_same = operations_applied_per_replica
299
+ .iter()
300
+ .all(|&c| c == operations_accepted);
289
301
  let converged = all_same && operations_applied_per_replica.len() == replica_count;
290
302
 
291
303
  // Estimate lag
@@ -295,7 +307,10 @@ async fn measure_replication_level(
295
307
  0
296
308
  };
297
309
 
298
- let correctness_check = converged && operations_applied_per_replica.iter().all(|&c| c == operations_accepted);
310
+ let correctness_check = converged
311
+ && operations_applied_per_replica
312
+ .iter()
313
+ .all(|&c| c == operations_accepted);
299
314
 
300
315
  ReplicationMetrics {
301
316
  replica_count,
@@ -346,59 +361,119 @@ fn main() {
346
361
  println!("\nTEST MATRIX:");
347
362
  println!(" Writers: {:?}", WRITERS);
348
363
  println!(" Replica counts: {:?}", REPLICA_COUNTS);
349
- println!(" Total combinations: {}\n", WRITERS.len() * REPLICA_COUNTS.len());
364
+ println!(
365
+ " Total combinations: {}\n",
366
+ WRITERS.len() * REPLICA_COUNTS.len()
367
+ );
350
368
 
351
369
  for &writer_count in WRITERS {
352
370
  println!("\n--- Writers: {} ---", writer_count);
353
371
  for &replica_count in REPLICA_COUNTS {
354
372
  let result = rt.block_on(measure_replication_level(writer_count, replica_count));
355
373
 
356
- println!("\n=== Writers={} Replicas={} ===", writer_count, replica_count);
374
+ println!(
375
+ "\n=== Writers={} Replicas={} ===",
376
+ writer_count, replica_count
377
+ );
357
378
  println!("\nREPLICATION SEMANTICS:");
358
- println!(" operations_attempted: {}", result.operations_attempted);
359
- println!(" operations_accepted_by_leader: {}", result.operations_accepted_by_leader);
360
- println!(" acceptance_rate_percent: {:.1}%", result.acceptance_rate_percent);
379
+ println!(
380
+ " operations_attempted: {}",
381
+ result.operations_attempted
382
+ );
383
+ println!(
384
+ " operations_accepted_by_leader: {}",
385
+ result.operations_accepted_by_leader
386
+ );
387
+ println!(
388
+ " acceptance_rate_percent: {:.1}%",
389
+ result.acceptance_rate_percent
390
+ );
361
391
 
362
392
  println!("\nREPLICATION THROUGHPUT:");
363
- println!(" replication_throughput_ops_sec: {:.3}",
393
+ println!(
394
+ " replication_throughput_ops_sec: {:.3}",
364
395
  if result.convergence_time_us > 0 {
365
- (result.operations_accepted_by_leader as f64 * 1_000_000.0) / result.convergence_time_us as f64
396
+ (result.operations_accepted_by_leader as f64 * 1_000_000.0)
397
+ / result.convergence_time_us as f64
366
398
  } else {
367
399
  0.0
368
- });
400
+ }
401
+ );
369
402
  for (i, &applied) in result.operations_applied_per_replica.iter().enumerate() {
370
403
  if i == 0 {
371
404
  println!(" operations_applied_by_leader: {}", applied);
372
405
  } else {
373
- println!(" operations_applied_by_replica_{}: {}", i - 1, applied);
406
+ println!(
407
+ " operations_applied_by_replica_{}: {}",
408
+ i - 1,
409
+ applied
410
+ );
374
411
  }
375
412
  }
376
413
 
377
414
  println!("\nREPLICATION LATENCY:");
378
- println!(" p50_replication_lag_us: {}", result.p50_replication_lag_us);
379
- println!(" p95_replication_lag_us: {}", result.p95_replication_lag_us);
380
- println!(" p99_replication_lag_us: {}", result.p99_replication_lag_us);
381
- println!(" max_replication_lag_us: {}", result.max_replication_lag_us);
415
+ println!(
416
+ " p50_replication_lag_us: {}",
417
+ result.p50_replication_lag_us
418
+ );
419
+ println!(
420
+ " p95_replication_lag_us: {}",
421
+ result.p95_replication_lag_us
422
+ );
423
+ println!(
424
+ " p99_replication_lag_us: {}",
425
+ result.p99_replication_lag_us
426
+ );
427
+ println!(
428
+ " max_replication_lag_us: {}",
429
+ result.max_replication_lag_us
430
+ );
382
431
 
383
432
  println!("\nCONVERGENCE:");
384
- println!(" convergence_time_us: {}", result.convergence_time_us);
385
- println!(" all_replicas_converged: {}",
386
- if result.all_replicas_converged { "YES" } else { "NO" });
433
+ println!(
434
+ " convergence_time_us: {}",
435
+ result.convergence_time_us
436
+ );
437
+ println!(
438
+ " all_replicas_converged: {}",
439
+ if result.all_replicas_converged {
440
+ "YES"
441
+ } else {
442
+ "NO"
443
+ }
444
+ );
387
445
 
388
446
  println!("\nRECONCILIATION:");
389
- println!(" reconciliation_messages: {}", result.reconciliation_messages);
390
- println!(" network_amplification: {:.3}", result.network_amplification);
447
+ println!(
448
+ " reconciliation_messages: {}",
449
+ result.reconciliation_messages
450
+ );
451
+ println!(
452
+ " network_amplification: {:.3}",
453
+ result.network_amplification
454
+ );
391
455
 
392
456
  println!("\nRESOURCES:");
393
- println!(" peak_heap_kb: {}", result.peak_heap_kb);
457
+ println!(
458
+ " peak_heap_kb: {}",
459
+ result.peak_heap_kb
460
+ );
394
461
 
395
462
  println!("\nCORRECTNESS:");
396
- println!(" expected_state_hash: {}", result.expected_hash);
463
+ println!(
464
+ " expected_state_hash: {}",
465
+ result.expected_hash
466
+ );
397
467
  for (i, hash) in result.replica_hashes.iter().enumerate() {
398
468
  println!(" replica_{}_state_hash: {}", i, hash);
399
469
  }
400
- println!(" correctness_verified: {}",
401
- if result.correctness_verified { "PASS" } else { "FAIL" }
470
+ println!(
471
+ " correctness_verified: {}",
472
+ if result.correctness_verified {
473
+ "PASS"
474
+ } else {
475
+ "FAIL"
476
+ }
402
477
  );
403
478
  }
404
479
  }