familia 2.0.0.pre5 → 2.0.0.pre6
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.
- checksums.yaml +4 -4
- data/CLAUDE.md +8 -5
- data/Gemfile +1 -1
- data/Gemfile.lock +4 -3
- data/docs/wiki/API-Reference.md +95 -18
- data/docs/wiki/Connection-Pooling-Guide.md +437 -0
- data/docs/wiki/Encrypted-Fields-Overview.md +40 -3
- data/docs/wiki/Expiration-Feature-Guide.md +596 -0
- data/docs/wiki/Feature-System-Guide.md +600 -0
- data/docs/wiki/Features-System-Developer-Guide.md +892 -0
- data/docs/wiki/Field-System-Guide.md +784 -0
- data/docs/wiki/Home.md +72 -15
- data/docs/wiki/Implementation-Guide.md +126 -33
- data/docs/wiki/Quantization-Feature-Guide.md +721 -0
- data/docs/wiki/RelatableObjects-Guide.md +563 -0
- data/docs/wiki/Security-Model.md +65 -25
- data/docs/wiki/Transient-Fields-Guide.md +280 -0
- data/lib/familia/base.rb +1 -1
- data/lib/familia/data_type/types/counter.rb +38 -0
- data/lib/familia/data_type/types/hashkey.rb +18 -0
- data/lib/familia/data_type/types/lock.rb +43 -0
- data/lib/familia/data_type/types/string.rb +9 -2
- data/lib/familia/data_type.rb +2 -2
- data/lib/familia/encryption/encrypted_data.rb +137 -0
- data/lib/familia/encryption/manager.rb +21 -4
- data/lib/familia/encryption/providers/aes_gcm_provider.rb +20 -0
- data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +20 -0
- data/lib/familia/encryption.rb +1 -1
- data/lib/familia/errors.rb +17 -3
- data/lib/familia/features/encrypted_fields/concealed_string.rb +295 -0
- data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +94 -26
- data/lib/familia/features/expiration.rb +1 -1
- data/lib/familia/features/quantization.rb +1 -1
- data/lib/familia/features/safe_dump.rb +1 -1
- data/lib/familia/features/transient_fields/redacted_string.rb +1 -1
- data/lib/familia/features/transient_fields.rb +1 -1
- data/lib/familia/field_type.rb +5 -2
- data/lib/familia/horreum/{connection.rb → core/connection.rb} +2 -8
- data/lib/familia/horreum/{database_commands.rb → core/database_commands.rb} +14 -3
- data/lib/familia/horreum/core/serialization.rb +535 -0
- data/lib/familia/horreum/{utils.rb → core/utils.rb} +0 -2
- data/lib/familia/horreum/core.rb +21 -0
- data/lib/familia/horreum/{settings.rb → shared/settings.rb} +0 -2
- data/lib/familia/horreum/{definition_methods.rb → subclass/definition.rb} +44 -28
- data/lib/familia/horreum/{management_methods.rb → subclass/management.rb} +9 -8
- data/lib/familia/horreum/{related_fields_management.rb → subclass/related_fields_management.rb} +15 -10
- data/lib/familia/horreum.rb +17 -17
- data/lib/familia/version.rb +1 -1
- data/lib/familia.rb +1 -1
- data/try/core/create_method_try.rb +240 -0
- data/try/core/database_consistency_try.rb +299 -0
- data/try/core/errors_try.rb +25 -4
- data/try/core/familia_try.rb +1 -1
- data/try/core/persistence_operations_try.rb +297 -0
- data/try/data_types/counter_try.rb +93 -0
- data/try/data_types/lock_try.rb +133 -0
- data/try/debugging/debug_aad_process.rb +82 -0
- data/try/debugging/debug_concealed_internal.rb +59 -0
- data/try/debugging/debug_concealed_reveal.rb +61 -0
- data/try/debugging/debug_context_aad.rb +68 -0
- data/try/debugging/debug_context_simple.rb +80 -0
- data/try/debugging/debug_cross_context.rb +62 -0
- data/try/debugging/debug_database_load.rb +64 -0
- data/try/debugging/debug_encrypted_json_check.rb +53 -0
- data/try/debugging/debug_encrypted_json_step_by_step.rb +62 -0
- data/try/debugging/debug_exists_lifecycle.rb +54 -0
- data/try/debugging/debug_field_decrypt.rb +74 -0
- data/try/debugging/debug_fresh_cross_context.rb +73 -0
- data/try/debugging/debug_load_path.rb +66 -0
- data/try/debugging/debug_method_definition.rb +46 -0
- data/try/debugging/debug_method_resolution.rb +41 -0
- data/try/debugging/debug_minimal.rb +24 -0
- data/try/debugging/debug_provider.rb +68 -0
- data/try/debugging/debug_secure_behavior.rb +73 -0
- data/try/debugging/debug_string_class.rb +46 -0
- data/try/debugging/debug_test.rb +46 -0
- data/try/debugging/debug_test_design.rb +80 -0
- data/try/encryption/encryption_core_try.rb +3 -3
- data/try/features/encrypted_fields_core_try.rb +19 -11
- data/try/features/encrypted_fields_integration_try.rb +66 -70
- data/try/features/encrypted_fields_no_cache_security_try.rb +22 -8
- data/try/features/encrypted_fields_security_try.rb +151 -144
- data/try/features/encryption_fields/aad_protection_try.rb +108 -23
- data/try/features/encryption_fields/concealed_string_core_try.rb +250 -0
- data/try/features/encryption_fields/context_isolation_try.rb +29 -8
- data/try/features/encryption_fields/error_conditions_try.rb +6 -6
- data/try/features/encryption_fields/fresh_key_derivation_try.rb +20 -14
- data/try/features/encryption_fields/fresh_key_try.rb +27 -22
- data/try/features/encryption_fields/key_rotation_try.rb +16 -10
- data/try/features/encryption_fields/nonce_uniqueness_try.rb +15 -13
- data/try/features/encryption_fields/secure_by_default_behavior_try.rb +310 -0
- data/try/features/encryption_fields/thread_safety_try.rb +6 -6
- data/try/features/encryption_fields/universal_serialization_safety_try.rb +174 -0
- data/try/features/feature_dependencies_try.rb +3 -3
- data/try/features/transient_fields_core_try.rb +1 -1
- data/try/features/transient_fields_integration_try.rb +1 -1
- data/try/helpers/test_helpers.rb +25 -0
- data/try/horreum/enhanced_conflict_handling_try.rb +1 -1
- data/try/horreum/initialization_try.rb +1 -1
- data/try/horreum/relations_try.rb +1 -1
- data/try/horreum/serialization_persistent_fields_try.rb +8 -8
- data/try/horreum/serialization_try.rb +39 -4
- data/try/models/customer_safe_dump_try.rb +1 -1
- data/try/models/customer_try.rb +1 -1
- metadata +51 -10
- data/TEST_COVERAGE.md +0 -40
- data/lib/familia/horreum/serialization.rb +0 -473
data/docs/wiki/Home.md
CHANGED
@@ -1,46 +1,103 @@
|
|
1
|
-
# Familia
|
1
|
+
# Familia v2.0 Documentation
|
2
2
|
|
3
|
-
Welcome to the
|
3
|
+
Welcome to the comprehensive documentation for Familia v2.0. This wiki covers all major features including security, connection management, architecture, and object relationships.
|
4
4
|
|
5
5
|
## 📚 Documentation Structure
|
6
6
|
|
7
|
-
###
|
7
|
+
### 🔐 Security & Data Protection
|
8
8
|
|
9
|
-
1. **[Encrypted Fields Overview](Encrypted-Fields-Overview.md)** -
|
9
|
+
1. **[Encrypted Fields Overview](Encrypted-Fields-Overview.md)** - Persistent encrypted storage with modular providers
|
10
|
+
2. **[Transient Fields Guide](Transient-Fields-Guide.md)** - Non-persistent secure data handling with RedactedString
|
11
|
+
3. **[Security Model](Security-Model.md)** - Cryptographic design and Ruby memory limitations
|
10
12
|
|
11
|
-
|
13
|
+
### 🏗️ Architecture & System Design
|
12
14
|
|
13
|
-
|
15
|
+
4. **[Feature System Guide](Feature-System-Guide.md)** - Modular architecture with dependencies and conflict resolution _(new!)_
|
16
|
+
5. **[Connection Pooling Guide](Connection-Pooling-Guide.md)** - Provider pattern for efficient Redis/Valkey pooling _(new!)_
|
17
|
+
6. **[RelatableObjects Guide](RelatableObjects-Guide.md)** - Object relationships and ownership system _(new!)_
|
14
18
|
|
15
|
-
###
|
19
|
+
### 🛠️ Implementation & Usage
|
16
20
|
|
17
|
-
|
21
|
+
7. **[Implementation Guide](Implementation-Guide.md)** - Configuration, providers, and advanced usage
|
22
|
+
8. **[API Reference](API-Reference.md)** - Complete class and method documentation
|
18
23
|
|
19
|
-
### Operations (As Needed)
|
24
|
+
### 🚀 Operations (As Needed)
|
20
25
|
|
21
|
-
|
22
|
-
|
26
|
+
9. **[Migration Guide](Migration-Guide.md)** - Upgrading existing fields _(coming soon)_
|
27
|
+
10. **[Key Management](Key-Management.md)** - Rotation and best practices _(coming soon)_
|
23
28
|
|
24
|
-
## 🚀 Quick Start
|
29
|
+
## 🚀 Quick Start Examples
|
25
30
|
|
31
|
+
### Encrypted Fields (Persistent)
|
26
32
|
```ruby
|
27
|
-
# 1. Add encrypted field to your model
|
28
33
|
class User < Familia::Horreum
|
34
|
+
feature :encrypted_fields
|
29
35
|
encrypted_field :secret_recipe
|
30
36
|
end
|
31
37
|
|
32
|
-
#
|
38
|
+
# Configure encryption
|
33
39
|
Familia.configure do |config|
|
34
40
|
config.encryption_keys = { v1: ENV['FAMILIA_ENCRYPTION_KEY'] }
|
35
41
|
config.current_key_version = :v1
|
36
42
|
end
|
37
43
|
|
38
|
-
# 3. Use like any other field
|
39
44
|
user = User.new(secret_recipe: "donna's cookies")
|
40
45
|
user.save
|
41
46
|
user.secret_recipe # => "donna's cookies" (automatically decrypted)
|
42
47
|
```
|
43
48
|
|
49
|
+
### Feature System (Modular)
|
50
|
+
```ruby
|
51
|
+
class Customer < Familia::Horreum
|
52
|
+
feature :safe_dump # API-safe serialization
|
53
|
+
feature :expiration # TTL support
|
54
|
+
feature :encrypted_fields # Secure storage
|
55
|
+
|
56
|
+
field :name, :email
|
57
|
+
encrypted_field :api_key
|
58
|
+
default_expiration 24.hours
|
59
|
+
safe_dump_fields :name, :email
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
### Connection Pooling (Performance)
|
64
|
+
```ruby
|
65
|
+
# Configure connection provider for multi-database pooling
|
66
|
+
Familia.connection_provider = lambda do |uri|
|
67
|
+
parsed = URI.parse(uri)
|
68
|
+
pool_key = "#{parsed.host}:#{parsed.port}/#{parsed.db || 0}"
|
69
|
+
|
70
|
+
@pools[pool_key] ||= ConnectionPool.new(size: 10) do
|
71
|
+
Redis.new(host: parsed.host, port: parsed.port, db: parsed.db || 0)
|
72
|
+
end
|
73
|
+
|
74
|
+
@pools[pool_key].with { |conn| conn }
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
### Object Relationships (RelatableObjects)
|
79
|
+
```ruby
|
80
|
+
class Customer < Familia::Horreum
|
81
|
+
feature :relatable_object
|
82
|
+
self.logical_database = 0
|
83
|
+
field :name, :email
|
84
|
+
end
|
85
|
+
|
86
|
+
class Domain < Familia::Horreum
|
87
|
+
feature :relatable_object
|
88
|
+
self.logical_database = 0
|
89
|
+
field :name, :dns_zone
|
90
|
+
end
|
91
|
+
|
92
|
+
# Create objects with automatic ID generation
|
93
|
+
customer = Customer.new(name: "Acme Corp")
|
94
|
+
domain = Domain.new(name: "acme.com")
|
95
|
+
|
96
|
+
# Establish ownership
|
97
|
+
Customer.owners.set(domain.objid, customer.objid)
|
98
|
+
domain.owner?(customer) # => true
|
99
|
+
```
|
100
|
+
|
44
101
|
|
45
102
|
## Related Resources
|
46
103
|
|
@@ -2,48 +2,88 @@
|
|
2
2
|
|
3
3
|
## Architecture Overview
|
4
4
|
|
5
|
-
The encrypted fields feature
|
5
|
+
The encrypted fields feature uses a modular provider system with field transformation hooks:
|
6
6
|
|
7
7
|
```
|
8
|
-
User Input → Field Setter →
|
9
|
-
Redis →
|
8
|
+
User Input → Field Setter → Provider Selection → Encryption → Redis/Valkey
|
9
|
+
Redis/Valkey → Algorithm Detection → Decryption → Field Getter → User Output
|
10
|
+
```
|
11
|
+
|
12
|
+
### Provider Architecture
|
13
|
+
|
14
|
+
```
|
15
|
+
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
16
|
+
│ Manager │ │ Registry │ │ Providers │
|
17
|
+
│ │ │ │ │ │
|
18
|
+
│ - encrypt() │───→│ - get() │───→│ XChaCha20Poly │
|
19
|
+
│ - decrypt() │ │ - register() │ │ AES-GCM │
|
20
|
+
│ - derive_key() │ │ - priority │ │ (Future: More) │
|
21
|
+
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
10
22
|
```
|
11
23
|
|
12
24
|
## Core Components
|
13
25
|
|
14
|
-
### 1.
|
26
|
+
### 1. Registry System
|
27
|
+
|
28
|
+
The Registry manages available encryption providers and selects the best one:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
module Familia::Encryption::Registry
|
32
|
+
# Auto-register available providers by priority
|
33
|
+
def self.setup!
|
34
|
+
|
35
|
+
# Get provider instance by algorithm
|
36
|
+
def self.get(algorithm)
|
37
|
+
|
38
|
+
# Get highest-priority available provider
|
39
|
+
def self.default_provider
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
### 2. Manager Class
|
15
44
|
|
16
|
-
|
45
|
+
The Manager handles encryption/decryption operations with provider delegation:
|
17
46
|
|
18
47
|
```ruby
|
19
|
-
|
20
|
-
|
21
|
-
:
|
22
|
-
|
23
|
-
|
24
|
-
)
|
48
|
+
class Familia::Encryption::Manager
|
49
|
+
# Use specific algorithm or auto-select best
|
50
|
+
def initialize(algorithm: nil)
|
51
|
+
|
52
|
+
# Encrypt with context-specific key derivation
|
53
|
+
def encrypt(plaintext, context:, additional_data: nil)
|
54
|
+
|
55
|
+
# Decrypt with automatic algorithm detection
|
56
|
+
def decrypt(encrypted_json, context:, additional_data: nil)
|
57
|
+
end
|
25
58
|
```
|
26
59
|
|
27
|
-
###
|
60
|
+
### 3. Provider Interface
|
28
61
|
|
29
|
-
|
62
|
+
All providers implement a common interface:
|
30
63
|
|
31
64
|
```ruby
|
32
|
-
|
33
|
-
|
34
|
-
def self.encrypt(plaintext, context:, additional_data: nil)
|
65
|
+
class Provider
|
66
|
+
ALGORITHM = 'algorithm-name'
|
35
67
|
|
36
|
-
#
|
37
|
-
def self.
|
68
|
+
def self.available? # Check if dependencies are met
|
69
|
+
def self.priority # Higher = preferred (XChaCha20: 100, AES: 50)
|
70
|
+
|
71
|
+
def encrypt(plaintext, key, additional_data)
|
72
|
+
def decrypt(ciphertext, key, nonce, auth_tag, additional_data)
|
73
|
+
def derive_key(master_key, context)
|
74
|
+
def generate_nonce
|
38
75
|
end
|
39
76
|
```
|
40
77
|
|
41
|
-
###
|
78
|
+
### 4. Key Derivation
|
42
79
|
|
43
|
-
Each field gets a unique encryption key:
|
80
|
+
Each field gets a unique encryption key using provider-specific methods:
|
44
81
|
|
45
82
|
```
|
46
|
-
Master Key + Field Context →
|
83
|
+
Master Key + Field Context → Provider KDF → Field-Specific Key
|
84
|
+
|
85
|
+
XChaCha20-Poly1305: BLAKE2b with personalization
|
86
|
+
AES-256-GCM: HKDF-SHA256
|
47
87
|
```
|
48
88
|
|
49
89
|
## Implementation Steps
|
@@ -79,14 +119,28 @@ Familia::Encryption.validate_configuration!
|
|
79
119
|
### Step 3: Generate Keys
|
80
120
|
|
81
121
|
```bash
|
82
|
-
# Generate a secure key
|
83
|
-
$
|
122
|
+
# Generate a secure 256-bit key (32 bytes)
|
123
|
+
$ openssl rand -base64 32
|
84
124
|
# => base64_encoded_key_here
|
85
125
|
|
86
126
|
# Add to environment
|
87
127
|
$ echo "FAMILIA_ENCRYPTION_KEY_V1=base64_encoded_key_here" >> .env
|
88
128
|
```
|
89
129
|
|
130
|
+
### Step 4: Install Optional Dependencies
|
131
|
+
|
132
|
+
For best security and performance, install RbNaCl:
|
133
|
+
|
134
|
+
```bash
|
135
|
+
# Add to Gemfile
|
136
|
+
gem 'rbnacl', '~> 7.1', '>= 7.1.1'
|
137
|
+
|
138
|
+
# Install
|
139
|
+
$ bundle install
|
140
|
+
```
|
141
|
+
|
142
|
+
Without RbNaCl, Familia falls back to OpenSSL AES-256-GCM (still secure but lower priority).
|
143
|
+
|
90
144
|
## Advanced Usage
|
91
145
|
|
92
146
|
### Custom Field Names
|
@@ -118,24 +172,63 @@ customers = Customer.batch_create([
|
|
118
172
|
])
|
119
173
|
```
|
120
174
|
|
175
|
+
## Provider-Specific Features
|
176
|
+
|
177
|
+
### XChaCha20-Poly1305 Provider (Recommended)
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
# Enable with RbNaCl gem
|
181
|
+
gem 'rbnacl', '~> 7.1'
|
182
|
+
|
183
|
+
# Benefits:
|
184
|
+
# - Extended nonce (192 bits vs 96 bits)
|
185
|
+
# - Better resistance to nonce reuse
|
186
|
+
# - BLAKE2b key derivation with personalization
|
187
|
+
# - Priority: 100 (highest)
|
188
|
+
```
|
189
|
+
|
190
|
+
### AES-256-GCM Provider (Fallback)
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
# Always available with OpenSSL
|
194
|
+
# - 256-bit keys, 96-bit nonces
|
195
|
+
# - HKDF-SHA256 key derivation
|
196
|
+
# - Priority: 50
|
197
|
+
# - Good compatibility, proven security
|
198
|
+
```
|
199
|
+
|
121
200
|
## Performance Optimization
|
122
201
|
|
123
|
-
###
|
202
|
+
### Provider Benchmarking
|
124
203
|
|
125
204
|
```ruby
|
126
|
-
#
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
205
|
+
# Compare provider performance
|
206
|
+
results = Familia::Encryption.benchmark(iterations: 1000)
|
207
|
+
puts results
|
208
|
+
# => {
|
209
|
+
# "xchacha20poly1305" => { time: 0.45, ops_per_sec: 4444, priority: 100 },
|
210
|
+
# "aes-256-gcm" => { time: 0.52, ops_per_sec: 3846, priority: 50 }
|
211
|
+
# }
|
212
|
+
```
|
213
|
+
|
214
|
+
### Key Derivation Monitoring
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
# Monitor key derivations (should increment with each operation)
|
218
|
+
puts Familia::Encryption.derivation_count.value
|
219
|
+
# => 42
|
220
|
+
|
221
|
+
# Reset counter for testing
|
222
|
+
Familia::Encryption.reset_derivation_count!
|
132
223
|
```
|
133
224
|
|
134
225
|
### Memory Management
|
135
226
|
|
136
|
-
|
137
|
-
|
138
|
-
-
|
227
|
+
**⚠️ Important**: Ruby provides no memory safety guarantees. See security warnings in provider files.
|
228
|
+
|
229
|
+
- Keys are cleared from variables after use (best effort)
|
230
|
+
- No protection against memory dumps or GC copying
|
231
|
+
- Plaintext exists in Ruby strings during processing
|
139
232
|
|
140
233
|
## Testing
|
141
234
|
|