@feltdb/core 0.15.0 → 0.16.1

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 (248) hide show
  1. package/dist/agent-state.d.ts +20 -0
  2. package/dist/agent-state.d.ts.map +1 -1
  3. package/dist/agent-state.js +36 -0
  4. package/dist/build-identity.json +12 -4
  5. package/dist/cli/commands.js +187 -4
  6. package/dist/cli/publish-engine.js +116 -16
  7. package/dist/collection.d.ts.map +1 -1
  8. package/dist/collection.js +20 -2
  9. package/dist/create/build-identity.json +12 -4
  10. package/dist/create/managed-account.js +93 -35
  11. package/dist/create/package-versions.js +1 -1
  12. package/dist/create/server-source/Cargo.lock +6 -509
  13. package/dist/create/server-source/Cargo.toml +2 -13
  14. package/dist/create/server-source/crates/feltdb-client/Cargo.toml +1 -1
  15. package/dist/create/server-source/crates/feltdb-server/Cargo.toml +1 -1
  16. package/dist/create/server-source/crates/feltdb-server/src/main.rs +356 -24
  17. package/dist/create/server-source/crates/feltdb-server/tests/rust_client.rs +10 -1
  18. package/dist/create/server-source/crates/feltdb-wasm/Cargo.toml +1 -1
  19. package/dist/db.d.ts +11 -1
  20. package/dist/db.d.ts.map +1 -1
  21. package/dist/db.js +15 -2
  22. package/dist/error-codes.d.ts +5 -0
  23. package/dist/error-codes.d.ts.map +1 -1
  24. package/dist/error-codes.js +9 -1
  25. package/dist/http-db.d.ts +16 -0
  26. package/dist/http-db.d.ts.map +1 -1
  27. package/dist/http-db.js +36 -6
  28. package/dist/managed-recovery.d.ts +6 -0
  29. package/dist/managed-recovery.d.ts.map +1 -1
  30. package/dist/managed-recovery.js +9 -0
  31. package/dist/studio-app/assets/{feltdb_wasm-BjM1ylL3.js → feltdb_wasm-BUIxCuTR.js} +1 -1
  32. package/dist/studio-app/assets/feltdb_wasm_bg-C3D6y6DK.wasm +0 -0
  33. package/dist/studio-app/assets/index-BhXYAhgS.js +37 -0
  34. package/dist/studio-app/index.html +1 -1
  35. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  36. package/dist/wasm/package.json +1 -1
  37. package/dist/workload.d.ts +55 -3
  38. package/dist/workload.d.ts.map +1 -1
  39. package/dist/workload.js +23 -0
  40. package/dist/workspace/workspace-connection.d.ts.map +1 -1
  41. package/dist/workspace/workspace-connection.js +14 -3
  42. package/package.json +1 -1
  43. package/dist/create/server-source/crates/feltdb/Cargo.lock +0 -175
  44. package/dist/create/server-source/crates/feltdb/Cargo.toml +0 -102
  45. package/dist/create/server-source/crates/feltdb/LICENSE +0 -21
  46. package/dist/create/server-source/crates/feltdb/README.md +0 -75
  47. package/dist/create/server-source/crates/feltdb/benches/baselines/gate-13-redux.json +0 -370
  48. package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +0 -589
  49. package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +0 -247
  50. package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +0 -440
  51. package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +0 -275
  52. package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +0 -381
  53. package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +0 -467
  54. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +0 -489
  55. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +0 -281
  56. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +0 -606
  57. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +0 -531
  58. package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +0 -462
  59. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +0 -505
  60. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +0 -484
  61. package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +0 -758
  62. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +0 -421
  63. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +0 -329
  64. package/dist/create/server-source/crates/feltdb/src/acceptance_tests.rs +0 -1705
  65. package/dist/create/server-source/crates/feltdb/src/acquisition.rs +0 -286
  66. package/dist/create/server-source/crates/feltdb/src/admission.rs +0 -185
  67. package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +0 -507
  68. package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +0 -539
  69. package/dist/create/server-source/crates/feltdb/src/agent_state.rs +0 -320
  70. package/dist/create/server-source/crates/feltdb/src/agent_transition_contract.rs +0 -1545
  71. package/dist/create/server-source/crates/feltdb/src/analytics.rs +0 -521
  72. package/dist/create/server-source/crates/feltdb/src/application.rs +0 -2674
  73. package/dist/create/server-source/crates/feltdb/src/application_runtime.rs +0 -1070
  74. package/dist/create/server-source/crates/feltdb/src/authority.rs +0 -479
  75. package/dist/create/server-source/crates/feltdb/src/authority_failover.rs +0 -847
  76. package/dist/create/server-source/crates/feltdb/src/authorization.rs +0 -1030
  77. package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +0 -1122
  78. package/dist/create/server-source/crates/feltdb/src/bin/feltdb-authority-client.rs +0 -32
  79. package/dist/create/server-source/crates/feltdb/src/bin/feltdb-authority.rs +0 -19
  80. package/dist/create/server-source/crates/feltdb/src/bin/feltdb_node.rs +0 -1474
  81. package/dist/create/server-source/crates/feltdb/src/capabilities/mod.rs +0 -8
  82. package/dist/create/server-source/crates/feltdb/src/capabilities/search.rs +0 -418
  83. package/dist/create/server-source/crates/feltdb/src/capabilities/vector.rs +0 -482
  84. package/dist/create/server-source/crates/feltdb/src/capability.rs +0 -903
  85. package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +0 -263
  86. package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -77
  87. package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +0 -496
  88. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +0 -2574
  89. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +0 -212
  90. package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +0 -422
  91. package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +0 -445
  92. package/dist/create/server-source/crates/feltdb/src/content_distribution.rs +0 -465
  93. package/dist/create/server-source/crates/feltdb/src/convergence.rs +0 -634
  94. package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +0 -427
  95. package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +0 -376
  96. package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +0 -365
  97. package/dist/create/server-source/crates/feltdb/src/cron.rs +0 -294
  98. package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +0 -483
  99. package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +0 -477
  100. package/dist/create/server-source/crates/feltdb/src/distributed_tests.rs +0 -1003
  101. package/dist/create/server-source/crates/feltdb/src/distributed_transactions.rs +0 -1334
  102. package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +0 -368
  103. package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +0 -231
  104. package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +0 -482
  105. package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +0 -203
  106. package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +0 -317
  107. package/dist/create/server-source/crates/feltdb/src/equality_index.rs +0 -595
  108. package/dist/create/server-source/crates/feltdb/src/execution.rs +0 -426
  109. package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +0 -214
  110. package/dist/create/server-source/crates/feltdb/src/indexing.rs +0 -776
  111. package/dist/create/server-source/crates/feltdb/src/lib.rs +0 -7365
  112. package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +0 -234
  113. package/dist/create/server-source/crates/feltdb/src/materialization.rs +0 -184
  114. package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -266
  115. package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +0 -310
  116. package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +0 -736
  117. package/dist/create/server-source/crates/feltdb/src/observability.rs +0 -379
  118. package/dist/create/server-source/crates/feltdb/src/operation.rs +0 -290
  119. package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +0 -439
  120. package/dist/create/server-source/crates/feltdb/src/operation_log.rs +0 -349
  121. package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +0 -332
  122. package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +0 -718
  123. package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +0 -487
  124. package/dist/create/server-source/crates/feltdb/src/peer_registry.rs +0 -166
  125. package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +0 -289
  126. package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +0 -566
  127. package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +0 -3391
  128. package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +0 -203
  129. package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +0 -261
  130. package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +0 -502
  131. package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +0 -216
  132. package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +0 -303
  133. package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +0 -323
  134. package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +0 -531
  135. package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +0 -406
  136. package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +0 -436
  137. package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +0 -387
  138. package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +0 -378
  139. package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +0 -359
  140. package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +0 -372
  141. package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +0 -404
  142. package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +0 -376
  143. package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +0 -461
  144. package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +0 -2125
  145. package/dist/create/server-source/crates/feltdb/src/production_api.rs +0 -418
  146. package/dist/create/server-source/crates/feltdb/src/provenance.rs +0 -207
  147. package/dist/create/server-source/crates/feltdb/src/query_execution_diagnostics.rs +0 -126
  148. package/dist/create/server-source/crates/feltdb/src/query_performance.rs +0 -218
  149. package/dist/create/server-source/crates/feltdb/src/read_basis.rs +0 -257
  150. package/dist/create/server-source/crates/feltdb/src/references.rs +0 -404
  151. package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +0 -401
  152. package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +0 -501
  153. package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +0 -680
  154. package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +0 -163
  155. package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +0 -133
  156. package/dist/create/server-source/crates/feltdb/src/routing.rs +0 -409
  157. package/dist/create/server-source/crates/feltdb/src/semantic_decision.rs +0 -2029
  158. package/dist/create/server-source/crates/feltdb/src/semantic_query.rs +0 -599
  159. package/dist/create/server-source/crates/feltdb/src/sharding.rs +0 -549
  160. package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +0 -516
  161. package/dist/create/server-source/crates/feltdb/src/state_contract.rs +0 -6003
  162. package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +0 -222
  163. package/dist/create/server-source/crates/feltdb/src/state_facade.rs +0 -320
  164. package/dist/create/server-source/crates/feltdb/src/state_hash.rs +0 -291
  165. package/dist/create/server-source/crates/feltdb/src/state_model.rs +0 -4158
  166. package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +0 -379
  167. package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +0 -673
  168. package/dist/create/server-source/crates/feltdb/src/storage.rs +0 -273
  169. package/dist/create/server-source/crates/feltdb/src/submission.rs +0 -471
  170. package/dist/create/server-source/crates/feltdb/src/sync.rs +0 -495
  171. package/dist/create/server-source/crates/feltdb/src/sync_contract.rs +0 -822
  172. package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +0 -433
  173. package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +0 -462
  174. package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +0 -965
  175. package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +0 -1120
  176. package/dist/create/server-source/crates/feltdb/src/transactions.rs +0 -643
  177. package/dist/create/server-source/crates/feltdb/src/trigger.rs +0 -390
  178. package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +0 -749
  179. package/dist/create/server-source/crates/feltdb/src/versioned_object_substrate.rs +0 -708
  180. package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +0 -1269
  181. package/dist/create/server-source/crates/feltdb/src/workflow.rs +0 -713
  182. package/dist/create/server-source/crates/feltdb/src/workflow_acceptance_tests.rs +0 -510
  183. package/dist/create/server-source/crates/feltdb/src/workflow_integration.rs +0 -354
  184. package/dist/create/server-source/crates/feltdb/src/workflow_runtime.rs +0 -594
  185. package/dist/create/server-source/crates/feltdb/src/workload.rs +0 -4222
  186. package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +0 -456
  187. package/dist/create/server-source/crates/feltdb/tests/agent_state_native.rs +0 -1188
  188. package/dist/create/server-source/crates/feltdb/tests/agent_transition_contract_conformance.rs +0 -2884
  189. package/dist/create/server-source/crates/feltdb/tests/authority_process.rs +0 -297
  190. package/dist/create/server-source/crates/feltdb/tests/authority_transaction_identity.rs +0 -534
  191. package/dist/create/server-source/crates/feltdb/tests/bounded_read_contract.rs +0 -132
  192. package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +0 -299
  193. package/dist/create/server-source/crates/feltdb/tests/common/mod.rs +0 -96
  194. package/dist/create/server-source/crates/feltdb/tests/compaction_stall_contract.rs +0 -272
  195. package/dist/create/server-source/crates/feltdb/tests/crash_durability_contract.rs +0 -467
  196. package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +0 -309
  197. package/dist/create/server-source/crates/feltdb/tests/durable_backup_contract.rs +0 -445
  198. package/dist/create/server-source/crates/feltdb/tests/durable_corruption_contract.rs +0 -518
  199. package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +0 -392
  200. package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +0 -850
  201. package/dist/create/server-source/crates/feltdb/tests/fixtures/agent_transition_corpus.json +0 -23340
  202. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +0 -1916
  203. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +0 -1878
  204. package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +0 -1862
  205. package/dist/create/server-source/crates/feltdb/tests/generalized_version_control_evidence.rs +0 -123
  206. package/dist/create/server-source/crates/feltdb/tests/generalized_version_control_substrate_completion.rs +0 -299
  207. package/dist/create/server-source/crates/feltdb/tests/local_process_ownership.rs +0 -69
  208. package/dist/create/server-source/crates/feltdb/tests/managed_incident_regression.rs +0 -191
  209. package/dist/create/server-source/crates/feltdb/tests/operational_health_contract.rs +0 -278
  210. package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +0 -234
  211. package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +0 -947
  212. package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +0 -404
  213. package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +0 -916
  214. package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +0 -1045
  215. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +0 -347
  216. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +0 -361
  217. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +0 -330
  218. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +0 -93
  219. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +0 -622
  220. package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +0 -517
  221. package/dist/create/server-source/crates/feltdb/tests/production_certification.rs +0 -1153
  222. package/dist/create/server-source/crates/feltdb/tests/production_contract.rs +0 -771
  223. package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +0 -1383
  224. package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +0 -868
  225. package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +0 -221
  226. package/dist/create/server-source/crates/feltdb/tests/replicated_history_contract.rs +0 -417
  227. package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +0 -338
  228. package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +0 -1039
  229. package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +0 -739
  230. package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +0 -452
  231. package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +0 -81
  232. package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +0 -438
  233. package/dist/create/server-source/crates/feltdb/tests/semantic_decision.rs +0 -1165
  234. package/dist/create/server-source/crates/feltdb/tests/semantic_query.rs +0 -767
  235. package/dist/create/server-source/crates/feltdb/tests/semantic_query_contract.rs +0 -363
  236. package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +0 -1799
  237. package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +0 -1316
  238. package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +0 -358
  239. package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +0 -365
  240. package/dist/create/server-source/crates/feltdb/tests/state_ref_authority.rs +0 -918
  241. package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +0 -299
  242. package/dist/create/server-source/crates/feltdb/tests/storage_independent_versioned_object_substrate.rs +0 -328
  243. package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +0 -255
  244. package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +0 -249
  245. package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +0 -994
  246. package/dist/create/server-source/crates/feltdb/tests/workload_envelope_contract.rs +0 -484
  247. package/dist/studio-app/assets/feltdb_wasm_bg-TseJn2Ax.wasm +0 -0
  248. package/dist/studio-app/assets/index-1wd0uKua.js +0 -30
@@ -1,771 +0,0 @@
1
- //! The FeltDB production contract.
2
- //!
3
- //! The certification matrix records what the repository *proves*. This file
4
- //! records what FeltDB is willing to *promise*, which is a smaller and
5
- //! different thing: a promise has an audience, and an audience reads a
6
- //! guarantee as unconditional unless the condition is written next to it.
7
- //!
8
- //! # Why this is executable
9
- //!
10
- //! A public contract is the natural place for evidence drift to end up. Nobody
11
- //! edits a matrix to make a sale; people edit a promise. So no promise here
12
- //! stands on its own wording — every one names the certification claims that
13
- //! back it, and the tier it may occupy is *derived* from their statuses:
14
- //!
15
- //! - **Certified** — every backing claim is `Proven`. Promised without
16
- //! qualification.
17
- //! - **Conditional** — every backing claim is `Proven`, and the promise states
18
- //! the condition it holds under. Fully proven, deliberately scoped.
19
- //! - **Not certified** — at least one backing claim is not `Proven`. Written
20
- //! down as a thing FeltDB does not promise, with the evidence that would
21
- //! change that.
22
- //!
23
- //! Promoting a promise therefore requires promoting a claim, which requires a
24
- //! test. There is no path from wanting a guarantee to publishing one.
25
- //!
26
- //! # What this is not
27
- //!
28
- //! It is not a second source of truth. Statuses are read out of
29
- //! `production_certification.rs`; nothing about a claim is restated here.
30
-
31
- use std::collections::{BTreeMap, BTreeSet};
32
-
33
- mod common;
34
-
35
- /// How strongly FeltDB stands behind a promise.
36
- #[derive(Debug, Clone, Copy, PartialEq, Eq)]
37
- enum Tier {
38
- Certified,
39
- Conditional,
40
- NotCertified,
41
- }
42
-
43
- impl Tier {
44
- const ALL: [Tier; 3] = [Tier::Certified, Tier::Conditional, Tier::NotCertified];
45
-
46
- fn label(self) -> &'static str {
47
- match self {
48
- Tier::Certified => "Certified",
49
- Tier::Conditional => "Conditional",
50
- Tier::NotCertified => "Not certified",
51
- }
52
- }
53
-
54
- /// A tier that promises something, as opposed to recording that FeltDB does
55
- /// not. The distinction decides which checks apply.
56
- fn promises(self) -> bool {
57
- matches!(self, Tier::Certified | Tier::Conditional)
58
- }
59
- }
60
-
61
- struct Promise {
62
- id: &'static str,
63
- area: &'static str,
64
- promise: &'static str,
65
- tier: Tier,
66
- /// For `Conditional`, the condition the promise holds under. For
67
- /// `Not certified`, the evidence that would change the answer. Empty only
68
- /// for `Certified`, which holds unconditionally or not at all.
69
- condition: &'static str,
70
- /// The certification claims this rests on. Never empty.
71
- backing: &'static [&'static str],
72
- }
73
-
74
- #[rustfmt::skip]
75
- const CONTRACT: &[Promise] = &[
76
- // ------------------------------------------------------------- Certified
77
- Promise { id: "P1", area: "Durability",
78
- promise: "State, revision history, retention policy and retention horizon survive a clean \
79
- restart, and a reopened database continues its history rather than starting a new one.",
80
- tier: Tier::Certified, condition: "", backing: &["D1", "D2", "D3", "D4"] },
81
- Promise { id: "P2", area: "Mutation",
82
- promise: "A write that has lost its fence is rejected and mints no revision, and concurrent \
83
- writes produce correct per-resource revision chains.",
84
- tier: Tier::Certified, condition: "", backing: &["A1", "A2", "A3"] },
85
- Promise { id: "P3", area: "Mutation",
86
- promise: "A duplicate remote operation is idempotent, and a remote operation arriving with a \
87
- sequence gap is rejected rather than applied.",
88
- tier: Tier::Certified, condition: "", backing: &["A4", "A5"] },
89
- Promise { id: "P4", area: "Crash recovery",
90
- promise: "A crash at any point leaves a clean prefix of the mutation sequence: never a partial \
91
- mutation, and never a revision for a record that was not written.",
92
- tier: Tier::Certified, condition: "", backing: &["A6", "D6", "D7"] },
93
- Promise { id: "P5", area: "Crash recovery",
94
- promise: "A transaction is all-or-nothing across a crash.",
95
- tier: Tier::Certified, condition: "", backing: &["D9"] },
96
- Promise { id: "P6", area: "Crash recovery",
97
- promise: "A committed write survives the process dying.",
98
- tier: Tier::Certified, condition: "", backing: &["D8"] },
99
- Promise { id: "P7", area: "Crash recovery",
100
- promise: "A database recovered from a crash replicates identically to one that never crashed.",
101
- tier: Tier::Certified, condition: "", backing: &["D10"] },
102
- Promise { id: "P8", area: "History",
103
- promise: "History is bounded by a retention policy and unbounded without one, a policy change \
104
- takes effect in both directions, maintenance never rewrites history, and forked \
105
- history is preserved.",
106
- tier: Tier::Certified, condition: "", backing: &["H1", "H2", "H3", "H4", "H5"] },
107
- Promise { id: "P9", area: "History",
108
- promise: "Ancestry expired by retention is distinguishable from ancestry that was damaged.",
109
- tier: Tier::Certified, condition: "", backing: &["R3"] },
110
- Promise { id: "P10", area: "Corruption",
111
- promise: "An incomplete final append is recovered and reported rather than silently dropped, \
112
- and a complete but invalid record refuses the open wherever it sits.",
113
- tier: Tier::Certified, condition: "", backing: &["R1", "R2"] },
114
- Promise { id: "P11", area: "Format",
115
- promise: "A durable database declares its format, and a format this build cannot interpret \
116
- refuses the open before any record is read, leaving the file byte-identical.",
117
- tier: Tier::Certified, condition: "", backing: &["U1", "U3", "U4", "U5", "U6"] },
118
- Promise { id: "P12", area: "Backup",
119
- promise: "A backup is self-contained and independently verifiable, a restore proves the result \
120
- means the same thing rather than merely that it parsed, an altered backup is refused, \
121
- and a restore never overwrites an existing database.",
122
- tier: Tier::Certified, condition: "", backing: &["B1", "B2", "B3", "B4"] },
123
- Promise { id: "P13", area: "Replication",
124
- promise: "Replication carries revision history with identical identities, preserving parents, \
125
- sequences, forks and provenance, and evaluates state equivalence separately from \
126
- historical equivalence.",
127
- tier: Tier::Certified, condition: "", backing: &["S1", "S2", "S3", "S4", "S5"] },
128
- Promise { id: "P14", area: "Overload",
129
- promise: "A request arriving while the server is saturated is refused with a status, an error \
130
- code and a retry hint, rather than absorbed into an unbounded queue.",
131
- tier: Tier::Certified, condition: "", backing: &["M4"] },
132
- Promise { id: "P15", area: "Reads",
133
- promise: "A keyed lookup reads one record, and a limited search visits no more rows than its limit.",
134
- tier: Tier::Certified, condition: "", backing: &["M5"] },
135
- Promise { id: "P16", area: "Maintenance",
136
- promise: "A timer-driven compaction prunes without rewriting the durable log, an explicit \
137
- compaction still rewrites immediately, and deferring the rewrite preserves state and history.",
138
- tier: Tier::Certified, condition: "", backing: &["M1", "M2", "M3"] },
139
- Promise { id: "P17", area: "Maintenance",
140
- promise: "A compaction running concurrently with traffic leaves scoped reads correct and bounded, \
141
- and leaves the database intact across a forced rewrite and a reopen.",
142
- tier: Tier::Certified, condition: "", backing: &["M8", "M9"] },
143
- Promise { id: "P18", area: "Health",
144
- promise: "A health report names only conditions that were observed, and a recovered open is \
145
- distinguishable from a clean one.",
146
- tier: Tier::Certified, condition: "", backing: &["O3", "O4"] },
147
-
148
- // ----------------------------------------------------------- Conditional
149
- Promise { id: "P19", area: "Durability mode",
150
- promise: "`Flushed`, the default, hands the write to the operating system and states that as its guarantee.",
151
- tier: Tier::Conditional,
152
- condition: "The write survives the process dying. It is not promised to survive the machine \
153
- losing power.",
154
- backing: &["D8", "E3", "E5"] },
155
- Promise { id: "P20", area: "Durability mode",
156
- promise: "`Synced` issues a stable-storage barrier for every write, at a cost this repository has measured.",
157
- tier: Tier::Conditional,
158
- condition: "The barrier is issued. What the hardware does with it is outside FeltDB's evidence, \
159
- so this narrows the power-loss window rather than closing it.",
160
- backing: &["E3", "E4", "E5"] },
161
- Promise { id: "P21", area: "Durability mode",
162
- promise: "`Grouped` names an exact bound on how many acknowledged writes have not yet been \
163
- through a barrier.",
164
- tier: Tier::Conditional,
165
- condition: "Up to `every - 1` acknowledged writes may be in that window. Choose this mode for \
166
- the stated window, not for throughput.",
167
- backing: &["E3", "E5"] },
168
- Promise { id: "P22", area: "Workload",
169
- promise: "Retention cost per write grows with the retention window, and retention inflates the \
170
- log before compaction.",
171
- tier: Tier::Conditional,
172
- condition: "Under the frozen workload in the envelope contract. The ordering is the promise; \
173
- the measured numbers are not.",
174
- backing: &["E1", "E2"] },
175
- Promise { id: "P23", area: "Durability mode",
176
- promise: "Selecting a durability mode changes the contract and not the stored database, so a \
177
- mode can be changed without migrating anything.",
178
- tier: Tier::Conditional,
179
- condition: "The stored bytes are identical across modes; the acknowledgement semantics are not.",
180
- backing: &["E5"] },
181
-
182
- // --------------------------------------------------------- Not certified
183
- Promise { id: "N1", area: "Durability",
184
- promise: "FeltDB does not promise that a single write survives operating-system or power loss.",
185
- tier: Tier::NotCertified,
186
- condition: "A test on hardware that can actually be cut, verifying the database after recovery.",
187
- backing: &["D5"] },
188
- Promise { id: "N2", area: "Workload",
189
- promise: "FeltDB does not promise that `Grouped` is faster than a barrier per write.",
190
- tier: Tier::NotCertified,
191
- condition: "A stable measurement showing the ordering holds across repeated runs. An earlier \
192
- assertion was removed after a run inverted it.",
193
- backing: &["E7"] },
194
- Promise { id: "N3", area: "Workload",
195
- promise: "FeltDB does not promise that its published performance numbers transfer to your hardware.",
196
- tier: Tier::NotCertified,
197
- condition: "A test asserting that each measurement carries the environment that produced it, \
198
- as the frozen workload already is.",
199
- backing: &["E6"] },
200
- Promise { id: "N4", area: "Backup",
201
- promise: "FeltDB does not provide an operator backup workflow. Backup and restore are library \
202
- primitives that something else must schedule and run.",
203
- tier: Tier::NotCertified,
204
- condition: "A command-line entry point with a contract test of its own.",
205
- backing: &["B5"] },
206
- Promise { id: "N5", area: "Monitoring",
207
- promise: "FeltDB does not surface ancestry damage on its own. Damage is found when ancestry is \
208
- walked, and nothing walks it unprompted.",
209
- tier: Tier::NotCertified,
210
- condition: "A database-wide ancestry scan, and something that runs it on a schedule.",
211
- backing: &["R4"] },
212
- Promise { id: "N6", area: "Inspection",
213
- promise: "FeltDB does not answer database-wide questions about history. Inspection is per resource.",
214
- tier: Tier::NotCertified,
215
- condition: "An aggregate across resources, so that \"is any ancestry anywhere damaged?\" does \
216
- not mean walking every revision.",
217
- backing: &["O1"] },
218
- Promise { id: "N7", area: "Health",
219
- promise: "FeltDB does not certify the behaviour of its HTTP health and readiness endpoints. The \
220
- values they report are tested at the library boundary; the handlers that compose them \
221
- are not exercised.",
222
- tier: Tier::NotCertified,
223
- condition: "An HTTP-level harness covering both handlers, including the stalled-storage path.",
224
- backing: &["O2", "M7"] },
225
- Promise { id: "N8", area: "Health",
226
- promise: "The `runtime`, `fabric`, `workflows` and `agents` fields of a health response are \
227
- compile-time constants and carry no information about the running system.",
228
- tier: Tier::NotCertified,
229
- condition: "An operational contract for each field, and then observation of it. Inventing those \
230
- contracts to fill the fields would repeat the defect being recorded.",
231
- backing: &["O5"] },
232
- Promise { id: "N9", area: "Operations",
233
- promise: "FeltDB does not promise a latency bound, and does not promise that a compaction will \
234
- not block concurrent requests. Reads and writes are serialized behind a single lock, \
235
- the durable rewrite is deferred rather than eliminated, and no test in this repository \
236
- measures latency. That is a statement about the available evidence, not a prediction \
237
- about any particular deployment.",
238
- tier: Tier::NotCertified,
239
- condition: "Latency measured under load, and a compaction that does not hold the lock that \
240
- serializes every read and write.",
241
- backing: &["M6"] },
242
- ];
243
-
244
- /// What an operator has to do because FeltDB does not.
245
- ///
246
- /// Every withheld claim lands here as work someone else owns. A gap that
247
- /// produced no obligation would be a gap nobody had to plan around, which is
248
- /// how a stated limitation quietly becomes an operational surprise.
249
- struct Obligation {
250
- id: &'static str,
251
- obligation: &'static str,
252
- because: &'static [&'static str],
253
- }
254
-
255
- #[rustfmt::skip]
256
- const OBLIGATIONS: &[Obligation] = &[
257
- Obligation { id: "G1",
258
- obligation: "If the deployment can lose power, treat the most recent acknowledged writes as at \
259
- risk and size recovery accordingly. `Synced` narrows that window; nothing in this \
260
- repository closes it.",
261
- because: &["D5"] },
262
- Obligation { id: "G2",
263
- obligation: "Schedule, run and retain backups yourself, and keep the verification step: FeltDB \
264
- will tell you a backup is sound, but only when asked.",
265
- because: &["B5"] },
266
- Obligation { id: "G3",
267
- obligation: "Walk ancestry on a schedule if damage needs to be found before a reader stumbles on it.",
268
- because: &["R4"] },
269
- Obligation { id: "G4",
270
- obligation: "Aggregate per-resource history yourself when the question is about the database \
271
- rather than about one resource.",
272
- because: &["O1"] },
273
- Obligation { id: "G5",
274
- obligation: "Re-measure the workload envelope on the hardware you intend to run on, before sizing anything.",
275
- because: &["E6"] },
276
- Obligation { id: "G6",
277
- obligation: "Do not select `Grouped` for throughput. Select it for the window it states.",
278
- because: &["E7"] },
279
- Obligation { id: "G7",
280
- obligation: "Monitor request latency and refusal rate outside the database. FeltDB reports \
281
- neither, and a saturated instance answers `/health` normally.",
282
- because: &["M6"] },
283
- Obligation { id: "G8",
284
- obligation: "Treat the HTTP health and readiness responses as unverified composition. Where \
285
- storage state matters, confirm it at the library boundary.",
286
- because: &["O2", "M7"] },
287
- Obligation { id: "G9",
288
- obligation: "Ignore the `runtime`, `fabric`, `workflows` and `agents` fields of a health response.",
289
- because: &["O5"] },
290
- ];
291
-
292
- /// Certification claims that deliberately reach no promise, and why.
293
- ///
294
- /// Enumerated rather than filtered, so the exemption cannot grow silently.
295
- const OUTSIDE_THE_CONTRACT: &[(&str, &str)] = &[(
296
- "U2",
297
- "Not Applicable: there is no pre-model revision history to migrate, so there is nothing to \
298
- promise or withhold about migrating it.",
299
- )];
300
-
301
- // ===========================================================================
302
- // The certification, read rather than restated
303
- // ===========================================================================
304
-
305
- struct Claim {
306
- status: String,
307
- kind: String,
308
- }
309
-
310
- /// Parse the certification matrix out of its own source.
311
- ///
312
- /// Reading the Rust rather than the published document is deliberate: the
313
- /// document is checked against the matrix by a different test binary, and a
314
- /// contract that depended on that check would silently lose its footing if the
315
- /// check were ever removed.
316
- fn certification() -> BTreeMap<String, Claim> {
317
- let source = include_str!("production_certification.rs");
318
- let start = source
319
- .find("const CERTIFICATION")
320
- .expect("the certification declares CERTIFICATION");
321
- let end = start
322
- + source[start..]
323
- .find("\n];")
324
- .expect("the certification table terminates");
325
- let table = &source[start..end];
326
-
327
- let mut claims = BTreeMap::new();
328
- for chunk in table.split("Claim {").skip(1) {
329
- let id = quoted_after(chunk, "id: \"").expect("every claim has an id");
330
- let status = word_after(chunk, "status: Status::").expect("every claim has a status");
331
- let kind = word_after(chunk, "kind: Evidence::").expect("every claim has an evidence kind");
332
- assert!(
333
- claims
334
- .insert(id.to_string(), Claim { status, kind })
335
- .is_none(),
336
- "{id} appears twice in the certification"
337
- );
338
- }
339
- assert!(
340
- claims.len() > 50,
341
- "the certification did not parse; it yielded {} claims",
342
- claims.len()
343
- );
344
- claims
345
- }
346
-
347
- fn quoted_after<'a>(chunk: &'a str, key: &str) -> Option<&'a str> {
348
- let rest = &chunk[chunk.find(key)? + key.len()..];
349
- Some(&rest[..rest.find('"')?])
350
- }
351
-
352
- fn word_after(chunk: &str, key: &str) -> Option<String> {
353
- let rest = &chunk[chunk.find(key)? + key.len()..];
354
- Some(
355
- rest.chars()
356
- .take_while(|character| character.is_alphanumeric())
357
- .collect(),
358
- )
359
- }
360
-
361
- fn contract() -> BTreeMap<&'static str, &'static Promise> {
362
- CONTRACT
363
- .iter()
364
- .map(|promise| (promise.id, promise))
365
- .collect()
366
- }
367
-
368
- // ===========================================================================
369
- // The tripwires
370
- // ===========================================================================
371
-
372
- /// Every promise rests on claims that exist, and no promise rests on nothing.
373
- #[test]
374
- fn every_promise_names_backing_that_exists() {
375
- let certified = certification();
376
- let mut problems = Vec::new();
377
-
378
- for promise in CONTRACT {
379
- if promise.backing.is_empty() {
380
- problems.push(format!(
381
- "{}: promises something and names no claim",
382
- promise.id
383
- ));
384
- }
385
- for id in promise.backing {
386
- if !certified.contains_key(*id) {
387
- problems.push(format!(
388
- "{}: rests on `{id}`, which is not a certification claim",
389
- promise.id
390
- ));
391
- }
392
- }
393
- }
394
-
395
- assert!(problems.is_empty(), "{}", problems.join("\n"));
396
- }
397
-
398
- /// **A promise may not be stronger than its evidence.**
399
- ///
400
- /// This is the whole mechanism. A `Certified` or `Conditional` promise requires
401
- /// every backing claim to be `Proven`; a `Not certified` entry requires at least
402
- /// one that is not. Wanting to promise something more is not a way to promise
403
- /// it — the only route is to prove a claim, which means writing a test.
404
- #[test]
405
- fn a_promises_tier_is_derived_from_its_evidence() {
406
- let certified = certification();
407
- let mut problems = Vec::new();
408
-
409
- for promise in CONTRACT {
410
- let statuses: Vec<&str> = promise
411
- .backing
412
- .iter()
413
- .filter_map(|id| certified.get(*id))
414
- .map(|claim| claim.status.as_str())
415
- .collect();
416
-
417
- let unproven: Vec<&&str> = promise
418
- .backing
419
- .iter()
420
- .filter(|id| {
421
- certified
422
- .get(**id)
423
- .map(|claim| claim.status != "Proven")
424
- .unwrap_or(false)
425
- })
426
- .collect();
427
-
428
- match promise.tier {
429
- Tier::Certified | Tier::Conditional if !unproven.is_empty() => problems.push(format!(
430
- "{} is published as `{}` and rests on {unproven:?}, which {} not Proven",
431
- promise.id,
432
- promise.tier.label(),
433
- if unproven.len() == 1 { "is" } else { "are" }
434
- )),
435
- Tier::NotCertified if unproven.is_empty() => problems.push(format!(
436
- "{} is published as `Not certified` and every claim it names is Proven ({statuses:?}); \
437
- either promise it or point it at the gap",
438
- promise.id
439
- )),
440
- _ => {}
441
- }
442
- }
443
-
444
- assert!(problems.is_empty(), "{}", problems.join("\n"));
445
- }
446
-
447
- /// A promise we make must not rest on someone having read the implementation.
448
- ///
449
- /// `inspection_alone_never_proves_a_behavioural_claim` already stops inspection
450
- /// from producing a `Proven` claim. This is the same rule one level up, so that
451
- /// a promise cannot inherit inspection through a chain of ids.
452
- #[test]
453
- fn no_promise_rests_on_implementation_inspection() {
454
- let certified = certification();
455
- for promise in CONTRACT {
456
- if !promise.tier.promises() {
457
- continue;
458
- }
459
- for id in promise.backing {
460
- let claim = &certified[*id];
461
- assert_ne!(
462
- claim.kind, "ImplementationInspection",
463
- "{} promises something backed by `{id}`, which rests on inspection",
464
- promise.id
465
- );
466
- }
467
- }
468
- }
469
-
470
- /// A conditional promise states its condition; a withheld one states what would
471
- /// change the answer. Only an unconditional promise may say nothing further.
472
- #[test]
473
- fn every_qualified_promise_states_its_qualification() {
474
- for promise in CONTRACT {
475
- match promise.tier {
476
- Tier::Certified => assert!(
477
- promise.condition.is_empty(),
478
- "{} is Certified and carries a condition; it belongs in Conditional",
479
- promise.id
480
- ),
481
- Tier::Conditional | Tier::NotCertified => assert!(
482
- !promise.condition.trim().is_empty(),
483
- "{} is `{}` and states no qualification",
484
- promise.id,
485
- promise.tier.label()
486
- ),
487
- }
488
- }
489
- }
490
-
491
- /// **Every claim reaches the contract, or is exempted by name.**
492
- ///
493
- /// Coverage in the direction that matters: a claim the certification withholds
494
- /// must not simply be left out of the public document. Silence about a gap
495
- /// reads as an absence of the gap.
496
- #[test]
497
- fn every_certification_claim_reaches_the_contract() {
498
- let certified = certification();
499
- let mentioned: BTreeSet<&str> = CONTRACT
500
- .iter()
501
- .flat_map(|promise| promise.backing.iter().copied())
502
- .collect();
503
-
504
- let mut missing = Vec::new();
505
- for (id, claim) in &certified {
506
- if mentioned.contains(id.as_str()) {
507
- continue;
508
- }
509
- match OUTSIDE_THE_CONTRACT.iter().find(|(exempt, _)| exempt == id) {
510
- Some((_, reason)) => assert!(
511
- !reason.trim().is_empty(),
512
- "{id} is exempted from the contract with no reason"
513
- ),
514
- None => missing.push(format!("{id} ({})", claim.status)),
515
- }
516
- }
517
- missing.sort();
518
-
519
- assert!(
520
- missing.is_empty(),
521
- "certified and absent from the contract: {}",
522
- missing.join(", ")
523
- );
524
-
525
- for (id, _) in OUTSIDE_THE_CONTRACT {
526
- assert!(
527
- certified.contains_key(*id),
528
- "{id} is exempted from a contract it was never in"
529
- );
530
- assert!(
531
- !mentioned.contains(id),
532
- "{id} is exempted and also named by a promise"
533
- );
534
- }
535
- }
536
-
537
- /// **Every gap becomes somebody's job.**
538
- ///
539
- /// A claim that is not `Proven` is work FeltDB is not doing. If nothing else
540
- /// picks it up, the limitation is real and invisible at the same time — the
541
- /// worst combination. So each one must produce at least one operator
542
- /// obligation.
543
- #[test]
544
- fn every_withheld_claim_creates_an_operator_obligation() {
545
- let certified = certification();
546
- let excused: BTreeSet<&str> = OUTSIDE_THE_CONTRACT.iter().map(|(id, _)| *id).collect();
547
- let owned: BTreeSet<&str> = OBLIGATIONS
548
- .iter()
549
- .flat_map(|obligation| obligation.because.iter().copied())
550
- .collect();
551
-
552
- let mut orphaned = Vec::new();
553
- for (id, claim) in &certified {
554
- let withheld = claim.status == "Unproven" || claim.status == "PartiallyProven";
555
- if withheld && !excused.contains(id.as_str()) && !owned.contains(id.as_str()) {
556
- orphaned.push(format!("{id} ({})", claim.status));
557
- }
558
- }
559
- orphaned.sort();
560
-
561
- assert!(
562
- orphaned.is_empty(),
563
- "withheld and nobody's job: {}",
564
- orphaned.join(", ")
565
- );
566
-
567
- for obligation in OBLIGATIONS {
568
- assert!(
569
- !obligation.because.is_empty(),
570
- "{} is an obligation with no cause",
571
- obligation.id
572
- );
573
- for id in obligation.because {
574
- let claim = certified
575
- .get(*id)
576
- .unwrap_or_else(|| panic!("{} cites `{id}`, which is not a claim", obligation.id));
577
- assert_ne!(
578
- claim.status, "Proven",
579
- "{} makes an operator responsible for `{id}`, which FeltDB proves",
580
- obligation.id
581
- );
582
- }
583
- }
584
- }
585
-
586
- /// **A promise reads as a promise; a refusal reads as a refusal.**
587
- ///
588
- /// Hedging inside a promise is how an unconditional guarantee gets quietly
589
- /// weakened after the fact, and guarantee-language inside a withheld one is how
590
- /// a gap gets quietly read as a feature. Both are wording failures that no
591
- /// status check would catch.
592
- ///
593
- /// The hedge rule applies to the promise itself and **not** to its condition.
594
- /// Describing what a promise does not cover is exactly where words like "may"
595
- /// belong: `Grouped`'s condition says up to `every - 1` acknowledged writes may
596
- /// not yet have been through a barrier, and that sentence is precise, not
597
- /// evasive. Forbidding it there would push the condition towards vaguer wording
598
- /// to satisfy a check — the opposite of the intent.
599
- #[test]
600
- fn a_promise_does_not_hedge_and_a_refusal_does_not_guarantee() {
601
- let hedges = [
602
- " may ",
603
- " might ",
604
- " should ",
605
- " typically",
606
- " generally",
607
- " usually",
608
- "best effort",
609
- "best-effort",
610
- " aims to ",
611
- " tries to ",
612
- " intended to ",
613
- ];
614
- let guarantees = [
615
- "guarantees that",
616
- "is guaranteed",
617
- "is certified",
618
- "we promise",
619
- ];
620
-
621
- let mut problems = Vec::new();
622
- for promise in CONTRACT {
623
- let text = format!("{} {}", promise.promise, promise.condition).to_lowercase();
624
- if promise.tier.promises() {
625
- let promised = promise.promise.to_lowercase();
626
- for hedge in hedges {
627
- if promised.contains(hedge) {
628
- problems.push(format!(
629
- "{} is `{}` and hedges with \"{}\"",
630
- promise.id,
631
- promise.tier.label(),
632
- hedge.trim()
633
- ));
634
- }
635
- }
636
- } else {
637
- for guarantee in guarantees {
638
- if common::asserts_phrase(&text, guarantee) {
639
- problems.push(format!(
640
- "{} is `Not certified` and asserts \"{guarantee}\"",
641
- promise.id
642
- ));
643
- }
644
- }
645
- }
646
- }
647
-
648
- assert!(problems.is_empty(), "{}", problems.join("\n"));
649
- }
650
-
651
- // ===========================================================================
652
- // The published contract
653
- // ===========================================================================
654
-
655
- fn published_document() -> String {
656
- let path = concat!(
657
- env!("CARGO_MANIFEST_DIR"),
658
- "/../../docs/architecture/production-contract.md"
659
- );
660
- std::fs::read_to_string(path).expect("the contract document exists and is readable")
661
- }
662
-
663
- /// **The published contract is a rendering, not a retelling.**
664
- ///
665
- /// Every promise appears with the same tier and the same backing. A promise
666
- /// that exists only in the document, or a tier that differs between the two,
667
- /// fails here — which is the case this whole file exists to prevent.
668
- #[test]
669
- fn the_published_contract_matches_the_executable_contract() {
670
- let document = published_document();
671
- let promised = contract();
672
-
673
- let mut rows: BTreeMap<String, (String, String)> = BTreeMap::new();
674
- for line in document.lines() {
675
- let Some(cells) = common::table_cells(line) else {
676
- continue;
677
- };
678
- // id | area | promise | tier | condition | backing
679
- if cells.len() != 6 {
680
- continue;
681
- }
682
- let id = cells[0].clone();
683
- let looks_like_an_id = id.len() >= 2
684
- && (id.starts_with('P') || id.starts_with('N'))
685
- && id[1..].chars().all(|c| c.is_ascii_digit());
686
- if !looks_like_an_id {
687
- continue;
688
- }
689
- assert!(
690
- rows.insert(id.clone(), (cells[3].clone(), cells[5].clone()))
691
- .is_none(),
692
- "the document publishes `{id}` more than once"
693
- );
694
- }
695
-
696
- let mut problems = Vec::new();
697
- for promise in CONTRACT {
698
- match rows.get(promise.id) {
699
- None => problems.push(format!("{}: absent from the document", promise.id)),
700
- Some((tier, backing)) => {
701
- if tier != promise.tier.label() {
702
- problems.push(format!(
703
- "{}: the document publishes `{tier}`, the contract says `{}`",
704
- promise.id,
705
- promise.tier.label()
706
- ));
707
- }
708
- let expected = promise.backing.join(", ");
709
- let published: String = backing.replace('`', "");
710
- if published != expected {
711
- problems.push(format!(
712
- "{}: the document rests it on `{published}`, the contract rests it on `{expected}`",
713
- promise.id
714
- ));
715
- }
716
- }
717
- }
718
- }
719
- for id in rows.keys() {
720
- if !promised.contains_key(id.as_str()) {
721
- problems.push(format!("{id}: in the document, absent from the contract"));
722
- }
723
- }
724
-
725
- assert!(problems.is_empty(), "{}", problems.join("\n"));
726
- }
727
-
728
- /// Every tier is published, including an empty one, so a bucket cannot vanish
729
- /// from the document because it was inconvenient.
730
- #[test]
731
- fn the_published_contract_publishes_every_tier() {
732
- let document = published_document();
733
- for tier in Tier::ALL {
734
- assert!(
735
- document.contains(tier.label()),
736
- "the contract document never mentions `{}`",
737
- tier.label()
738
- );
739
- }
740
- for obligation in OBLIGATIONS {
741
- assert!(
742
- document.contains(obligation.id),
743
- "{} is an operator obligation the document does not publish",
744
- obligation.id
745
- );
746
- }
747
- }
748
-
749
- /// The contract document is held to the same rule as every other document: it
750
- /// may name a withheld guarantee, and may not assert one.
751
- #[test]
752
- fn the_contract_document_asserts_nothing_the_certification_withholds() {
753
- let forbidden = [
754
- "power-loss safe",
755
- "power loss safe",
756
- "guaranteed durable",
757
- "compaction is non-blocking",
758
- "compaction no longer blocks",
759
- "all reads are bounded",
760
- "supported capacity",
761
- ];
762
-
763
- let prose = common::prose_excluding_withheld_rows(&published_document(), &["Not certified"]);
764
- let mut violations = Vec::new();
765
- for phrase in forbidden {
766
- if common::asserts_phrase(&prose, phrase) {
767
- violations.push(format!("the contract asserts \"{phrase}\""));
768
- }
769
- }
770
- assert!(violations.is_empty(), "{}", violations.join("\n"));
771
- }