@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,1862 +0,0 @@
1
- {
2
- "about": "Deterministic conformance corpus for the feltdb.trigger.match contract. Every case is executed by both the native and the WASM implementation and their canonical output bytes must be identical to each other and to expected_output. Cases with 'input' are canonically encoded by the harness; cases with 'raw_input' are fed to the contract verbatim so that malformed and non-canonical encodings are testable. Regenerate expected_output with FELTDB_TRIGGER_CONTRACT_BLESS=1 cargo test -p feltdb --test trigger_contract_conformance -- bless --ignored",
3
- "cases": [
4
- {
5
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
6
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
7
- "input": {
8
- "change": {
9
- "change_kind": "insert",
10
- "collection": "orders",
11
- "value": {
12
- "status": "paid"
13
- }
14
- },
15
- "contract": "feltdb.trigger.match",
16
- "trigger": {
17
- "change_kind": "insert",
18
- "enabled": true,
19
- "source_collection": "orders"
20
- },
21
- "version": 1
22
- },
23
- "name": "collection_matches",
24
- "why": "the change is in the trigger's source collection"
25
- },
26
- {
27
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"customers\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
28
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"collection_mismatch\"},\"version\":1}",
29
- "input": {
30
- "change": {
31
- "change_kind": "insert",
32
- "collection": "customers",
33
- "value": {
34
- "status": "paid"
35
- }
36
- },
37
- "contract": "feltdb.trigger.match",
38
- "trigger": {
39
- "change_kind": "insert",
40
- "enabled": true,
41
- "source_collection": "orders"
42
- },
43
- "version": 1
44
- },
45
- "name": "collection_differs",
46
- "why": "a change in another collection is not this trigger's"
47
- },
48
- {
49
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"Orders\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
50
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"collection_mismatch\"},\"version\":1}",
51
- "input": {
52
- "change": {
53
- "change_kind": "insert",
54
- "collection": "Orders",
55
- "value": {
56
- "status": "paid"
57
- }
58
- },
59
- "contract": "feltdb.trigger.match",
60
- "trigger": {
61
- "change_kind": "insert",
62
- "enabled": true,
63
- "source_collection": "orders"
64
- },
65
- "version": 1
66
- },
67
- "name": "collection_differs_by_case",
68
- "why": "collection comparison is exact, not case-folded"
69
- },
70
- {
71
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"order\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
72
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"collection_mismatch\"},\"version\":1}",
73
- "input": {
74
- "change": {
75
- "change_kind": "insert",
76
- "collection": "order",
77
- "value": {
78
- "status": "paid"
79
- }
80
- },
81
- "contract": "feltdb.trigger.match",
82
- "trigger": {
83
- "change_kind": "insert",
84
- "enabled": true,
85
- "source_collection": "orders"
86
- },
87
- "version": 1
88
- },
89
- "name": "collection_differs_by_prefix",
90
- "why": "a prefix of the source collection is not the source collection"
91
- },
92
- {
93
- "canonical_input": "{\"change\":{\"change_kind\":\"update\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"update\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
94
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
95
- "input": {
96
- "change": {
97
- "change_kind": "update",
98
- "collection": "orders",
99
- "value": {
100
- "status": "paid"
101
- }
102
- },
103
- "contract": "feltdb.trigger.match",
104
- "trigger": {
105
- "change_kind": "update",
106
- "enabled": true,
107
- "source_collection": "orders"
108
- },
109
- "version": 1
110
- },
111
- "name": "change_kind_update_matches",
112
- "why": "an update trigger accepts an update"
113
- },
114
- {
115
- "canonical_input": "{\"change\":{\"change_kind\":\"delete\",\"collection\":\"orders\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"delete\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
116
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
117
- "input": {
118
- "change": {
119
- "change_kind": "delete",
120
- "collection": "orders"
121
- },
122
- "contract": "feltdb.trigger.match",
123
- "trigger": {
124
- "change_kind": "delete",
125
- "enabled": true,
126
- "source_collection": "orders"
127
- },
128
- "version": 1
129
- },
130
- "name": "change_kind_delete_matches",
131
- "why": "a delete trigger accepts a delete with no value"
132
- },
133
- {
134
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"update\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
135
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"change_kind_mismatch\"},\"version\":1}",
136
- "input": {
137
- "change": {
138
- "change_kind": "insert",
139
- "collection": "orders",
140
- "value": {
141
- "status": "paid"
142
- }
143
- },
144
- "contract": "feltdb.trigger.match",
145
- "trigger": {
146
- "change_kind": "update",
147
- "enabled": true,
148
- "source_collection": "orders"
149
- },
150
- "version": 1
151
- },
152
- "name": "change_kind_insert_against_update_trigger",
153
- "why": "an insert is not an update"
154
- },
155
- {
156
- "canonical_input": "{\"change\":{\"change_kind\":\"delete\",\"collection\":\"orders\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
157
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"change_kind_mismatch\"},\"version\":1}",
158
- "input": {
159
- "change": {
160
- "change_kind": "delete",
161
- "collection": "orders"
162
- },
163
- "contract": "feltdb.trigger.match",
164
- "trigger": {
165
- "change_kind": "insert",
166
- "enabled": true,
167
- "source_collection": "orders"
168
- },
169
- "version": 1
170
- },
171
- "name": "change_kind_delete_against_insert_trigger",
172
- "why": "a delete is not an insert"
173
- },
174
- {
175
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":false,\"predicate\":{\"equals\":\"paid\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
176
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"trigger_disabled\"},\"version\":1}",
177
- "input": {
178
- "change": {
179
- "change_kind": "insert",
180
- "collection": "orders",
181
- "value": {
182
- "status": "paid"
183
- }
184
- },
185
- "contract": "feltdb.trigger.match",
186
- "trigger": {
187
- "change_kind": "insert",
188
- "enabled": false,
189
- "predicate": {
190
- "equals": "paid",
191
- "field": "status"
192
- },
193
- "source_collection": "orders"
194
- },
195
- "version": 1
196
- },
197
- "name": "disabled_trigger_rejects_matching_change",
198
- "why": "a disabled trigger never matches, even when everything else agrees"
199
- },
200
- {
201
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"customers\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":false,\"source_collection\":\"orders\"},\"version\":1}",
202
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"trigger_disabled\"},\"version\":1}",
203
- "input": {
204
- "change": {
205
- "change_kind": "insert",
206
- "collection": "customers",
207
- "value": {
208
- "status": "paid"
209
- }
210
- },
211
- "contract": "feltdb.trigger.match",
212
- "trigger": {
213
- "change_kind": "insert",
214
- "enabled": false,
215
- "source_collection": "orders"
216
- },
217
- "version": 1
218
- },
219
- "name": "disabled_trigger_outranks_collection_mismatch",
220
- "why": "disabled is checked before collection, so the reason is stable"
221
- },
222
- {
223
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"anything\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
224
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
225
- "input": {
226
- "change": {
227
- "change_kind": "insert",
228
- "collection": "orders",
229
- "value": {
230
- "status": "anything"
231
- }
232
- },
233
- "contract": "feltdb.trigger.match",
234
- "trigger": {
235
- "change_kind": "insert",
236
- "enabled": true,
237
- "source_collection": "orders"
238
- },
239
- "version": 1
240
- },
241
- "name": "predicate_absent_matches_any_value",
242
- "why": "no predicate means collection and kind decide alone"
243
- },
244
- {
245
- "canonical_input": "{\"change\":{\"change_kind\":\"delete\",\"collection\":\"orders\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"delete\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
246
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
247
- "input": {
248
- "change": {
249
- "change_kind": "delete",
250
- "collection": "orders"
251
- },
252
- "contract": "feltdb.trigger.match",
253
- "trigger": {
254
- "change_kind": "delete",
255
- "enabled": true,
256
- "source_collection": "orders"
257
- },
258
- "version": 1
259
- },
260
- "name": "predicate_absent_matches_absent_value",
261
- "why": "no predicate means a valueless change still matches"
262
- },
263
- {
264
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"paid\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
265
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
266
- "input": {
267
- "change": {
268
- "change_kind": "insert",
269
- "collection": "orders",
270
- "value": {
271
- "status": "paid"
272
- }
273
- },
274
- "contract": "feltdb.trigger.match",
275
- "trigger": {
276
- "change_kind": "insert",
277
- "enabled": true,
278
- "predicate": {
279
- "equals": "paid",
280
- "field": "status"
281
- },
282
- "source_collection": "orders"
283
- },
284
- "version": 1
285
- },
286
- "name": "predicate_matches_string",
287
- "why": "the field resolves and equals the expected value"
288
- },
289
- {
290
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"draft\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"paid\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
291
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
292
- "input": {
293
- "change": {
294
- "change_kind": "insert",
295
- "collection": "orders",
296
- "value": {
297
- "status": "draft"
298
- }
299
- },
300
- "contract": "feltdb.trigger.match",
301
- "trigger": {
302
- "change_kind": "insert",
303
- "enabled": true,
304
- "predicate": {
305
- "equals": "paid",
306
- "field": "status"
307
- },
308
- "source_collection": "orders"
309
- },
310
- "version": 1
311
- },
312
- "name": "predicate_value_mismatch",
313
- "why": "the field resolves to a different value"
314
- },
315
- {
316
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"state\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"paid\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
317
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_field_absent\"},\"version\":1}",
318
- "input": {
319
- "change": {
320
- "change_kind": "insert",
321
- "collection": "orders",
322
- "value": {
323
- "state": "paid"
324
- }
325
- },
326
- "contract": "feltdb.trigger.match",
327
- "trigger": {
328
- "change_kind": "insert",
329
- "enabled": true,
330
- "predicate": {
331
- "equals": "paid",
332
- "field": "status"
333
- },
334
- "source_collection": "orders"
335
- },
336
- "version": 1
337
- },
338
- "name": "predicate_field_absent",
339
- "why": "the field path does not resolve"
340
- },
341
- {
342
- "canonical_input": "{\"change\":{\"change_kind\":\"delete\",\"collection\":\"orders\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"delete\",\"enabled\":true,\"predicate\":{\"equals\":\"paid\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
343
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"change_value_absent\"},\"version\":1}",
344
- "input": {
345
- "change": {
346
- "change_kind": "delete",
347
- "collection": "orders"
348
- },
349
- "contract": "feltdb.trigger.match",
350
- "trigger": {
351
- "change_kind": "delete",
352
- "enabled": true,
353
- "predicate": {
354
- "equals": "paid",
355
- "field": "status"
356
- },
357
- "source_collection": "orders"
358
- },
359
- "version": 1
360
- },
361
- "name": "predicate_against_absent_value",
362
- "why": "a predicate cannot be evaluated against a change that carried no record"
363
- },
364
- {
365
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":{\"status\":\"paid\"},\"field\":\"\"},\"source_collection\":\"orders\"},\"version\":1}",
366
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
367
- "input": {
368
- "change": {
369
- "change_kind": "insert",
370
- "collection": "orders",
371
- "value": {
372
- "status": "paid"
373
- }
374
- },
375
- "contract": "feltdb.trigger.match",
376
- "trigger": {
377
- "change_kind": "insert",
378
- "enabled": true,
379
- "predicate": {
380
- "equals": {
381
- "status": "paid"
382
- },
383
- "field": ""
384
- },
385
- "source_collection": "orders"
386
- },
387
- "version": 1
388
- },
389
- "name": "predicate_empty_field_path_selects_whole_value",
390
- "why": "an empty path compares the whole record"
391
- },
392
- {
393
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":{\"status\":\"draft\"},\"field\":\"\"},\"source_collection\":\"orders\"},\"version\":1}",
394
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
395
- "input": {
396
- "change": {
397
- "change_kind": "insert",
398
- "collection": "orders",
399
- "value": {
400
- "status": "paid"
401
- }
402
- },
403
- "contract": "feltdb.trigger.match",
404
- "trigger": {
405
- "change_kind": "insert",
406
- "enabled": true,
407
- "predicate": {
408
- "equals": {
409
- "status": "draft"
410
- },
411
- "field": ""
412
- },
413
- "source_collection": "orders"
414
- },
415
- "version": 1
416
- },
417
- "name": "predicate_empty_field_path_mismatch",
418
- "why": "an empty path comparing an unequal record"
419
- },
420
- {
421
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":\"paid\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"paid\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
422
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_field_absent\"},\"version\":1}",
423
- "input": {
424
- "change": {
425
- "change_kind": "insert",
426
- "collection": "orders",
427
- "value": "paid"
428
- },
429
- "contract": "feltdb.trigger.match",
430
- "trigger": {
431
- "change_kind": "insert",
432
- "enabled": true,
433
- "predicate": {
434
- "equals": "paid",
435
- "field": "status"
436
- },
437
- "source_collection": "orders"
438
- },
439
- "version": 1
440
- },
441
- "name": "predicate_field_on_scalar_value",
442
- "why": "a scalar record has no members to address"
443
- },
444
- {
445
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"a.b\":1}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":1,\"field\":\"a.b\"},\"source_collection\":\"orders\"},\"version\":1}",
446
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_field_absent\"},\"version\":1}",
447
- "input": {
448
- "change": {
449
- "change_kind": "insert",
450
- "collection": "orders",
451
- "value": {
452
- "a.b": 1
453
- }
454
- },
455
- "contract": "feltdb.trigger.match",
456
- "trigger": {
457
- "change_kind": "insert",
458
- "enabled": true,
459
- "predicate": {
460
- "equals": 1,
461
- "field": "a.b"
462
- },
463
- "source_collection": "orders"
464
- },
465
- "version": 1
466
- },
467
- "name": "predicate_dotted_key_is_a_path_not_a_key",
468
- "why": "a literal dotted key is not addressable, because the path splits first"
469
- },
470
- {
471
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":null},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":null,\"field\":\"\"},\"source_collection\":\"orders\"},\"version\":1}",
472
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
473
- "input": {
474
- "change": {
475
- "change_kind": "insert",
476
- "collection": "orders",
477
- "value": null
478
- },
479
- "contract": "feltdb.trigger.match",
480
- "trigger": {
481
- "change_kind": "insert",
482
- "enabled": true,
483
- "predicate": {
484
- "equals": null,
485
- "field": ""
486
- },
487
- "source_collection": "orders"
488
- },
489
- "version": 1
490
- },
491
- "name": "value_null_present_with_whole_record_predicate",
492
- "why": "a record that is JSON null is present and comparable"
493
- },
494
- {
495
- "canonical_input": "{\"change\":{\"change_kind\":\"delete\",\"collection\":\"orders\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"delete\",\"enabled\":true,\"predicate\":{\"equals\":null,\"field\":\"\"},\"source_collection\":\"orders\"},\"version\":1}",
496
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"change_value_absent\"},\"version\":1}",
497
- "input": {
498
- "change": {
499
- "change_kind": "delete",
500
- "collection": "orders"
501
- },
502
- "contract": "feltdb.trigger.match",
503
- "trigger": {
504
- "change_kind": "delete",
505
- "enabled": true,
506
- "predicate": {
507
- "equals": null,
508
- "field": ""
509
- },
510
- "source_collection": "orders"
511
- },
512
- "version": 1
513
- },
514
- "name": "value_absent_with_whole_record_predicate",
515
- "why": "an absent record is not JSON null, so the same predicate rejects"
516
- },
517
- {
518
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"cancelled_at\":null}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":null,\"field\":\"cancelled_at\"},\"source_collection\":\"orders\"},\"version\":1}",
519
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
520
- "input": {
521
- "change": {
522
- "change_kind": "insert",
523
- "collection": "orders",
524
- "value": {
525
- "cancelled_at": null
526
- }
527
- },
528
- "contract": "feltdb.trigger.match",
529
- "trigger": {
530
- "change_kind": "insert",
531
- "enabled": true,
532
- "predicate": {
533
- "equals": null,
534
- "field": "cancelled_at"
535
- },
536
- "source_collection": "orders"
537
- },
538
- "version": 1
539
- },
540
- "name": "predicate_matches_null_field",
541
- "why": "a field whose value is null equals a null expectation"
542
- },
543
- {
544
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"cancelled_at\":null}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"never\",\"field\":\"cancelled_at\"},\"source_collection\":\"orders\"},\"version\":1}",
545
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
546
- "input": {
547
- "change": {
548
- "change_kind": "insert",
549
- "collection": "orders",
550
- "value": {
551
- "cancelled_at": null
552
- }
553
- },
554
- "contract": "feltdb.trigger.match",
555
- "trigger": {
556
- "change_kind": "insert",
557
- "enabled": true,
558
- "predicate": {
559
- "equals": "never",
560
- "field": "cancelled_at"
561
- },
562
- "source_collection": "orders"
563
- },
564
- "version": 1
565
- },
566
- "name": "null_field_is_not_a_missing_field",
567
- "why": "a present null field resolves; it is not the absent case"
568
- },
569
- {
570
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":null,\"field\":\"cancelled_at\"},\"source_collection\":\"orders\"},\"version\":1}",
571
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_field_absent\"},\"version\":1}",
572
- "input": {
573
- "change": {
574
- "change_kind": "insert",
575
- "collection": "orders",
576
- "value": {
577
- "status": "paid"
578
- }
579
- },
580
- "contract": "feltdb.trigger.match",
581
- "trigger": {
582
- "change_kind": "insert",
583
- "enabled": true,
584
- "predicate": {
585
- "equals": null,
586
- "field": "cancelled_at"
587
- },
588
- "source_collection": "orders"
589
- },
590
- "version": 1
591
- },
592
- "name": "missing_field_does_not_equal_null",
593
- "why": "an absent field never equals null"
594
- },
595
- {
596
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"flag\":null}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":false,\"field\":\"flag\"},\"source_collection\":\"orders\"},\"version\":1}",
597
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
598
- "input": {
599
- "change": {
600
- "change_kind": "insert",
601
- "collection": "orders",
602
- "value": {
603
- "flag": null
604
- }
605
- },
606
- "contract": "feltdb.trigger.match",
607
- "trigger": {
608
- "change_kind": "insert",
609
- "enabled": true,
610
- "predicate": {
611
- "equals": false,
612
- "field": "flag"
613
- },
614
- "source_collection": "orders"
615
- },
616
- "version": 1
617
- },
618
- "name": "null_is_not_false",
619
- "why": "JSON null and false are different values"
620
- },
621
- {
622
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"customer\":{\"billing\":{\"country\":\"NL\"}}}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"NL\",\"field\":\"customer.billing.country\"},\"source_collection\":\"orders\"},\"version\":1}",
623
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
624
- "input": {
625
- "change": {
626
- "change_kind": "insert",
627
- "collection": "orders",
628
- "value": {
629
- "customer": {
630
- "billing": {
631
- "country": "NL"
632
- }
633
- }
634
- }
635
- },
636
- "contract": "feltdb.trigger.match",
637
- "trigger": {
638
- "change_kind": "insert",
639
- "enabled": true,
640
- "predicate": {
641
- "equals": "NL",
642
- "field": "customer.billing.country"
643
- },
644
- "source_collection": "orders"
645
- },
646
- "version": 1
647
- },
648
- "name": "nested_path_matches",
649
- "why": "a dotted path descends through nested objects"
650
- },
651
- {
652
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"customer\":{\"billing\":{\"country\":\"BE\"}}}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"NL\",\"field\":\"customer.billing.country\"},\"source_collection\":\"orders\"},\"version\":1}",
653
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
654
- "input": {
655
- "change": {
656
- "change_kind": "insert",
657
- "collection": "orders",
658
- "value": {
659
- "customer": {
660
- "billing": {
661
- "country": "BE"
662
- }
663
- }
664
- }
665
- },
666
- "contract": "feltdb.trigger.match",
667
- "trigger": {
668
- "change_kind": "insert",
669
- "enabled": true,
670
- "predicate": {
671
- "equals": "NL",
672
- "field": "customer.billing.country"
673
- },
674
- "source_collection": "orders"
675
- },
676
- "version": 1
677
- },
678
- "name": "nested_path_mismatch",
679
- "why": "a nested path that resolves to another value"
680
- },
681
- {
682
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"customer\":{\"shipping\":{\"country\":\"NL\"}}}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"NL\",\"field\":\"customer.billing.country\"},\"source_collection\":\"orders\"},\"version\":1}",
683
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_field_absent\"},\"version\":1}",
684
- "input": {
685
- "change": {
686
- "change_kind": "insert",
687
- "collection": "orders",
688
- "value": {
689
- "customer": {
690
- "shipping": {
691
- "country": "NL"
692
- }
693
- }
694
- }
695
- },
696
- "contract": "feltdb.trigger.match",
697
- "trigger": {
698
- "change_kind": "insert",
699
- "enabled": true,
700
- "predicate": {
701
- "equals": "NL",
702
- "field": "customer.billing.country"
703
- },
704
- "source_collection": "orders"
705
- },
706
- "version": 1
707
- },
708
- "name": "nested_path_stops_at_missing_segment",
709
- "why": "an intermediate segment that does not exist stops the walk"
710
- },
711
- {
712
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"customer\":{\"alpha\":2,\"zeta\":1}}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":{\"alpha\":2,\"zeta\":1},\"field\":\"customer\"},\"source_collection\":\"orders\"},\"version\":1}",
713
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
714
- "input": {
715
- "change": {
716
- "change_kind": "insert",
717
- "collection": "orders",
718
- "value": {
719
- "customer": {
720
- "alpha": 2,
721
- "zeta": 1
722
- }
723
- }
724
- },
725
- "contract": "feltdb.trigger.match",
726
- "trigger": {
727
- "change_kind": "insert",
728
- "enabled": true,
729
- "predicate": {
730
- "equals": {
731
- "alpha": 2,
732
- "zeta": 1
733
- },
734
- "field": "customer"
735
- },
736
- "source_collection": "orders"
737
- },
738
- "version": 1
739
- },
740
- "name": "nested_object_equality_ignores_key_order",
741
- "why": "objects compare as maps, so the encoded key order cannot decide"
742
- },
743
- {
744
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"customer\":{\"alpha\":2,\"zeta\":1}}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":{\"alpha\":2},\"field\":\"customer\"},\"source_collection\":\"orders\"},\"version\":1}",
745
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
746
- "input": {
747
- "change": {
748
- "change_kind": "insert",
749
- "collection": "orders",
750
- "value": {
751
- "customer": {
752
- "alpha": 2,
753
- "zeta": 1
754
- }
755
- }
756
- },
757
- "contract": "feltdb.trigger.match",
758
- "trigger": {
759
- "change_kind": "insert",
760
- "enabled": true,
761
- "predicate": {
762
- "equals": {
763
- "alpha": 2
764
- },
765
- "field": "customer"
766
- },
767
- "source_collection": "orders"
768
- },
769
- "version": 1
770
- },
771
- "name": "nested_object_equality_rejects_extra_key",
772
- "why": "an object with an extra member is a different object"
773
- },
774
- {
775
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"a\":{\"b\":{\"c\":{\"d\":{\"e\":{\"f\":{\"g\":{\"h\":{\"i\":{\"j\":\"deep\"}}}}}}}}}}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"deep\",\"field\":\"a.b.c.d.e.f.g.h.i.j\"},\"source_collection\":\"orders\"},\"version\":1}",
776
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
777
- "input": {
778
- "change": {
779
- "change_kind": "insert",
780
- "collection": "orders",
781
- "value": {
782
- "a": {
783
- "b": {
784
- "c": {
785
- "d": {
786
- "e": {
787
- "f": {
788
- "g": {
789
- "h": {
790
- "i": {
791
- "j": "deep"
792
- }
793
- }
794
- }
795
- }
796
- }
797
- }
798
- }
799
- }
800
- }
801
- }
802
- },
803
- "contract": "feltdb.trigger.match",
804
- "trigger": {
805
- "change_kind": "insert",
806
- "enabled": true,
807
- "predicate": {
808
- "equals": "deep",
809
- "field": "a.b.c.d.e.f.g.h.i.j"
810
- },
811
- "source_collection": "orders"
812
- },
813
- "version": 1
814
- },
815
- "name": "deeply_nested_value",
816
- "why": "nesting well inside the shared recursion bound"
817
- },
818
- {
819
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"tags\":[\"a\",\"b\",\"c\"]}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":[\"a\",\"b\",\"c\"],\"field\":\"tags\"},\"source_collection\":\"orders\"},\"version\":1}",
820
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
821
- "input": {
822
- "change": {
823
- "change_kind": "insert",
824
- "collection": "orders",
825
- "value": {
826
- "tags": [
827
- "a",
828
- "b",
829
- "c"
830
- ]
831
- }
832
- },
833
- "contract": "feltdb.trigger.match",
834
- "trigger": {
835
- "change_kind": "insert",
836
- "enabled": true,
837
- "predicate": {
838
- "equals": [
839
- "a",
840
- "b",
841
- "c"
842
- ],
843
- "field": "tags"
844
- },
845
- "source_collection": "orders"
846
- },
847
- "version": 1
848
- },
849
- "name": "array_equality_matches",
850
- "why": "arrays compare elementwise and in order"
851
- },
852
- {
853
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"tags\":[\"c\",\"b\",\"a\"]}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":[\"a\",\"b\",\"c\"],\"field\":\"tags\"},\"source_collection\":\"orders\"},\"version\":1}",
854
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
855
- "input": {
856
- "change": {
857
- "change_kind": "insert",
858
- "collection": "orders",
859
- "value": {
860
- "tags": [
861
- "c",
862
- "b",
863
- "a"
864
- ]
865
- }
866
- },
867
- "contract": "feltdb.trigger.match",
868
- "trigger": {
869
- "change_kind": "insert",
870
- "enabled": true,
871
- "predicate": {
872
- "equals": [
873
- "a",
874
- "b",
875
- "c"
876
- ],
877
- "field": "tags"
878
- },
879
- "source_collection": "orders"
880
- },
881
- "version": 1
882
- },
883
- "name": "array_order_is_significant",
884
- "why": "the same members in another order are a different array"
885
- },
886
- {
887
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"tags\":[\"a\",\"b\"]}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":[\"a\",\"b\",\"c\"],\"field\":\"tags\"},\"source_collection\":\"orders\"},\"version\":1}",
888
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
889
- "input": {
890
- "change": {
891
- "change_kind": "insert",
892
- "collection": "orders",
893
- "value": {
894
- "tags": [
895
- "a",
896
- "b"
897
- ]
898
- }
899
- },
900
- "contract": "feltdb.trigger.match",
901
- "trigger": {
902
- "change_kind": "insert",
903
- "enabled": true,
904
- "predicate": {
905
- "equals": [
906
- "a",
907
- "b",
908
- "c"
909
- ],
910
- "field": "tags"
911
- },
912
- "source_collection": "orders"
913
- },
914
- "version": 1
915
- },
916
- "name": "array_length_is_significant",
917
- "why": "a prefix is not the array"
918
- },
919
- {
920
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"tags\":[\"a\",\"b\"]}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"a\",\"field\":\"tags.0\"},\"source_collection\":\"orders\"},\"version\":1}",
921
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_field_absent\"},\"version\":1}",
922
- "input": {
923
- "change": {
924
- "change_kind": "insert",
925
- "collection": "orders",
926
- "value": {
927
- "tags": [
928
- "a",
929
- "b"
930
- ]
931
- }
932
- },
933
- "contract": "feltdb.trigger.match",
934
- "trigger": {
935
- "change_kind": "insert",
936
- "enabled": true,
937
- "predicate": {
938
- "equals": "a",
939
- "field": "tags.0"
940
- },
941
- "source_collection": "orders"
942
- },
943
- "version": 1
944
- },
945
- "name": "array_elements_are_not_addressable",
946
- "why": "a numeric path segment does not index an array"
947
- },
948
- {
949
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"lines\":[{\"qty\":2,\"sku\":\"x\"},{\"qty\":1,\"sku\":\"y\"}]}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":[{\"qty\":2,\"sku\":\"x\"},{\"qty\":1,\"sku\":\"y\"}],\"field\":\"lines\"},\"source_collection\":\"orders\"},\"version\":1}",
950
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
951
- "input": {
952
- "change": {
953
- "change_kind": "insert",
954
- "collection": "orders",
955
- "value": {
956
- "lines": [
957
- {
958
- "qty": 2,
959
- "sku": "x"
960
- },
961
- {
962
- "qty": 1,
963
- "sku": "y"
964
- }
965
- ]
966
- }
967
- },
968
- "contract": "feltdb.trigger.match",
969
- "trigger": {
970
- "change_kind": "insert",
971
- "enabled": true,
972
- "predicate": {
973
- "equals": [
974
- {
975
- "qty": 2,
976
- "sku": "x"
977
- },
978
- {
979
- "qty": 1,
980
- "sku": "y"
981
- }
982
- ],
983
- "field": "lines"
984
- },
985
- "source_collection": "orders"
986
- },
987
- "version": 1
988
- },
989
- "name": "array_of_objects_equality",
990
- "why": "nested structure inside array elements participates"
991
- },
992
- {
993
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"tags\":[]}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":[],\"field\":\"tags\"},\"source_collection\":\"orders\"},\"version\":1}",
994
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
995
- "input": {
996
- "change": {
997
- "change_kind": "insert",
998
- "collection": "orders",
999
- "value": {
1000
- "tags": []
1001
- }
1002
- },
1003
- "contract": "feltdb.trigger.match",
1004
- "trigger": {
1005
- "change_kind": "insert",
1006
- "enabled": true,
1007
- "predicate": {
1008
- "equals": [],
1009
- "field": "tags"
1010
- },
1011
- "source_collection": "orders"
1012
- },
1013
- "version": 1
1014
- },
1015
- "name": "empty_array_matches_empty_array",
1016
- "why": "an empty array is a value"
1017
- },
1018
- {
1019
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"tags\":[]}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":{},\"field\":\"tags\"},\"source_collection\":\"orders\"},\"version\":1}",
1020
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1021
- "input": {
1022
- "change": {
1023
- "change_kind": "insert",
1024
- "collection": "orders",
1025
- "value": {
1026
- "tags": []
1027
- }
1028
- },
1029
- "contract": "feltdb.trigger.match",
1030
- "trigger": {
1031
- "change_kind": "insert",
1032
- "enabled": true,
1033
- "predicate": {
1034
- "equals": {},
1035
- "field": "tags"
1036
- },
1037
- "source_collection": "orders"
1038
- },
1039
- "version": 1
1040
- },
1041
- "name": "empty_array_is_not_empty_object",
1042
- "why": "an empty array and an empty object are different values"
1043
- },
1044
- {
1045
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"total\":42}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":42,\"field\":\"total\"},\"source_collection\":\"orders\"},\"version\":1}",
1046
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1047
- "input": {
1048
- "change": {
1049
- "change_kind": "insert",
1050
- "collection": "orders",
1051
- "value": {
1052
- "total": 42
1053
- }
1054
- },
1055
- "contract": "feltdb.trigger.match",
1056
- "trigger": {
1057
- "change_kind": "insert",
1058
- "enabled": true,
1059
- "predicate": {
1060
- "equals": 42,
1061
- "field": "total"
1062
- },
1063
- "source_collection": "orders"
1064
- },
1065
- "version": 1
1066
- },
1067
- "name": "integer_equality_matches",
1068
- "why": "integers compare by value"
1069
- },
1070
- {
1071
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"total\":42}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":42.0,\"field\":\"total\"},\"source_collection\":\"orders\"},\"version\":1}",
1072
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1073
- "input": {
1074
- "change": {
1075
- "change_kind": "insert",
1076
- "collection": "orders",
1077
- "value": {
1078
- "total": 42
1079
- }
1080
- },
1081
- "contract": "feltdb.trigger.match",
1082
- "trigger": {
1083
- "change_kind": "insert",
1084
- "enabled": true,
1085
- "predicate": {
1086
- "equals": 42.0,
1087
- "field": "total"
1088
- },
1089
- "source_collection": "orders"
1090
- },
1091
- "version": 1
1092
- },
1093
- "name": "integer_and_float_are_different_values",
1094
- "why": "42 is not 42.0 under JSON value equality"
1095
- },
1096
- {
1097
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"total\":42.0}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":42,\"field\":\"total\"},\"source_collection\":\"orders\"},\"version\":1}",
1098
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1099
- "input": {
1100
- "change": {
1101
- "change_kind": "insert",
1102
- "collection": "orders",
1103
- "value": {
1104
- "total": 42.0
1105
- }
1106
- },
1107
- "contract": "feltdb.trigger.match",
1108
- "trigger": {
1109
- "change_kind": "insert",
1110
- "enabled": true,
1111
- "predicate": {
1112
- "equals": 42,
1113
- "field": "total"
1114
- },
1115
- "source_collection": "orders"
1116
- },
1117
- "version": 1
1118
- },
1119
- "name": "float_and_integer_are_different_values",
1120
- "why": "and the comparison is symmetric"
1121
- },
1122
- {
1123
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"rate\":0.125}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":0.125,\"field\":\"rate\"},\"source_collection\":\"orders\"},\"version\":1}",
1124
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1125
- "input": {
1126
- "change": {
1127
- "change_kind": "insert",
1128
- "collection": "orders",
1129
- "value": {
1130
- "rate": 0.125
1131
- }
1132
- },
1133
- "contract": "feltdb.trigger.match",
1134
- "trigger": {
1135
- "change_kind": "insert",
1136
- "enabled": true,
1137
- "predicate": {
1138
- "equals": 0.125,
1139
- "field": "rate"
1140
- },
1141
- "source_collection": "orders"
1142
- },
1143
- "version": 1
1144
- },
1145
- "name": "float_equality_matches",
1146
- "why": "floats compare by value"
1147
- },
1148
- {
1149
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"delta\":-7}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":-7,\"field\":\"delta\"},\"source_collection\":\"orders\"},\"version\":1}",
1150
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1151
- "input": {
1152
- "change": {
1153
- "change_kind": "insert",
1154
- "collection": "orders",
1155
- "value": {
1156
- "delta": -7
1157
- }
1158
- },
1159
- "contract": "feltdb.trigger.match",
1160
- "trigger": {
1161
- "change_kind": "insert",
1162
- "enabled": true,
1163
- "predicate": {
1164
- "equals": -7,
1165
- "field": "delta"
1166
- },
1167
- "source_collection": "orders"
1168
- },
1169
- "version": 1
1170
- },
1171
- "name": "negative_integer_matches",
1172
- "why": "negative integers are their own variant"
1173
- },
1174
- {
1175
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1176
- "name": "negative_zero_is_not_integer_zero",
1177
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"delta\":-0}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":0,\"field\":\"delta\"},\"source_collection\":\"orders\"},\"version\":1}",
1178
- "why": "the literal -0 carries a sign no integer can hold, so it decodes as a float and never equals the integer 0"
1179
- },
1180
- {
1181
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"counter\":18446744073709551615}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":18446744073709551615,\"field\":\"counter\"},\"source_collection\":\"orders\"},\"version\":1}",
1182
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1183
- "input": {
1184
- "change": {
1185
- "change_kind": "insert",
1186
- "collection": "orders",
1187
- "value": {
1188
- "counter": 18446744073709551615
1189
- }
1190
- },
1191
- "contract": "feltdb.trigger.match",
1192
- "trigger": {
1193
- "change_kind": "insert",
1194
- "enabled": true,
1195
- "predicate": {
1196
- "equals": 18446744073709551615,
1197
- "field": "counter"
1198
- },
1199
- "source_collection": "orders"
1200
- },
1201
- "version": 1
1202
- },
1203
- "name": "large_unsigned_integer_matches",
1204
- "why": "a u64 near the top of the range stays an integer"
1205
- },
1206
- {
1207
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"floor\":-9223372036854775808}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":-9223372036854775808,\"field\":\"floor\"},\"source_collection\":\"orders\"},\"version\":1}",
1208
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1209
- "input": {
1210
- "change": {
1211
- "change_kind": "insert",
1212
- "collection": "orders",
1213
- "value": {
1214
- "floor": -9223372036854775808
1215
- }
1216
- },
1217
- "contract": "feltdb.trigger.match",
1218
- "trigger": {
1219
- "change_kind": "insert",
1220
- "enabled": true,
1221
- "predicate": {
1222
- "equals": -9223372036854775808,
1223
- "field": "floor"
1224
- },
1225
- "source_collection": "orders"
1226
- },
1227
- "version": 1
1228
- },
1229
- "name": "smallest_signed_integer_matches",
1230
- "why": "i64::MIN stays an integer"
1231
- },
1232
- {
1233
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"total\":0}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":0,\"field\":\"total\"},\"source_collection\":\"orders\"},\"version\":1}",
1234
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1235
- "input": {
1236
- "change": {
1237
- "change_kind": "insert",
1238
- "collection": "orders",
1239
- "value": {
1240
- "total": 0
1241
- }
1242
- },
1243
- "contract": "feltdb.trigger.match",
1244
- "trigger": {
1245
- "change_kind": "insert",
1246
- "enabled": true,
1247
- "predicate": {
1248
- "equals": 0,
1249
- "field": "total"
1250
- },
1251
- "source_collection": "orders"
1252
- },
1253
- "version": 1
1254
- },
1255
- "name": "zero_matches_zero",
1256
- "why": "zero is an ordinary value"
1257
- },
1258
- {
1259
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"flag\":0}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":false,\"field\":\"flag\"},\"source_collection\":\"orders\"},\"version\":1}",
1260
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1261
- "input": {
1262
- "change": {
1263
- "change_kind": "insert",
1264
- "collection": "orders",
1265
- "value": {
1266
- "flag": 0
1267
- }
1268
- },
1269
- "contract": "feltdb.trigger.match",
1270
- "trigger": {
1271
- "change_kind": "insert",
1272
- "enabled": true,
1273
- "predicate": {
1274
- "equals": false,
1275
- "field": "flag"
1276
- },
1277
- "source_collection": "orders"
1278
- },
1279
- "version": 1
1280
- },
1281
- "name": "zero_is_not_false",
1282
- "why": "a number and a boolean are different values"
1283
- },
1284
- {
1285
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"total\":\"42\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":42,\"field\":\"total\"},\"source_collection\":\"orders\"},\"version\":1}",
1286
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1287
- "input": {
1288
- "change": {
1289
- "change_kind": "insert",
1290
- "collection": "orders",
1291
- "value": {
1292
- "total": "42"
1293
- }
1294
- },
1295
- "contract": "feltdb.trigger.match",
1296
- "trigger": {
1297
- "change_kind": "insert",
1298
- "enabled": true,
1299
- "predicate": {
1300
- "equals": 42,
1301
- "field": "total"
1302
- },
1303
- "source_collection": "orders"
1304
- },
1305
- "version": 1
1306
- },
1307
- "name": "numeric_string_is_not_a_number",
1308
- "why": "\"42\" is not 42"
1309
- },
1310
- {
1311
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"\"},\"version\":1}",
1312
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1313
- "input": {
1314
- "change": {
1315
- "change_kind": "insert",
1316
- "collection": "",
1317
- "value": {
1318
- "status": "paid"
1319
- }
1320
- },
1321
- "contract": "feltdb.trigger.match",
1322
- "trigger": {
1323
- "change_kind": "insert",
1324
- "enabled": true,
1325
- "source_collection": ""
1326
- },
1327
- "version": 1
1328
- },
1329
- "name": "empty_collection_names_match",
1330
- "why": "an empty collection name is compared like any other"
1331
- },
1332
- {
1333
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"orders\"},\"version\":1}",
1334
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"collection_mismatch\"},\"version\":1}",
1335
- "input": {
1336
- "change": {
1337
- "change_kind": "insert",
1338
- "collection": "",
1339
- "value": {
1340
- "status": "paid"
1341
- }
1342
- },
1343
- "contract": "feltdb.trigger.match",
1344
- "trigger": {
1345
- "change_kind": "insert",
1346
- "enabled": true,
1347
- "source_collection": "orders"
1348
- },
1349
- "version": 1
1350
- },
1351
- "name": "empty_collection_against_named_trigger",
1352
- "why": "an empty collection name is not a wildcard"
1353
- },
1354
- {
1355
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":{},\"field\":\"\"},\"source_collection\":\"orders\"},\"version\":1}",
1356
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1357
- "input": {
1358
- "change": {
1359
- "change_kind": "insert",
1360
- "collection": "orders",
1361
- "value": {}
1362
- },
1363
- "contract": "feltdb.trigger.match",
1364
- "trigger": {
1365
- "change_kind": "insert",
1366
- "enabled": true,
1367
- "predicate": {
1368
- "equals": {},
1369
- "field": ""
1370
- },
1371
- "source_collection": "orders"
1372
- },
1373
- "version": 1
1374
- },
1375
- "name": "empty_object_record",
1376
- "why": "a record with no members"
1377
- },
1378
- {
1379
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
1380
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1381
- "input": {
1382
- "change": {
1383
- "change_kind": "insert",
1384
- "collection": "orders",
1385
- "value": {
1386
- "status": ""
1387
- }
1388
- },
1389
- "contract": "feltdb.trigger.match",
1390
- "trigger": {
1391
- "change_kind": "insert",
1392
- "enabled": true,
1393
- "predicate": {
1394
- "equals": "",
1395
- "field": "status"
1396
- },
1397
- "source_collection": "orders"
1398
- },
1399
- "version": 1
1400
- },
1401
- "name": "empty_string_field_value",
1402
- "why": "an empty string is a value, not an absence"
1403
- },
1404
- {
1405
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"paid\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
1406
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1407
- "input": {
1408
- "change": {
1409
- "change_kind": "insert",
1410
- "collection": "orders",
1411
- "value": {
1412
- "status": ""
1413
- }
1414
- },
1415
- "contract": "feltdb.trigger.match",
1416
- "trigger": {
1417
- "change_kind": "insert",
1418
- "enabled": true,
1419
- "predicate": {
1420
- "equals": "paid",
1421
- "field": "status"
1422
- },
1423
- "source_collection": "orders"
1424
- },
1425
- "version": 1
1426
- },
1427
- "name": "empty_string_is_not_missing",
1428
- "why": "an empty string does not satisfy a non-empty expectation"
1429
- },
1430
- {
1431
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"\":{\"status\":\"paid\"}}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"paid\",\"field\":\".status\"},\"source_collection\":\"orders\"},\"version\":1}",
1432
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1433
- "input": {
1434
- "change": {
1435
- "change_kind": "insert",
1436
- "collection": "orders",
1437
- "value": {
1438
- "": {
1439
- "status": "paid"
1440
- }
1441
- }
1442
- },
1443
- "contract": "feltdb.trigger.match",
1444
- "trigger": {
1445
- "change_kind": "insert",
1446
- "enabled": true,
1447
- "predicate": {
1448
- "equals": "paid",
1449
- "field": ".status"
1450
- },
1451
- "source_collection": "orders"
1452
- },
1453
- "version": 1
1454
- },
1455
- "name": "empty_key_segment_in_path",
1456
- "why": "a leading dot addresses a member whose name is the empty string"
1457
- },
1458
- {
1459
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"naïve\":\"café ☕\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"café ☕\",\"field\":\"naïve\"},\"source_collection\":\"orders\"},\"version\":1}",
1460
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1461
- "input": {
1462
- "change": {
1463
- "change_kind": "insert",
1464
- "collection": "orders",
1465
- "value": {
1466
- "naïve": "café ☕"
1467
- }
1468
- },
1469
- "contract": "feltdb.trigger.match",
1470
- "trigger": {
1471
- "change_kind": "insert",
1472
- "enabled": true,
1473
- "predicate": {
1474
- "equals": "café ☕",
1475
- "field": "naïve"
1476
- },
1477
- "source_collection": "orders"
1478
- },
1479
- "version": 1
1480
- },
1481
- "name": "unicode_field_and_value",
1482
- "why": "non-ASCII keys and values survive canonical encoding on both sides"
1483
- },
1484
- {
1485
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"note\":\"line\\nbreak\\ttab\\\"quote\\\\slash\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"line\\nbreak\\ttab\\\"quote\\\\slash\",\"field\":\"note\"},\"source_collection\":\"orders\"},\"version\":1}",
1486
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1487
- "input": {
1488
- "change": {
1489
- "change_kind": "insert",
1490
- "collection": "orders",
1491
- "value": {
1492
- "note": "line\nbreak\ttab\"quote\\slash"
1493
- }
1494
- },
1495
- "contract": "feltdb.trigger.match",
1496
- "trigger": {
1497
- "change_kind": "insert",
1498
- "enabled": true,
1499
- "predicate": {
1500
- "equals": "line\nbreak\ttab\"quote\\slash",
1501
- "field": "note"
1502
- },
1503
- "source_collection": "orders"
1504
- },
1505
- "version": 1
1506
- },
1507
- "name": "escaped_control_characters_in_value",
1508
- "why": "a value containing characters the encoder must escape"
1509
- },
1510
- {
1511
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\",\"total\":42}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"paid\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
1512
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1513
- "input": {
1514
- "change": {
1515
- "change_kind": "insert",
1516
- "collection": "orders",
1517
- "value": {
1518
- "status": "paid",
1519
- "total": 42
1520
- }
1521
- },
1522
- "contract": "feltdb.trigger.match",
1523
- "trigger": {
1524
- "change_kind": "insert",
1525
- "enabled": true,
1526
- "predicate": {
1527
- "equals": "paid",
1528
- "field": "status"
1529
- },
1530
- "source_collection": "orders"
1531
- },
1532
- "version": 1
1533
- },
1534
- "name": "fanout_first_trigger_matches",
1535
- "why": "one change against the first of several triggers"
1536
- },
1537
- {
1538
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\",\"total\":42}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":42,\"field\":\"total\"},\"source_collection\":\"orders\"},\"version\":1}",
1539
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1540
- "input": {
1541
- "change": {
1542
- "change_kind": "insert",
1543
- "collection": "orders",
1544
- "value": {
1545
- "status": "paid",
1546
- "total": 42
1547
- }
1548
- },
1549
- "contract": "feltdb.trigger.match",
1550
- "trigger": {
1551
- "change_kind": "insert",
1552
- "enabled": true,
1553
- "predicate": {
1554
- "equals": 42,
1555
- "field": "total"
1556
- },
1557
- "source_collection": "orders"
1558
- },
1559
- "version": 1
1560
- },
1561
- "name": "fanout_second_trigger_matches",
1562
- "why": "the same change against a second, differently-predicated trigger"
1563
- },
1564
- {
1565
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\",\"total\":42}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"shipped\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
1566
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1567
- "input": {
1568
- "change": {
1569
- "change_kind": "insert",
1570
- "collection": "orders",
1571
- "value": {
1572
- "status": "paid",
1573
- "total": 42
1574
- }
1575
- },
1576
- "contract": "feltdb.trigger.match",
1577
- "trigger": {
1578
- "change_kind": "insert",
1579
- "enabled": true,
1580
- "predicate": {
1581
- "equals": "shipped",
1582
- "field": "status"
1583
- },
1584
- "source_collection": "orders"
1585
- },
1586
- "version": 1
1587
- },
1588
- "name": "fanout_third_trigger_rejects",
1589
- "why": "the same change against a third trigger that does not match"
1590
- },
1591
- {
1592
- "canonical_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"paid\",\"total\":42}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":false,\"predicate\":{\"equals\":\"paid\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
1593
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"trigger_disabled\"},\"version\":1}",
1594
- "input": {
1595
- "change": {
1596
- "change_kind": "insert",
1597
- "collection": "orders",
1598
- "value": {
1599
- "status": "paid",
1600
- "total": 42
1601
- }
1602
- },
1603
- "contract": "feltdb.trigger.match",
1604
- "trigger": {
1605
- "change_kind": "insert",
1606
- "enabled": false,
1607
- "predicate": {
1608
- "equals": "paid",
1609
- "field": "status"
1610
- },
1611
- "source_collection": "orders"
1612
- },
1613
- "version": 1
1614
- },
1615
- "name": "fanout_fourth_trigger_disabled",
1616
- "why": "the same change against a disabled trigger"
1617
- },
1618
- {
1619
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1620
- "name": "malformed_not_json",
1621
- "raw_input": "not json at all",
1622
- "why": "bytes that are not JSON at all"
1623
- },
1624
- {
1625
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1626
- "name": "malformed_empty_input",
1627
- "raw_input": "",
1628
- "why": "zero bytes"
1629
- },
1630
- {
1631
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1632
- "name": "malformed_truncated_object",
1633
- "raw_input": "{\"change\":",
1634
- "why": "a JSON document that ends mid-value"
1635
- },
1636
- {
1637
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1638
- "name": "malformed_trailing_content",
1639
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1} trailing",
1640
- "why": "a complete document followed by more bytes"
1641
- },
1642
- {
1643
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1644
- "name": "malformed_trailing_comma",
1645
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\",},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1646
- "why": "a trailing comma is not JSON"
1647
- },
1648
- {
1649
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1650
- "name": "malformed_single_quotes",
1651
- "raw_input": "{'contract':'feltdb.trigger.match'}",
1652
- "why": "single-quoted strings are not JSON"
1653
- },
1654
- {
1655
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1656
- "name": "malformed_top_level_array",
1657
- "raw_input": "[]",
1658
- "why": "the input must be an object"
1659
- },
1660
- {
1661
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1662
- "name": "malformed_top_level_string",
1663
- "raw_input": "\"feltdb.trigger.match\"",
1664
- "why": "the input must be an object"
1665
- },
1666
- {
1667
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1668
- "name": "malformed_missing_change",
1669
- "raw_input": "{\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1670
- "why": "a required member is absent"
1671
- },
1672
- {
1673
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1674
- "name": "malformed_missing_trigger",
1675
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"version\":1}",
1676
- "why": "a required member is absent"
1677
- },
1678
- {
1679
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1680
- "name": "malformed_unknown_top_level_field",
1681
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"extra\":true,\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1682
- "why": "the contract denies unknown members"
1683
- },
1684
- {
1685
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1686
- "name": "malformed_unknown_trigger_field",
1687
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\",\"target_capability\":\"identity\"},\"version\":1}",
1688
- "why": "the contract denies unknown members in nested objects"
1689
- },
1690
- {
1691
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1692
- "name": "malformed_duplicate_field",
1693
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1694
- "why": "a repeated contract member is rejected"
1695
- },
1696
- {
1697
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1698
- "name": "malformed_change_kind_value",
1699
- "raw_input": "{\"change\":{\"change_kind\":\"upsert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1700
- "why": "change_kind is a closed set"
1701
- },
1702
- {
1703
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1704
- "name": "malformed_enabled_is_not_bool",
1705
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":1,\"source_collection\":\"o\"},\"version\":1}",
1706
- "why": "enabled must be a boolean, not a truthy value"
1707
- },
1708
- {
1709
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1710
- "name": "malformed_collection_is_not_string",
1711
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":7},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1712
- "why": "collection must be a string"
1713
- },
1714
- {
1715
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1716
- "name": "malformed_predicate_missing_field",
1717
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"x\"},\"source_collection\":\"o\"},\"version\":1}",
1718
- "why": "a predicate needs both members"
1719
- },
1720
- {
1721
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1722
- "name": "malformed_version_is_float",
1723
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1.0}",
1724
- "why": "version is an integer"
1725
- },
1726
- {
1727
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1728
- "name": "malformed_version_is_negative",
1729
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":-1}",
1730
- "why": "version is unsigned"
1731
- },
1732
- {
1733
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_ID_MISMATCH\"},\"version\":1}",
1734
- "name": "contract_id_mismatch",
1735
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.other\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1736
- "why": "a well-formed input addressed to another contract"
1737
- },
1738
- {
1739
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_VERSION_UNSUPPORTED\"},\"version\":1}",
1740
- "name": "contract_version_unsupported",
1741
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":2}",
1742
- "why": "a well-formed input at a version this implementation does not implement"
1743
- },
1744
- {
1745
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1746
- "name": "malformed_and_misaddressed",
1747
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\"},\"contract\":\"feltdb.trigger.other\",\"extra\":1,\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1748
- "why": "shape is validated before identity, so this is an input error"
1749
- },
1750
- {
1751
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1752
- "name": "null_predicate_is_no_predicate",
1753
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\",\"value\":{\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":null,\"source_collection\":\"o\"},\"version\":1}",
1754
- "why": "an explicit null predicate is the absent predicate"
1755
- },
1756
- {
1757
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1758
- "name": "whitespace_around_document",
1759
- "raw_input": " {\"change\" : {\"change_kind\":\"insert\",\"collection\":\"o\"} , \"contract\":\"feltdb.trigger.match\", \"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"}, \"version\":1} ",
1760
- "why": "insignificant whitespace does not change the decision"
1761
- },
1762
- {
1763
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1764
- "name": "unsorted_input_keys_are_still_valid_input",
1765
- "raw_input": "{\"version\":1,\"trigger\":{\"source_collection\":\"o\",\"enabled\":true,\"change_kind\":\"insert\"},\"contract\":\"feltdb.trigger.match\",\"change\":{\"collection\":\"o\",\"change_kind\":\"insert\"}}",
1766
- "why": "canonical ordering is how FeltDB emits input, not a parsing requirement"
1767
- },
1768
- {
1769
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1770
- "name": "unsorted_nested_keys_still_compare_equal",
1771
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"customer\":{\"zeta\":1,\"alpha\":2}}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":{\"alpha\":2,\"zeta\":1},\"field\":\"customer\"},\"source_collection\":\"orders\"},\"version\":1}",
1772
- "why": "object equality is by member, so a record encoded with unsorted keys still equals a sorted expectation"
1773
- },
1774
- {
1775
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1776
- "name": "duplicate_key_inside_record_resolves_last_wins",
1777
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"status\":\"draft\",\"status\":\"paid\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"paid\",\"field\":\"status\"},\"source_collection\":\"orders\"},\"version\":1}",
1778
- "why": "a repeated member inside an opaque record collapses to its last value, as a map-backed decoder does"
1779
- },
1780
- {
1781
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1782
- "name": "escaped_unicode_equals_literal_unicode",
1783
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"note\":\"caf\\u00e9\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"café\",\"field\":\"note\"},\"source_collection\":\"orders\"},\"version\":1}",
1784
- "why": "\\u escapes and literal UTF-8 decode to the same string, so the encoding of the input cannot decide"
1785
- },
1786
- {
1787
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1788
- "name": "surrogate_pair_escape_decodes",
1789
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"note\":\"\\ud83d\\udd25\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":\"🔥\",\"field\":\"note\"},\"source_collection\":\"orders\"},\"version\":1}",
1790
- "why": "an astral character written as a surrogate pair equals the same character written literally"
1791
- },
1792
- {
1793
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1794
- "name": "exponent_notation_is_a_float",
1795
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"total\":1e2}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":100,\"field\":\"total\"},\"source_collection\":\"orders\"},\"version\":1}",
1796
- "why": "1e2 is a float and 100 is an integer, so they are different values"
1797
- },
1798
- {
1799
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1800
- "name": "exponent_notation_equals_decimal_float",
1801
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"total\":1e2}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":100.0,\"field\":\"total\"},\"source_collection\":\"orders\"},\"version\":1}",
1802
- "why": "1e2 and 100.0 are the same float"
1803
- },
1804
- {
1805
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1806
- "name": "integer_beyond_u64_becomes_a_float",
1807
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"counter\":18446744073709551616}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":18446744073709551615,\"field\":\"counter\"},\"source_collection\":\"orders\"},\"version\":1}",
1808
- "why": "an integer literal too large for u64 is a float on both sides, so it cannot equal an integer"
1809
- },
1810
- {
1811
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1812
- "name": "high_precision_float_round_trips",
1813
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"rate\":3.141592653589793}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":3.141592653589793,\"field\":\"rate\"},\"source_collection\":\"orders\"},\"version\":1}",
1814
- "why": "a float needing full precision decodes identically on both sides"
1815
- },
1816
- {
1817
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1818
- "name": "malformed_leading_zero_number",
1819
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\",\"value\":{\"total\":01}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1820
- "why": "01 is not a JSON number"
1821
- },
1822
- {
1823
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1824
- "name": "malformed_nan_literal",
1825
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\",\"value\":{\"total\":NaN}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1826
- "why": "NaN is not a JSON value, and a contract that accepted it would admit a value with no equality"
1827
- },
1828
- {
1829
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1830
- "name": "malformed_raw_control_character_in_string",
1831
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\",\"value\":{\"note\":\"a\nb\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1832
- "why": "an unescaped control character is not legal inside a JSON string"
1833
- },
1834
- {
1835
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"error\":{\"code\":\"CONTRACT_INPUT_INVALID\"},\"version\":1}",
1836
- "name": "malformed_lone_surrogate_escape",
1837
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"o\",\"value\":{\"note\":\"\\ud83d\"}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"source_collection\":\"o\"},\"version\":1}",
1838
- "why": "an unpaired surrogate does not name a character"
1839
- },
1840
- {
1841
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1842
- "name": "negative_zero_equals_negative_zero",
1843
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"delta\":-0}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":-0.0,\"field\":\"delta\"},\"source_collection\":\"orders\"},\"version\":1}",
1844
- "why": "-0 and -0.0 decode to the same float"
1845
- },
1846
- {
1847
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":true,\"reason\":\"matched\"},\"version\":1}",
1848
- "name": "negative_zero_float_equals_positive_zero_float",
1849
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"delta\":-0.0}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":0.0,\"field\":\"delta\"},\"source_collection\":\"orders\"},\"version\":1}",
1850
- "why": "float equality is IEEE equality, under which -0.0 and 0.0 are equal"
1851
- },
1852
- {
1853
- "expected_output": "{\"contract\":\"feltdb.trigger.match\",\"outcome\":{\"matched\":false,\"reason\":\"predicate_value_mismatch\"},\"version\":1}",
1854
- "name": "negative_integer_beyond_i64_becomes_a_float",
1855
- "raw_input": "{\"change\":{\"change_kind\":\"insert\",\"collection\":\"orders\",\"value\":{\"floor\":-9223372036854775809}},\"contract\":\"feltdb.trigger.match\",\"trigger\":{\"change_kind\":\"insert\",\"enabled\":true,\"predicate\":{\"equals\":-9223372036854775808,\"field\":\"floor\"},\"source_collection\":\"orders\"},\"version\":1}",
1856
- "why": "a negative integer literal too small for i64 decodes as a float"
1857
- }
1858
- ],
1859
- "contract": "feltdb.trigger.match",
1860
- "contract_version": 1,
1861
- "corpus_version": 1
1862
- }