familia 2.0.0.pre8 → 2.0.0.pre12

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +13 -0
  3. data/.github/workflows/docs.yml +1 -1
  4. data/.gitignore +9 -9
  5. data/.rubocop.yml +19 -0
  6. data/.yardopts +22 -1
  7. data/CHANGELOG.md +247 -0
  8. data/CLAUDE.md +12 -59
  9. data/Gemfile.lock +1 -1
  10. data/README.md +62 -2
  11. data/changelog.d/README.md +77 -0
  12. data/docs/archive/.gitignore +2 -0
  13. data/docs/archive/FAMILIA_RELATIONSHIPS.md +210 -0
  14. data/docs/archive/FAMILIA_TECHNICAL.md +823 -0
  15. data/docs/archive/FAMILIA_UPDATE.md +226 -0
  16. data/docs/archive/README.md +63 -0
  17. data/docs/guides/.gitignore +2 -0
  18. data/docs/{wiki → guides}/Home.md +1 -1
  19. data/docs/{wiki → guides}/Implementation-Guide.md +1 -1
  20. data/docs/{wiki → guides}/Relationships-Guide.md +103 -50
  21. data/docs/guides/relationships-methods.md +266 -0
  22. data/docs/migrating/.gitignore +2 -0
  23. data/docs/migrating/v2.0.0-pre.md +84 -0
  24. data/docs/migrating/v2.0.0-pre11.md +255 -0
  25. data/docs/migrating/v2.0.0-pre12.md +306 -0
  26. data/docs/migrating/v2.0.0-pre5.md +110 -0
  27. data/docs/migrating/v2.0.0-pre6.md +154 -0
  28. data/docs/migrating/v2.0.0-pre7.md +222 -0
  29. data/docs/overview.md +6 -7
  30. data/{examples/redis_command_validation_example.rb → docs/reference/auditing_database_commands.rb} +29 -32
  31. data/examples/{bit_encoding_integration.rb → permissions.rb} +30 -27
  32. data/examples/relationships.rb +205 -0
  33. data/examples/safe_dump.rb +281 -0
  34. data/familia.gemspec +4 -4
  35. data/lib/familia/base.rb +52 -0
  36. data/lib/familia/connection.rb +4 -21
  37. data/lib/familia/{encryption_request_cache.rb → encryption/request_cache.rb} +1 -1
  38. data/lib/familia/errors.rb +2 -0
  39. data/lib/familia/features/autoloader.rb +57 -0
  40. data/lib/familia/features/external_identifier.rb +310 -0
  41. data/lib/familia/features/object_identifier.rb +307 -0
  42. data/lib/familia/features/relationships/indexing.rb +160 -175
  43. data/lib/familia/features/relationships/membership.rb +16 -21
  44. data/lib/familia/features/relationships/tracking.rb +61 -21
  45. data/lib/familia/features/relationships.rb +15 -8
  46. data/lib/familia/features/safe_dump.rb +66 -72
  47. data/lib/familia/features.rb +93 -5
  48. data/lib/familia/horreum/subclass/definition.rb +49 -3
  49. data/lib/familia/horreum.rb +15 -24
  50. data/lib/familia/secure_identifier.rb +51 -75
  51. data/lib/familia/verifiable_identifier.rb +162 -0
  52. data/lib/familia/version.rb +1 -1
  53. data/lib/familia.rb +1 -0
  54. data/setup.cfg +5 -0
  55. data/try/core/secure_identifier_try.rb +47 -18
  56. data/try/core/verifiable_identifier_try.rb +171 -0
  57. data/try/features/{external_identifiers/external_identifiers_try.rb → external_identifier/external_identifier_try.rb} +25 -28
  58. data/try/features/feature_improvements_try.rb +126 -0
  59. data/try/features/{object_identifiers/object_identifiers_integration_try.rb → object_identifier/object_identifier_integration_try.rb} +28 -30
  60. data/try/features/{object_identifiers/object_identifiers_try.rb → object_identifier/object_identifier_try.rb} +13 -13
  61. data/try/features/real_feature_integration_try.rb +7 -6
  62. data/try/features/relationships/relationships_api_changes_try.rb +339 -0
  63. data/try/features/relationships/relationships_try.rb +6 -5
  64. data/try/features/safe_dump/safe_dump_try.rb +8 -9
  65. data/try/helpers/test_helpers.rb +17 -17
  66. metadata +62 -41
  67. data/examples/relationships_basic.rb +0 -273
  68. data/lib/familia/features/external_identifiers/external_identifier_field_type.rb +0 -120
  69. data/lib/familia/features/external_identifiers.rb +0 -111
  70. data/lib/familia/features/object_identifiers/object_identifier_field_type.rb +0 -91
  71. data/lib/familia/features/object_identifiers.rb +0 -194
  72. /data/docs/{wiki → guides}/API-Reference.md +0 -0
  73. /data/docs/{wiki → guides}/Connection-Pooling-Guide.md +0 -0
  74. /data/docs/{wiki → guides}/Encrypted-Fields-Overview.md +0 -0
  75. /data/docs/{wiki → guides}/Expiration-Feature-Guide.md +0 -0
  76. /data/docs/{wiki → guides}/Feature-System-Guide.md +0 -0
  77. /data/docs/{wiki → guides}/Features-System-Developer-Guide.md +0 -0
  78. /data/docs/{wiki → guides}/Field-System-Guide.md +0 -0
  79. /data/docs/{wiki → guides}/Quantization-Feature-Guide.md +0 -0
  80. /data/docs/{wiki → guides}/Security-Model.md +0 -0
  81. /data/docs/{wiki → guides}/Transient-Fields-Guide.md +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5ab18b134425a370c5d40f464e87747e85e713dc44c2a7906b7b024a66b23a4
4
- data.tar.gz: f5a2e3fd2ca4553781b7f58f4f0e7a6d5e9228c18f34c7a1f5cf1af7695d580d
3
+ metadata.gz: 003a28f3135f0e89f6813e61cf08482350dbff865d2d97971998c714aafcc898
4
+ data.tar.gz: 6c713c9861043c71d7b2cfc99a37c4522e404ed7461d8dafed5462022735440b
5
5
  SHA512:
6
- metadata.gz: fba2c7586cb19181461f90ef2718c767de34f034d51ebc23c1643c8b526cc9c28fe64a2c3e3e46857bc1d816c8e9db9f76a6b57510f9b918756558b5e09c6fc9
7
- data.tar.gz: 2f98337dbe62a833b310e9ddcd5916a7971e2b551a0603dbb153fa3ba5c99a81e9dfe86270a0d0500b359625ea23efbebc58ab26b327a03fc5138ee643475472
6
+ metadata.gz: b0e4cb9f390ee0a3e1d83cc94a2248690fe757ce343665ef6e4ea6dbd2c74f8f7d07e352661380f0aac23e91f437315300a409847d28896b58b4ddf567d5e953
7
+ data.tar.gz: 2ec7616c6b2d64d522d441447ac93e58fe89f35eccd357bfdfc65305fc4324122148e5a3722c4bfd613d1f194fac1e5c0228d72b3774aa0e86e09bcdfe8b90fb
@@ -66,3 +66,16 @@ jobs:
66
66
 
67
67
  - name: Run the tryouts
68
68
  run: bundle exec try -vf
69
+
70
+ - name: Validate examples
71
+ continue-on-error: true
72
+ run: |
73
+ echo "=== Validating example syntax ==="
74
+ find examples/ -name "*.rb" -exec ruby -c {} \;
75
+
76
+ echo "=== Running executable examples ==="
77
+ cd examples
78
+ for example in *.rb; do
79
+ echo "Running $example..."
80
+ ruby "$example" || echo "Warning: $example failed to run"
81
+ done
@@ -41,7 +41,7 @@ jobs:
41
41
 
42
42
  - name: Build YARD documentation
43
43
  run: |
44
- bundle exec yard doc --output-dir ./doc --readme README.md
44
+ bundle exec yard doc --output-dir ./doc
45
45
  # Ensure doc directory exists and create .nojekyll file to prevent GitHub Pages Jekyll processing
46
46
  mkdir -p ./doc
47
47
  touch ./doc/.nojekyll
data/.gitignore CHANGED
@@ -12,20 +12,20 @@
12
12
  .*.json
13
13
  *.env
14
14
  *.log
15
- *.md
16
- .mcp.json
17
- !README.md
18
- !CLAUDE.md
19
15
  *.txt
20
- !LICENSE.txt
21
16
  .ruby-version
22
17
  appendonlydir
23
- etc/config
24
18
  log
25
19
  tmp
26
20
  vendor
27
21
  *.gem
28
22
  doc/
29
- !docs/overview.md
30
- !docs/connection_pooling.md
31
- !docs/wiki/**/*.md
23
+
24
+ # Ignore WIP or temp dev files with uppercase names
25
+ [A-Z]*.md
26
+
27
+ # Exclusions
28
+ !README.md
29
+ !CHANGELOG.md
30
+ !CLAUDE.md
31
+ !LICENSE.txt
data/.rubocop.yml CHANGED
@@ -34,6 +34,25 @@ AllCops:
34
34
  - "try/*.rb"
35
35
  - "vendor/**/*"
36
36
 
37
+ #
38
+ # Trailing commas
39
+ Style/TrailingCommaInHashLiteral:
40
+ EnforcedStyleForMultiline: comma
41
+ Enabled: true
42
+
43
+ Style/TrailingCommaInArrayLiteral:
44
+ EnforcedStyleForMultiline: comma
45
+ Enabled: true
46
+
47
+ Style/TrailingCommaInArguments:
48
+ Enabled: true
49
+
50
+ Style/TrailingCommaInBlockArgs:
51
+ Enabled: true
52
+
53
+ Lint/TrailingCommaInAttributeDeclaration:
54
+ Enabled: true
55
+
37
56
  Gemspec/DeprecatedAttributeAssignment:
38
57
  Enabled: true
39
58
 
data/.yardopts CHANGED
@@ -4,6 +4,27 @@
4
4
  --markup-provider kramdown
5
5
  --protected
6
6
  --no-private
7
+ --embed-mixin ClassMethods
8
+ --embed-mixin Features
9
+ --tag feature:"Feature"
10
+ --tag since:"Since Version"
11
+ --tag example:"Example Usage"
12
+ --tag note:"Note"
13
+ --tag warning:"Warning"
14
+ --tag deprecated:"Deprecated"
15
+ --hide-tag nodoc
16
+ --exclude lib/familia/version.rb
7
17
  lib/**/*.rb
8
18
  -
9
- - LICENSE.txt
19
+ CHANGELOG.md
20
+ LICENSE.txt
21
+ docs/guides/Home.md
22
+ docs/guides/Getting-Started.md
23
+ docs/guides/Feature-System-Guide.md
24
+ docs/guides/Relationships-Guide.md
25
+ docs/guides/relationships-methods.md
26
+ docs/guides/Encrypted-Fields-Overview.md
27
+ docs/guides/Connection-Pooling-Guide.md
28
+ docs/reference/api-technical.md
29
+ docs/migration/*.md
30
+ examples/*.rb
data/CHANGELOG.md ADDED
@@ -0,0 +1,247 @@
1
+ # CHANGELOG.md
2
+
3
+ All notable changes to Familia are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ <!--scriv-insert-here-->
9
+
10
+ <a id='changelog-2.0.0.pre12'></a>
11
+ ## 2.0.0.pre12 — 2025-09-04
12
+
13
+ ### Added
14
+
15
+ - Added the `Familia::VerifiableIdentifier` module to create and verify identifiers with an embedded HMAC signature. This allows an application to stateless-ly confirm that an identifier was generated by itself, preventing forged IDs from malicious sources.
16
+
17
+ - **Scoped VerifiableIdentifier**: Added `scope` parameter to `generate_verifiable_id()` and `verified_identifier?()` methods, enabling cryptographically isolated identifier namespaces for multi-tenant, multi-domain, or multi-environment applications while maintaining full backward compatibility with existing code.
18
+
19
+ ### Changed
20
+
21
+ - ObjectIdentifier feature now tracks which generator (uuid_v7, uuid_v4, hex, or custom) was used for each objid to provide provenance information for security-sensitive operations.
22
+ - Updated external identifier derivation to normalize objid format based on the known generator type, eliminating format ambiguity between UUID and hex formats.
23
+
24
+ - Refactored identifier generation methods for clarity and consistency. Method `generate_objid` is now `generate_object_identifier`, and `generate_external_identifier` is now `derive_external_identifier` to reflect its deterministic nature.
25
+
26
+ ### Removed
27
+
28
+ - Removed the `generate_extid` class method, which was less secure than the instance-level derivation logic.
29
+
30
+ ### Security
31
+
32
+ - Hardened external identifier derivation with provenance validation. ExternalIdentifier now validates that objid values come from the ObjectIdentifier feature before deriving external identifiers, preventing derivation from potentially malicious or unvalidated objid values while maintaining deterministic behavior for legitimate use cases.
33
+
34
+ - Improved the security of external identifiers (`extid`) by using the internal object identifier (`objid`) as a seed for a new random value, rather than deriving the `extid` directly. This prevents potential information leakage from the internal `objid`.
35
+
36
+ ### Documentation
37
+
38
+ - Added detailed YARD documentation for `VerifiableIdentifier`, explaining how to securely generate and manage the required `VERIFIABLE_ID_HMAC_SECRET` key.
39
+
40
+ ### AI Assistance
41
+
42
+ - Security analysis of external identifier derivation and hardened design approach was discussed and developed with AI assistance, including provenance tracking, validation logic, format normalization, and comprehensive test updates.
43
+
44
+ - Implementation of scoped verifiable identifiers was developed with AI assistance to ensure cryptographic security properties and comprehensive test coverage.
45
+
46
+ <a id='changelog-2.0.0.pre11'></a>
47
+ ## 2.0.0.pre11 - 2025-09-03
48
+
49
+ ### Added
50
+
51
+ - **Enhanced Feature System**: Introduced a hierarchical feature system with ancestry chain traversal for model-specific feature registration. This enables better organization, standardized naming, and automatic loading of project-specific features via the new `Familia::Features::Autoloader` module.
52
+ - **Improved SafeDump DSL**: Replaced the internal `@safe_dump_fields` implementation with a cleaner, more robust DSL using `safe_dump_field` and `safe_dump_fields` methods.
53
+ - Added `generate_short_id` and `shorten_securely` utility methods for creating short, secure identifiers, adapted from `OT::Utils::SecureNumbers`.
54
+ - For a detailed guide on migrating to the new feature system, see `docs/migration/v2.0.0-pre11.md`.
55
+
56
+ ### Changed
57
+
58
+ - External identifier now raises an `ExternalIdentifierError` if the model does not have an objid field. Previously: returned nil. In practice this should never happen, since the external_identifier feature declares its dependency on object_identifier.
59
+ - Moved lib/familia/encryption_request_cache.rb to lib/familia/encryption/request_cache.rb for consistency.
60
+ - **Simplified ObjectIdentifier Feature Implementation**: Consolidated the ObjectIdentifier feature from two files (~190 lines) to a single file (~140 lines) by moving the ObjectIdentifierFieldType class inline. This reduces complexity while maintaining all existing functionality including lazy generation, data integrity preservation, and multiple generator strategies.
61
+ - **Renamed Identifier Features to Singular Form**: Renamed `object_identifier` → `object_identifier` and `external_identifier` → `external_identifier` for more accurate naming. Added full-length aliases (`object_identifier`/`external_identifier`) alongside the short forms (`objid`/`extid`) for clarity when needed.
62
+ - **Simplified ExternalIdentifier Feature Implementation**: Consolidated the ExternalIdentifier feature from two files (~240 lines) to a single file (~120 lines) by moving the ExternalIdentifierFieldType class inline, following the same pattern as ObjectIdentifier.
63
+
64
+ ### Fixed
65
+
66
+ - Fixed external identifier generation returning all zeros for UUID-based objids. The `shorten_to_external_id` method now correctly handles both 256-bit secure identifiers and 128-bit UUIDs by detecting input length and applying appropriate bit truncation only when needed.
67
+
68
+ ### Security
69
+
70
+ - Improved input validation in `shorten_to_external_id` method by replacing insecure character count checking with proper bit length calculation and explicit validation. Invalid inputs now raise clear error messages instead of being silently processed incorrectly.
71
+
72
+ <a id='changelog-2.0.0-pre10'></a>
73
+ ## 2.0.0-pre10 - 2025-09-02
74
+
75
+ ### Added
76
+
77
+ - The `Familia::Horreum` initializer now supports creating an object directly from its identifier by passing a single argument (e.g., `Customer.new(customer_id)`). This provides a more convenient and intuitive way to instantiate objects from lookups.
78
+
79
+ - Automatic indexing and class-level tracking on `save()` operations, eliminating the need for manual index updates.
80
+ - Enhanced collection syntax supports the Ruby-idiomatic `<<` operator for more natural relationship management.
81
+
82
+ ### Changed
83
+
84
+ - The `member_of` relationship is now bidirectional. A single call to `member.add_to_owner_collection(owner)` is sufficient to establish the relationship, removing the need for a second, redundant call on the owner object. This fixes bugs where members could be added to collections twice.
85
+
86
+ - **BREAKING**: Refactored Familia Relationships API to remove "global" terminology and simplify method generation. (Closes #86)
87
+ - Split `generate_indexing_instance_methods` into focused `generate_direct_index_methods` and `generate_relationship_index_methods` for better separation between direct class-level and relationship-based indexing.
88
+ - Simplified method generation by removing complex global vs parent conditionals.
89
+ - All indexes are now stored at the class level for consistency.
90
+
91
+ ### Fixed
92
+
93
+ - Fixed a bug in the `class_indexed_by` feature where finder methods (e.g., `find_by_email`) would fail to correctly instantiate objects from the index, returning partially-formed objects.
94
+
95
+ - Refactored connection handling to properly cache and reuse Redis connections. This eliminates repetitive "Overriding existing connection" warnings and improves performance.
96
+
97
+ - Method generation now works consistently for both `class_indexed_by` and `indexed_by` with a `parent:`.
98
+ - Resolved metadata storage issues for dynamically created classes.
99
+ - Improved error handling for nil class names in tracking relationships.
100
+
101
+ ### Documentation
102
+
103
+ - Updated the `examples/relationships_basic.rb` script to reflect the improved, bidirectional `member_of` API and to ensure a clean database state for each run.
104
+
105
+ ### AI Assistance
106
+
107
+ - This refactoring was implemented with Claude Code assistance, including comprehensive test updates and API modernization.
108
+
109
+ <a id='changelog-2.0.0-pre9'></a>
110
+ ## 2.0.0-pre9 - 2025-09-02
111
+
112
+ ### Added
113
+
114
+ - Added `class_tracked_in` method for global tracking relationships following Horreum's established `class_` prefix convention
115
+ - Added `class_indexed_by` method for global index relationships with consistent API design
116
+
117
+ ### Changed
118
+
119
+ - **BREAKING**: `tracked_in :global, collection` syntax now raises ArgumentError - use `class_tracked_in collection` instead
120
+ - **BREAKING**: `indexed_by field, index, context: :global` syntax replaced with `class_indexed_by field, index`
121
+ - **BREAKING**: `indexed_by field, index, context: SomeClass` syntax replaced with `indexed_by field, index, parent: SomeClass`
122
+ - Relationships API now provides consistent parameter naming across all relationship types
123
+
124
+ ### Documentation
125
+
126
+ - Updated Relationships Guide with new API syntax and migration examples
127
+ - Updated relationships method documentation with new method signatures
128
+ - Updated basic relationships example to demonstrate new API patterns
129
+ - Added tryouts test coverage in try/features/relationships/relationships_api_changes_try.rb
130
+
131
+
132
+ <a id='changelog-2.0.0-pre8'></a>
133
+ ## 2.0.0-pre8 - 2025-09-01
134
+
135
+ ### Added
136
+
137
+ - Implemented Scriv-based changelog system for sustainable documentation
138
+ - Added fragment-based workflow for tracking changes
139
+ - Created structured changelog templates and configuration
140
+
141
+ ### Documentation
142
+
143
+ - Set up Scriv configuration and directory structure
144
+ - Created README for changelog fragment workflow
145
+
146
+ <!-- scriv-end-here -->
147
+
148
+ <a id='changelog-2.0.0-pre7'></a>
149
+ ## 2.0.0-pre7 - 2025-08-31
150
+
151
+ ### Added
152
+
153
+ - Comprehensive relationships system with three relationship types:
154
+ - `tracked_in` - Multi-presence tracking with score encoding
155
+ - `indexed_by` - O(1) hash-based lookups
156
+ - `member_of` - Bidirectional membership with collision-free naming
157
+ - Categorical permission system with bit-encoded permissions
158
+ - Time-based permission scoring for temporal access control
159
+ - Permission tier hierarchies with inheritance patterns
160
+ - Scalable permission management for large object collections
161
+ - Score-based sorting with custom scoring functions
162
+ - Permission-aware queries filtering by access levels
163
+ - Relationship validation framework ensuring data integrity
164
+
165
+ ### Changed
166
+
167
+ - Performance optimizations for large-scale relationship operations
168
+
169
+ ### Security
170
+
171
+ - GitHub Actions security hardening with matrix optimization
172
+
173
+
174
+ <a id='changelog-2.0.0-pre6'></a>
175
+ ## 2.0.0-pre6 - 2025-08-15
176
+
177
+ ### Added
178
+
179
+ - New `save_if_not_exists` method for conditional persistence
180
+ - Atomic persistence operations with transaction support
181
+ - Enhanced error handling for persistence failures
182
+ - Improved data consistency guarantees
183
+
184
+ ### Changed
185
+
186
+ - Connection provider pattern for flexible pooling strategies
187
+ - Multi-database support with intelligent pool management
188
+ - Thread-safe connection handling for concurrent applications
189
+ - Configurable pool sizing and timeout management
190
+ - Modular class structure with cleaner separation of concerns
191
+ - Enhanced feature system with dependency management
192
+ - Improved inheritance patterns for better code organization
193
+ - Streamlined base class functionality
194
+
195
+ ### Fixed
196
+
197
+ - Critical security fixes in Ruby workflow vulnerabilities
198
+ - Systematic dependency resolution via multi-constraint optimization
199
+
200
+
201
+ <a id='changelog-2.0.0-pre5'></a>
202
+ ## 2.0.0-pre5 - 2025-08-05
203
+
204
+ ### Added
205
+
206
+ - Field-level encryption with transparent access patterns
207
+ - Multiple encryption providers:
208
+ - XChaCha20-Poly1305 (preferred, requires rbnacl)
209
+ - AES-256-GCM (fallback, OpenSSL-based)
210
+ - Field-specific key derivation for cryptographic domain separation
211
+ - Configurable key versioning supporting key rotation
212
+ - Non-persistent field storage for sensitive runtime data
213
+ - RedactedString wrapper preventing accidental logging/serialization
214
+ - Memory-safe handling of sensitive data in Ruby objects
215
+ - API-safe serialization excluding transient fields
216
+
217
+ ### Security
218
+
219
+ - Encryption field security hardening with additional validation
220
+ - Enhanced memory protection for sensitive data handling
221
+ - Improved key management patterns and best practices
222
+ - Security test suite expansion with comprehensive coverage
223
+
224
+
225
+ <a id='changelog-2.0.0-pre'></a>
226
+ ## 2.0.0-pre - 2025-07-25
227
+
228
+ ### Added
229
+
230
+ - Complete API redesign for clarity and modern Ruby conventions
231
+ - Valkey compatibility alongside traditional Redis support
232
+ - Ruby 3.4+ modernization with fiber and thread safety improvements
233
+ - Connection pooling foundation with provider pattern architecture
234
+
235
+ ### Changed
236
+
237
+ - `Familia::Base` replaced by `Familia::Horreum` as the primary base class
238
+ - Connection configuration moved from simple string to block-based setup
239
+ - Feature activation changed from `include` to `feature` declarations
240
+ - Method naming updated for consistency (`delete` → `destroy`, `exists` → `exists?`, `dump` → `serialize`)
241
+
242
+ ### Documentation
243
+
244
+ - YARD documentation workflow with automated GitHub Pages deployment
245
+ - Comprehensive migrating guide for v1.x to v2.0.0-pre transition
246
+
247
+ <!-- scriv-end-here -->
data/CLAUDE.md CHANGED
@@ -32,9 +32,10 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
32
32
 
33
33
  **Debugging options:**
34
34
  - **Stack traces**: `bundle exec try -s` (stack traces without debug logging)
35
+ - **Verbose failures**: `bundle exec try -vfs` (detailed failure output)
35
36
  - **Debug mode**: `bundle exec try -D` (additional logging including stack traces)
36
- - **Verbose failures**: `bundle exec try -vf` (detailed failure output)
37
- - **Fresh context**: `bundle exec try --fresh-context` (isolate test cases)
37
+ - **Shared context**: `bundle exec try --shared-context` (DEFAULT - reuse shared context across setup, testcases, and teardown)
38
+ - **Fresh context**: `bundle exec try --no-shared-context` (isolate test cases, no shared variables)
38
39
 
39
40
  *Note: Use `--agent` mode for optimal token efficiency when analyzing test results programmatically.*
40
41
 
@@ -44,21 +45,21 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44
45
  - **Generate documentation**: `bundle exec yard`
45
46
  - **Code linting**: `bundle exec rubocop`
46
47
 
48
+ ### Changelog Management
49
+
50
+ Add changelog fragment with each user-facing or documented change (optional but encouraged). See:
51
+ @changelog.d/README.md
52
+
47
53
  ### Known Issues & Quirks
48
- - **Reserved Keywords**: Cannot use `ttl`, `db`, `redis` as field names - use prefixed alternatives
54
+ - **Reserved Keywords**: Cannot use `ttl`, `db`, `valkey`, `redis` as field names - use prefixed alternatives
49
55
  - **Empty Identifiers**: Cause stack overflow in key generation - validate before operations
50
56
  - **Connection Pool Race Conditions**: Thread safety issues under high concurrency
51
- - **Manual Key Sync**: `key` field doesn't auto-sync with identifier changes
52
- - **RedisType Redis Parameter**: `:redis` parameter silently ignored (missing setter)
53
57
 
54
58
  ### Debugging
55
- - **Database command logging**: `tail plop.log` - Real-time Database command monitoring
59
+ - **Database command logging**: You can request real-time Database command monitoring from the user
56
60
  - Shows all Database operations with timestamps, database numbers, and full commands
57
61
  - Updates live as tests run or code executes
58
- - Essential for debugging Familia ORM Database interactions
59
-
60
- ### Testing Framework
61
- This project uses `tryouts` instead of RSpec/Minitest. Test files are located in the `try/` directory and follow the pattern `*_try.rb`.
62
+ - Essential for debugging Familia ORM Database interactions, multi/exec, pipelining, logical_database issues
62
63
 
63
64
  ## Architecture Overview
64
65
 
@@ -85,7 +86,7 @@ This project uses `tryouts` instead of RSpec/Minitest. Test files are located in
85
86
  Familia uses a modular feature system where features are mixed into classes:
86
87
  - **Expiration** (`lib/familia/features/expiration.rb`) - TTL management with cascading
87
88
  - **SafeDump** (`lib/familia/features/safe_dump.rb`) - API-safe object serialization
88
- - **Quantization** (`lib/familia/features/quantization.rb`) - Time-based data bucketing
89
+ - **Relationships** (`lib/familia/features/relationships.rb`) - CRUD operations for related objects
89
90
 
90
91
  #### Key Architectural Patterns
91
92
 
@@ -107,15 +108,6 @@ end
107
108
  - Proc: `identifier ->(user) { "user:#{user.email}" }`
108
109
  - Array: `identifier [:type, :email]`
109
110
 
110
- ### Directory Structure
111
-
112
- - `lib/familia.rb` - Main entry point and module definition
113
- - `lib/familia/horreum/` - Horreum class implementation (class_methods, commands, serialization, etc.)
114
- - `lib/familia/data_type/` - Valkey/Redis type implementations and commands
115
- - `lib/familia/features/` - Modular feature implementations
116
- - `try/` - Test files using tryouts framework
117
- - `try/test_helpers.rb` - Shared test utilities and sample classes
118
-
119
111
  ### Database Connection Management
120
112
  - Connection handling in `lib/familia/connection.rb`
121
113
  - Settings management in `lib/familia/settings.rb`
@@ -125,46 +117,7 @@ end
125
117
  ### Important Implementation Notes
126
118
 
127
119
  **Field Initialization**: Objects can be initialized with positional args (brittle) or keyword args (robust). Keyword args are recommended.
128
-
129
120
  **Serialization**: Uses JSON by default but supports custom `serialize_value`/`deserialize_value` methods.
130
-
131
121
  **Database Key Generation**: Automatic key generation using class name, identifier, and field/type names (aka dbkey). Pattern: `classname:identifier:fieldname`
132
-
133
122
  **Memory Efficiency**: Only non-nil values are stored in keystore database to optimize memory usage.
134
-
135
123
  **Thread Safety**: Data types are frozen after instantiation to ensure immutability.
136
-
137
- ## Common Patterns
138
-
139
- ### Defining a Horreum Class
140
- ```ruby
141
- class Customer < Familia::Horreum
142
- feature :safe_dump
143
- feature :expiration
144
-
145
- identifier_field :custid
146
- default_expiration 5.years
147
-
148
- field :custid
149
- field :email
150
- list :sessions
151
- hashkey :settings
152
- end
153
- ```
154
-
155
- ### Using Features
156
- ```ruby
157
- # Safe dump for API responses
158
- customer.safe_dump # Returns only whitelisted fields
159
-
160
- # Expiration management
161
- customer.update_expiration(default_expiration: 1.hour)
162
- ```
163
-
164
- ### Transaction Support
165
- ```ruby
166
- customer.transaction do |conn|
167
- conn.set("key1", "value1")
168
- conn.zadd("key2", score, member)
169
- end
170
- ```
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- familia (2.0.0.pre8)
4
+ familia (2.0.0.pre12)
5
5
  benchmark
6
6
  connection_pool
7
7
  csv
data/README.md CHANGED
@@ -118,6 +118,56 @@ user.transaction do |conn|
118
118
  end
119
119
  ```
120
120
 
121
+ ### Object Relationships
122
+
123
+ Familia includes a powerful relationships system for managing object associations:
124
+
125
+ ```ruby
126
+ class Customer < Familia::Horreum
127
+ feature :relationships
128
+
129
+ identifier_field :custid
130
+ field :custid, :name, :email
131
+ set :domains # Collection for related objects
132
+
133
+ # Automatic indexing and tracking
134
+ class_indexed_by :email, :email_lookup
135
+ class_tracked_in :all_customers, score: :created_at
136
+ end
137
+
138
+ class Domain < Familia::Horreum
139
+ feature :relationships
140
+
141
+ identifier_field :domain_id
142
+ field :domain_id, :name, :status
143
+
144
+ # Bidirectional membership
145
+ member_of Customer, :domains
146
+ end
147
+
148
+ # Clean, Ruby-like syntax
149
+ customer = Customer.new(custid: "cust123", email: "admin@acme.com")
150
+ customer.save # Automatically indexed and tracked
151
+
152
+ domain = Domain.new(domain_id: "dom456", name: "acme.com")
153
+ customer.domains << domain # Clean collection syntax
154
+
155
+ # Fast O(1) lookups
156
+ found_customer = Customer.find_by_email("admin@acme.com")
157
+ ```
158
+
159
+ ## Advanced Features
160
+
161
+ ### Relationships and Associations
162
+
163
+ Familia provides three types of relationships with automatic management:
164
+
165
+ - **`member_of`** - Bidirectional membership with clean `<<` operator support
166
+ - **`indexed_by`** - O(1) hash-based field lookups (class-level or relationship-scoped)
167
+ - **`tracked_in`** - Scored collections for rankings, time-series, and analytics
168
+
169
+ All relationships support automatic indexing and tracking - objects are automatically added to class-level collections when saved, with no manual management required.
170
+
121
171
  ## Organizing Complex Models
122
172
 
123
173
  For large applications, you can organize model complexity using custom features:
@@ -153,9 +203,19 @@ end
153
203
 
154
204
  This keeps complex models organized while maintaining Familia's clean, declarative style.
155
205
 
156
- ## Conclusion
206
+ ## AI Development Assistance
207
+
208
+ This version of Familia was developed with assistance from AI tools. The following tools provided significant help with architecture design, code generation, and documentation:
209
+
210
+ - **Google Gemini** - Refactoring, code generation, and documentation.
211
+ - **Claude Sonnet 4, Opus 4.1** - Architecture design, code generation, and documentation
212
+ - **Claude Desktop & Claude Code (Max plan)** - Interactive development sessions and debugging
213
+ - **GitHub Copilot** - Code completion and refactoring assistance
214
+ - **Qodo Merge Pro** - Code review and quality improvements
215
+
216
+ I remain responsible for all design decisions and the final code. I believe in being transparent about development tools, especially as AI becomes more integrated into our workflows as developers.
157
217
 
158
- Familia provides a powerful and flexible way to work with Valkey-compatible in Ruby applications. Its features like automatic expiration, safe dumping, and quantization make it suitable for a wide range of use cases, from simple key-value storage to complex time-series data management.
218
+ ## Epilogue
159
219
 
160
220
  For more information, visit:
161
221
  - [Github Repository](https://github.com/delano/familia)
@@ -0,0 +1,77 @@
1
+ # Changelog Fragments
2
+
3
+ This directory contains changelog fragments managed by [Scriv](https://scriv.readthedocs.io/).
4
+
5
+ ## Our Approach
6
+
7
+ Changelogs are for humans and agents, not just machines. We follow the core principles of [Keep a Changelog](https://keepachangelog.com) and semvar to ensure our release notes are clear, consistent, and useful.
8
+
9
+ To achieve this, we use a fragment-based workflow with `scriv`. Instead of a single, large `CHANGELOG.md` file that can cause merge conflicts, each developer includes a small changelog fragment with their pull request. At release time, these fragments are collected and aggregated into the main changelog.
10
+
11
+ This approach provides several benefits:
12
+ - **Reduces Merge Conflicts:** Developers can work in parallel without conflicting over a central changelog file.
13
+ - **Improves Developer Experience:** Creating a small, focused fragment is a simple and repeatable task during development.
14
+ - **Ensures Consistency:** Automation helps maintain a consistent structure for all changelog entries.
15
+ - **AI Transparency:** An opportunity to be specific and detailed about the assistance provided.
16
+ - **Builds Trust:** A clear and well-maintained changelog communicates respect for our users and collaborators.
17
+
18
+ ## Relevant paths
19
+
20
+ * `changelog.d/` - (e.g. changelog.d/YYYYMMDD_HHmmss_username_branch.md)
21
+ * `docs/migrating/` - (e.g. docs/migrating/v2.0.0-pre.md)
22
+ * `CHANGELOG.md` - The full changelog for all releases, in reverse chronological order. Careful: LARGE DOCUMENT. Limit reading to the first 50 lines.
23
+
24
+ * `setup.cfg` - Scriv tool settings
25
+
26
+ ## How to Add a Changelog Entry
27
+
28
+ 1. **Create a New Fragment:**
29
+
30
+ ```bash
31
+ # This will create a new file in the `changelog.d/` directory.
32
+ scriv create
33
+ ```
34
+
35
+ 2. **Edit the Fragment File:**
36
+ Open the newly created file and add your entry under the relevant category. See the guidelines below for writing good CHANGELOG entries.
37
+
38
+ 3. **Add or Update Migrating Guide:** (optional)
39
+ Include technical details to help developers update to the new version. Start with a specific introduction, e.g. "This version introduces significant improvements to Familia's feature system, making it easier to organize and use features across complex projects.". Including code snippets and multi-line content that is too detailed for the CHANGELOG.
40
+
41
+ Use the content of an existing `docs/migrating/vMajor.Minor.Patch*.md file as a reference.
42
+
43
+ Compare the headers of your draft content with the headers of the previous migration guide to make sure it does not repeat or overlap.
44
+
45
+ 4. **Commit with Your Code:**
46
+ ```bash
47
+ git add changelog.d/YYYYMMDD_HHmmss_username_branch.md [docs/migrating/v2.0.0-pre.md]
48
+ git commit
49
+ ```
50
+
51
+ ## Fragment Guidelines
52
+
53
+ - **One Fragment Per Change:** Keep each fragment focused on a single feature, fix, or improvement.
54
+ - **Documenting AI Assistance:** If a change involved significant AI assistance, place it in its own fragment. This ensures the `### AI Assistance` section clearly corresponds to the single change described in that fragment.
55
+ - **Write for a Human Audience:** Describe the *impact* of the change, not just the implementation details.
56
+ - **Good:** "Improved the performance and stability of Redis connections under high load."
57
+ - **Bad:** "Refactored the `RedisManager`."
58
+ - **Be Specific:** Avoid generic messages like "fixed a bug." Clearly state what was fixed.
59
+ - **Include Context:** Reference issue or pull request numbers to provide a link to the discussion and implementation details. `scriv` will automatically create links for them.
60
+ - **Example:** `- Fixed a bug where users could not reset their passwords. PR #123`
61
+
62
+ ### Categories
63
+
64
+ Use these categories:
65
+
66
+ - **Added**: New features or capabilities.
67
+ - **Changed**: Changes to existing functionality.
68
+ - **Deprecated**: Soon-to-be removed features.
69
+ - **Removed**: Now removed features.
70
+ - **Fixed**: Bug fixes.
71
+ - **Security**: Security-related improvements.
72
+ - **Documentation**: Documentation improvements.
73
+ - **AI Assistance**: Significant AI assistance in the change, including discussion, rubber ducking, formatting, writing documentation, writing tests.
74
+
75
+ ## Release Process
76
+
77
+ At release time, scriv will collect all fragments into the main `CHANGELOG.md` file with th command `scriv collect`. The version is taken automatically from `lib/familia/version.rb`.
@@ -0,0 +1,2 @@
1
+ # Even all uppercase markdown docs get the blues
2
+ !*.md