familia 2.0.0.pre10 → 2.0.0.pre13

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +2 -3
  3. data/CHANGELOG.rst +507 -0
  4. data/CLAUDE.md +5 -55
  5. data/Gemfile +1 -6
  6. data/Gemfile.lock +13 -7
  7. data/changelog.d/README.md +45 -34
  8. data/changelog.d/scriv.ini +5 -0
  9. data/docs/archive/FAMILIA_RELATIONSHIPS.md +1 -1
  10. data/docs/archive/FAMILIA_UPDATE.md +1 -1
  11. data/docs/archive/README.md +15 -19
  12. data/docs/guides/Feature-System-Autoloading.md +228 -0
  13. data/docs/guides/Home.md +1 -1
  14. data/docs/guides/Implementation-Guide.md +1 -1
  15. data/docs/guides/relationships-methods.md +1 -1
  16. data/docs/guides/time-utilities.md +221 -0
  17. data/docs/migrating/.gitignore +2 -0
  18. data/docs/migrating/v2.0.0-pre.md +84 -0
  19. data/docs/migrating/v2.0.0-pre11.md +253 -0
  20. data/docs/migrating/v2.0.0-pre12.md +306 -0
  21. data/docs/migrating/v2.0.0-pre13.md +329 -0
  22. data/docs/migrating/v2.0.0-pre5.md +110 -0
  23. data/docs/migrating/v2.0.0-pre6.md +154 -0
  24. data/docs/migrating/v2.0.0-pre7.md +222 -0
  25. data/docs/overview.md +6 -7
  26. data/{examples/redis_command_validation_example.rb → docs/reference/auditing_database_commands.rb} +29 -32
  27. data/examples/autoloader/mega_customer/safe_dump_fields.rb +6 -0
  28. data/examples/autoloader/mega_customer.rb +17 -0
  29. data/examples/{bit_encoding_integration.rb → permissions.rb} +30 -27
  30. data/examples/{relationships_basic.rb → relationships.rb} +2 -3
  31. data/examples/safe_dump.rb +281 -0
  32. data/familia.gemspec +5 -4
  33. data/lib/familia/autoloader.rb +53 -0
  34. data/lib/familia/base.rb +57 -0
  35. data/lib/familia/data_type.rb +4 -0
  36. data/lib/familia/encryption/encrypted_data.rb +4 -4
  37. data/lib/familia/encryption/manager.rb +6 -4
  38. data/lib/familia/{encryption_request_cache.rb → encryption/request_cache.rb} +1 -1
  39. data/lib/familia/encryption.rb +1 -1
  40. data/lib/familia/errors.rb +5 -0
  41. data/lib/familia/features/autoloadable.rb +113 -0
  42. data/lib/familia/features/encrypted_fields/concealed_string.rb +4 -2
  43. data/lib/familia/features/expiration.rb +4 -0
  44. data/lib/familia/features/external_identifier.rb +310 -0
  45. data/lib/familia/features/object_identifier.rb +307 -0
  46. data/lib/familia/features/quantization.rb +5 -0
  47. data/lib/familia/features/safe_dump.rb +74 -73
  48. data/lib/familia/features.rb +109 -17
  49. data/lib/familia/field_type.rb +2 -0
  50. data/lib/familia/horreum/core/serialization.rb +3 -3
  51. data/lib/familia/horreum/subclass/definition.rb +50 -7
  52. data/lib/familia/horreum.rb +2 -0
  53. data/lib/familia/json_serializer.rb +70 -0
  54. data/lib/familia/logging.rb +12 -10
  55. data/lib/familia/refinements/logger_trace.rb +57 -0
  56. data/lib/familia/refinements/snake_case.rb +40 -0
  57. data/lib/familia/refinements/time_utils.rb +248 -0
  58. data/lib/familia/refinements.rb +3 -49
  59. data/lib/familia/secure_identifier.rb +51 -75
  60. data/lib/familia/utils.rb +2 -0
  61. data/lib/familia/validation/{test_helpers.rb → validation_helpers.rb} +2 -2
  62. data/lib/familia/validation.rb +1 -1
  63. data/lib/familia/verifiable_identifier.rb +162 -0
  64. data/lib/familia/version.rb +1 -1
  65. data/lib/familia.rb +15 -2
  66. data/try/core/autoloader_try.rb +112 -0
  67. data/try/core/extensions_try.rb +38 -21
  68. data/try/core/familia_extended_try.rb +4 -3
  69. data/try/core/secure_identifier_try.rb +47 -18
  70. data/try/core/time_utils_try.rb +130 -0
  71. data/try/core/verifiable_identifier_try.rb +171 -0
  72. data/try/data_types/datatype_base_try.rb +3 -2
  73. data/try/features/autoloadable/autoloadable_try.rb +61 -0
  74. data/try/features/encrypted_fields/concealed_string_core_try.rb +8 -3
  75. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +59 -17
  76. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +36 -12
  77. data/try/features/{external_identifiers/external_identifiers_try.rb → external_identifier/external_identifier_try.rb} +25 -28
  78. data/try/features/feature_improvements_try.rb +127 -0
  79. data/try/features/{object_identifiers/object_identifiers_integration_try.rb → object_identifier/object_identifier_integration_try.rb} +28 -30
  80. data/try/features/{object_identifiers/object_identifiers_try.rb → object_identifier/object_identifier_try.rb} +13 -13
  81. data/try/features/real_feature_integration_try.rb +8 -7
  82. data/try/features/safe_dump/safe_dump_autoloading_try.rb +111 -0
  83. data/try/features/safe_dump/safe_dump_try.rb +8 -9
  84. data/try/helpers/test_helpers.rb +41 -17
  85. data/try/integration/cross_component_try.rb +3 -1
  86. metadata +61 -26
  87. data/CHANGELOG.md +0 -184
  88. data/changelog.d/fragments/.keep +0 -0
  89. data/changelog.d/template.md.j2 +0 -29
  90. data/lib/familia/core_ext.rb +0 -135
  91. data/lib/familia/features/external_identifiers/external_identifier_field_type.rb +0 -120
  92. data/lib/familia/features/external_identifiers.rb +0 -111
  93. data/lib/familia/features/object_identifiers/object_identifier_field_type.rb +0 -91
  94. data/lib/familia/features/object_identifiers.rb +0 -194
  95. data/setup.cfg +0 -12
data/Gemfile.lock CHANGED
@@ -1,11 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- familia (2.0.0.pre10)
5
- benchmark
6
- connection_pool
7
- csv
8
- logger
4
+ familia (2.0.0.pre13)
5
+ benchmark (~> 0.4)
6
+ connection_pool (~> 2.5)
7
+ csv (~> 3.3)
8
+ logger (~> 1.7)
9
+ oj (~> 3.16)
9
10
  redis (>= 4.8.1, < 6.0)
10
11
  stringio (~> 3.1.1)
11
12
  uri-valkey (~> 1.4)
@@ -16,6 +17,7 @@ GEM
16
17
  ast (2.4.3)
17
18
  base64 (0.3.0)
18
19
  benchmark (0.4.1)
20
+ bigdecimal (3.2.3)
19
21
  byebug (11.1.3)
20
22
  coderay (1.1.3)
21
23
  concurrent-ruby (1.3.5)
@@ -39,6 +41,10 @@ GEM
39
41
  logger (1.7.0)
40
42
  method_source (1.1.0)
41
43
  minitest (5.25.5)
44
+ oj (3.16.11)
45
+ bigdecimal (>= 3.0)
46
+ ostruct (>= 0.2)
47
+ ostruct (0.6.3)
42
48
  parallel (1.27.0)
43
49
  parser (3.3.8.0)
44
50
  ast (~> 2.4.1)
@@ -113,7 +119,7 @@ GEM
113
119
  ruby-progressbar (1.13.0)
114
120
  stackprof (0.2.27)
115
121
  stringio (3.1.7)
116
- tryouts (3.5.2)
122
+ tryouts (3.6.0)
117
123
  concurrent-ruby (~> 1.0)
118
124
  irb
119
125
  minitest (~> 5.0)
@@ -148,7 +154,7 @@ DEPENDENCIES
148
154
  rubocop-thread_safety
149
155
  ruby-prof
150
156
  stackprof
151
- tryouts (~> 3.5.2)
157
+ tryouts (~> 3.6.0)
152
158
  yard (~> 0.9)
153
159
 
154
160
  BUNDLED WITH
@@ -4,7 +4,7 @@ This directory contains changelog fragments managed by [Scriv](https://scriv.rea
4
4
 
5
5
  ## Our Approach
6
6
 
7
- Changelogs are for humans and agents, not just machines. We follow the core principles of [Keep a Changelog](https://keepachangelog.com) to ensure our release notes are clear, consistent, and trustworthy.
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
8
 
9
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
10
 
@@ -12,55 +12,66 @@ This approach provides several benefits:
12
12
  - **Reduces Merge Conflicts:** Developers can work in parallel without conflicting over a central changelog file.
13
13
  - **Improves Developer Experience:** Creating a small, focused fragment is a simple and repeatable task during development.
14
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.
15
16
  - **Builds Trust:** A clear and well-maintained changelog communicates respect for our users and collaborators.
16
17
 
18
+ ## Relevant paths
19
+
20
+ * `changelog.d/` - (e.g. changelog.d/YYYYMMDD_HHmmss_username_branch.rst)
21
+ * `docs/migrating/` - (e.g. docs/migrating/v2.0.0-pre.md)
22
+ * `CHANGELOG.rst` - The full changelog for all releases, in reverse chronological order. Careful: LARGE DOCUMENT. Limit reading to the first 50 lines.
23
+
24
+ * `changelog.d/scriv.ini` - Scriv tool settings
25
+
17
26
  ## How to Add a Changelog Entry
18
27
 
19
28
  1. **Create a New Fragment:**
20
- ```bash
21
- scriv create
22
- ```
23
- This will create a new file in the `changelog.d/fragments/` directory.
24
29
 
25
- **Alternative:** Use `scriv create --edit` to create and immediately open in your editor.
26
- **Important:** You must add content and save before exiting, or scriv will abort with "Empty fragment, aborting..."
30
+ ```bash
31
+ # This will create a new file in the `changelog.d/` directory.
32
+ scriv create
33
+ ```
27
34
 
28
35
  2. **Edit the Fragment File:**
29
- Open the newly created file and add your entry under the relevant category. See the guidelines below for writing good entries.
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.
30
42
 
31
- 3. **Commit with Your Code:**
32
- ```bash
33
- git add changelog.d/fragments/your_fragment_name.md
34
- git commit
35
- ```
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.rst [docs/migrating/v2.0.0-pre.md]
48
+ git commit
49
+ ```
36
50
 
37
51
  ## Fragment Guidelines
38
52
 
39
- - **One Fragment Per Change:** Keep each fragment focused on a single feature, fix, or improvement.
40
- - **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.
41
- - **Write for a Human Audience:** Describe the *impact* of the change, not just the implementation details.
42
- - **Good:** "Improved the performance and stability of Redis connections under high load."
43
- - **Bad:** "Refactored the `RedisManager` to use a connection pool."
44
- - **Be Specific:** Avoid generic messages like "fixed a bug." Clearly state what was fixed.
45
- - **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.
46
- - **Example:** `- Fixed a bug where users could not reset their passwords. (Closes #123)`
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`
47
61
 
48
62
  ### Categories
49
63
 
50
- Use these categories from [Keep a Changelog](https://keepachangelog.com):
64
+ Use these categories:
51
65
 
52
- - **Added**: New features or capabilities.
53
- - **Changed**: Changes to existing functionality.
54
- - **Deprecated**: Soon-to-be removed features.
55
- - **Removed**: Now removed features.
56
- - **Fixed**: Bug fixes.
57
- - **Security**: Security-related improvements.
58
- - **Documentation**: Documentation improvements.
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.
59
74
 
60
75
  ## Release Process
61
76
 
62
- At release time, an authorized maintainer will collect all fragments into the main `CHANGELOG.md` file:
63
-
64
- ```bash
65
- scriv collect --version 2.0.0
66
- ```
77
+ At release time, scriv will collect all fragments into the main `CHANGELOG.rst` file with th command `scriv collect`. The version is taken automatically from `lib/familia/version.rb`.
@@ -0,0 +1,5 @@
1
+ [scriv]
2
+ format = rst
3
+ categories = Added, Changed, Deprecated, Removed, Fixed, Security, Documentation, AI Assistance
4
+ version = command: ruby -r ./lib/familia/version.rb -e "puts Familia::VERSION"
5
+ main_branches = main, develop
@@ -189,7 +189,7 @@ customer.find_by_name("production-api-key")
189
189
  customer.find_all_by_scope(["read", "write"])
190
190
  ```
191
191
 
192
- ### Migration Guide
192
+ ### Migrating Guide
193
193
  If you have existing code with incorrect syntax, here's how to fix it:
194
194
 
195
195
  ```ruby
@@ -179,7 +179,7 @@ end
179
179
 
180
180
  ---
181
181
 
182
- ## Migration Guide Summary
182
+ ## Migrating Guide Summary
183
183
 
184
184
  ### From v1.x to v2.0.0-pre
185
185
  1. **Update connection configuration** to use new pooling system
@@ -10,9 +10,9 @@ This directory contains original documentation files that have been migrated to
10
10
  ### FAMILIA_UPDATE.md
11
11
  **Original Purpose:** Version summary table and detailed release notes for v2.0.0-pre series
12
12
 
13
- **Migration Destinations:**
13
+ **Migrating Destinations:**
14
14
  - **Changelog entries** → Extracted to Scriv fragments, aggregated into `CHANGELOG.md`
15
- - **Migration guides** → Reorganized into `docs/migration/v2.0.0-pre*.md`
15
+ - **Migrating guides** → Reorganized into `docs/migrating/v2.0.0-pre*.md`
16
16
  - **Feature descriptions** → Cross-referenced with existing feature guides in `docs/guides/`
17
17
 
18
18
  ### FAMILIA_RELATIONSHIPS.md
@@ -33,26 +33,22 @@ This directory contains original documentation files that have been migrated to
33
33
 
34
34
  ```
35
35
  docs/
36
- ├── migration/ # Version-specific migration guides
37
- │ ├── v2.0.0-pre.md # Foundation migration
38
- │ ├── v2.0.0-pre5.md # Security features
39
- │ ├── v2.0.0-pre6.md # Architecture improvements
40
- │ └── v2.0.0-pre7.md # Relationships system
41
- ├── guides/ # Feature guides (moved from wiki/)
42
- ├── relationships-methods.md # From FAMILIA_RELATIONSHIPS.md
36
+ ├── migrating/ # Version-specific migrating guides
37
+ │ ├── v2.0.0-pre.md
38
+ │ ├── v2.0.0-pre5.md # Security features
39
+ │ ├── v2.0.0-pre6.md # Architecture improvements
40
+ │ └── v2.0.0-pre7.md # Relationships system
41
+
42
+ ├── guides/ # Feature-specific guides (moved from wiki/)
43
+ │ ├── relationships.md # From FAMILIA_RELATIONSHIPS.md
43
44
  │ └── [other guides...]
44
- ├── reference/ # Technical reference
45
- │ └── api-technical.md # From FAMILIA_TECHNICAL.md
46
- └── archive/ # This directory
45
+
46
+ ├── reference/ # Technical reference
47
+ └── api-technical.md
48
+
49
+ └── archive/ # This directory
47
50
  ```
48
51
 
49
- ## Why These Files Were Archived
50
-
51
- 1. **Sustainability** - The original files accumulated overlapping content without clear organization
52
- 2. **Maintainability** - Scriv fragment system prevents documentation bloat
53
- 3. **Clarity** - Separation of changelog, guides, and reference improves findability
54
- 4. **Workflow** - Fragment-based workflow scales better with development
55
-
56
52
  ## Finding Migrated Content
57
53
 
58
54
  - **Version changes** → Check `CHANGELOG.md` (generated from fragments)
@@ -0,0 +1,228 @@
1
+ # Feature System Autoloading
2
+
3
+ ## Overview
4
+
5
+ Familia's feature system includes an autoloading mechanism that automatically discovers and loads feature-specific extension files when features are included in your classes. This allows you to keep your main model files clean while organizing feature-specific configurations in separate files.
6
+
7
+ ## The Problem It Solves
8
+
9
+ When you include a feature like `safe_dump` in a Familia class:
10
+
11
+ ```ruby
12
+ class User < Familia::Horreum
13
+ feature :safe_dump # This line should trigger autoloading
14
+ end
15
+ ```
16
+
17
+ You want to be able to define the safe dump configuration in a separate file:
18
+
19
+ ```ruby
20
+ # user/safe_dump_extensions.rb
21
+ class User
22
+ safe_dump_fields :name, :email # Don't dump :password
23
+ end
24
+ ```
25
+
26
+ But there's a **timing problem**: when should this extension file be loaded?
27
+
28
+ ## Why Standard `included` Hook Doesn't Work
29
+
30
+ The original approach tried to use the standard `included` hook:
31
+
32
+ ```ruby
33
+ module SafeDump
34
+ def self.included(base)
35
+ # Try to autoload here - BUT THIS IS TOO EARLY!
36
+ autoload_files_for(base)
37
+ end
38
+ end
39
+ ```
40
+
41
+ **Problem**: This happens **during** the feature inclusion process, before the feature is fully set up. The class isn't in a stable state yet.
42
+
43
+ ## The Solution: Post-Inclusion Hook
44
+
45
+ The `post_inclusion_autoload` system works in **two phases**:
46
+
47
+ ### Phase 1: Feature System Hook
48
+
49
+ In `lib/familia/features.rb`, after including the feature module:
50
+
51
+ ```ruby
52
+ def feature(feature_name, **options)
53
+ # ... setup code ...
54
+
55
+ include feature_class # Include the feature module
56
+
57
+ # NOW call the post-inclusion hook
58
+ if feature_class.respond_to?(:post_inclusion_autoload)
59
+ feature_class.post_inclusion_autoload(self, feature_name, options)
60
+ end
61
+ end
62
+ ```
63
+
64
+ ### Phase 2: Autoloadable Implementation
65
+
66
+ The `post_inclusion_autoload` method in `lib/familia/features/autoloadable.rb`:
67
+
68
+ 1. **Gets the source location** of the user's class file using Ruby's introspection:
69
+ ```ruby
70
+ location_info = Module.const_source_location(base.name)
71
+ source_location = location_info&.first # e.g., "/path/to/models/user.rb"
72
+ ```
73
+
74
+ 2. **Calculates extension file paths** based on conventions:
75
+ ```ruby
76
+ base_dir = File.dirname(location_path) # "/path/to/models"
77
+ model_name = base.name.snake_case # "user"
78
+
79
+ # Look for files like:
80
+ patterns = [
81
+ "/path/to/models/user/safe_dump_*.rb",
82
+ "/path/to/models/user/features/safe_dump_*.rb",
83
+ "/path/to/models/features/safe_dump_*.rb"
84
+ ]
85
+ ```
86
+
87
+ 3. **Loads any matching files** found in those locations
88
+
89
+ ## Why This Timing Matters
90
+
91
+ ```ruby
92
+ class User < Familia::Horreum
93
+ feature :safe_dump # ← Timing is critical here
94
+ end
95
+ ```
96
+
97
+ **What happens in order:**
98
+
99
+ 1. `feature :safe_dump` is called
100
+ 2. Feature system includes `Familia::Features::SafeDump` module
101
+ 3. **Feature is now fully included and stable**
102
+ 4. `post_inclusion_autoload` is called
103
+ 5. Extension files are discovered and loaded
104
+ 6. `safe_dump_fields :name, :email` executes in the extension file
105
+
106
+ ## File Naming Conventions
107
+
108
+ The autoloading system looks for files matching these patterns (in order of precedence):
109
+
110
+ 1. `{model_directory}/{model_name}/{feature_name}_*.rb`
111
+ 2. `{model_directory}/{model_name}/features/{feature_name}_*.rb`
112
+ 3. `{model_directory}/features/{feature_name}_*.rb`
113
+
114
+ ### Examples
115
+
116
+ For a `User` class defined in `app/models/user.rb` with `feature :safe_dump`:
117
+
118
+ ```
119
+ app/models/user/safe_dump_extensions.rb # ← Most specific
120
+ app/models/user/safe_dump_config.rb # ← Also matches pattern
121
+ app/models/user/features/safe_dump_*.rb # ← Feature subdirectory
122
+ app/models/features/safe_dump_*.rb # ← Shared feature configs
123
+ ```
124
+
125
+ ## Complete Example
126
+
127
+ ### Main Model File
128
+
129
+ ```ruby
130
+ # app/models/user.rb
131
+ class User < Familia::Horreum
132
+ field :name
133
+ field :email
134
+ field :password
135
+ field :created_at
136
+
137
+ feature :safe_dump # ← Triggers autoloading
138
+ feature :expiration
139
+ end
140
+ ```
141
+
142
+ ### Safe Dump Extensions
143
+
144
+ ```ruby
145
+ # app/models/user/safe_dump_extensions.rb
146
+ class User
147
+ # Configure which fields are safe to dump in API responses
148
+ safe_dump_fields :name, :email, :created_at
149
+ # Note: :password is intentionally excluded for security
150
+
151
+ def safe_dump_display_name
152
+ "#{name} (#{email})"
153
+ end
154
+ end
155
+ ```
156
+
157
+ ### Expiration Extensions
158
+
159
+ ```ruby
160
+ # app/models/user/expiration_config.rb
161
+ class User
162
+ # Set default TTL for user objects
163
+ expires_in 30.days
164
+
165
+ # Custom expiration logic
166
+ def should_expire?
167
+ !active? && last_login_at < 90.days.ago
168
+ end
169
+ end
170
+ ```
171
+
172
+ ### Result
173
+
174
+ After loading, the `User` class has:
175
+ - `User.safe_dump_field_names` returns `[:name, :email, :created_at]`
176
+ - `User.ttl` returns the configured expiration
177
+ - All extension methods are available on instances
178
+
179
+ ## Key Benefits
180
+
181
+ 1. **Separation of Concerns**: Main model file focuses on core definition, extension files handle feature-specific configuration
182
+
183
+ 2. **Convention Over Configuration**: No manual requires, just follow naming conventions
184
+
185
+ 3. **Safe Timing**: Extension files load after the feature is fully set up
186
+
187
+ 4. **Thread Safe**: No shared state between classes
188
+
189
+ 5. **Discoverable**: Clear file organization makes extensions easy to find
190
+
191
+ ## Why It's Better Than Alternatives
192
+
193
+ - **Manual requires**: Error-prone, verbose, easy to forget
194
+ - **Configuration blocks**: Clutters the main model file
195
+ - **Included hook**: Wrong timing, class not stable yet
196
+ - **Class_eval strings**: Complex, hard to debug and maintain
197
+
198
+ The `post_inclusion_autoload` system provides a clean, automatic, and safe way to extend feature behavior without polluting the main class definitions.
199
+
200
+ ## Implementation Details
201
+
202
+ ### Autoloadable Module
203
+
204
+ Features that support autoloading include the `Familia::Features::Autoloadable` module:
205
+
206
+ ```ruby
207
+ module Familia::Features::SafeDump
208
+ include Familia::Features::Autoloadable # ← Enables autoloading
209
+
210
+ # Feature implementation...
211
+ end
212
+ ```
213
+
214
+ ### Anonymous Class Handling
215
+
216
+ The system gracefully handles edge cases:
217
+
218
+ - **Anonymous classes**: Classes without names (e.g., `Class.new`) are skipped
219
+ - **Eval contexts**: Classes defined in `eval` or irb are skipped
220
+ - **Missing files**: No errors if extension files don't exist
221
+
222
+ ### Error Handling
223
+
224
+ - Missing extension files are silently ignored
225
+ - Syntax errors in extension files propagate normally
226
+ - `NameError` during constant resolution is caught and logged
227
+
228
+ This robust error handling ensures the autoloading system never breaks your application, even with unusual class definitions or missing files.
data/docs/guides/Home.md CHANGED
@@ -23,7 +23,7 @@ Welcome to the comprehensive documentation for Familia v2.0. This wiki covers al
23
23
 
24
24
  ### 🚀 Operations (As Needed)
25
25
 
26
- 9. **[Migration Guide](Migration-Guide.md)** - Upgrading existing fields _(coming soon)_
26
+ 9. **[Migrating Guide](Migrating-Guide.md)** - Upgrading existing fields _(coming soon)_
27
27
  10. **[Key Management](Key-Management.md)** - Rotation and best practices _(coming soon)_
28
28
 
29
29
  ## 🚀 Quick Start Examples
@@ -273,4 +273,4 @@ end
273
273
 
274
274
  - [Security Model](Security-Model) - Understand the cryptographic design
275
275
  - [Key Management](Key-Management) - Rotation and best practices
276
- - [Migration Guide](Migration-Guide) - Upgrade existing fields
276
+ - [Migrating Guide](Migrating-Guide) - Upgrade existing fields
@@ -234,7 +234,7 @@ customer.find_by_name("production-api-key")
234
234
  customer.find_all_by_scope(["read", "write"])
235
235
  ```
236
236
 
237
- ### Migration Guide
237
+ ### Migrating Guide
238
238
  If you have existing code with old syntax, here's how to update it:
239
239
 
240
240
  ```ruby