@feltdb/core 0.15.0 → 0.16.0

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 (247) 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 +3 -0
  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 +255 -12
  17. package/dist/create/server-source/crates/feltdb-wasm/Cargo.toml +1 -1
  18. package/dist/db.d.ts +11 -1
  19. package/dist/db.d.ts.map +1 -1
  20. package/dist/db.js +15 -2
  21. package/dist/error-codes.d.ts +5 -0
  22. package/dist/error-codes.d.ts.map +1 -1
  23. package/dist/error-codes.js +9 -1
  24. package/dist/http-db.d.ts +16 -0
  25. package/dist/http-db.d.ts.map +1 -1
  26. package/dist/http-db.js +36 -6
  27. package/dist/managed-recovery.d.ts +6 -0
  28. package/dist/managed-recovery.d.ts.map +1 -1
  29. package/dist/managed-recovery.js +9 -0
  30. package/dist/studio-app/assets/{feltdb_wasm-BjM1ylL3.js → feltdb_wasm-DtybUY0q.js} +1 -1
  31. package/dist/studio-app/assets/feltdb_wasm_bg-DsgIUwaB.wasm +0 -0
  32. package/dist/studio-app/assets/index-C4OffsZl.js +37 -0
  33. package/dist/studio-app/index.html +1 -1
  34. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  35. package/dist/wasm/package.json +1 -1
  36. package/dist/workload.d.ts +55 -3
  37. package/dist/workload.d.ts.map +1 -1
  38. package/dist/workload.js +23 -0
  39. package/dist/workspace/workspace-connection.d.ts.map +1 -1
  40. package/dist/workspace/workspace-connection.js +14 -3
  41. package/package.json +1 -1
  42. package/dist/create/server-source/crates/feltdb/Cargo.lock +0 -175
  43. package/dist/create/server-source/crates/feltdb/Cargo.toml +0 -102
  44. package/dist/create/server-source/crates/feltdb/LICENSE +0 -21
  45. package/dist/create/server-source/crates/feltdb/README.md +0 -75
  46. package/dist/create/server-source/crates/feltdb/benches/baselines/gate-13-redux.json +0 -370
  47. package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +0 -589
  48. package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +0 -247
  49. package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +0 -440
  50. package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +0 -275
  51. package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +0 -381
  52. package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +0 -467
  53. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +0 -489
  54. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +0 -281
  55. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +0 -606
  56. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +0 -531
  57. package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +0 -462
  58. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +0 -505
  59. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +0 -484
  60. package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +0 -758
  61. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +0 -421
  62. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +0 -329
  63. package/dist/create/server-source/crates/feltdb/src/acceptance_tests.rs +0 -1705
  64. package/dist/create/server-source/crates/feltdb/src/acquisition.rs +0 -286
  65. package/dist/create/server-source/crates/feltdb/src/admission.rs +0 -185
  66. package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +0 -507
  67. package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +0 -539
  68. package/dist/create/server-source/crates/feltdb/src/agent_state.rs +0 -320
  69. package/dist/create/server-source/crates/feltdb/src/agent_transition_contract.rs +0 -1545
  70. package/dist/create/server-source/crates/feltdb/src/analytics.rs +0 -521
  71. package/dist/create/server-source/crates/feltdb/src/application.rs +0 -2674
  72. package/dist/create/server-source/crates/feltdb/src/application_runtime.rs +0 -1070
  73. package/dist/create/server-source/crates/feltdb/src/authority.rs +0 -479
  74. package/dist/create/server-source/crates/feltdb/src/authority_failover.rs +0 -847
  75. package/dist/create/server-source/crates/feltdb/src/authorization.rs +0 -1030
  76. package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +0 -1122
  77. package/dist/create/server-source/crates/feltdb/src/bin/feltdb-authority-client.rs +0 -32
  78. package/dist/create/server-source/crates/feltdb/src/bin/feltdb-authority.rs +0 -19
  79. package/dist/create/server-source/crates/feltdb/src/bin/feltdb_node.rs +0 -1474
  80. package/dist/create/server-source/crates/feltdb/src/capabilities/mod.rs +0 -8
  81. package/dist/create/server-source/crates/feltdb/src/capabilities/search.rs +0 -418
  82. package/dist/create/server-source/crates/feltdb/src/capabilities/vector.rs +0 -482
  83. package/dist/create/server-source/crates/feltdb/src/capability.rs +0 -903
  84. package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +0 -263
  85. package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -77
  86. package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +0 -496
  87. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +0 -2574
  88. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +0 -212
  89. package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +0 -422
  90. package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +0 -445
  91. package/dist/create/server-source/crates/feltdb/src/content_distribution.rs +0 -465
  92. package/dist/create/server-source/crates/feltdb/src/convergence.rs +0 -634
  93. package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +0 -427
  94. package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +0 -376
  95. package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +0 -365
  96. package/dist/create/server-source/crates/feltdb/src/cron.rs +0 -294
  97. package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +0 -483
  98. package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +0 -477
  99. package/dist/create/server-source/crates/feltdb/src/distributed_tests.rs +0 -1003
  100. package/dist/create/server-source/crates/feltdb/src/distributed_transactions.rs +0 -1334
  101. package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +0 -368
  102. package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +0 -231
  103. package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +0 -482
  104. package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +0 -203
  105. package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +0 -317
  106. package/dist/create/server-source/crates/feltdb/src/equality_index.rs +0 -595
  107. package/dist/create/server-source/crates/feltdb/src/execution.rs +0 -426
  108. package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +0 -214
  109. package/dist/create/server-source/crates/feltdb/src/indexing.rs +0 -776
  110. package/dist/create/server-source/crates/feltdb/src/lib.rs +0 -7365
  111. package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +0 -234
  112. package/dist/create/server-source/crates/feltdb/src/materialization.rs +0 -184
  113. package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -266
  114. package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +0 -310
  115. package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +0 -736
  116. package/dist/create/server-source/crates/feltdb/src/observability.rs +0 -379
  117. package/dist/create/server-source/crates/feltdb/src/operation.rs +0 -290
  118. package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +0 -439
  119. package/dist/create/server-source/crates/feltdb/src/operation_log.rs +0 -349
  120. package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +0 -332
  121. package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +0 -718
  122. package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +0 -487
  123. package/dist/create/server-source/crates/feltdb/src/peer_registry.rs +0 -166
  124. package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +0 -289
  125. package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +0 -566
  126. package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +0 -3391
  127. package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +0 -203
  128. package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +0 -261
  129. package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +0 -502
  130. package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +0 -216
  131. package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +0 -303
  132. package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +0 -323
  133. package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +0 -531
  134. package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +0 -406
  135. package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +0 -436
  136. package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +0 -387
  137. package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +0 -378
  138. package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +0 -359
  139. package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +0 -372
  140. package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +0 -404
  141. package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +0 -376
  142. package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +0 -461
  143. package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +0 -2125
  144. package/dist/create/server-source/crates/feltdb/src/production_api.rs +0 -418
  145. package/dist/create/server-source/crates/feltdb/src/provenance.rs +0 -207
  146. package/dist/create/server-source/crates/feltdb/src/query_execution_diagnostics.rs +0 -126
  147. package/dist/create/server-source/crates/feltdb/src/query_performance.rs +0 -218
  148. package/dist/create/server-source/crates/feltdb/src/read_basis.rs +0 -257
  149. package/dist/create/server-source/crates/feltdb/src/references.rs +0 -404
  150. package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +0 -401
  151. package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +0 -501
  152. package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +0 -680
  153. package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +0 -163
  154. package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +0 -133
  155. package/dist/create/server-source/crates/feltdb/src/routing.rs +0 -409
  156. package/dist/create/server-source/crates/feltdb/src/semantic_decision.rs +0 -2029
  157. package/dist/create/server-source/crates/feltdb/src/semantic_query.rs +0 -599
  158. package/dist/create/server-source/crates/feltdb/src/sharding.rs +0 -549
  159. package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +0 -516
  160. package/dist/create/server-source/crates/feltdb/src/state_contract.rs +0 -6003
  161. package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +0 -222
  162. package/dist/create/server-source/crates/feltdb/src/state_facade.rs +0 -320
  163. package/dist/create/server-source/crates/feltdb/src/state_hash.rs +0 -291
  164. package/dist/create/server-source/crates/feltdb/src/state_model.rs +0 -4158
  165. package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +0 -379
  166. package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +0 -673
  167. package/dist/create/server-source/crates/feltdb/src/storage.rs +0 -273
  168. package/dist/create/server-source/crates/feltdb/src/submission.rs +0 -471
  169. package/dist/create/server-source/crates/feltdb/src/sync.rs +0 -495
  170. package/dist/create/server-source/crates/feltdb/src/sync_contract.rs +0 -822
  171. package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +0 -433
  172. package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +0 -462
  173. package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +0 -965
  174. package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +0 -1120
  175. package/dist/create/server-source/crates/feltdb/src/transactions.rs +0 -643
  176. package/dist/create/server-source/crates/feltdb/src/trigger.rs +0 -390
  177. package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +0 -749
  178. package/dist/create/server-source/crates/feltdb/src/versioned_object_substrate.rs +0 -708
  179. package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +0 -1269
  180. package/dist/create/server-source/crates/feltdb/src/workflow.rs +0 -713
  181. package/dist/create/server-source/crates/feltdb/src/workflow_acceptance_tests.rs +0 -510
  182. package/dist/create/server-source/crates/feltdb/src/workflow_integration.rs +0 -354
  183. package/dist/create/server-source/crates/feltdb/src/workflow_runtime.rs +0 -594
  184. package/dist/create/server-source/crates/feltdb/src/workload.rs +0 -4222
  185. package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +0 -456
  186. package/dist/create/server-source/crates/feltdb/tests/agent_state_native.rs +0 -1188
  187. package/dist/create/server-source/crates/feltdb/tests/agent_transition_contract_conformance.rs +0 -2884
  188. package/dist/create/server-source/crates/feltdb/tests/authority_process.rs +0 -297
  189. package/dist/create/server-source/crates/feltdb/tests/authority_transaction_identity.rs +0 -534
  190. package/dist/create/server-source/crates/feltdb/tests/bounded_read_contract.rs +0 -132
  191. package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +0 -299
  192. package/dist/create/server-source/crates/feltdb/tests/common/mod.rs +0 -96
  193. package/dist/create/server-source/crates/feltdb/tests/compaction_stall_contract.rs +0 -272
  194. package/dist/create/server-source/crates/feltdb/tests/crash_durability_contract.rs +0 -467
  195. package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +0 -309
  196. package/dist/create/server-source/crates/feltdb/tests/durable_backup_contract.rs +0 -445
  197. package/dist/create/server-source/crates/feltdb/tests/durable_corruption_contract.rs +0 -518
  198. package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +0 -392
  199. package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +0 -850
  200. package/dist/create/server-source/crates/feltdb/tests/fixtures/agent_transition_corpus.json +0 -23340
  201. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +0 -1916
  202. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +0 -1878
  203. package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +0 -1862
  204. package/dist/create/server-source/crates/feltdb/tests/generalized_version_control_evidence.rs +0 -123
  205. package/dist/create/server-source/crates/feltdb/tests/generalized_version_control_substrate_completion.rs +0 -299
  206. package/dist/create/server-source/crates/feltdb/tests/local_process_ownership.rs +0 -69
  207. package/dist/create/server-source/crates/feltdb/tests/managed_incident_regression.rs +0 -191
  208. package/dist/create/server-source/crates/feltdb/tests/operational_health_contract.rs +0 -278
  209. package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +0 -234
  210. package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +0 -947
  211. package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +0 -404
  212. package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +0 -916
  213. package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +0 -1045
  214. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +0 -347
  215. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +0 -361
  216. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +0 -330
  217. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +0 -93
  218. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +0 -622
  219. package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +0 -517
  220. package/dist/create/server-source/crates/feltdb/tests/production_certification.rs +0 -1153
  221. package/dist/create/server-source/crates/feltdb/tests/production_contract.rs +0 -771
  222. package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +0 -1383
  223. package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +0 -868
  224. package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +0 -221
  225. package/dist/create/server-source/crates/feltdb/tests/replicated_history_contract.rs +0 -417
  226. package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +0 -338
  227. package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +0 -1039
  228. package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +0 -739
  229. package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +0 -452
  230. package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +0 -81
  231. package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +0 -438
  232. package/dist/create/server-source/crates/feltdb/tests/semantic_decision.rs +0 -1165
  233. package/dist/create/server-source/crates/feltdb/tests/semantic_query.rs +0 -767
  234. package/dist/create/server-source/crates/feltdb/tests/semantic_query_contract.rs +0 -363
  235. package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +0 -1799
  236. package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +0 -1316
  237. package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +0 -358
  238. package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +0 -365
  239. package/dist/create/server-source/crates/feltdb/tests/state_ref_authority.rs +0 -918
  240. package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +0 -299
  241. package/dist/create/server-source/crates/feltdb/tests/storage_independent_versioned_object_substrate.rs +0 -328
  242. package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +0 -255
  243. package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +0 -249
  244. package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +0 -994
  245. package/dist/create/server-source/crates/feltdb/tests/workload_envelope_contract.rs +0 -484
  246. package/dist/studio-app/assets/feltdb_wasm_bg-TseJn2Ax.wasm +0 -0
  247. 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
- }