@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
@@ -166,7 +166,8 @@ fn a_scan_result_survives_concurrent_mutation() {
166
166
  // The scan returns owned records, so mutation after the lock is released
167
167
  // cannot invalidate or rewrite what the caller already holds.
168
168
  for index in 0..200 {
169
- db.delete(&format!("items:record-{index:05}")).expect("delete");
169
+ db.delete(&format!("items:record-{index:05}"))
170
+ .expect("delete");
170
171
  }
171
172
 
172
173
  assert_eq!(matches.len(), 50);
@@ -41,7 +41,8 @@ fn database() -> (TempDir, FeltDb) {
41
41
  /// A database with `status` and `tenantId` indexed on `items`.
42
42
  fn indexed() -> (TempDir, FeltDb) {
43
43
  let (directory, db) = database();
44
- db.create_equality_index("items", "status").expect("declare");
44
+ db.create_equality_index("items", "status")
45
+ .expect("declare");
45
46
  db.create_equality_index("items", "tenantId")
46
47
  .expect("declare");
47
48
  (directory, db)
@@ -53,7 +54,9 @@ fn indexed() -> (TempDir, FeltDb) {
53
54
  fn assert_index_matches_state(db: &FeltDb, after: &str) {
54
55
  match db.verify_equality_index().expect("verify") {
55
56
  Ok(()) => {}
56
- Err(divergence) => panic!("index diverged from authoritative state after {after}: {divergence}"),
57
+ Err(divergence) => {
58
+ panic!("index diverged from authoritative state after {after}: {divergence}")
59
+ }
57
60
  }
58
61
  }
59
62
 
@@ -67,7 +70,11 @@ fn ids(db: &FeltDb, field: &str, value: Value) -> Vec<String> {
67
70
  candidates(db, field, value)
68
71
  .expect("the field is indexed and the value is indexable")
69
72
  .into_iter()
70
- .map(|key| key.split_once(':').map(|(_, id)| id.to_string()).unwrap_or(key))
73
+ .map(|key| {
74
+ key.split_once(':')
75
+ .map(|(_, id)| id.to_string())
76
+ .unwrap_or(key)
77
+ })
71
78
  .collect()
72
79
  }
73
80
 
@@ -155,7 +162,11 @@ fn an_update_that_leaves_the_indexed_field_alone_leaves_the_index_alone() {
155
162
  db.update("items:a", &json!({ "status": "active", "note": "after" }))
156
163
  .expect("update");
157
164
 
158
- assert_eq!(snapshot(&db), before, "an unrelated field change is invisible to the index");
165
+ assert_eq!(
166
+ snapshot(&db),
167
+ before,
168
+ "an unrelated field change is invisible to the index"
169
+ );
159
170
  assert_index_matches_state(&db, "an unrelated field changing");
160
171
  }
161
172
 
@@ -260,7 +271,11 @@ fn unindexable_values_are_excluded_rather_than_coerced() {
260
271
  put(&db, "object", json!({ "status": { "state": "active" } }));
261
272
  put(&db, "array", json!({ "status": ["active"] }));
262
273
  put(&db, "scalar", json!({ "status": "active" }));
263
- put(&db, "not-an-object", json!("items are usually objects, but need not be"));
274
+ put(
275
+ &db,
276
+ "not-an-object",
277
+ json!("items are usually objects, but need not be"),
278
+ );
264
279
 
265
280
  assert_eq!(
266
281
  ids(&db, "status", json!("active")),
@@ -351,8 +366,16 @@ fn conditional_creation_maintains_the_index_when_it_wins_and_not_when_it_loses()
351
366
  key: "items:a".into(),
352
367
  value: Some(json!({ "status": "active" })),
353
368
  };
354
- db.apply_atomic_transaction_guarded("pr35-put-1", None, None, &[], &[absent.clone()], &[write.clone()], None)
355
- .expect("the record is absent, so the creation wins");
369
+ db.apply_atomic_transaction_guarded(
370
+ "pr35-put-1",
371
+ None,
372
+ None,
373
+ &[],
374
+ &[absent.clone()],
375
+ &[write.clone()],
376
+ None,
377
+ )
378
+ .expect("the record is absent, so the creation wins");
356
379
  assert_eq!(ids(&db, "status", json!("active")), vec!["a".to_string()]);
357
380
  assert_index_matches_state(&db, "a conditional creation that won");
358
381
 
@@ -520,14 +543,17 @@ fn declaring_an_index_populates_it_from_state_that_already_exists() {
520
543
  None,
521
544
  "before declaration there is no index to consult",
522
545
  );
523
- assert!(db.create_equality_index("items", "status").expect("declare"));
546
+ assert!(db
547
+ .create_equality_index("items", "status")
548
+ .expect("declare"));
524
549
  assert_eq!(
525
550
  ids(&db, "status", json!("active")),
526
551
  vec!["a".to_string()],
527
552
  "declaration derives the index from the records already held",
528
553
  );
529
554
  assert!(
530
- !db.create_equality_index("items", "status").expect("declare"),
555
+ !db.create_equality_index("items", "status")
556
+ .expect("declare"),
531
557
  "re-declaring an existing index reports that it created nothing",
532
558
  );
533
559
  assert_index_matches_state(&db, "declaring an index over existing state");
@@ -548,8 +574,11 @@ fn an_explicit_rebuild_reproduces_the_maintained_index_exactly() {
548
574
  );
549
575
  }
550
576
  db.delete("items:record-000").expect("delete");
551
- db.update("items:record-001", &json!({ "status": "active", "tenantId": "tenant-9" }))
552
- .expect("update");
577
+ db.update(
578
+ "items:record-001",
579
+ &json!({ "status": "active", "tenantId": "tenant-9" }),
580
+ )
581
+ .expect("update");
553
582
 
554
583
  let maintained = snapshot(&db);
555
584
  db.rebuild_equality_indexes().expect("rebuild");
@@ -567,8 +596,10 @@ fn reopening_the_database_rebuilds_the_index_from_durable_state() {
567
596
 
568
597
  let before = {
569
598
  let db = FeltDb::open(&path).expect("open");
570
- db.create_equality_index("items", "status").expect("declare");
571
- db.create_equality_index("items", "tenantId").expect("declare");
599
+ db.create_equality_index("items", "status")
600
+ .expect("declare");
601
+ db.create_equality_index("items", "tenantId")
602
+ .expect("declare");
572
603
  for step in 0..48 {
573
604
  db.insert(
574
605
  &format!("items:record-{step:03}"),
@@ -577,8 +608,11 @@ fn reopening_the_database_rebuilds_the_index_from_durable_state() {
577
608
  .expect("insert");
578
609
  }
579
610
  db.delete("items:record-005").expect("delete");
580
- db.update("items:record-006", &json!({ "status": "active", "tenantId": "tenant-0" }))
581
- .expect("update");
611
+ db.update(
612
+ "items:record-006",
613
+ &json!({ "status": "active", "tenantId": "tenant-0" }),
614
+ )
615
+ .expect("update");
582
616
  db.apply_atomic_transaction_guarded(
583
617
  "pr35-restart-tx",
584
618
  None,
@@ -587,7 +621,10 @@ fn reopening_the_database_rebuilds_the_index_from_durable_state() {
587
621
  &[],
588
622
  &[
589
623
  mutation("items:record-007", None),
590
- mutation("items:record-100", Some(json!({ "status": "active", "tenantId": "tenant-1" }))),
624
+ mutation(
625
+ "items:record-100",
626
+ Some(json!({ "status": "active", "tenantId": "tenant-1" })),
627
+ ),
591
628
  ],
592
629
  None,
593
630
  )
@@ -600,8 +637,12 @@ fn reopening_the_database_rebuilds_the_index_from_durable_state() {
600
637
  reopened.equality_indexes().expect("indexes").is_empty(),
601
638
  "an index is derived state: nothing about it is read back from the log",
602
639
  );
603
- reopened.create_equality_index("items", "status").expect("declare");
604
- reopened.create_equality_index("items", "tenantId").expect("declare");
640
+ reopened
641
+ .create_equality_index("items", "status")
642
+ .expect("declare");
643
+ reopened
644
+ .create_equality_index("items", "tenantId")
645
+ .expect("declare");
605
646
 
606
647
  assert_eq!(
607
648
  snapshot(&reopened),
@@ -699,8 +740,11 @@ fn indexed_execution_returns_exactly_what_the_scan_returns() {
699
740
 
700
741
  // The conjunction actually narrows rather than merely re-filtering: the
701
742
  // intersection is smaller than either side.
702
- let both = indexed_query(&db, &[("status", json!("active")), ("tenantId", json!("tenant-1"))])
703
- .expect("both fields are indexed");
743
+ let both = indexed_query(
744
+ &db,
745
+ &[("status", json!("active")), ("tenantId", json!("tenant-1"))],
746
+ )
747
+ .expect("both fields are indexed");
704
748
  let one = indexed_query(&db, &[("status", json!("active"))]).expect("indexed");
705
749
  assert!(!both.is_empty() && both.len() < one.len());
706
750
  }
@@ -718,8 +762,11 @@ fn the_index_selects_candidates_and_the_predicate_still_decides() {
718
762
  "the index answers with candidates, both of which satisfy only the indexed condition",
719
763
  );
720
764
 
721
- let result = indexed_query(&db, &[("status", json!("active")), ("role", json!("admin"))])
722
- .expect("indexed");
765
+ let result = indexed_query(
766
+ &db,
767
+ &[("status", json!("active")), ("role", json!("admin"))],
768
+ )
769
+ .expect("indexed");
723
770
  assert_eq!(
724
771
  result,
725
772
  vec!["items:a".to_string()],
@@ -834,14 +881,19 @@ fn concurrent_mutation_and_indexed_query_stay_coherent() {
834
881
  // mean a partially committed transaction became queryable.
835
882
  for (sibling, count) in halves {
836
883
  if count != 2 {
837
- failures.push(format!("transaction pair {sibling} was observed {count} times, not 2"));
884
+ failures.push(format!(
885
+ "transaction pair {sibling} was observed {count} times, not 2"
886
+ ));
838
887
  }
839
888
  }
840
889
  observations += 1;
841
890
  }
842
891
 
843
892
  running.store(false, Ordering::Relaxed);
844
- let cycles: usize = writers.into_iter().map(|handle| handle.join().expect("writer")).sum();
893
+ let cycles: usize = writers
894
+ .into_iter()
895
+ .map(|handle| handle.join().expect("writer"))
896
+ .sum();
845
897
 
846
898
  assert!(cycles > 0, "the writers actually mutated the collection");
847
899
  assert!(observations > 0, "the reader actually queried");
@@ -881,7 +933,10 @@ fn indexed_and_scan_execution_agree_on_a_concurrently_built_state() {
881
933
  for conditions in [
882
934
  vec![("status", json!("active"))],
883
935
  vec![("tenantId", json!("tenant-3"))],
884
- vec![("status", json!("archived")), ("tenantId", json!("tenant-2"))],
936
+ vec![
937
+ ("status", json!("archived")),
938
+ ("tenantId", json!("tenant-2")),
939
+ ],
885
940
  ] {
886
941
  assert_eq!(
887
942
  indexed_query(&db, &conditions).expect("indexed"),
@@ -17,10 +17,8 @@
17
17
 
18
18
  use feltdb::{
19
19
  state_contract::{
20
- StateSchema, CollectionSchema, FieldSchema, FieldType, PrimitiveType,
21
- FieldConstraints,
22
- AuthorizationContext, CanonicalQuery, begin_read, execute_query,
23
- QueryFilter,
20
+ begin_read, execute_query, AuthorizationContext, CanonicalQuery, CollectionSchema,
21
+ FieldConstraints, FieldSchema, FieldType, PrimitiveType, QueryFilter, StateSchema,
24
22
  },
25
23
  FeltDb,
26
24
  };
@@ -324,8 +322,7 @@ fn pr7_phase3_self_authorization_proof() -> Result<(), Box<dyn std::error::Error
324
322
  field_projections: Default::default(),
325
323
  };
326
324
 
327
- let _bob_context = begin_read(&db, &schema, "app", bob_auth)
328
- .map_err(|e| format!("{:?}", e))?;
325
+ let _bob_context = begin_read(&db, &schema, "app", bob_auth).map_err(|e| format!("{:?}", e))?;
329
326
 
330
327
  // Query as Bob with self(user) policy
331
328
  let _query = CanonicalQuery {
@@ -360,8 +357,8 @@ fn pr7_phase3_self_authorization_proof() -> Result<(), Box<dyn std::error::Error
360
357
  field_projections: Default::default(),
361
358
  };
362
359
 
363
- let _alice_context = begin_read(&db, &schema, "app", alice_auth)
364
- .map_err(|e| format!("{:?}", e))?;
360
+ let _alice_context =
361
+ begin_read(&db, &schema, "app", alice_auth).map_err(|e| format!("{:?}", e))?;
365
362
 
366
363
  println!(" • Alice is member of Org A");
367
364
  println!(" • Invitation.organization = {}", org_a_id);
@@ -17,8 +17,7 @@
17
17
 
18
18
  use feltdb::{
19
19
  state_contract::{
20
- StateSchema, CollectionSchema, FieldSchema, FieldType, PrimitiveType,
21
- FieldConstraints,
20
+ CollectionSchema, FieldConstraints, FieldSchema, FieldType, PrimitiveType, StateSchema,
22
21
  },
23
22
  FeltDb,
24
23
  };
@@ -150,10 +149,7 @@ fn pr8_resource_inventory_and_pattern_mapping() -> Result<(), Box<dyn std::error
150
149
  for primitive in primitives {
151
150
  let count = resources
152
151
  .iter()
153
- .filter(|r| {
154
- r.read_policy.contains(primitive)
155
- || r.write_policy.contains(primitive)
156
- })
152
+ .filter(|r| r.read_policy.contains(primitive) || r.write_policy.contains(primitive))
157
153
  .count();
158
154
  if count > 0 {
159
155
  println!(" ✓ {} - Used in {} resources", primitive, count);
@@ -184,37 +180,35 @@ fn pr8_pattern_class_1_personal_identity_scoped() -> Result<(), Box<dyn std::err
184
180
  schema_version: 1,
185
181
  application_id: "saas-portal".to_string(),
186
182
  revision_id: "rev-1".to_string(),
187
- collections: vec![
188
- CollectionSchema {
189
- name: "User".to_string(),
190
- version: 1,
191
- fields: vec![
192
- FieldSchema {
193
- name: "_id".to_string(),
194
- field_type: FieldType::Primitive {
195
- primitive: PrimitiveType::String,
196
- },
197
- nullable: false,
198
- required: true,
199
- default: None,
200
- constraints: FieldConstraints::default(),
201
- computed: None,
183
+ collections: vec![CollectionSchema {
184
+ name: "User".to_string(),
185
+ version: 1,
186
+ fields: vec![
187
+ FieldSchema {
188
+ name: "_id".to_string(),
189
+ field_type: FieldType::Primitive {
190
+ primitive: PrimitiveType::String,
202
191
  },
203
- FieldSchema {
204
- name: "email".to_string(),
205
- field_type: FieldType::Primitive {
206
- primitive: PrimitiveType::String,
207
- },
208
- nullable: false,
209
- required: true,
210
- default: None,
211
- constraints: FieldConstraints::default(),
212
- computed: None,
192
+ nullable: false,
193
+ required: true,
194
+ default: None,
195
+ constraints: FieldConstraints::default(),
196
+ computed: None,
197
+ },
198
+ FieldSchema {
199
+ name: "email".to_string(),
200
+ field_type: FieldType::Primitive {
201
+ primitive: PrimitiveType::String,
213
202
  },
214
- ],
215
- indexes: vec![],
216
- },
217
- ],
203
+ nullable: false,
204
+ required: true,
205
+ default: None,
206
+ constraints: FieldConstraints::default(),
207
+ computed: None,
208
+ },
209
+ ],
210
+ indexes: vec![],
211
+ }],
218
212
  };
219
213
 
220
214
  // Setup test data
@@ -415,11 +409,17 @@ fn pr8_pattern_class_2_organizational_relational() -> Result<(), Box<dyn std::er
415
409
  let org_a_id = "org-a";
416
410
  let proj_id = "proj-1";
417
411
 
418
- db.insert("User#user-alice", json!({ "_id": alice_id, "email": "alice@example.com" }))
419
- .map_err(|e| format!("{:?}", e))?;
412
+ db.insert(
413
+ "User#user-alice",
414
+ json!({ "_id": alice_id, "email": "alice@example.com" }),
415
+ )
416
+ .map_err(|e| format!("{:?}", e))?;
420
417
 
421
- db.insert("User#user-bob", json!({ "_id": bob_id, "email": "bob@example.com" }))
422
- .map_err(|e| format!("{:?}", e))?;
418
+ db.insert(
419
+ "User#user-bob",
420
+ json!({ "_id": bob_id, "email": "bob@example.com" }),
421
+ )
422
+ .map_err(|e| format!("{:?}", e))?;
423
423
 
424
424
  db.insert(
425
425
  "Organization#org-a",
@@ -672,11 +672,17 @@ fn pr8_pattern_class_4_composition_multiple_audiences() -> Result<(), Box<dyn st
672
672
  let org_a_id = "org-a";
673
673
  let inv_id = "inv-1";
674
674
 
675
- db.insert("User#user-alice", json!({ "_id": alice_id, "email": "alice@example.com" }))
676
- .map_err(|e| format!("{:?}", e))?;
675
+ db.insert(
676
+ "User#user-alice",
677
+ json!({ "_id": alice_id, "email": "alice@example.com" }),
678
+ )
679
+ .map_err(|e| format!("{:?}", e))?;
677
680
 
678
- db.insert("User#user-bob", json!({ "_id": bob_id, "email": "bob@example.com" }))
679
- .map_err(|e| format!("{:?}", e))?;
681
+ db.insert(
682
+ "User#user-bob",
683
+ json!({ "_id": bob_id, "email": "bob@example.com" }),
684
+ )
685
+ .map_err(|e| format!("{:?}", e))?;
680
686
 
681
687
  db.insert(
682
688
  "Organization#org-a",
@@ -853,7 +859,9 @@ fn pr8_final_conclusion() -> Result<(), Box<dyn std::error::Error>> {
853
859
 
854
860
  println!("RESULTS\n");
855
861
  println!(" Gaps: NONE");
856
- println!(" Redundancies: owner (minor - can be expressed as self, but kept for convenience)\n");
862
+ println!(
863
+ " Redundancies: owner (minor - can be expressed as self, but kept for convenience)\n"
864
+ );
857
865
 
858
866
  println!("VERDICT: VOCABULARY IS COMPLETE ✓\n");
859
867
 
@@ -22,15 +22,14 @@
22
22
 
23
23
  use feltdb::{
24
24
  state_contract::{
25
- StateSchema, CollectionSchema, FieldSchema, FieldType, PrimitiveType,
26
- FieldConstraints, AuthorizationContext, begin_read, execute_query,
27
- CanonicalQuery, QueryFilter,
25
+ begin_read, execute_query, AuthorizationContext, CanonicalQuery, CollectionSchema,
26
+ FieldConstraints, FieldSchema, FieldType, PrimitiveType, QueryFilter, StateSchema,
28
27
  },
29
28
  FeltDb,
30
29
  };
31
30
  use serde_json::{json, Value};
32
- use tempfile::TempDir;
33
31
  use std::fmt;
32
+ use tempfile::TempDir;
34
33
 
35
34
  /// Result of testing an operation at the FeltDB boundary
36
35
  #[derive(Debug, Clone, PartialEq, Eq)]
@@ -322,19 +321,31 @@ impl TeamBoundaryTestFixture {
322
321
  let team_id = "team-backend".to_string();
323
322
 
324
323
  // Create users
325
- db.insert("User#user-owner", json!({ "_id": owner_id, "email": "owner@example.com" }))
326
- .map_err(|e| format!("{:?}", e))?;
327
- db.insert("User#user-admin", json!({ "_id": admin_id, "email": "admin@example.com" }))
328
- .map_err(|e| format!("{:?}", e))?;
329
- db.insert("User#user-member", json!({ "_id": member_id, "email": "member@example.com" }))
330
- .map_err(|e| format!("{:?}", e))?;
324
+ db.insert(
325
+ "User#user-owner",
326
+ json!({ "_id": owner_id, "email": "owner@example.com" }),
327
+ )
328
+ .map_err(|e| format!("{:?}", e))?;
329
+ db.insert(
330
+ "User#user-admin",
331
+ json!({ "_id": admin_id, "email": "admin@example.com" }),
332
+ )
333
+ .map_err(|e| format!("{:?}", e))?;
334
+ db.insert(
335
+ "User#user-member",
336
+ json!({ "_id": member_id, "email": "member@example.com" }),
337
+ )
338
+ .map_err(|e| format!("{:?}", e))?;
331
339
  db.insert(
332
340
  "User#user-non-member",
333
341
  json!({ "_id": non_member_id, "email": "nonmember@example.com" }),
334
342
  )
335
343
  .map_err(|e| format!("{:?}", e))?;
336
- db.insert("User#user-revoked", json!({ "_id": revoked_id, "email": "revoked@example.com" }))
337
- .map_err(|e| format!("{:?}", e))?;
344
+ db.insert(
345
+ "User#user-revoked",
346
+ json!({ "_id": revoked_id, "email": "revoked@example.com" }),
347
+ )
348
+ .map_err(|e| format!("{:?}", e))?;
338
349
  db.insert(
339
350
  "User#user-cross-tenant",
340
351
  json!({ "_id": cross_tenant_id, "email": "cross@example.com" }),
@@ -342,10 +353,16 @@ impl TeamBoundaryTestFixture {
342
353
  .map_err(|e| format!("{:?}", e))?;
343
354
 
344
355
  // Create organizations
345
- db.insert("Organization#org-main", json!({ "_id": org_id, "name": "Main Org" }))
346
- .map_err(|e| format!("{:?}", e))?;
347
- db.insert("Organization#org-other", json!({ "_id": cross_org_id, "name": "Other Org" }))
348
- .map_err(|e| format!("{:?}", e))?;
356
+ db.insert(
357
+ "Organization#org-main",
358
+ json!({ "_id": org_id, "name": "Main Org" }),
359
+ )
360
+ .map_err(|e| format!("{:?}", e))?;
361
+ db.insert(
362
+ "Organization#org-other",
363
+ json!({ "_id": cross_org_id, "name": "Other Org" }),
364
+ )
365
+ .map_err(|e| format!("{:?}", e))?;
349
366
 
350
367
  // Create org memberships (establishes organization access)
351
368
  db.insert(
@@ -18,8 +18,8 @@
18
18
 
19
19
  use feltdb::{
20
20
  state_contract::{
21
- StateSchema, CollectionSchema, FieldSchema, FieldType, PrimitiveType,
22
- FieldConstraints, AuthorizationContext,
21
+ AuthorizationContext, CollectionSchema, FieldConstraints, FieldSchema, FieldType,
22
+ PrimitiveType, StateSchema,
23
23
  },
24
24
  FeltDb,
25
25
  };
@@ -66,13 +66,28 @@ impl PathATestFixture {
66
66
  let team_id = "team-backend".to_string();
67
67
 
68
68
  // Create users
69
- db.insert("User#user-owner", json!({"_id": owner_id, "email": "owner@example.com"}))?;
70
- db.insert("User#user-admin", json!({"_id": admin_id, "email": "admin@example.com"}))?;
71
- db.insert("User#user-member", json!({"_id": member_id, "email": "member@example.com"}))?;
72
- db.insert("User#user-non-member", json!({"_id": non_member_id, "email": "non-member@example.com"}))?;
69
+ db.insert(
70
+ "User#user-owner",
71
+ json!({"_id": owner_id, "email": "owner@example.com"}),
72
+ )?;
73
+ db.insert(
74
+ "User#user-admin",
75
+ json!({"_id": admin_id, "email": "admin@example.com"}),
76
+ )?;
77
+ db.insert(
78
+ "User#user-member",
79
+ json!({"_id": member_id, "email": "member@example.com"}),
80
+ )?;
81
+ db.insert(
82
+ "User#user-non-member",
83
+ json!({"_id": non_member_id, "email": "non-member@example.com"}),
84
+ )?;
73
85
 
74
86
  // Create organization
75
- db.insert("Organization#org-1", json!({"_id": org_id, "name": "Org 1"}))?;
87
+ db.insert(
88
+ "Organization#org-1",
89
+ json!({"_id": org_id, "name": "Org 1"}),
90
+ )?;
76
91
 
77
92
  // Create memberships for all users in the organization
78
93
  db.insert(
@@ -3,10 +3,7 @@
3
3
  //! Test that the new authorized mutation API properly enforces authorization.
4
4
  //! Authorization evaluation happens INSIDE the FeltDB boundary, before mutations are applied.
5
5
 
6
- use feltdb::{
7
- state_contract::AuthorizationContext,
8
- FeltDb,
9
- };
6
+ use feltdb::{state_contract::AuthorizationContext, FeltDb};
10
7
  use serde_json::json;
11
8
  use tempfile::TempDir;
12
9
 
@@ -43,7 +40,11 @@ fn authorized_insert_requires_state_write_capability() -> Result<(), Box<dyn std
43
40
  json!({"_id": "user-1", "name": "Alice"}),
44
41
  &authorized_context,
45
42
  );
46
- assert!(result.is_ok(), "Authorized insert should succeed: {:?}", result);
43
+ assert!(
44
+ result.is_ok(),
45
+ "Authorized insert should succeed: {:?}",
46
+ result
47
+ );
47
48
 
48
49
  // Verify record was inserted
49
50
  let value = db.get::<serde_json::Value>("User#user-1")?;
@@ -63,7 +64,10 @@ fn authorized_insert_requires_state_write_capability() -> Result<(), Box<dyn std
63
64
 
64
65
  // Verify unauthorized insert did not create record
65
66
  let value = db.get::<serde_json::Value>("User#user-2")?;
66
- assert!(value.is_none(), "Unauthorized insert should not create record");
67
+ assert!(
68
+ value.is_none(),
69
+ "Unauthorized insert should not create record"
70
+ );
67
71
 
68
72
  Ok(())
69
73
  }
@@ -123,11 +127,18 @@ fn authorized_delete_requires_state_write_capability() -> Result<(), Box<dyn std
123
127
 
124
128
  // Authorized delete should succeed
125
129
  let result = db.delete_with_authorization("Team#team-1", &authorized_context);
126
- assert!(result.is_ok(), "Authorized delete should succeed: {:?}", result);
130
+ assert!(
131
+ result.is_ok(),
132
+ "Authorized delete should succeed: {:?}",
133
+ result
134
+ );
127
135
 
128
136
  // Verify record is deleted
129
137
  let value = db.get::<serde_json::Value>("Team#team-1")?;
130
- assert!(value.is_none(), "Record should be deleted after authorized delete");
138
+ assert!(
139
+ value.is_none(),
140
+ "Record should be deleted after authorized delete"
141
+ );
131
142
 
132
143
  Ok(())
133
144
  }
@@ -167,7 +178,13 @@ fn authorized_update_requires_state_write_capability() -> Result<(), Box<dyn std
167
178
  )?;
168
179
 
169
180
  let original = db.get::<serde_json::Value>("Organization#org-1")?;
170
- assert_eq!(original.as_ref().and_then(|v| v.get("name")).and_then(|v| v.as_str()), Some("Acme Corp"));
181
+ assert_eq!(
182
+ original
183
+ .as_ref()
184
+ .and_then(|v| v.get("name"))
185
+ .and_then(|v| v.as_str()),
186
+ Some("Acme Corp")
187
+ );
171
188
 
172
189
  // Unauthorized update should fail
173
190
  let result = db.update_with_authorization(
@@ -184,7 +201,10 @@ fn authorized_update_requires_state_write_capability() -> Result<(), Box<dyn std
184
201
  // Verify record was not changed
185
202
  let value = db.get::<serde_json::Value>("Organization#org-1")?;
186
203
  assert_eq!(
187
- value.as_ref().and_then(|v| v.get("name")).and_then(|v| v.as_str()),
204
+ value
205
+ .as_ref()
206
+ .and_then(|v| v.get("name"))
207
+ .and_then(|v| v.as_str()),
188
208
  Some("Acme Corp"),
189
209
  "Unauthorized update should not change record"
190
210
  );
@@ -195,12 +215,19 @@ fn authorized_update_requires_state_write_capability() -> Result<(), Box<dyn std
195
215
  json!({"_id": "org-1", "name": "Acme Inc"}),
196
216
  &authorized_context,
197
217
  );
198
- assert!(result.is_ok(), "Authorized update should succeed: {:?}", result);
218
+ assert!(
219
+ result.is_ok(),
220
+ "Authorized update should succeed: {:?}",
221
+ result
222
+ );
199
223
 
200
224
  // Verify record was updated
201
225
  let value = db.get::<serde_json::Value>("Organization#org-1")?;
202
226
  assert_eq!(
203
- value.as_ref().and_then(|v| v.get("name")).and_then(|v| v.as_str()),
227
+ value
228
+ .as_ref()
229
+ .and_then(|v| v.get("name"))
230
+ .and_then(|v| v.as_str()),
204
231
  Some("Acme Inc"),
205
232
  "Authorized update should change record"
206
233
  );
@@ -276,16 +303,8 @@ fn atomic_transaction_with_authorization_denies_on_any_mutation_failure(
276
303
  };
277
304
 
278
305
  // Create initial records
279
- db.insert_with_authorization(
280
- "User#user-1",
281
- json!({"_id": "user-1"}),
282
- &authorized_context,
283
- )?;
284
- db.insert_with_authorization(
285
- "Team#team-1",
286
- json!({"_id": "team-1"}),
287
- &authorized_context,
288
- )?;
306
+ db.insert_with_authorization("User#user-1", json!({"_id": "user-1"}), &authorized_context)?;
307
+ db.insert_with_authorization("Team#team-1", json!({"_id": "team-1"}), &authorized_context)?;
289
308
 
290
309
  // Attempt atomic transaction with unauthorized context
291
310
  // Should be rejected without applying ANY mutations