familia 2.0.0.pre19 → 2.0.0.pre21

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 (372) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/claude-code-review.yml +4 -9
  3. data/.github/workflows/code-smells.yml +64 -3
  4. data/.pre-commit-config.yaml +8 -6
  5. data/.reek.yml +10 -9
  6. data/.rubocop.yml +4 -0
  7. data/CHANGELOG.rst +177 -112
  8. data/CLAUDE.md +28 -1
  9. data/Gemfile +1 -1
  10. data/Gemfile.lock +20 -17
  11. data/bin/try +16 -0
  12. data/bin/tryouts +16 -0
  13. data/changelog.d/20251105_flexible_external_identifier_format.rst +66 -0
  14. data/changelog.d/20251107_112554_delano_179_participation_asymmetry.rst +44 -0
  15. data/changelog.d/20251107_213121_delano_fix_thread_safety_races_011CUumCP492Twxm4NLt2FvL.rst +20 -0
  16. data/changelog.d/20251107_fix_participates_in_symbol_resolution.rst +91 -0
  17. data/changelog.d/20251107_optimized_redis_exists_checks.rst +94 -0
  18. data/changelog.d/20251108_frozen_string_literal_pragma.rst +44 -0
  19. data/docs/1106-participates_in-bidirectional-solution.md +129 -0
  20. data/docs/guides/encryption.md +486 -0
  21. data/docs/guides/feature-encrypted-fields.md +123 -7
  22. data/docs/guides/feature-expiration.md +161 -117
  23. data/docs/guides/feature-external-identifiers.md +415 -443
  24. data/docs/guides/feature-object-identifiers.md +400 -269
  25. data/docs/guides/feature-quantization.md +120 -6
  26. data/docs/guides/feature-relationships-indexing.md +318 -0
  27. data/docs/guides/feature-relationships-methods.md +146 -604
  28. data/docs/guides/feature-relationships-participation.md +263 -0
  29. data/docs/guides/feature-relationships.md +118 -136
  30. data/docs/guides/feature-system-devs.md +176 -693
  31. data/docs/guides/feature-system.md +119 -6
  32. data/docs/guides/feature-transient-fields.md +81 -0
  33. data/docs/guides/field-system.md +778 -0
  34. data/docs/guides/index.md +32 -15
  35. data/docs/guides/logging.md +187 -0
  36. data/docs/guides/optimized-loading.md +674 -0
  37. data/docs/guides/thread-safety-monitoring.md +61 -0
  38. data/docs/guides/{time-utilities.md → time-literals.md} +12 -12
  39. data/docs/migrating/v2.0.0-pre22.md +241 -0
  40. data/docs/overview.md +7 -9
  41. data/docs/reference/api-technical.md +267 -320
  42. data/examples/autoloader/mega_customer/features/deprecated_fields.rb +2 -0
  43. data/examples/autoloader/mega_customer/safe_dump_fields.rb +2 -0
  44. data/examples/autoloader/mega_customer.rb +2 -0
  45. data/examples/datatype_standalone.rb +4 -3
  46. data/examples/encrypted_fields.rb +2 -1
  47. data/examples/json_usage_patterns.rb +2 -0
  48. data/examples/relationships.rb +3 -0
  49. data/examples/safe_dump.rb +2 -1
  50. data/examples/sampling_demo.rb +53 -0
  51. data/examples/single_connection_transaction_confusions.rb +2 -1
  52. data/familia.gemspec +2 -1
  53. data/lib/familia/base.rb +2 -0
  54. data/lib/familia/connection/behavior.rb +2 -0
  55. data/lib/familia/connection/handlers.rb +2 -0
  56. data/lib/familia/connection/individual_command_proxy.rb +2 -0
  57. data/lib/familia/connection/middleware.rb +34 -24
  58. data/lib/familia/connection/operation_core.rb +2 -0
  59. data/lib/familia/connection/operations.rb +2 -0
  60. data/lib/familia/connection/pipelined_core.rb +2 -0
  61. data/lib/familia/connection/transaction_core.rb +68 -0
  62. data/lib/familia/connection.rb +18 -3
  63. data/lib/familia/data_type/class_methods.rb +3 -1
  64. data/lib/familia/data_type/connection.rb +2 -0
  65. data/lib/familia/data_type/database_commands.rb +2 -0
  66. data/lib/familia/data_type/serialization.rb +6 -4
  67. data/lib/familia/data_type/settings.rb +2 -0
  68. data/lib/familia/data_type/types/counter.rb +2 -0
  69. data/lib/familia/data_type/types/hashkey.rb +7 -5
  70. data/lib/familia/data_type/types/listkey.rb +2 -0
  71. data/lib/familia/data_type/types/lock.rb +2 -0
  72. data/lib/familia/data_type/types/sorted_set.rb +2 -0
  73. data/lib/familia/data_type/types/stringkey.rb +2 -0
  74. data/lib/familia/data_type/types/unsorted_set.rb +2 -0
  75. data/lib/familia/data_type.rb +2 -0
  76. data/lib/familia/encryption/encrypted_data.rb +4 -2
  77. data/lib/familia/encryption/manager.rb +2 -0
  78. data/lib/familia/encryption/provider.rb +2 -0
  79. data/lib/familia/encryption/providers/aes_gcm_provider.rb +2 -0
  80. data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +2 -0
  81. data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +2 -0
  82. data/lib/familia/encryption/registry.rb +2 -0
  83. data/lib/familia/encryption/request_cache.rb +2 -0
  84. data/lib/familia/encryption.rb +9 -2
  85. data/lib/familia/errors.rb +2 -0
  86. data/lib/familia/features/autoloader.rb +2 -0
  87. data/lib/familia/features/encrypted_fields/concealed_string.rb +2 -0
  88. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +4 -0
  89. data/lib/familia/features/encrypted_fields.rb +2 -2
  90. data/lib/familia/features/expiration/extensions.rb +3 -1
  91. data/lib/familia/features/expiration.rb +12 -4
  92. data/lib/familia/features/external_identifier.rb +33 -7
  93. data/lib/familia/features/object_identifier.rb +2 -0
  94. data/lib/familia/features/quantization.rb +3 -1
  95. data/lib/familia/features/relationships/README.md +3 -1
  96. data/lib/familia/features/relationships/collection_operations.rb +2 -0
  97. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +138 -9
  98. data/lib/familia/features/relationships/indexing/rebuild_strategies.rb +479 -0
  99. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +89 -21
  100. data/lib/familia/features/relationships/indexing.rb +3 -0
  101. data/lib/familia/features/relationships/indexing_relationship.rb +3 -1
  102. data/lib/familia/features/relationships/participation/participant_methods.rb +131 -14
  103. data/lib/familia/features/relationships/participation/rebuild_strategies.md +41 -0
  104. data/lib/familia/features/relationships/participation/target_methods.rb +6 -6
  105. data/lib/familia/features/relationships/participation.rb +155 -69
  106. data/lib/familia/features/relationships/participation_membership.rb +69 -0
  107. data/lib/familia/features/relationships/participation_relationship.rb +34 -6
  108. data/lib/familia/features/relationships/score_encoding.rb +2 -0
  109. data/lib/familia/features/relationships.rb +5 -3
  110. data/lib/familia/features/safe_dump.rb +2 -0
  111. data/lib/familia/features/transient_fields/redacted_string.rb +2 -0
  112. data/lib/familia/features/transient_fields/single_use_redacted_string.rb +2 -0
  113. data/lib/familia/features/transient_fields/transient_field_type.rb +5 -3
  114. data/lib/familia/features/transient_fields.rb +2 -0
  115. data/lib/familia/features.rb +2 -0
  116. data/lib/familia/field_type.rb +3 -1
  117. data/lib/familia/horreum/connection.rb +17 -1
  118. data/lib/familia/horreum/database_commands.rb +2 -0
  119. data/lib/familia/horreum/definition.rb +16 -6
  120. data/lib/familia/horreum/management.rb +212 -42
  121. data/lib/familia/horreum/persistence.rb +176 -108
  122. data/lib/familia/horreum/related_fields.rb +2 -0
  123. data/lib/familia/horreum/serialization.rb +23 -4
  124. data/lib/familia/horreum/settings.rb +2 -0
  125. data/lib/familia/horreum/utils.rb +2 -0
  126. data/lib/familia/horreum.rb +15 -1
  127. data/lib/familia/identifier_extractor.rb +2 -0
  128. data/lib/familia/instrumentation.rb +156 -0
  129. data/lib/familia/json_serializer.rb +2 -0
  130. data/lib/familia/logging.rb +92 -32
  131. data/lib/familia/refinements/dear_json.rb +2 -0
  132. data/lib/familia/refinements/stylize_words.rb +2 -14
  133. data/lib/familia/refinements/time_literals.rb +2 -0
  134. data/lib/familia/refinements.rb +2 -0
  135. data/lib/familia/secure_identifier.rb +10 -2
  136. data/lib/familia/settings.rb +2 -0
  137. data/lib/familia/thread_safety/instrumented_mutex.rb +166 -0
  138. data/lib/familia/thread_safety/monitor.rb +328 -0
  139. data/lib/familia/utils.rb +13 -0
  140. data/lib/familia/verifiable_identifier.rb +3 -1
  141. data/lib/familia/version.rb +3 -1
  142. data/lib/familia.rb +31 -4
  143. data/lib/middleware/database_command_counter.rb +152 -0
  144. data/lib/middleware/database_logger.rb +295 -170
  145. data/lib/multi_result.rb +2 -0
  146. data/try/edge_cases/empty_identifiers_try.rb +2 -0
  147. data/try/edge_cases/hash_symbolization_try.rb +2 -0
  148. data/try/edge_cases/json_serialization_try.rb +2 -0
  149. data/try/edge_cases/legacy_data_detection/deserialization_edge_cases_try.rb +4 -0
  150. data/try/edge_cases/race_conditions_try.rb +4 -0
  151. data/try/edge_cases/reserved_keywords_try.rb +4 -0
  152. data/try/edge_cases/string_coercion_try.rb +2 -0
  153. data/try/edge_cases/ttl_side_effects_try.rb +4 -0
  154. data/try/features/encrypted_fields/aad_protection_try.rb +4 -0
  155. data/try/features/encrypted_fields/concealed_string_core_try.rb +4 -0
  156. data/try/features/encrypted_fields/context_isolation_try.rb +4 -0
  157. data/try/features/encrypted_fields/encrypted_fields_core_try.rb +33 -0
  158. data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +4 -0
  159. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +4 -0
  160. data/try/features/encrypted_fields/encrypted_fields_security_try.rb +4 -0
  161. data/try/features/encrypted_fields/error_conditions_try.rb +4 -0
  162. data/try/features/encrypted_fields/fresh_key_derivation_try.rb +4 -0
  163. data/try/features/encrypted_fields/fresh_key_try.rb +4 -0
  164. data/try/features/encrypted_fields/key_rotation_try.rb +4 -0
  165. data/try/features/encrypted_fields/memory_security_try.rb +4 -0
  166. data/try/features/encrypted_fields/missing_current_key_version_try.rb +4 -0
  167. data/try/features/encrypted_fields/nonce_uniqueness_try.rb +4 -0
  168. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +4 -0
  169. data/try/features/encrypted_fields/thread_safety_try.rb +4 -0
  170. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +4 -0
  171. data/try/features/encryption/config_persistence_try.rb +4 -0
  172. data/try/features/encryption/core_try.rb +4 -0
  173. data/try/features/encryption/instance_variable_scope_try.rb +4 -0
  174. data/try/features/encryption/module_loading_try.rb +4 -0
  175. data/try/features/encryption/providers/aes_gcm_provider_try.rb +4 -0
  176. data/try/features/encryption/providers/xchacha20_poly1305_provider_try.rb +4 -0
  177. data/try/features/encryption/roundtrip_validation_try.rb +4 -0
  178. data/try/features/encryption/secure_memory_handling_try.rb +4 -0
  179. data/try/features/expiration/expiration_try.rb +4 -0
  180. data/try/features/external_identifier/external_identifier_try.rb +171 -8
  181. data/try/features/feature_dependencies_try.rb +2 -0
  182. data/try/features/feature_improvements_try.rb +2 -0
  183. data/try/features/field_groups_try.rb +2 -0
  184. data/try/features/object_identifier/object_identifier_integration_try.rb +12 -9
  185. data/try/features/object_identifier/object_identifier_try.rb +2 -0
  186. data/try/features/quantization/quantization_try.rb +4 -0
  187. data/try/features/real_feature_integration_try.rb +2 -0
  188. data/try/features/relationships/indexing_commands_verification_try.rb +2 -0
  189. data/try/features/relationships/indexing_rebuild_try.rb +600 -0
  190. data/try/features/relationships/indexing_try.rb +2 -0
  191. data/try/features/relationships/participation_bidirectional_try.rb +242 -0
  192. data/try/features/relationships/participation_commands_verification_spec.rb +4 -0
  193. data/try/features/relationships/participation_commands_verification_try.rb +2 -0
  194. data/try/features/relationships/participation_performance_improvements_try.rb +11 -9
  195. data/try/features/relationships/participation_reverse_index_try.rb +15 -13
  196. data/try/features/relationships/participation_target_class_resolution_try.rb +209 -0
  197. data/try/features/relationships/participation_unresolved_target_try.rb +109 -0
  198. data/try/features/relationships/relationships_api_changes_try.rb +2 -0
  199. data/try/features/relationships/relationships_edge_cases_try.rb +4 -0
  200. data/try/features/relationships/relationships_performance_minimal_try.rb +4 -0
  201. data/try/features/relationships/relationships_performance_simple_try.rb +4 -0
  202. data/try/features/relationships/relationships_performance_try.rb +4 -0
  203. data/try/features/relationships/relationships_performance_working_try.rb +4 -0
  204. data/try/features/relationships/relationships_try.rb +6 -4
  205. data/try/features/safe_dump/safe_dump_advanced_try.rb +4 -0
  206. data/try/features/safe_dump/safe_dump_try.rb +4 -0
  207. data/try/features/transient_fields/redacted_string_try.rb +2 -0
  208. data/try/features/transient_fields/refresh_reset_try.rb +3 -0
  209. data/try/features/transient_fields/simple_refresh_test.rb +3 -0
  210. data/try/features/transient_fields/single_use_redacted_string_try.rb +2 -0
  211. data/try/features/transient_fields/transient_fields_core_try.rb +4 -0
  212. data/try/features/transient_fields/transient_fields_integration_try.rb +4 -0
  213. data/try/integration/connection/fiber_context_preservation_try.rb +4 -0
  214. data/try/integration/connection/handler_constraints_try.rb +4 -0
  215. data/try/integration/connection/isolated_dbclient_try.rb +4 -0
  216. data/try/integration/connection/middleware_reconnect_try.rb +2 -0
  217. data/try/integration/connection/operation_mode_guards_try.rb +4 -0
  218. data/try/integration/connection/pipeline_fallback_integration_try.rb +3 -0
  219. data/try/integration/connection/pools_try.rb +4 -0
  220. data/try/integration/connection/responsibility_chain_tracking_try.rb +4 -0
  221. data/try/integration/connection/transaction_fallback_integration_try.rb +4 -0
  222. data/try/integration/connection/transaction_mode_permissive_try.rb +4 -0
  223. data/try/integration/connection/transaction_mode_strict_try.rb +4 -0
  224. data/try/integration/connection/transaction_mode_warn_try.rb +4 -0
  225. data/try/integration/connection/transaction_modes_try.rb +4 -0
  226. data/try/integration/conventional_inheritance_try.rb +4 -0
  227. data/try/integration/create_method_try.rb +4 -0
  228. data/try/integration/cross_component_try.rb +4 -0
  229. data/try/integration/data_types/datatype_pipelines_try.rb +4 -0
  230. data/try/integration/data_types/datatype_transactions_try.rb +4 -0
  231. data/try/integration/database_consistency_try.rb +4 -0
  232. data/try/integration/familia_extended_try.rb +4 -0
  233. data/try/integration/familia_members_methods_try.rb +4 -0
  234. data/try/integration/models/customer_safe_dump_try.rb +4 -0
  235. data/try/integration/models/customer_try.rb +4 -0
  236. data/try/integration/models/datatype_base_try.rb +4 -0
  237. data/try/integration/models/familia_object_try.rb +4 -0
  238. data/try/integration/persistence_operations_try.rb +4 -0
  239. data/try/integration/relationships_persistence_round_trip_try.rb +17 -14
  240. data/try/integration/save_methods_consistency_try.rb +241 -0
  241. data/try/integration/scenarios_try.rb +4 -0
  242. data/try/integration/secure_identifier_try.rb +4 -0
  243. data/try/integration/transaction_safety_core_try.rb +176 -0
  244. data/try/integration/transaction_safety_workflow_try.rb +291 -0
  245. data/try/integration/verifiable_identifier_try.rb +4 -0
  246. data/try/investigation/pipeline_routing/README.md +228 -0
  247. data/try/performance/benchmarks_try.rb +4 -0
  248. data/try/performance/transaction_safety_benchmark_try.rb +238 -0
  249. data/try/support/benchmarks/deserialization_benchmark.rb +3 -1
  250. data/try/support/benchmarks/deserialization_correctness_test.rb +3 -1
  251. data/try/support/debugging/cache_behavior_tracer.rb +4 -0
  252. data/try/support/debugging/debug_aad_process.rb +3 -0
  253. data/try/support/debugging/debug_concealed_internal.rb +3 -0
  254. data/try/support/debugging/debug_concealed_reveal.rb +3 -0
  255. data/try/support/debugging/debug_context_aad.rb +3 -0
  256. data/try/support/debugging/debug_context_simple.rb +3 -0
  257. data/try/support/debugging/debug_cross_context.rb +3 -0
  258. data/try/support/debugging/debug_database_load.rb +3 -0
  259. data/try/support/debugging/debug_encrypted_json_check.rb +3 -0
  260. data/try/support/debugging/debug_encrypted_json_step_by_step.rb +3 -0
  261. data/try/support/debugging/debug_exists_lifecycle.rb +3 -0
  262. data/try/support/debugging/debug_field_decrypt.rb +3 -0
  263. data/try/support/debugging/debug_fresh_cross_context.rb +3 -0
  264. data/try/support/debugging/debug_load_path.rb +3 -0
  265. data/try/support/debugging/debug_method_definition.rb +3 -0
  266. data/try/support/debugging/debug_method_resolution.rb +3 -0
  267. data/try/support/debugging/debug_minimal.rb +3 -0
  268. data/try/support/debugging/debug_provider.rb +3 -0
  269. data/try/support/debugging/debug_secure_behavior.rb +3 -0
  270. data/try/support/debugging/debug_string_class.rb +3 -0
  271. data/try/support/debugging/debug_test.rb +3 -0
  272. data/try/support/debugging/debug_test_design.rb +3 -0
  273. data/try/support/debugging/encryption_method_tracer.rb +4 -0
  274. data/try/support/debugging/provider_diagnostics.rb +4 -0
  275. data/try/support/helpers/test_cleanup.rb +4 -0
  276. data/try/support/helpers/test_helpers.rb +5 -0
  277. data/try/support/memory/memory_basic_test.rb +4 -0
  278. data/try/support/memory/memory_detailed_test.rb +4 -0
  279. data/try/support/memory/memory_search_for_string.rb +4 -0
  280. data/try/support/memory/test_actual_redactedstring_protection.rb +4 -0
  281. data/try/support/prototypes/atomic_saves_v1_context_proxy.rb +4 -0
  282. data/try/support/prototypes/atomic_saves_v2_connection_switching.rb +4 -0
  283. data/try/support/prototypes/atomic_saves_v3_connection_pool.rb +4 -0
  284. data/try/support/prototypes/atomic_saves_v4.rb +4 -0
  285. data/try/support/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +4 -0
  286. data/try/support/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -0
  287. data/try/support/prototypes/pooling/configurable_stress_test.rb +4 -0
  288. data/try/support/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -0
  289. data/try/support/prototypes/pooling/lib/connection_pool_metrics.rb +4 -0
  290. data/try/support/prototypes/pooling/lib/connection_pool_stress_test.rb +4 -0
  291. data/try/support/prototypes/pooling/lib/connection_pool_threading_models.rb +4 -0
  292. data/try/support/prototypes/pooling/lib/visualize_stress_results.rb +4 -2
  293. data/try/support/prototypes/pooling/pool_siege.rb +4 -2
  294. data/try/support/prototypes/pooling/run_stress_tests.rb +4 -2
  295. data/try/thread_safety/README.md +496 -0
  296. data/try/thread_safety/class_connection_chain_race_try.rb +265 -0
  297. data/try/thread_safety/connection_chain_race_try.rb +148 -0
  298. data/try/thread_safety/encryption_manager_cache_race_try.rb +166 -0
  299. data/try/thread_safety/feature_registry_race_try.rb +226 -0
  300. data/try/thread_safety/fiber_pipeline_isolation_try.rb +235 -0
  301. data/try/thread_safety/fiber_transaction_isolation_try.rb +208 -0
  302. data/try/thread_safety/field_registration_race_try.rb +222 -0
  303. data/try/thread_safety/logger_initialization_race_try.rb +170 -0
  304. data/try/thread_safety/middleware_registration_race_try.rb +154 -0
  305. data/try/thread_safety/module_config_race_try.rb +175 -0
  306. data/try/thread_safety/secure_identifier_cache_race_try.rb +226 -0
  307. data/try/unit/core/autoloader_try.rb +4 -0
  308. data/try/unit/core/base_enhancements_try.rb +4 -0
  309. data/try/unit/core/connection_try.rb +4 -0
  310. data/try/unit/core/errors_try.rb +4 -0
  311. data/try/unit/core/extensions_try.rb +4 -0
  312. data/try/unit/core/familia_logger_try.rb +2 -0
  313. data/try/unit/core/familia_try.rb +4 -0
  314. data/try/unit/core/middleware_sampling_try.rb +335 -0
  315. data/try/unit/core/middleware_test_helpers_bug_try.rb +58 -0
  316. data/try/unit/core/middleware_thread_safety_try.rb +245 -0
  317. data/try/unit/core/middleware_try.rb +4 -0
  318. data/try/unit/core/settings_try.rb +4 -0
  319. data/try/unit/core/time_utils_try.rb +4 -0
  320. data/try/unit/core/tools_try.rb +4 -0
  321. data/try/unit/core/utils_try.rb +37 -0
  322. data/try/unit/data_types/boolean_try.rb +4 -0
  323. data/try/unit/data_types/counter_try.rb +4 -0
  324. data/try/unit/data_types/datatype_base_try.rb +4 -0
  325. data/try/unit/data_types/hash_try.rb +4 -0
  326. data/try/unit/data_types/list_try.rb +4 -0
  327. data/try/unit/data_types/lock_try.rb +4 -0
  328. data/try/unit/data_types/sorted_set_try.rb +4 -0
  329. data/try/unit/data_types/sorted_set_zadd_options_try.rb +4 -0
  330. data/try/unit/data_types/string_try.rb +4 -0
  331. data/try/unit/data_types/unsortedset_try.rb +4 -0
  332. data/try/unit/familia_resolve_class_try.rb +116 -0
  333. data/try/unit/horreum/auto_indexing_on_save_try.rb +5 -1
  334. data/try/unit/horreum/automatic_index_validation_try.rb +2 -0
  335. data/try/unit/horreum/base_try.rb +4 -0
  336. data/try/unit/horreum/class_methods_try.rb +4 -0
  337. data/try/unit/horreum/commands_try.rb +4 -0
  338. data/try/unit/horreum/defensive_initialization_try.rb +4 -0
  339. data/try/unit/horreum/destroy_related_fields_cleanup_try.rb +4 -0
  340. data/try/unit/horreum/enhanced_conflict_handling_try.rb +4 -0
  341. data/try/unit/horreum/field_categories_try.rb +4 -0
  342. data/try/unit/horreum/field_definition_try.rb +4 -0
  343. data/try/unit/horreum/initialization_try.rb +4 -0
  344. data/try/unit/horreum/json_type_preservation_try.rb +2 -0
  345. data/try/unit/horreum/optimized_loading_try.rb +156 -0
  346. data/try/unit/horreum/relations_try.rb +4 -0
  347. data/try/unit/horreum/serialization_persistent_fields_try.rb +4 -0
  348. data/try/unit/horreum/serialization_try.rb +4 -0
  349. data/try/unit/horreum/settings_try.rb +4 -0
  350. data/try/unit/horreum/unique_index_edge_cases_try.rb +4 -0
  351. data/try/unit/horreum/unique_index_guard_validation_try.rb +2 -0
  352. data/try/unit/middleware/database_command_counter_methods_try.rb +139 -0
  353. data/try/unit/middleware/database_logger_methods_try.rb +251 -0
  354. data/try/unit/refinements/dear_json_array_methods_try.rb +4 -0
  355. data/try/unit/refinements/dear_json_hash_methods_try.rb +4 -0
  356. data/try/unit/refinements/time_literals_numeric_methods_try.rb +4 -0
  357. data/try/unit/refinements/time_literals_string_methods_try.rb +4 -0
  358. data/try/unit/thread_safety_monitor_try.rb +149 -0
  359. metadata +72 -17
  360. data/.github/workflows/code-quality.yml +0 -138
  361. data/changelog.d/20251011_012003_delano_159_datatype_transaction_pipeline_support.rst +0 -91
  362. data/changelog.d/20251011_203905_delano_next.rst +0 -30
  363. data/changelog.d/20251011_212633_delano_next.rst +0 -13
  364. data/changelog.d/20251011_221253_delano_next.rst +0 -26
  365. data/docs/archive/FAMILIA_RELATIONSHIPS.md +0 -210
  366. data/docs/archive/FAMILIA_TECHNICAL.md +0 -823
  367. data/docs/archive/FAMILIA_UPDATE.md +0 -226
  368. data/docs/archive/README.md +0 -64
  369. data/docs/archive/api-reference.md +0 -333
  370. data/docs/guides/core-field-system.md +0 -806
  371. data/docs/guides/implementation.md +0 -276
  372. data/docs/guides/security-model.md +0 -183
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/context_isolation_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encryption_fields/context_isolation_try.rb
2
6
 
3
7
  require 'base64'
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/encrypted_fields_core_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encrypted_fields_core_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -122,4 +126,33 @@ end
122
126
  @user2.api_key.reveal { |decrypted| decrypted }
123
127
  #=> 'secret-key-123'
124
128
 
129
+ ## encrypted_data? returns false when no encrypted fields have values
130
+ class SecureUser6 < Familia::Horreum
131
+ feature :encrypted_fields
132
+ identifier_field :user_id
133
+ field :user_id
134
+ encrypted_field :ssn
135
+ encrypted_field :api_key
136
+ end
137
+
138
+ @user3 = SecureUser6.new(user_id: 'test-user-006')
139
+ @user3.encrypted_data?
140
+ #=> false
141
+
142
+ ## encrypted_data? returns true when at least one encrypted field has a value
143
+ @user3.ssn = '123-45-6789'
144
+ @user3.encrypted_data?
145
+ #=> true
146
+
147
+ ## encrypted_data? returns true with multiple encrypted fields set
148
+ @user3.api_key = 'secret-key-456'
149
+ @user3.encrypted_data?
150
+ #=> true
151
+
152
+ ## encrypted_data? returns false after clearing encrypted fields
153
+ @user3.ssn = nil
154
+ @user3.api_key = nil
155
+ @user3.encrypted_data?
156
+ #=> false
157
+
125
158
  Fiber[:familia_key_cache]&.clear if Fiber[:familia_key_cache]
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/encrypted_fields_integration_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encrypted_fields_integration_try.rb
2
6
 
3
7
  # Test constants will be redefined in each test since variables don't persist
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encrypted_fields_no_cache_security_try.rb
2
6
  #
3
7
  # Security tests for the no-cache encryption strategy
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/encrypted_fields_security_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encrypted_fields_security_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/error_conditions_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encryption_fields/error_conditions_try.rb
2
6
 
3
7
  require 'base64'
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/fresh_key_derivation_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encryption_fields/fresh_key_derivation_try.rb
2
6
 
3
7
  require 'base64'
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/fresh_key_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  require_relative '../../support/helpers/test_helpers'
2
6
  require 'base64'
3
7
 
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/key_rotation_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encryption_fields/key_rotation_try.rb
2
6
 
3
7
  require 'base64'
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/memory_security_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encryption_fields/memory_security_try.rb
2
6
 
3
7
  require 'base64'
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/missing_current_key_version_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encryption_fields/missing_current_key_version_try.rb
2
6
 
3
7
  require 'base64'
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/nonce_uniqueness_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encryption_fields/nonce_uniqueness_try.rb
2
6
 
3
7
  require 'base64'
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/secure_by_default_behavior_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encryption_fields/secure_by_default_behavior_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/thread_safety_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encryption_fields/thread_safety_try.rb
2
6
 
3
7
  require 'concurrent'
@@ -1,3 +1,7 @@
1
+ # try/features/encrypted_fields/universal_serialization_safety_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/encryption_fields/universal_serialization_safety_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/features/encryption/config_persistence_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/encryption/debug2_try.rb
2
6
 
3
7
  # - Tests configuration persistence between test sections
@@ -1,3 +1,7 @@
1
+ # try/features/encryption/core_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/encryption/encryption_core_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/features/encryption/instance_variable_scope_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/encryption/debug3_try.rb
2
6
 
3
7
  # - Tests instance variable scoping in tryouts framework
@@ -1,3 +1,7 @@
1
+ # try/features/encryption/module_loading_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/encryption/debug_try.rb
2
6
 
3
7
  # - Tests that the encryption module loads correctly
@@ -1,3 +1,7 @@
1
+ # try/features/encryption/providers/aes_gcm_provider_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/encryption/providers/aes_gcm_provider_try.rb
2
6
 
3
7
  require_relative '../../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/features/encryption/providers/xchacha20_poly1305_provider_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/encryption/providers/xchacha20_poly1305_provider_try.rb
2
6
 
3
7
  require_relative '../../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/features/encryption/roundtrip_validation_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/encryption/debug4_try.rb
2
6
 
3
7
  # - Tests full encryption/decryption round trips
@@ -1,3 +1,7 @@
1
+ # try/features/encryption/secure_memory_handling_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/encryption/secure_memory_handling_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/features/expiration/expiration_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/expiration_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,4 +1,6 @@
1
1
  # try/features/external_identifier/external_identifier_try.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative '../../support/helpers/test_helpers'
4
6
 
@@ -15,10 +17,28 @@ class ExternalIdTest < Familia::Horreum
15
17
  field :name
16
18
  end
17
19
 
18
- # Class with custom prefix
20
+ # Class with custom format using different prefix
19
21
  class CustomPrefixTest < Familia::Horreum
20
22
  feature :object_identifier
21
- feature :external_identifier, prefix: 'cust'
23
+ feature :external_identifier, format: 'cust_%{id}'
24
+ identifier_field :id
25
+ field :id
26
+ field :name
27
+ end
28
+
29
+ # Class with custom format template using hyphen separator
30
+ class CustomFormatTest < Familia::Horreum
31
+ feature :object_identifier
32
+ feature :external_identifier, format: 'ext-%{id}'
33
+ identifier_field :id
34
+ field :id
35
+ field :name
36
+ end
37
+
38
+ # Class with format template without traditional prefix
39
+ class NoPrefixFormatTest < Familia::Horreum
40
+ feature :object_identifier
41
+ feature :external_identifier, format: 'api/%{id}'
22
42
  identifier_field :id
23
43
  field :id
24
44
  field :name
@@ -77,6 +97,28 @@ custom_obj = CustomPrefixTest.new
77
97
  custom_obj.extid.start_with?('cust_')
78
98
  #==> true
79
99
 
100
+ ## Custom format with hyphen separator
101
+ format_obj = CustomFormatTest.new
102
+ format_obj.extid.start_with?('ext-')
103
+ #==> true
104
+
105
+ ## Custom format uses hyphen not underscore
106
+ format_obj = CustomFormatTest.new
107
+ extid = format_obj.extid
108
+ extid.include?('-') && !extid.include?('_')
109
+ #==> true
110
+
111
+ ## Format without prefix placeholder uses literal format
112
+ no_prefix_obj = NoPrefixFormatTest.new
113
+ no_prefix_obj.extid.start_with?('api/')
114
+ #==> true
115
+
116
+ ## Format without prefix does not include underscore
117
+ no_prefix_obj = NoPrefixFormatTest.new
118
+ extid = no_prefix_obj.extid
119
+ !extid.include?('_') && !extid.include?('ext')
120
+ #==> true
121
+
80
122
  ## External ID is URL-safe base-36 format
81
123
  obj = ExternalIdTest.new
82
124
  extid = obj.extid
@@ -154,13 +196,21 @@ obj1.extid != obj2.extid
154
196
  ExternalIdTest.field_types[:extid]
155
197
  #=:> Familia::Features::ExternalIdentifier::ExternalIdentifierFieldType
156
198
 
157
- ## Feature options contain correct prefix
158
- ExternalIdTest.feature_options(:external_identifier)[:prefix]
159
- #=> "ext"
199
+ ## Feature options contain default format
200
+ ExternalIdTest.feature_options(:external_identifier)[:format]
201
+ #=> "ext_%{id}"
202
+
203
+ ## Custom prefix format options
204
+ CustomPrefixTest.feature_options(:external_identifier)[:format]
205
+ #=> "cust_%{id}"
206
+
207
+ ## Custom format with hyphen options
208
+ CustomFormatTest.feature_options(:external_identifier)[:format]
209
+ #=> "ext-%{id}"
160
210
 
161
- ## Custom prefix feature options
162
- CustomPrefixTest.feature_options(:external_identifier)[:prefix]
163
- #=> "cust"
211
+ ## No traditional prefix format options
212
+ NoPrefixFormatTest.feature_options(:external_identifier)[:format]
213
+ #=> "api/%{id}"
164
214
 
165
215
  ## External ID is shorter than UUID objid
166
216
  obj = ExternalIdTest.new
@@ -224,3 +274,116 @@ destroy_test_obj.destroy!
224
274
  # Verify mapping was cleaned up
225
275
  ExternalIdTest.extid_lookup.key?(destroy_extid)
226
276
  #=> false
277
+
278
+ # ========================================
279
+ # Comprehensive Format Option Test Coverage
280
+ # ========================================
281
+
282
+ ## Format option: default format produces ext_ prefix
283
+ default_obj = ExternalIdTest.new
284
+ default_obj.extid.start_with?('ext_')
285
+ #==> true
286
+
287
+ ## Format option: custom format with different prefix works
288
+ custom_prefix_obj = CustomPrefixTest.new
289
+ custom_prefix_obj.extid.start_with?('cust_')
290
+ #==> true
291
+
292
+ ## Format option: custom format with hyphen separator works
293
+ hyphen_obj = CustomFormatTest.new
294
+ hyphen_obj.extid.start_with?('ext-')
295
+ #==> true
296
+
297
+ ## Format option: hyphen format does not contain underscore
298
+ hyphen_obj = CustomFormatTest.new
299
+ !hyphen_obj.extid.include?('_')
300
+ #==> true
301
+
302
+ ## Format option: format without prefix works
303
+ no_prefix_obj = NoPrefixFormatTest.new
304
+ no_prefix_obj.extid.start_with?('api/')
305
+ #==> true
306
+
307
+ ## Format option: no prefix format uses slash separator
308
+ no_prefix_obj = NoPrefixFormatTest.new
309
+ no_prefix_obj.extid.include?('/')
310
+ #==> true
311
+
312
+ ## Format option: %{id} placeholder is properly interpolated
313
+ obj = ExternalIdTest.new
314
+ # The extid should not contain the literal string '%{id}'
315
+ !obj.extid.include?('%{id}')
316
+ #==> true
317
+
318
+ ## Format option: generated ID part is base36 alphanumeric
319
+ obj = ExternalIdTest.new
320
+ extid = obj.extid
321
+ id_part = extid.gsub(/^ext_/, '')
322
+ id_part.match?(/\A[0-9a-z]+\z/)
323
+ #==> true
324
+
325
+ ## Format option: hyphen format ID part is base36 alphanumeric
326
+ hyphen_obj = CustomFormatTest.new
327
+ extid = hyphen_obj.extid
328
+ id_part = extid.gsub(/^ext-/, '')
329
+ id_part.match?(/\A[0-9a-z]+\z/)
330
+ #==> true
331
+
332
+ ## Format option: no prefix format ID part is base36 alphanumeric
333
+ no_prefix_obj = NoPrefixFormatTest.new
334
+ extid = no_prefix_obj.extid
335
+ id_part = extid.gsub(/^api\//, '')
336
+ id_part.match?(/\A[0-9a-z]+\z/)
337
+ #==> true
338
+
339
+ ## Format option: different formats produce different prefixes but same ID length
340
+ default_obj = ExternalIdTest.new
341
+ custom_obj = CustomPrefixTest.new
342
+ hyphen_obj = CustomFormatTest.new
343
+ # All should have similar length IDs (within a few characters due to prefix differences)
344
+ default_id_len = default_obj.extid.length
345
+ custom_id_len = custom_obj.extid.length
346
+ hyphen_id_len = hyphen_obj.extid.length
347
+ (default_id_len - custom_id_len).abs <= 5 && (default_id_len - hyphen_id_len).abs <= 5
348
+ #==> true
349
+
350
+ ## Format option: custom formats maintain determinism
351
+ obj = CustomPrefixTest.new
352
+ first_extid = obj.extid
353
+ second_extid = obj.extid
354
+ first_extid == second_extid
355
+ #==> true
356
+
357
+ ## Format option: formats work correctly with save/load cycle
358
+ format_save_obj = CustomFormatTest.new(id: 'format_save_test', name: 'Format Save Test')
359
+ original_extid = format_save_obj.extid
360
+ format_save_obj.save
361
+ loaded_obj = CustomFormatTest.new(id: 'format_save_test')
362
+ loaded_obj.extid == original_extid
363
+ #==> true
364
+
365
+ ## Format option: find_by_extid works with custom formats
366
+ findable_custom = CustomPrefixTest.new(id: 'findable_custom', name: 'Findable Custom')
367
+ findable_custom.save
368
+ found_custom = CustomPrefixTest.find_by_extid(findable_custom.extid)
369
+ found_custom&.id
370
+ #=> "findable_custom"
371
+
372
+ ## Format option: find_by_extid works with hyphen format
373
+ findable_hyphen = CustomFormatTest.new(id: 'findable_hyphen', name: 'Findable Hyphen')
374
+ findable_hyphen.save
375
+ found_hyphen = CustomFormatTest.find_by_extid(findable_hyphen.extid)
376
+ found_hyphen&.id
377
+ #=> "findable_hyphen"
378
+
379
+ ## Format option: find_by_extid works with no-prefix format
380
+ findable_no_prefix = NoPrefixFormatTest.new(id: 'findable_no_prefix', name: 'Findable No Prefix')
381
+ findable_no_prefix.save
382
+ found_no_prefix = NoPrefixFormatTest.find_by_extid(findable_no_prefix.extid)
383
+ found_no_prefix&.id
384
+ #=> "findable_no_prefix"
385
+
386
+ # Cleanup format test objects
387
+ findable_custom.destroy! rescue nil
388
+ findable_hyphen.destroy! rescue nil
389
+ findable_no_prefix.destroy! rescue nil
@@ -1,4 +1,6 @@
1
1
  # try/features/feature_dependencies_try.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative '../support/helpers/test_helpers'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # try/features/feature_improvements_try.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative '../support/helpers/test_helpers'
4
6
 
@@ -1,3 +1,5 @@
1
+ # try/features/field_groups_try.rb
2
+ #
1
3
  # frozen_string_literal: true
2
4
 
3
5
  # try/features/field_groups_try.rb
@@ -1,4 +1,6 @@
1
1
  # try/features/object_identifier/object_identifier_integration_try.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative '../../support/helpers/test_helpers'
4
6
 
@@ -19,7 +21,7 @@ end
19
21
  # Class with custom configurations for both features
20
22
  class ::CustomIntegrationTest < Familia::Horreum
21
23
  feature :object_identifier, generator: :hex
22
- feature :external_identifier, prefix: 'custom'
24
+ feature :external_identifier, format: 'custom_%{id}'
23
25
  identifier_field :id
24
26
  field :id
25
27
  field :name
@@ -96,8 +98,9 @@ original_extid = persistence_obj.extid
96
98
  persistence_obj.save
97
99
 
98
100
  # Load from Valkey/Redis
99
- loaded_obj = PersistenceTest.load(id: 'persistence_test')
100
- #=> nil
101
+ loaded_obj = PersistenceTest.load('persistence_test')
102
+ loaded_obj.objid == original_objid && loaded_obj.extid == original_extid
103
+ #==> true
101
104
 
102
105
  ## objid persists after save/load
103
106
  persistence_obj = PersistenceTest.new
@@ -169,17 +172,17 @@ opts.key?(:external_identifier)
169
172
  IntegrationTest.feature_options(:object_identifier)[:generator]
170
173
  #=> :uuid_v7
171
174
 
172
- ## Prefix default configuration is applied correctly
173
- IntegrationTest.feature_options(:external_identifier)[:prefix]
174
- #=> "ext"
175
+ ## Format default configuration is applied correctly
176
+ IntegrationTest.feature_options(:external_identifier)[:format]
177
+ #=> "ext_%{id}"
175
178
 
176
179
  ## Custom generator configuration is applied correctly
177
180
  CustomIntegrationTest.feature_options(:object_identifier)[:generator]
178
181
  #=> :hex
179
182
 
180
- ## Custom prefix configuration is applied correctly
181
- CustomIntegrationTest.feature_options(:external_identifier)[:prefix]
182
- #=> "custom"
183
+ ## Custom format configuration is applied correctly
184
+ CustomIntegrationTest.feature_options(:external_identifier)[:format]
185
+ #=> "custom_%{id}"
183
186
 
184
187
  ## objid is URL-safe (UUID format)
185
188
  obj = IntegrationTest.new
@@ -1,4 +1,6 @@
1
1
  # try/features/object_identifier/object_identifier_try.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative '../../support/helpers/test_helpers'
4
6
 
@@ -1,3 +1,7 @@
1
+ # try/features/quantization/quantization_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/quantization_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,4 +1,6 @@
1
1
  # try/features/real_feature_integration_try.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative '../support/helpers/test_helpers'
4
6
 
@@ -1,5 +1,7 @@
1
1
  # try/features/relationships/indexing_commands_verification_try.rb
2
2
  #
3
+ # frozen_string_literal: true
4
+
3
5
  # Verification of proper Redis command generation for indexing operations
4
6
  # This test ensures the indexing system uses proper DataType methods instead of direct Redis calls
5
7
  #