familia 2.0.0.pre19 → 2.0.0.pre22

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 (370) 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/.talismanrc +5 -1
  8. data/CHANGELOG.rst +220 -112
  9. data/CLAUDE.md +28 -1
  10. data/Gemfile +1 -1
  11. data/Gemfile.lock +20 -17
  12. data/bin/try +16 -0
  13. data/bin/tryouts +16 -0
  14. data/docs/1106-participates_in-bidirectional-solution.md +129 -0
  15. data/docs/guides/encryption.md +486 -0
  16. data/docs/guides/feature-encrypted-fields.md +123 -7
  17. data/docs/guides/feature-expiration.md +161 -117
  18. data/docs/guides/feature-external-identifiers.md +415 -443
  19. data/docs/guides/feature-object-identifiers.md +400 -269
  20. data/docs/guides/feature-quantization.md +120 -6
  21. data/docs/guides/feature-relationships-indexing.md +318 -0
  22. data/docs/guides/feature-relationships-methods.md +146 -604
  23. data/docs/guides/feature-relationships-participation.md +263 -0
  24. data/docs/guides/feature-relationships.md +118 -136
  25. data/docs/guides/feature-system-devs.md +176 -693
  26. data/docs/guides/feature-system.md +119 -6
  27. data/docs/guides/feature-transient-fields.md +81 -0
  28. data/docs/guides/field-system.md +778 -0
  29. data/docs/guides/index.md +32 -15
  30. data/docs/guides/logging.md +187 -0
  31. data/docs/guides/optimized-loading.md +674 -0
  32. data/docs/guides/thread-safety-monitoring.md +61 -0
  33. data/docs/guides/{time-utilities.md → time-literals.md} +12 -12
  34. data/docs/migrating/v2.0.0-pre22.md +241 -0
  35. data/docs/overview.md +7 -9
  36. data/docs/reference/api-technical.md +267 -320
  37. data/examples/autoloader/mega_customer/features/deprecated_fields.rb +2 -0
  38. data/examples/autoloader/mega_customer/safe_dump_fields.rb +2 -0
  39. data/examples/autoloader/mega_customer.rb +2 -0
  40. data/examples/datatype_standalone.rb +4 -3
  41. data/examples/encrypted_fields.rb +2 -1
  42. data/examples/json_usage_patterns.rb +2 -0
  43. data/examples/relationships.rb +3 -0
  44. data/examples/safe_dump.rb +2 -1
  45. data/examples/sampling_demo.rb +53 -0
  46. data/examples/single_connection_transaction_confusions.rb +2 -1
  47. data/familia.gemspec +2 -1
  48. data/lib/familia/base.rb +2 -0
  49. data/lib/familia/connection/behavior.rb +2 -0
  50. data/lib/familia/connection/handlers.rb +2 -0
  51. data/lib/familia/connection/individual_command_proxy.rb +2 -0
  52. data/lib/familia/connection/middleware.rb +34 -24
  53. data/lib/familia/connection/operation_core.rb +3 -2
  54. data/lib/familia/connection/operations.rb +2 -0
  55. data/lib/familia/connection/pipelined_core.rb +3 -3
  56. data/lib/familia/connection/transaction_core.rb +69 -2
  57. data/lib/familia/connection.rb +18 -3
  58. data/lib/familia/data_type/class_methods.rb +3 -1
  59. data/lib/familia/data_type/connection.rb +2 -0
  60. data/lib/familia/data_type/database_commands.rb +2 -0
  61. data/lib/familia/data_type/serialization.rb +79 -52
  62. data/lib/familia/data_type/settings.rb +2 -0
  63. data/lib/familia/data_type/types/counter.rb +2 -0
  64. data/lib/familia/data_type/types/hashkey.rb +7 -5
  65. data/lib/familia/data_type/types/listkey.rb +2 -0
  66. data/lib/familia/data_type/types/lock.rb +2 -0
  67. data/lib/familia/data_type/types/sorted_set.rb +7 -10
  68. data/lib/familia/data_type/types/stringkey.rb +24 -0
  69. data/lib/familia/data_type/types/unsorted_set.rb +2 -0
  70. data/lib/familia/data_type.rb +2 -0
  71. data/lib/familia/encryption/encrypted_data.rb +4 -2
  72. data/lib/familia/encryption/manager.rb +2 -0
  73. data/lib/familia/encryption/provider.rb +2 -0
  74. data/lib/familia/encryption/providers/aes_gcm_provider.rb +2 -0
  75. data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +2 -0
  76. data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +2 -0
  77. data/lib/familia/encryption/registry.rb +2 -0
  78. data/lib/familia/encryption/request_cache.rb +2 -0
  79. data/lib/familia/encryption.rb +9 -2
  80. data/lib/familia/errors.rb +2 -0
  81. data/lib/familia/features/autoloader.rb +2 -0
  82. data/lib/familia/features/encrypted_fields/concealed_string.rb +2 -0
  83. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +4 -0
  84. data/lib/familia/features/encrypted_fields.rb +2 -2
  85. data/lib/familia/features/expiration/extensions.rb +3 -1
  86. data/lib/familia/features/expiration.rb +12 -4
  87. data/lib/familia/features/external_identifier.rb +62 -7
  88. data/lib/familia/features/object_identifier.rb +49 -0
  89. data/lib/familia/features/quantization.rb +3 -1
  90. data/lib/familia/features/relationships/README.md +3 -1
  91. data/lib/familia/features/relationships/collection_operations.rb +2 -0
  92. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +138 -9
  93. data/lib/familia/features/relationships/indexing/rebuild_strategies.rb +479 -0
  94. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +97 -21
  95. data/lib/familia/features/relationships/indexing.rb +3 -0
  96. data/lib/familia/features/relationships/indexing_relationship.rb +3 -1
  97. data/lib/familia/features/relationships/participation/participant_methods.rb +131 -14
  98. data/lib/familia/features/relationships/participation/rebuild_strategies.md +41 -0
  99. data/lib/familia/features/relationships/participation/target_methods.rb +6 -6
  100. data/lib/familia/features/relationships/participation.rb +155 -69
  101. data/lib/familia/features/relationships/participation_membership.rb +69 -0
  102. data/lib/familia/features/relationships/participation_relationship.rb +34 -6
  103. data/lib/familia/features/relationships/score_encoding.rb +2 -0
  104. data/lib/familia/features/relationships.rb +5 -3
  105. data/lib/familia/features/safe_dump.rb +2 -0
  106. data/lib/familia/features/transient_fields/redacted_string.rb +2 -0
  107. data/lib/familia/features/transient_fields/single_use_redacted_string.rb +2 -0
  108. data/lib/familia/features/transient_fields/transient_field_type.rb +5 -3
  109. data/lib/familia/features/transient_fields.rb +2 -0
  110. data/lib/familia/features.rb +2 -0
  111. data/lib/familia/field_type.rb +3 -1
  112. data/lib/familia/horreum/connection.rb +17 -1
  113. data/lib/familia/horreum/database_commands.rb +8 -1
  114. data/lib/familia/horreum/definition.rb +16 -6
  115. data/lib/familia/horreum/management.rb +353 -52
  116. data/lib/familia/horreum/persistence.rb +179 -108
  117. data/lib/familia/horreum/related_fields.rb +2 -0
  118. data/lib/familia/horreum/serialization.rb +23 -4
  119. data/lib/familia/horreum/settings.rb +2 -0
  120. data/lib/familia/horreum/utils.rb +2 -0
  121. data/lib/familia/horreum.rb +15 -1
  122. data/lib/familia/identifier_extractor.rb +3 -1
  123. data/lib/familia/instrumentation.rb +156 -0
  124. data/lib/familia/json_serializer.rb +2 -0
  125. data/lib/familia/logging.rb +92 -32
  126. data/lib/familia/refinements/dear_json.rb +2 -0
  127. data/lib/familia/refinements/stylize_words.rb +2 -14
  128. data/lib/familia/refinements/time_literals.rb +2 -0
  129. data/lib/familia/refinements.rb +2 -0
  130. data/lib/familia/secure_identifier.rb +10 -2
  131. data/lib/familia/settings.rb +2 -0
  132. data/lib/familia/thread_safety/instrumented_mutex.rb +166 -0
  133. data/lib/familia/thread_safety/monitor.rb +328 -0
  134. data/lib/familia/utils.rb +13 -0
  135. data/lib/familia/verifiable_identifier.rb +3 -1
  136. data/lib/familia/version.rb +3 -1
  137. data/lib/familia.rb +31 -4
  138. data/lib/middleware/database_command_counter.rb +152 -0
  139. data/lib/middleware/database_logger.rb +295 -170
  140. data/lib/multi_result.rb +61 -31
  141. data/try/edge_cases/empty_identifiers_try.rb +2 -0
  142. data/try/edge_cases/hash_symbolization_try.rb +2 -0
  143. data/try/edge_cases/json_serialization_try.rb +2 -0
  144. data/try/edge_cases/legacy_data_detection/deserialization_edge_cases_try.rb +4 -0
  145. data/try/edge_cases/race_conditions_try.rb +4 -0
  146. data/try/edge_cases/reserved_keywords_try.rb +4 -0
  147. data/try/edge_cases/string_coercion_try.rb +2 -0
  148. data/try/edge_cases/ttl_side_effects_try.rb +4 -0
  149. data/try/features/count_any_edge_cases_try.rb +486 -0
  150. data/try/features/count_any_methods_try.rb +197 -0
  151. data/try/features/encrypted_fields/aad_protection_try.rb +4 -0
  152. data/try/features/encrypted_fields/concealed_string_core_try.rb +4 -0
  153. data/try/features/encrypted_fields/context_isolation_try.rb +4 -0
  154. data/try/features/encrypted_fields/encrypted_fields_core_try.rb +33 -0
  155. data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +4 -0
  156. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +4 -0
  157. data/try/features/encrypted_fields/encrypted_fields_security_try.rb +4 -0
  158. data/try/features/encrypted_fields/error_conditions_try.rb +4 -0
  159. data/try/features/encrypted_fields/fresh_key_derivation_try.rb +4 -0
  160. data/try/features/encrypted_fields/fresh_key_try.rb +4 -0
  161. data/try/features/encrypted_fields/key_rotation_try.rb +4 -0
  162. data/try/features/encrypted_fields/memory_security_try.rb +4 -0
  163. data/try/features/encrypted_fields/missing_current_key_version_try.rb +4 -0
  164. data/try/features/encrypted_fields/nonce_uniqueness_try.rb +4 -0
  165. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +4 -0
  166. data/try/features/encrypted_fields/thread_safety_try.rb +4 -0
  167. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +4 -0
  168. data/try/features/encryption/config_persistence_try.rb +4 -0
  169. data/try/features/encryption/core_try.rb +4 -0
  170. data/try/features/encryption/instance_variable_scope_try.rb +4 -0
  171. data/try/features/encryption/module_loading_try.rb +4 -0
  172. data/try/features/encryption/providers/aes_gcm_provider_try.rb +4 -0
  173. data/try/features/encryption/providers/xchacha20_poly1305_provider_try.rb +4 -0
  174. data/try/features/encryption/roundtrip_validation_try.rb +4 -0
  175. data/try/features/encryption/secure_memory_handling_try.rb +4 -0
  176. data/try/features/expiration/expiration_try.rb +4 -0
  177. data/try/features/external_identifier/external_identifier_try.rb +305 -8
  178. data/try/features/feature_dependencies_try.rb +2 -0
  179. data/try/features/feature_improvements_try.rb +2 -0
  180. data/try/features/field_groups_try.rb +2 -0
  181. data/try/features/object_identifier/object_identifier_integration_try.rb +12 -9
  182. data/try/features/object_identifier/object_identifier_try.rb +140 -0
  183. data/try/features/quantization/quantization_try.rb +4 -0
  184. data/try/features/real_feature_integration_try.rb +2 -0
  185. data/try/features/relationships/indexing_commands_verification_try.rb +2 -0
  186. data/try/features/relationships/indexing_rebuild_try.rb +606 -0
  187. data/try/features/relationships/indexing_try.rb +2 -0
  188. data/try/features/relationships/participation_bidirectional_try.rb +242 -0
  189. data/try/features/relationships/participation_commands_verification_spec.rb +4 -0
  190. data/try/features/relationships/participation_commands_verification_try.rb +2 -0
  191. data/try/features/relationships/participation_performance_improvements_try.rb +11 -9
  192. data/try/features/relationships/participation_reverse_index_try.rb +15 -13
  193. data/try/features/relationships/participation_target_class_resolution_try.rb +209 -0
  194. data/try/features/relationships/participation_unresolved_target_try.rb +109 -0
  195. data/try/features/relationships/relationships_api_changes_try.rb +2 -0
  196. data/try/features/relationships/relationships_edge_cases_try.rb +4 -0
  197. data/try/features/relationships/relationships_performance_minimal_try.rb +4 -0
  198. data/try/features/relationships/relationships_performance_simple_try.rb +4 -0
  199. data/try/features/relationships/relationships_performance_try.rb +4 -0
  200. data/try/features/relationships/relationships_performance_working_try.rb +4 -0
  201. data/try/features/relationships/relationships_try.rb +6 -4
  202. data/try/features/safe_dump/safe_dump_advanced_try.rb +4 -0
  203. data/try/features/safe_dump/safe_dump_try.rb +4 -0
  204. data/try/features/transient_fields/redacted_string_try.rb +2 -0
  205. data/try/features/transient_fields/refresh_reset_try.rb +3 -0
  206. data/try/features/transient_fields/simple_refresh_test.rb +3 -0
  207. data/try/features/transient_fields/single_use_redacted_string_try.rb +2 -0
  208. data/try/features/transient_fields/transient_fields_core_try.rb +4 -0
  209. data/try/features/transient_fields/transient_fields_integration_try.rb +4 -0
  210. data/try/integration/connection/fiber_context_preservation_try.rb +4 -0
  211. data/try/integration/connection/handler_constraints_try.rb +4 -0
  212. data/try/integration/connection/isolated_dbclient_try.rb +4 -0
  213. data/try/integration/connection/middleware_reconnect_try.rb +2 -0
  214. data/try/integration/connection/operation_mode_guards_try.rb +4 -0
  215. data/try/integration/connection/pipeline_fallback_integration_try.rb +3 -0
  216. data/try/integration/connection/pools_try.rb +4 -0
  217. data/try/integration/connection/responsibility_chain_tracking_try.rb +4 -0
  218. data/try/integration/connection/transaction_fallback_integration_try.rb +4 -0
  219. data/try/integration/connection/transaction_mode_permissive_try.rb +4 -0
  220. data/try/integration/connection/transaction_mode_strict_try.rb +4 -0
  221. data/try/integration/connection/transaction_mode_warn_try.rb +4 -0
  222. data/try/integration/connection/transaction_modes_try.rb +4 -0
  223. data/try/integration/conventional_inheritance_try.rb +4 -0
  224. data/try/integration/create_method_try.rb +4 -0
  225. data/try/integration/cross_component_try.rb +4 -0
  226. data/try/integration/data_types/datatype_pipelines_try.rb +9 -3
  227. data/try/integration/data_types/datatype_transactions_try.rb +17 -7
  228. data/try/integration/database_consistency_try.rb +4 -0
  229. data/try/integration/familia_extended_try.rb +4 -0
  230. data/try/integration/familia_members_methods_try.rb +4 -0
  231. data/try/integration/models/customer_safe_dump_try.rb +4 -0
  232. data/try/integration/models/customer_try.rb +7 -3
  233. data/try/integration/models/datatype_base_try.rb +4 -0
  234. data/try/integration/models/familia_object_try.rb +4 -0
  235. data/try/integration/persistence_operations_try.rb +4 -0
  236. data/try/integration/relationships_persistence_round_trip_try.rb +17 -14
  237. data/try/integration/save_methods_consistency_try.rb +241 -0
  238. data/try/integration/scenarios_try.rb +4 -0
  239. data/try/integration/secure_identifier_try.rb +4 -0
  240. data/try/integration/transaction_safety_core_try.rb +176 -0
  241. data/try/integration/transaction_safety_workflow_try.rb +291 -0
  242. data/try/integration/verifiable_identifier_try.rb +4 -0
  243. data/try/investigation/pipeline_routing/README.md +228 -0
  244. data/try/performance/benchmarks_try.rb +4 -0
  245. data/try/performance/transaction_safety_benchmark_try.rb +238 -0
  246. data/try/support/benchmarks/deserialization_benchmark.rb +3 -1
  247. data/try/support/benchmarks/deserialization_correctness_test.rb +3 -1
  248. data/try/support/debugging/cache_behavior_tracer.rb +4 -0
  249. data/try/support/debugging/debug_aad_process.rb +3 -0
  250. data/try/support/debugging/debug_concealed_internal.rb +3 -0
  251. data/try/support/debugging/debug_concealed_reveal.rb +3 -0
  252. data/try/support/debugging/debug_context_aad.rb +3 -0
  253. data/try/support/debugging/debug_context_simple.rb +3 -0
  254. data/try/support/debugging/debug_cross_context.rb +3 -0
  255. data/try/support/debugging/debug_database_load.rb +3 -0
  256. data/try/support/debugging/debug_encrypted_json_check.rb +3 -0
  257. data/try/support/debugging/debug_encrypted_json_step_by_step.rb +3 -0
  258. data/try/support/debugging/debug_exists_lifecycle.rb +3 -0
  259. data/try/support/debugging/debug_field_decrypt.rb +3 -0
  260. data/try/support/debugging/debug_fresh_cross_context.rb +3 -0
  261. data/try/support/debugging/debug_load_path.rb +3 -0
  262. data/try/support/debugging/debug_method_definition.rb +3 -0
  263. data/try/support/debugging/debug_method_resolution.rb +3 -0
  264. data/try/support/debugging/debug_minimal.rb +3 -0
  265. data/try/support/debugging/debug_provider.rb +3 -0
  266. data/try/support/debugging/debug_secure_behavior.rb +3 -0
  267. data/try/support/debugging/debug_string_class.rb +3 -0
  268. data/try/support/debugging/debug_test.rb +3 -0
  269. data/try/support/debugging/debug_test_design.rb +3 -0
  270. data/try/support/debugging/encryption_method_tracer.rb +4 -0
  271. data/try/support/debugging/provider_diagnostics.rb +4 -0
  272. data/try/support/helpers/test_cleanup.rb +4 -0
  273. data/try/support/helpers/test_helpers.rb +5 -0
  274. data/try/support/memory/memory_basic_test.rb +4 -0
  275. data/try/support/memory/memory_detailed_test.rb +4 -0
  276. data/try/support/memory/memory_search_for_string.rb +4 -0
  277. data/try/support/memory/test_actual_redactedstring_protection.rb +4 -0
  278. data/try/support/prototypes/atomic_saves_v1_context_proxy.rb +4 -0
  279. data/try/support/prototypes/atomic_saves_v2_connection_switching.rb +4 -0
  280. data/try/support/prototypes/atomic_saves_v3_connection_pool.rb +4 -0
  281. data/try/support/prototypes/atomic_saves_v4.rb +4 -0
  282. data/try/support/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +4 -0
  283. data/try/support/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -0
  284. data/try/support/prototypes/pooling/configurable_stress_test.rb +4 -0
  285. data/try/support/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -0
  286. data/try/support/prototypes/pooling/lib/connection_pool_metrics.rb +4 -0
  287. data/try/support/prototypes/pooling/lib/connection_pool_stress_test.rb +4 -0
  288. data/try/support/prototypes/pooling/lib/connection_pool_threading_models.rb +4 -0
  289. data/try/support/prototypes/pooling/lib/visualize_stress_results.rb +4 -2
  290. data/try/support/prototypes/pooling/pool_siege.rb +4 -2
  291. data/try/support/prototypes/pooling/run_stress_tests.rb +4 -2
  292. data/try/thread_safety/README.md +496 -0
  293. data/try/thread_safety/class_connection_chain_race_try.rb +265 -0
  294. data/try/thread_safety/connection_chain_race_try.rb +148 -0
  295. data/try/thread_safety/encryption_manager_cache_race_try.rb +166 -0
  296. data/try/thread_safety/feature_registry_race_try.rb +226 -0
  297. data/try/thread_safety/fiber_pipeline_isolation_try.rb +235 -0
  298. data/try/thread_safety/fiber_transaction_isolation_try.rb +208 -0
  299. data/try/thread_safety/field_registration_race_try.rb +222 -0
  300. data/try/thread_safety/logger_initialization_race_try.rb +170 -0
  301. data/try/thread_safety/middleware_registration_race_try.rb +154 -0
  302. data/try/thread_safety/module_config_race_try.rb +175 -0
  303. data/try/thread_safety/secure_identifier_cache_race_try.rb +226 -0
  304. data/try/unit/core/autoloader_try.rb +4 -0
  305. data/try/unit/core/base_enhancements_try.rb +4 -0
  306. data/try/unit/core/connection_try.rb +4 -0
  307. data/try/unit/core/errors_try.rb +4 -0
  308. data/try/unit/core/extensions_try.rb +4 -0
  309. data/try/unit/core/familia_logger_try.rb +2 -0
  310. data/try/unit/core/familia_try.rb +4 -0
  311. data/try/unit/core/middleware_sampling_try.rb +335 -0
  312. data/try/unit/core/middleware_test_helpers_bug_try.rb +58 -0
  313. data/try/unit/core/middleware_thread_safety_try.rb +245 -0
  314. data/try/unit/core/middleware_try.rb +4 -0
  315. data/try/unit/core/settings_try.rb +4 -0
  316. data/try/unit/core/time_utils_try.rb +4 -0
  317. data/try/unit/core/tools_try.rb +4 -0
  318. data/try/unit/core/utils_try.rb +37 -0
  319. data/try/unit/data_types/boolean_try.rb +39 -22
  320. data/try/unit/data_types/counter_try.rb +4 -0
  321. data/try/unit/data_types/datatype_base_try.rb +4 -0
  322. data/try/unit/data_types/hash_try.rb +6 -2
  323. data/try/unit/data_types/list_try.rb +4 -0
  324. data/try/unit/data_types/lock_try.rb +4 -0
  325. data/try/unit/data_types/serialization_try.rb +386 -0
  326. data/try/unit/data_types/sorted_set_try.rb +4 -0
  327. data/try/unit/data_types/sorted_set_zadd_options_try.rb +4 -0
  328. data/try/unit/data_types/string_try.rb +4 -0
  329. data/try/unit/data_types/unsortedset_try.rb +4 -0
  330. data/try/unit/familia_resolve_class_try.rb +116 -0
  331. data/try/unit/horreum/auto_indexing_on_save_try.rb +5 -1
  332. data/try/unit/horreum/automatic_index_validation_try.rb +2 -0
  333. data/try/unit/horreum/base_try.rb +4 -0
  334. data/try/unit/horreum/class_methods_try.rb +4 -0
  335. data/try/unit/horreum/commands_try.rb +4 -0
  336. data/try/unit/horreum/defensive_initialization_try.rb +4 -0
  337. data/try/unit/horreum/destroy_related_fields_cleanup_try.rb +6 -1
  338. data/try/unit/horreum/enhanced_conflict_handling_try.rb +4 -0
  339. data/try/unit/horreum/field_categories_try.rb +4 -0
  340. data/try/unit/horreum/field_definition_try.rb +4 -0
  341. data/try/unit/horreum/initialization_try.rb +4 -0
  342. data/try/unit/horreum/json_type_preservation_try.rb +2 -0
  343. data/try/unit/horreum/optimized_loading_try.rb +156 -0
  344. data/try/unit/horreum/relations_try.rb +4 -0
  345. data/try/unit/horreum/serialization_persistent_fields_try.rb +4 -0
  346. data/try/unit/horreum/serialization_try.rb +4 -0
  347. data/try/unit/horreum/settings_try.rb +4 -0
  348. data/try/unit/horreum/unique_index_edge_cases_try.rb +4 -0
  349. data/try/unit/horreum/unique_index_guard_validation_try.rb +2 -0
  350. data/try/unit/middleware/database_command_counter_methods_try.rb +139 -0
  351. data/try/unit/middleware/database_logger_methods_try.rb +251 -0
  352. data/try/unit/refinements/dear_json_array_methods_try.rb +4 -0
  353. data/try/unit/refinements/dear_json_hash_methods_try.rb +4 -0
  354. data/try/unit/refinements/time_literals_numeric_methods_try.rb +4 -0
  355. data/try/unit/refinements/time_literals_string_methods_try.rb +4 -0
  356. data/try/unit/thread_safety_monitor_try.rb +149 -0
  357. metadata +69 -17
  358. data/.github/workflows/code-quality.yml +0 -138
  359. data/changelog.d/20251011_012003_delano_159_datatype_transaction_pipeline_support.rst +0 -91
  360. data/changelog.d/20251011_203905_delano_next.rst +0 -30
  361. data/changelog.d/20251011_212633_delano_next.rst +0 -13
  362. data/changelog.d/20251011_221253_delano_next.rst +0 -26
  363. data/docs/archive/FAMILIA_RELATIONSHIPS.md +0 -210
  364. data/docs/archive/FAMILIA_TECHNICAL.md +0 -823
  365. data/docs/archive/FAMILIA_UPDATE.md +0 -226
  366. data/docs/archive/README.md +0 -64
  367. data/docs/archive/api-reference.md +0 -333
  368. data/docs/guides/core-field-system.md +0 -806
  369. data/docs/guides/implementation.md +0 -276
  370. data/docs/guides/security-model.md +0 -183
@@ -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}"
160
206
 
161
- ## Custom prefix feature options
162
- CustomPrefixTest.feature_options(:external_identifier)[:prefix]
163
- #=> "cust"
207
+ ## Custom format with hyphen options
208
+ CustomFormatTest.feature_options(:external_identifier)[:format]
209
+ #=> "ext-%{id}"
210
+
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,250 @@ 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
390
+
391
+ # ========================================
392
+ # extid? Method Test Coverage
393
+ # ========================================
394
+
395
+ ## extid? returns false for nil
396
+ ExternalIdTest.extid?(nil)
397
+ #=> false
398
+
399
+ ## extid? returns false for empty string
400
+ ExternalIdTest.extid?('')
401
+ #=> false
402
+
403
+ ## extid? returns false for whitespace-only string
404
+ ExternalIdTest.extid?(' ')
405
+ #=> false
406
+
407
+ ## extid? returns true for valid extid with default format
408
+ # Valid format: ext_ prefix + exactly 25 alphanumeric characters
409
+ ExternalIdTest.extid?('ext_0123456789abcdefghijklmno')
410
+ #=> true
411
+
412
+ ## extid? returns true for valid extid with uppercase characters
413
+ # The pattern allows [0-9a-zA-Z] for the ID part
414
+ ExternalIdTest.extid?('ext_0123456789ABCDEFGHIJKLMNO')
415
+ #=> true
416
+
417
+ ## extid? returns true for valid extid with mixed case
418
+ ExternalIdTest.extid?('ext_0123456789AbCdEfGhIjKlMnO')
419
+ #=> true
420
+
421
+ ## extid? returns true for generated extid
422
+ obj = ExternalIdTest.new
423
+ ExternalIdTest.extid?(obj.extid)
424
+ #=> true
425
+
426
+ ## extid? returns false for wrong prefix
427
+ ExternalIdTest.extid?('xxx_0123456789abcdefghijklmno')
428
+ #=> false
429
+
430
+ ## extid? returns false for missing prefix
431
+ ExternalIdTest.extid?('0123456789abcdefghijklmno')
432
+ #=> false
433
+
434
+ ## extid? accepts ID part with 24 chars (within 20-32 range)
435
+ ExternalIdTest.extid?('ext_0123456789abcdefghijklmn')
436
+ #=> true
437
+
438
+ ## extid? accepts ID part with 26 chars (within 20-32 range)
439
+ ExternalIdTest.extid?('ext_0123456789abcdefghijklmnop')
440
+ #=> true
441
+
442
+ ## extid? returns false for ID part too short (19 chars, below minimum)
443
+ ExternalIdTest.extid?('ext_0123456789abcdefghi')
444
+ #=> false
445
+
446
+ ## extid? returns false for ID part too long (33 chars, above maximum)
447
+ ExternalIdTest.extid?('ext_0123456789abcdefghijklmnopqrstuvw')
448
+ #=> false
449
+
450
+ ## extid? returns false for invalid characters in ID (underscore)
451
+ ExternalIdTest.extid?('ext_0123456789abcdefghij_lmno')
452
+ #=> false
453
+
454
+ ## extid? returns false for invalid characters in ID (hyphen)
455
+ ExternalIdTest.extid?('ext_0123456789abcdefghij-lmno')
456
+ #=> false
457
+
458
+ ## extid? returns false for invalid characters in ID (special chars)
459
+ ExternalIdTest.extid?('ext_0123456789abcdefghij!@#$%')
460
+ #=> false
461
+
462
+ ## extid? with custom prefix format returns true for valid extid
463
+ CustomPrefixTest.extid?('cust_0123456789abcdefghijklmno')
464
+ #=> true
465
+
466
+ ## extid? with custom prefix format returns false for default prefix
467
+ CustomPrefixTest.extid?('ext_0123456789abcdefghijklmno')
468
+ #=> false
469
+
470
+ ## extid? with custom prefix format returns true for generated extid
471
+ custom_obj = CustomPrefixTest.new
472
+ CustomPrefixTest.extid?(custom_obj.extid)
473
+ #=> true
474
+
475
+ ## extid? with hyphen format returns true for valid extid
476
+ CustomFormatTest.extid?('ext-0123456789abcdefghijklmno')
477
+ #=> true
478
+
479
+ ## extid? with hyphen format returns false for underscore format
480
+ CustomFormatTest.extid?('ext_0123456789abcdefghijklmno')
481
+ #=> false
482
+
483
+ ## extid? with hyphen format returns true for generated extid
484
+ hyphen_obj = CustomFormatTest.new
485
+ CustomFormatTest.extid?(hyphen_obj.extid)
486
+ #=> true
487
+
488
+ ## extid? with no-prefix format returns true for valid extid
489
+ NoPrefixFormatTest.extid?('api/0123456789abcdefghijklmno')
490
+ #=> true
491
+
492
+ ## extid? with no-prefix format returns false for default format
493
+ NoPrefixFormatTest.extid?('ext_0123456789abcdefghijklmno')
494
+ #=> false
495
+
496
+ ## extid? with no-prefix format returns true for generated extid
497
+ no_prefix_obj = NoPrefixFormatTest.new
498
+ NoPrefixFormatTest.extid?(no_prefix_obj.extid)
499
+ #=> true
500
+
501
+ ## extid? returns false for partial match at start
502
+ ExternalIdTest.extid?('ext_0123456789abcdefghijklmno_extra')
503
+ #=> false
504
+
505
+ ## extid? returns false for partial match with leading chars
506
+ ExternalIdTest.extid?('prefix_ext_0123456789abcdefghijklmno')
507
+ #=> false
508
+
509
+ ## extid? returns false for spaces in ID
510
+ ExternalIdTest.extid?('ext_0123456789 bcdefghijklmno')
511
+ #=> false
512
+
513
+ ## extid? returns false for just the prefix
514
+ ExternalIdTest.extid?('ext_')
515
+ #=> false
516
+
517
+ ## extid? with Symbol input (symbols support =~ matching)
518
+ ExternalIdTest.extid?(:ext_0123456789abcdefghijklmno)
519
+ #=> true
520
+
521
+ ## extid? with Symbol input returns false for invalid format
522
+ ExternalIdTest.extid?(:invalid_symbol)
523
+ #=> false
@@ -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
 
@@ -199,3 +201,141 @@ race_obj.save # Save so find_by_objid can locate
199
201
  found = BasicObjectTest.find_by_objid(generated_objid)
200
202
  found && found.id == "race_test_123"
201
203
  #=> true
204
+
205
+ # ========================================
206
+ # objid? Method Test Coverage
207
+ # ========================================
208
+
209
+ ## objid? returns false for nil
210
+ BasicObjectTest.objid?(nil)
211
+ #=> false
212
+
213
+ ## objid? returns false for empty string
214
+ BasicObjectTest.objid?('')
215
+ #=> false
216
+
217
+ ## objid? returns false for whitespace-only string
218
+ BasicObjectTest.objid?(' ')
219
+ #=> false
220
+
221
+ ## objid? returns true for valid UUID v7 format
222
+ # UUID v7 format: xxxxxxxx-xxxx-7xxx-xxxx-xxxxxxxxxxxx (version char is '7')
223
+ BasicObjectTest.objid?('01234567-89ab-7def-89ab-0123456789ab')
224
+ #=> true
225
+
226
+ ## objid? returns true for generated UUID v7 objid
227
+ obj = BasicObjectTest.new
228
+ BasicObjectTest.objid?(obj.objid)
229
+ #=> true
230
+
231
+ ## objid? returns false for UUID v4 in UUID v7 class
232
+ # Version char is '4' instead of '7'
233
+ BasicObjectTest.objid?('01234567-89ab-4def-89ab-0123456789ab')
234
+ #=> false
235
+
236
+ ## objid? returns false for wrong version char
237
+ BasicObjectTest.objid?('01234567-89ab-5def-89ab-0123456789ab')
238
+ #=> false
239
+
240
+ ## objid? returns false for missing hyphens
241
+ BasicObjectTest.objid?('0123456789ab7def89ab0123456789ab')
242
+ #=> false
243
+
244
+ ## objid? returns false for wrong length (too short)
245
+ BasicObjectTest.objid?('01234567-89ab-7def-89ab-012345678')
246
+ #=> false
247
+
248
+ ## objid? returns false for wrong length (too long)
249
+ BasicObjectTest.objid?('01234567-89ab-7def-89ab-0123456789abcd')
250
+ #=> false
251
+
252
+ ## objid? returns false for hyphens in wrong positions
253
+ BasicObjectTest.objid?('0123456-789ab-7def-89ab-0123456789ab')
254
+ #=> false
255
+
256
+ ## objid? returns false for UUID with non-hex characters
257
+ # Validates that all characters are valid hexadecimal digits
258
+ BasicObjectTest.objid?('gggggggg-gggg-7ggg-gggg-gggggggggggg')
259
+ #=> false
260
+
261
+ ## objid? with UUID v4 generator returns true for valid v4 format
262
+ UuidV4Test.objid?('01234567-89ab-4def-89ab-0123456789ab')
263
+ #=> true
264
+
265
+ ## objid? with UUID v4 generator returns true for generated objid
266
+ v4_obj = UuidV4Test.new
267
+ UuidV4Test.objid?(v4_obj.objid)
268
+ #=> true
269
+
270
+ ## objid? with UUID v4 generator returns false for v7 format
271
+ UuidV4Test.objid?('01234567-89ab-7def-89ab-0123456789ab')
272
+ #=> false
273
+
274
+ ## objid? with hex generator returns true for valid hex string
275
+ HexTest.objid?('0123456789abcdef')
276
+ #=> true
277
+
278
+ ## objid? with hex generator returns true for generated hex objid
279
+ hex_obj = HexTest.new
280
+ HexTest.objid?(hex_obj.objid)
281
+ #=> true
282
+
283
+ ## objid? with hex generator returns true for uppercase hex
284
+ HexTest.objid?('0123456789ABCDEF')
285
+ #=> true
286
+
287
+ ## objid? with hex generator returns true for mixed case hex
288
+ HexTest.objid?('0123456789AbCdEf')
289
+ #=> true
290
+
291
+ ## objid? with hex generator returns false for non-hex chars
292
+ HexTest.objid?('0123456789ghijkl')
293
+ #=> false
294
+
295
+ ## objid? with hex generator returns false for UUID format
296
+ HexTest.objid?('01234567-89ab-7def-89ab-0123456789ab')
297
+ #=> false
298
+
299
+ ## objid? with hex generator returns true for short hex
300
+ HexTest.objid?('abc')
301
+ #=> true
302
+
303
+ ## objid? with hex generator returns true for long hex
304
+ HexTest.objid?('0123456789abcdef0123456789abcdef')
305
+ #=> true
306
+
307
+ ## objid? with custom proc generator returns false (unsupported)
308
+ CustomProcTest.objid?('custom_12345678')
309
+ #=> false
310
+
311
+ ## objid? with custom proc generator returns false for any input
312
+ CustomProcTest.objid?('anything')
313
+ #=> false
314
+
315
+ ## objid? UUID validation checks position 8 for hyphen
316
+ BasicObjectTest.objid?('01234567X89ab-7def-89ab-0123456789ab')
317
+ #=> false
318
+
319
+ ## objid? UUID validation checks position 13 for hyphen
320
+ BasicObjectTest.objid?('01234567-89abX7def-89ab-0123456789ab')
321
+ #=> false
322
+
323
+ ## objid? UUID validation checks position 18 for hyphen
324
+ BasicObjectTest.objid?('01234567-89ab-7defX89ab-0123456789ab')
325
+ #=> false
326
+
327
+ ## objid? UUID validation checks position 23 for hyphen
328
+ BasicObjectTest.objid?('01234567-89ab-7def-89abX0123456789ab')
329
+ #=> false
330
+
331
+ ## objid? returns false for partial UUID match
332
+ BasicObjectTest.objid?('01234567-89ab-7def')
333
+ #=> false
334
+
335
+ ## objid? with Symbol input for UUID v7 (symbols support string comparison)
336
+ BasicObjectTest.objid?(:'01234567-89ab-7def-89ab-0123456789ab')
337
+ #=> true
338
+
339
+ ## objid? with Symbol input returns false for invalid format
340
+ BasicObjectTest.objid?(:invalid_objid)
341
+ #=> false
@@ -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
  #