orfeas_lyra 0.6.0

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 +7 -0
  2. data/CHANGELOG.md +222 -0
  3. data/LICENSE +21 -0
  4. data/README.md +1165 -0
  5. data/Rakefile +728 -0
  6. data/app/controllers/lyra/application_controller.rb +23 -0
  7. data/app/controllers/lyra/dashboard_controller.rb +624 -0
  8. data/app/controllers/lyra/flow_controller.rb +224 -0
  9. data/app/controllers/lyra/privacy_controller.rb +182 -0
  10. data/app/views/lyra/dashboard/audit_trail.html.erb +324 -0
  11. data/app/views/lyra/dashboard/discrepancies.html.erb +125 -0
  12. data/app/views/lyra/dashboard/event_graph_view.html.erb +525 -0
  13. data/app/views/lyra/dashboard/heatmap_view.html.erb +155 -0
  14. data/app/views/lyra/dashboard/index.html.erb +119 -0
  15. data/app/views/lyra/dashboard/model_overview.html.erb +115 -0
  16. data/app/views/lyra/dashboard/projections.html.erb +302 -0
  17. data/app/views/lyra/dashboard/schema.html.erb +283 -0
  18. data/app/views/lyra/dashboard/schema_history.html.erb +78 -0
  19. data/app/views/lyra/dashboard/schema_version.html.erb +340 -0
  20. data/app/views/lyra/dashboard/verification.html.erb +370 -0
  21. data/app/views/lyra/flow/crud_mapping.html.erb +125 -0
  22. data/app/views/lyra/flow/timeline.html.erb +260 -0
  23. data/app/views/lyra/privacy/pii_detection.html.erb +148 -0
  24. data/app/views/lyra/privacy/policy.html.erb +188 -0
  25. data/app/workflows/es_async_mode_workflow.rb +80 -0
  26. data/app/workflows/es_sync_mode_workflow.rb +64 -0
  27. data/app/workflows/hijack_mode_workflow.rb +54 -0
  28. data/app/workflows/lifecycle_workflow.rb +43 -0
  29. data/app/workflows/monitor_mode_workflow.rb +39 -0
  30. data/config/privacy_policies.rb +273 -0
  31. data/config/routes.rb +48 -0
  32. data/lib/lyra/aggregate.rb +131 -0
  33. data/lib/lyra/associations/event_aware.rb +225 -0
  34. data/lib/lyra/command.rb +81 -0
  35. data/lib/lyra/command_handler.rb +155 -0
  36. data/lib/lyra/configuration.rb +124 -0
  37. data/lib/lyra/consistency/read_your_writes.rb +91 -0
  38. data/lib/lyra/correlation.rb +144 -0
  39. data/lib/lyra/dual_view.rb +231 -0
  40. data/lib/lyra/engine.rb +67 -0
  41. data/lib/lyra/event.rb +71 -0
  42. data/lib/lyra/event_analyzer.rb +135 -0
  43. data/lib/lyra/event_flow.rb +449 -0
  44. data/lib/lyra/event_mapper.rb +106 -0
  45. data/lib/lyra/event_store_adapter.rb +72 -0
  46. data/lib/lyra/id_generator.rb +137 -0
  47. data/lib/lyra/interceptors/association_interceptor.rb +169 -0
  48. data/lib/lyra/interceptors/crud_interceptor.rb +543 -0
  49. data/lib/lyra/privacy/gdpr_compliance.rb +161 -0
  50. data/lib/lyra/privacy/pii_detector.rb +85 -0
  51. data/lib/lyra/privacy/pii_masker.rb +66 -0
  52. data/lib/lyra/privacy/policy_integration.rb +253 -0
  53. data/lib/lyra/projection.rb +94 -0
  54. data/lib/lyra/projections/async_projection_job.rb +63 -0
  55. data/lib/lyra/projections/cached_projection.rb +322 -0
  56. data/lib/lyra/projections/cached_relation.rb +757 -0
  57. data/lib/lyra/projections/event_store_reader.rb +127 -0
  58. data/lib/lyra/projections/model_projection.rb +143 -0
  59. data/lib/lyra/schema/diff.rb +331 -0
  60. data/lib/lyra/schema/event_class_registrar.rb +63 -0
  61. data/lib/lyra/schema/generator.rb +190 -0
  62. data/lib/lyra/schema/reporter.rb +188 -0
  63. data/lib/lyra/schema/store.rb +156 -0
  64. data/lib/lyra/schema/validator.rb +100 -0
  65. data/lib/lyra/strict_data_access.rb +363 -0
  66. data/lib/lyra/verification/crud_lifecycle_workflow.rb +456 -0
  67. data/lib/lyra/verification/workflow_generator.rb +540 -0
  68. data/lib/lyra/version.rb +3 -0
  69. data/lib/lyra/visualization/activity_heatmap.rb +215 -0
  70. data/lib/lyra/visualization/event_graph.rb +310 -0
  71. data/lib/lyra/visualization/timeline.rb +398 -0
  72. data/lib/lyra.rb +150 -0
  73. data/lib/tasks/dist.rake +391 -0
  74. data/lib/tasks/gems.rake +185 -0
  75. data/lib/tasks/lyra_schema.rake +231 -0
  76. data/lib/tasks/lyra_workflows.rake +452 -0
  77. data/lib/tasks/public_release.rake +351 -0
  78. data/lib/tasks/stats.rake +175 -0
  79. data/lib/tasks/testbed.rake +479 -0
  80. data/lib/tasks/version.rake +159 -0
  81. metadata +221 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3d1fc3fab85a30b1ed635864d084fee35468b77ff0ad0ce2aec0b0d004fe43e7
4
+ data.tar.gz: e050efff730bc551ef67c3d0107dc5c11fb5c5e8ba433970f188c17d3517e3c5
5
+ SHA512:
6
+ metadata.gz: 5650de44e8ade792aa79bf9fba6e42dd6144e08521a47aa5132e34df94215af9c464faa3d08f87c7d8b98a03649b0f4600e8636a3e334da89100eb0e257a6170
7
+ data.tar.gz: 03d0c2c5419ffddd950f86d8d97dcc3033be8bbd81dda0a8470ef9ab2c4e743c98484788cb74a59a41cf3933c946496f06201d77341b2c9280e58accd26012f7
data/CHANGELOG.md ADDED
@@ -0,0 +1,222 @@
1
+ # Changelog
2
+
3
+ All notable changes to the Lyra project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.6.0] - 2026-01-05
11
+
12
+ ### Added
13
+
14
+ #### Core CRUD-to-Event Sourcing Engine
15
+ - Monitor mode for non-intrusive CRUD operation logging
16
+ - Hijack mode for full event sourcing transformation
17
+ - Rails Event Store integration
18
+ - CRUD interceptor using ActiveRecord callbacks
19
+ - Event mapping layer (CRUD operations → Domain events)
20
+ - Command/Aggregate pattern for hijack mode
21
+ - Dual-view comparison (CRUD state vs Event-sourced state)
22
+ - State reconstruction from event streams
23
+ - Audit trail generation
24
+ - Dashboard API endpoints
25
+ - ERB-based dashboard views
26
+ - Pluggable event store backend
27
+ - Custom aggregate support
28
+ - Custom event mapper support
29
+ - Projection system for read models
30
+ - **Custom Metadata Proc** (`metadata_proc`) - Inject custom metadata into every event:
31
+ - Capture user context from `Current`/`CurrentAttributes`
32
+ - Support for Devise/Warden authentication
33
+ - Thread-safe per-request metadata
34
+ - Graceful error handling (returns `{}` on failure)
35
+ - **Rails Engine Namespaced Model Support** - Properly handle namespaced models:
36
+ - `MyEngine::Order` → `MyEngineOrderCreated` (sanitized event class name)
37
+ - Preserves original namespace in `model_class` attribute
38
+ - Supports deeply nested namespaces (e.g., `MyEngine::Admin::Widget`)
39
+
40
+ #### Privacy Extraction to PAM DSL
41
+ - **PAM DSL as Optional Dependency** - Privacy features gracefully degrade without PAM DSL
42
+ - **PIIDetector Delegation** - `Lyra::Privacy::PIIDetector` delegates to `PamDsl::PIIDetector`
43
+ - **PIIMasker Delegation** - `Lyra::Privacy::PIIMasker` delegates to `PamDsl::PIIMasker`
44
+ - **GDPRCompliance Delegation** - `Lyra::Privacy::GDPRCompliance` delegates to `PamDsl::GDPRCompliance`
45
+ - **PolicyIntegration Enhancements**:
46
+ - `use_detector: true` option (default) - Falls back to PIIDetector for fields not in policy
47
+ - `use_detector: false` - Policy-only mode, no pattern-based detection
48
+ - `pam_dsl_available?` - Check if PAM DSL is loaded
49
+ - `source: :policy` or `source: :detector` in detection results
50
+ - Retention returns `nil` (infinite/manual) when no policy defined
51
+ - 28 new tests for PolicyIntegration
52
+
53
+ #### Unified PII Detection System
54
+ - **Consolidated PIIDetector** - Lyra now delegates to `PamDsl::PIIDetector` for unified PII detection
55
+ - **Partial Matching Mode** (default) - Detects PII in compound field names using word boundaries
56
+ - Matches prefixed fields: `customer_email`, `billing_phone`, `user_name`
57
+ - Matches suffixed fields: `home_phone`, `work_email`, `shipping_address`
58
+ - Supports camelCase suffix boundaries: `emailAddress`, `phoneNumber`
59
+ - **Exact Matching Mode** - Optional strict mode for specific known field names only
60
+ - **Configurable via `PamDsl::PIIDetector.partial_match`** - Toggle between matching modes
61
+ - **New PII Types**:
62
+ - `:identifier` - VAT numbers, tax IDs, passport numbers, AFM (Greek tax ID)
63
+ - `:financial` - IBAN, bank accounts, salary, income
64
+ - `:health` - Medical records, diagnosis, prescriptions
65
+ - `:biometric` - Fingerprints, face ID, retina scans
66
+ - `:location` - GPS coordinates, latitude/longitude
67
+ - **Exclusion Patterns** - Prevents false positives on:
68
+ - Timestamps: `*_at`, `*_on`, `*_date`, `*_time`
69
+ - Counters/amounts: `*_count`, `*_amount`, `*_total`
70
+ - Flags: `*_verified`, `*_confirmed`, `*_enabled`, `is_*`, `has_*`
71
+ - Codes: `*_code` (except `postal_code`, `zip_code`)
72
+ - Security: `*_digest`, `*_token`, `*_hash`, `encrypted_*`
73
+ - **Sensitivity Levels with Legislative Background**:
74
+ - `:public` - Publicly accessible data
75
+ - `:internal` - Low risk, basic protection (GDPR Art. 6)
76
+ - `:confidential` - Medium risk, enhanced protection (GDPR Art. 6, Art. 32)
77
+ - `:restricted` - High risk, special categories (GDPR Art. 9, PCI DSS)
78
+ - **PII Masking** - Type-specific masking for safe display
79
+ - **56 tests with 188 assertions** for comprehensive coverage
80
+
81
+ #### Event Schema Validation System
82
+ - **Schema Store** (`lib/lyra/schema/store.rb`) - Versioned schema file persistence in `db/lyra_schemas/`
83
+ - **Schema Generator** (`lib/lyra/schema/generator.rb`) - Generates schemas from monitored ActiveRecord models
84
+ - **Schema Diff** (`lib/lyra/schema/diff.rb`) - Compares schemas with severity classification (BREAKING, WARNING, INFO)
85
+ - **Schema Validator** (`lib/lyra/schema/validator.rb`) - Enforces schema consistency with strict mode support
86
+ - **Schema Reporter** (`lib/lyra/schema/reporter.rb`) - Human-readable model→event mapping reports
87
+ - **Rake Tasks** for schema management:
88
+ - `rake lyra:schema:create` - Generate initial schema
89
+ - `rake lyra:schema:update` - Create new schema version
90
+ - `rake lyra:schema:verify` - Check for schema changes
91
+ - `rake lyra:schema:report` - Display model→event mappings
92
+ - `rake lyra:schema:history` - Show version history
93
+ - `rake lyra:schema:diff[v1,v2]` - Compare two schema versions
94
+
95
+ #### Event Class Registration for RailsEventStore Compatibility
96
+ - **EventClassRegistrar** (`lib/lyra/schema/event_class_registrar.rb`) - Pre-registers event classes at Rails startup
97
+ - Ensures `Object.const_get()` works when RailsEventStore deserializes events after app restart
98
+ - Registers events from both monitored models configuration and stored schema (for legacy events)
99
+
100
+ #### Event Sourcing with Disabled Projections (Sixth Mode)
101
+ - **CachedRelation** (`lib/lyra/projections/cached_relation.rb`) - ActiveRecord::Relation-like wrapper for in-memory cached data
102
+ - Full query interface: `where`, `order`, `limit`, `offset`, `first`, `last`, `find`, `find_by`
103
+ - Type coercion for string/integer and boolean comparisons (handles params from controllers)
104
+ - Aggregation methods: `sum`, `average`, `minimum`, `maximum`, `pluck`
105
+ - Pagination support: `page`, `per` (Kaminari-compatible)
106
+ - Chainable no-ops for AR methods: `includes`, `joins`, `preload`, `distinct`
107
+ - Rails 8 Arel predicate value extraction support
108
+
109
+ - **AssociationInterceptor** (`lib/lyra/interceptors/association_interceptor.rb`) - Patches AR associations for cache-based loading
110
+ - `BelongsToAssociationPatch` - Intercepts belongs_to association loading
111
+ - `HasOneAssociationPatch` - Intercepts has_one association loading
112
+ - `HasManyAssociationPatch` - Intercepts has_many association loading with count/size support
113
+ - Polymorphic association support for belongs_to
114
+ - Rails 8 async: keyword argument compatibility
115
+
116
+ - **EventStoreReader** (`lib/lyra/projections/event_store_reader.rb`) - Reads and caches entity state from event store
117
+ - Reconstructs current state by replaying events
118
+ - Solid Cache / Rails.cache integration for fast reads
119
+ - Cache warming and invalidation on writes
120
+ - Full query interface via CachedRelation
121
+
122
+ - **CrudInterceptor first/last overrides** - Proper ordering by primary key
123
+ - `Model.first` now orders by `primary_key ASC` before returning first record
124
+ - `Model.last` now orders by `primary_key DESC` before returning first record
125
+
126
+ #### Benchmark Infrastructure
127
+ - **Mode Comparison Benchmark** (`perf/run_mode_comparison_benchmark.rb`)
128
+ - Comprehensive benchmarking across all 7 Lyra modes
129
+ - Scales from 500 to 100,000 operations
130
+ - Four scenarios: CRUD, batch, query, mixed workloads
131
+ - Checkpoint/resume support for long-running benchmarks
132
+ - Automatic chart generation (PNG) via gnuplot
133
+ - JSON, CSV, and Markdown report output
134
+ - **Object allocations tracking** - measures Ruby allocations per operation via GC.stat
135
+ - **Allocations charts** - per-scale bar charts and scaling comparison line chart
136
+ - Warmup phase for JIT/cache priming
137
+ - Cache warming for ES Disabled mode before measurements
138
+
139
+ #### Testing Infrastructure
140
+ - **Comprehensive CachedRelation test suite** (`test/projections/cached_relation_test.rb`)
141
+ - 37 tests covering enumerable, finders, where filtering, type coercion, ordering, pagination, aggregations
142
+ - Isolated unit tests with MockRecord and MockModel classes
143
+
144
+ - **Unified 6-mode test runner** - All Lyra modes tested together
145
+ - `rake lyra:test:all_modes` runs all 6 configurations in single execution
146
+ - Configurations: disabled, monitor, hijack, event_sourcing+sync, event_sourcing+async, event_sourcing+disabled
147
+ - Comprehensive report with pass/fail status per configuration
148
+
149
+ #### Configuration Options
150
+ - `strict_schema` - Fail startup if schema changes detected (recommended for production)
151
+ - `schema_path` - Custom path for schema files (defaults to `db/lyra_schemas/`)
152
+
153
+ #### Database Support
154
+ - PostgreSQL primary database support
155
+ - SQLite alternative for small deployments
156
+
157
+ #### Example Application
158
+ - Aegean E-Pay Testbed with student registrations
159
+ - Payment processing with multiple channels
160
+ - Complete database schema and seed data
161
+
162
+ ### Fixed
163
+
164
+ #### StrictDataAccess Compatibility with Event Sourcing Mode
165
+ - Fixed conflict between `StrictDataAccess` and ES mode sync projections
166
+ - Projections now correctly bypass strict access checks (using `Thread.current[:lyra_bypass_strict_access]`)
167
+ - This is safe because projections are internal Lyra operations with events already recorded
168
+ - Fixed require order in `lib/lyra.rb` to load `strict_data_access` before projections
169
+
170
+ #### CachedRelation Exception Handling in ES Disabled Mode
171
+ - Fixed `CachedRelation.method_missing` swallowing `StrictDataAccessViolation` exceptions
172
+ - `update_all` and `delete_all` on `CachedRelation` now correctly raise violations when strict mode is enabled
173
+ - The generic scope delegation rescue clause now re-raises framework violations instead of suppressing them
174
+
175
+ #### Automatic Event Creation for `dependent: :nullify` Operations
176
+ - When `dependent: :nullify` triggers `update_all(foreign_key: nil)`, Lyra now creates events for affected child records
177
+ - This ensures the event stream captures foreign key nullification when parent records are destroyed
178
+ - Events include `nullify_source: "dependent_association"` in metadata for traceability
179
+ - Works in both DB-backed modes (plucks from DB) and ES Disabled mode (queries event store cache)
180
+ - Resolves event stream completeness gap where child state changes were previously invisible
181
+
182
+ #### Automatic Event Creation for Callback-Bypassing Operations
183
+ - `update_columns` and `update_column` now create events when allowed (strict mode off or bypassed)
184
+ - `delete` now creates a "Destroyed" event when allowed
185
+ - Events include `bypass_source: "update_columns"` or `bypass_source: "delete"` in metadata
186
+ - This ensures the event stream remains complete even when developers intentionally bypass callbacks
187
+ - Only applies to Lyra-monitored models when mode is not `:disabled`
188
+
189
+ #### Test Isolation Issues
190
+ - Fixed test contamination between controller and integration tests
191
+ - Integration tests now create their own event store if none exists
192
+ - Added `create_event_store` helper to `multi_mode_integration_test.rb` and `event_sourcing_mode_test.rb`
193
+ - Fixed `assert_not_nil` → `refute_nil` (Minitest syntax)
194
+ - Added proper `Lyra.config.monitor_model` calls for correct event naming
195
+
196
+ ### Changed
197
+
198
+ #### Test Coverage Configuration
199
+ - Increased SimpleCov minimum coverage thresholds (50% line, 47% branch)
200
+ - Added coverage groups for Projections and Schema modules
201
+ - All 584 tests now pass with proper isolation
202
+ - Added comprehensive tests for Schema::Diff (column limit changes, event renames, config changes)
203
+ - Added comprehensive tests for Schema::Reporter (report generation, PII summaries, model mappings)
204
+ - Added comprehensive tests for Visualization::Timeline (Mermaid, ASCII, D3.js output)
205
+ - Added comprehensive tests for EventAnalyzer (timeline, operations, privacy analysis)
206
+ - Added comprehensive tests for CommandHandler (event data, metadata, error handling)
207
+ - Added comprehensive tests for DualView (value normalization, type coercion)
208
+
209
+ ### Core Components
210
+ - `CrudInterceptor` - ActiveRecord callback integration
211
+ - `EventMapper` - CRUD to event mapping
212
+ - `Command` - Command pattern implementation
213
+ - `CommandHandler` - Command processing
214
+ - `Aggregate` - Domain aggregate base class
215
+ - `GenericAggregate` - Default aggregate for monitored models
216
+ - `Projection` - Read model projection base
217
+ - `StateProjection` - State reconstruction
218
+ - `AuditProjection` - Audit trail generation
219
+ - `DualView` - CRUD vs Event-sourced comparison
220
+ - `StateAnalyzer` - State analysis and recommendations
221
+ - `EventStoreAdapter` - Pluggable event storage
222
+ - `Configuration` - Centralized configuration
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019-2026 Michail Pantelelis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.