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
data/README.md ADDED
@@ -0,0 +1,1165 @@
1
+ # Lyra
2
+
3
+ **CRUD to Event Sourcing Transformation Engine**
4
+
5
+ *Part of the ORFEAS (Object-Relational to Event-Sourcing Architecture) Framework*
6
+
7
+ ## Author
8
+
9
+ **Michail Pantelelis** (mpantel@aegean.gr)
10
+ PhD Candidate, University of the Aegean
11
+ Department of Information and Communication Systems Engineering
12
+
13
+ ---
14
+
15
+ ## Table of Contents
16
+
17
+ 1. [Overview](#overview)
18
+ 2. [The Problem](#the-problem)
19
+ 3. [The Solution: ORFEAS Framework](#the-solution-orfeas-framework)
20
+ 4. [Key Features](#key-features)
21
+ 5. [Architecture](#architecture)
22
+ 6. [Components](#components)
23
+ 7. [Installation](#installation)
24
+ 8. [Quick Start](#quick-start)
25
+ 9. [Usage Guide](#usage-guide)
26
+ 10. [Example Application](#example-application)
27
+ 11. [Benefits](#benefits)
28
+ 12. [Documentation](#documentation)
29
+ 13. [Research Foundation](#research-foundation)
30
+ 14. [Development Methodology](#development-methodology)
31
+ 15. [Contributing](#contributing)
32
+ 16. [Citation](#citation)
33
+ 17. [Support](#support)
34
+
35
+ ---
36
+
37
+ ## Overview
38
+
39
+ Lyra is a Rails engine that enables **gradual, non-intrusive transformation** of traditional CRUD (Create, Read, Update, Delete) operations into Event Sourcing architectures, with built-in privacy compliance capabilities. It is the practical implementation of the **ORFEAS (Object-Relational to Event-Sourcing Architecture)** framework, developed as part of a PhD thesis addressing the fundamental challenge of bridging 40+ years of ORM dominance with modern event-driven, GDPR-compliant application architectures.
40
+
41
+ ### What Makes Lyra Unique?
42
+
43
+ - **Dual-Mode Operation**: Monitor existing applications non-intrusively, then gradually transform to full event sourcing
44
+ - **Formal Mathematical Foundation**: Built on Petri nets (P/T nets for verification, CPNs for advanced modeling) and matrix analysis for rigorous CRUD-to-event mapping
45
+ - **Privacy-First Design**: Integrated Privacy Attribute Matrix (PAM) for GDPR compliance
46
+ - **Zero-Downtime Migration**: Maintain CRUD as a safety net while transitioning to event sourcing
47
+ - **Research-Backed**: Grounded in peer-reviewed research on event sourcing patterns and privacy preservation
48
+
49
+ ---
50
+
51
+ ## The Problem
52
+
53
+ Modern enterprise systems face a critical architectural challenge:
54
+
55
+ ### The Legacy Dilemma
56
+ - **40+ Years of ORM Investment**: Decades of business logic encoded in Object-Relational Mapping systems
57
+ - **CRUD Limitations**: State-based systems lose behavioral history and temporal context
58
+ - **Privacy Requirements**: GDPR mandates comprehensive data lineage and processing transparency
59
+ - **Migration Risk**: Complete rewrites from CRUD to Event Sourcing are expensive and risky
60
+
61
+ ### The Event Sourcing Promise
62
+ - **Complete Audit Trails**: Every state change recorded as an immutable event
63
+ - **Temporal Queries**: Query system state at any point in time
64
+ - **Behavioral Analysis**: Understand *how* and *why* state changes occurred
65
+ - **Microservices Alignment**: Natural fit for distributed, event-driven architectures
66
+
67
+ ### The Gap
68
+ **There is no formal, proven method for gradually migrating CRUD systems to event sourcing while maintaining operational safety and privacy compliance.**
69
+
70
+ ---
71
+
72
+ ## The Solution: ORFEAS Framework
73
+
74
+ The **ORFEAS (Object-Relational to Event-Sourcing Architecture)** framework provides:
75
+
76
+ 1. **Formal Mathematical Models**: Petri nets map CRUD operations to event sequences with formal verification (P/T nets for structural proofs, CPNs optional for data modeling)
77
+ 2. **Privacy Compliance**: Privacy Attribute Matrix (PAM) ensures GDPR compliance throughout the transformation
78
+ 3. **Gradual Migration Path**: Two operational modes support safe, incremental transition
79
+ 4. **Dual-View Analysis**: Compare CRUD and event-sourced views to verify correctness
80
+ 5. **Practical Tooling**: Lyra implements ORFEAS as a production-ready Rails engine
81
+
82
+ ### Theoretical Foundation
83
+
84
+ ORFEAS is built on three pillars:
85
+
86
+ 1. **Petri Nets**: Model CRUD-to-event transformations (P/T nets for verification proofs; CPNs with tokens, guards, and arc expressions for advanced data modeling)
87
+ 2. **Matrix Analysis**: Complementary linear algebra approach for causation and lineage tracking
88
+ 3. **Privacy Attribute Matrix (PAM)**: DSL for declaring field-level privacy policies and transformations
89
+
90
+ [Read the complete theoretical foundation →](docs/ORFEAS_FRAMEWORK_OVERVIEW.md)
91
+
92
+ ---
93
+
94
+ ## Key Features
95
+
96
+ ### Operational Features
97
+ - ✅ **Non-intrusive Monitoring** - Works with existing Rails applications without code changes
98
+ - ✅ **Dual Operational Modes** - Monitor or hijack CRUD operations
99
+ - ✅ **Automatic Event Mapping** - CRUD operations automatically mapped to domain events
100
+ - ✅ **State Reconstruction** - Rebuild state from event streams
101
+ - ✅ **Dual-View Dashboard** - Compare CRUD state vs event-sourced state
102
+
103
+ ### Technical Features
104
+ - ✅ **Rails Event Store Integration** - Built on proven event sourcing infrastructure
105
+ - ✅ **Pluggable Event Backends** - Support for custom event storage (Kafka, EventStoreDB)
106
+ - ✅ **Aggregate Support** - Custom domain aggregates for complex business logic
107
+ - ✅ **Command/Query Separation** - CQRS-ready architecture
108
+ - ✅ **Event Versioning** - Support for event schema evolution
109
+
110
+ ### Privacy & Compliance
111
+ - ✅ **Privacy Attribute Matrix (PAM)** - Built-in PAM DSL for defining privacy policies
112
+ - ✅ **GDPR Compliance** - Purpose-based access control, consent management, retention policies
113
+ - ✅ **PII Detection & Transformation** - Automatic PII field identification and transformation
114
+ - ✅ **Audit Trails** - Complete lineage tracking for regulatory compliance
115
+
116
+ ---
117
+
118
+ ## Architecture
119
+
120
+ ### High-Level Architecture
121
+
122
+ ```
123
+ ┌─────────────────────────────────────────────────────────────┐
124
+ │ Rails Application │
125
+ ├─────────────────────────────────────────────────────────────┤
126
+ │ │
127
+ │ ActiveRecord Models (with monitor_with_lyra) │
128
+ │ │ │
129
+ │ ▼ │
130
+ │ ┌──────────────────┐ │
131
+ │ │ CRUD Interceptor │ │
132
+ │ └────────┬─────────┘ │
133
+ │ │ │
134
+ │ ┌────┴────┐ │
135
+ │ │ │ │
136
+ │ MONITOR HIJACK │
137
+ │ MODE MODE │
138
+ │ │ │ │
139
+ │ ▼ ▼ │
140
+ │ ┌─────┐ ┌─────────┐ │
141
+ │ │ Log │ │ Command │ │
142
+ │ │Event│ │ Handler │ │
143
+ │ └──┬──┘ └────┬────┘ │
144
+ │ │ │ │
145
+ │ └─────┬─────┘ │
146
+ │ ▼ │
147
+ │ ┌─────────────────┐ │
148
+ │ │ Event Store │ │
149
+ │ │ (Rails Event │ │
150
+ │ │ Store) │ │
151
+ │ └─────────────────┘ │
152
+ │ │ │
153
+ │ ▼ │
154
+ │ ┌─────────────────┐ │
155
+ │ │ Aggregates & │ │
156
+ │ │ Projections │ │
157
+ │ └─────────────────┘ │
158
+ │ │
159
+ └─────────────────────────────────────────────────────────────┘
160
+ ```
161
+
162
+ ### Operational Modes
163
+
164
+ #### 1. Monitor Mode (Non-intrusive)
165
+ - Observes CRUD operations and logs them as domain events
166
+ - **No changes** to application behavior
167
+ - Perfect for **analysis and planning** migration
168
+ - Zero risk to production systems
169
+
170
+ #### 2. Hijack Mode (Transformative)
171
+ - Intercepts CRUD operations and routes through event sourcing
172
+ - Replaces traditional relational backend
173
+ - Maintains CRUD interface for **backward compatibility**
174
+ - Full event sourcing benefits
175
+
176
+ [See detailed architecture documentation →](docs/ARCHITECTURE.md)
177
+
178
+ ---
179
+
180
+ ## Components
181
+
182
+ ### Lyra Engine (Core)
183
+ The main Rails engine providing:
184
+ - CRUD interception and monitoring
185
+ - Event mapping and publishing
186
+ - Dual-view analysis
187
+ - Command/Query handlers
188
+ - State reconstruction
189
+
190
+ ### PetriFlow Gem
191
+ Complete Petri net and Colored Petri Net library:
192
+ - Core Petri net components (places, transitions, arcs)
193
+ - Colored extensions (guards, arc expressions, token types)
194
+ - Matrix analysis (CRUD-event mapping, causation, lineage)
195
+ - Visualization (GraphViz, Mermaid, ASCII)
196
+ - Formal verification (reachability, boundedness, liveness)
197
+ - Export functionality (PNML, CPN Tools, JSON, YAML)
198
+
199
+ [Read the PetriFlow documentation →](gems/petri_flow/README.md)
200
+
201
+ ### PAM DSL Gem
202
+ Privacy Attribute Matrix Domain-Specific Language:
203
+ - Field-level PII classification with sensitivity levels
204
+ - Purpose-based access control aligned with GDPR
205
+ - Retention policies with field-level granularity
206
+ - Consent management with expiration tracking
207
+ - Data transformation for different contexts (display, logging, API)
208
+
209
+ [Read the PAM DSL documentation →](gems/pam_dsl/README.md)
210
+
211
+ ### Monorepo Structure
212
+
213
+ This repository is organized as a monorepo:
214
+ - **`/` (root)** - Lyra Rails engine
215
+ - **`gems/petri_flow/`** - PetriFlow Petri net library
216
+ - **`gems/pam_dsl/`** - PAM DSL privacy policy language
217
+ - **`docs/`** - Theoretical documentation
218
+ - **`docs-site/`** - Jekyll documentation site
219
+ - **`examples/`** - Example applications
220
+
221
+ [See complete monorepo structure →](docs/MONOREPO.md)
222
+
223
+ ---
224
+
225
+ ## Installation
226
+
227
+ ### Prerequisites
228
+
229
+ - Ruby 3.4.5+ (tested up to Ruby 4.0) and Rails 8.0+
230
+ - PostgreSQL 14+ (recommended for Rails Event Store)
231
+ - Bundler
232
+
233
+ ### Add to Gemfile
234
+
235
+ ```ruby
236
+ gem 'lyra', path: 'path/to/lyra' # or from git/rubygems when published
237
+ gem 'pam_dsl', '~> 0.1.0' # Privacy Attribute Matrix DSL
238
+ gem 'petri_flow', '~> 0.1.0' # Petri net library
239
+ ```
240
+
241
+ ### Install Dependencies
242
+
243
+ ```bash
244
+ bundle install
245
+ rails generate rails_event_store_active_record:migration
246
+ rails db:migrate
247
+ ```
248
+
249
+ ---
250
+
251
+ ## Quick Start
252
+
253
+ ### 1. Configure Lyra
254
+
255
+ Create `config/initializers/lyra.rb`:
256
+
257
+ ```ruby
258
+ Lyra.configure do |config|
259
+ # Start in monitor mode (non-intrusive)
260
+ config.mode = :monitor
261
+
262
+ # Configure event store
263
+ config.event_backend = :rails_event_store
264
+ config.event_store = RailsEventStore::Client.new
265
+
266
+ # Optional: User tracking for audit trails (see User Tracking section below)
267
+ # config.metadata_proc = ->(record, operation) { { user_id: Current.user&.id } }
268
+ end
269
+ ```
270
+
271
+ ### 2. Monitor a Model
272
+
273
+ Add monitoring to your ActiveRecord models:
274
+
275
+ ```ruby
276
+ class Order < ApplicationRecord
277
+ # Enable Lyra monitoring
278
+ monitor_with_lyra
279
+
280
+ # Your existing code continues to work normally
281
+ validates :total, presence: true
282
+ belongs_to :customer
283
+ end
284
+ ```
285
+
286
+ ### 3. Observe Events
287
+
288
+ All CRUD operations are now logged as events:
289
+
290
+ ```ruby
291
+ order = Order.create!(total: 100, customer: customer)
292
+ # => Publishes OrderCreated event
293
+
294
+ order.update!(total: 150)
295
+ # => Publishes OrderUpdated event
296
+
297
+ order.destroy!
298
+ # => Publishes OrderDestroyed event
299
+ ```
300
+
301
+ ### 4. Analyze State
302
+
303
+ Compare CRUD vs event-sourced views:
304
+
305
+ ```ruby
306
+ comparison = Lyra::DualView.new(Order, order.id).compare
307
+
308
+ puts comparison[:differences]
309
+ # => { no_differences: true }
310
+
311
+ # View complete audit trail
312
+ audit = Lyra::DualView.new(Order, order.id).audit_trail
313
+ # => [{ timestamp: ..., operation: :created, changes: {...} }, ...]
314
+ ```
315
+
316
+ [Continue to full usage guide →](#usage-guide)
317
+
318
+ ---
319
+
320
+ ## Usage Guide
321
+
322
+ ### Basic Model Monitoring
323
+
324
+ Add monitoring to any ActiveRecord model:
325
+
326
+ ```ruby
327
+ class Order < ApplicationRecord
328
+ monitor_with_lyra
329
+
330
+ validates :total, presence: true
331
+ belongs_to :customer
332
+ end
333
+ ```
334
+
335
+ ### Privacy Policies with PAM DSL
336
+
337
+ Define privacy policies for your models:
338
+
339
+ ```ruby
340
+ # config/privacy_policies.rb
341
+ PamDsl.define_policy :order_system do
342
+ # Define PII fields
343
+ field :email, type: :email, sensitivity: :internal do
344
+ allow_for :order_processing, :communication
345
+ transform :display { |v| "#{v[0]}***@#{v.split('@').last}" }
346
+ end
347
+
348
+ field :credit_card, type: :credit_card, sensitivity: :restricted do
349
+ allow_for :payment_processing
350
+ transform :display { |v| "****-****-****-#{v[-4..]}" }
351
+ end
352
+
353
+ # Define processing purposes
354
+ purpose :order_processing do
355
+ basis :contract
356
+ requires :email
357
+ end
358
+
359
+ purpose :marketing do
360
+ basis :consent
361
+ requires :email
362
+ end
363
+
364
+ # Configure retention
365
+ retention do
366
+ for_model 'Order' do
367
+ keep_for 7.years
368
+ on_expiry :anonymize
369
+ end
370
+ end
371
+ end
372
+
373
+ # Apply to model
374
+ class Order < ApplicationRecord
375
+ monitor_with_lyra privacy_policy: :order_system
376
+ end
377
+ ```
378
+
379
+ [See complete PAM DSL guide →](gems/pam_dsl/docs/PAM_DSL_INTEGRATION.md)
380
+
381
+ ### Schema Validation (Strict Mode)
382
+
383
+ Lyra can enforce schema consistency to prevent silent breaking changes in production:
384
+
385
+ ```ruby
386
+ # config/initializers/lyra.rb
387
+ Lyra.configure do |config|
388
+ config.mode = :monitor
389
+
390
+ # Enable strict schema validation (recommended for production)
391
+ config.strict_schema = Rails.env.production?
392
+
393
+ # Custom schema storage path (optional, defaults to db/lyra_schemas/)
394
+ config.schema_path = Rails.root.join('db/lyra_schemas')
395
+
396
+ config.monitor_model User
397
+ config.monitor_model Order
398
+ end
399
+ ```
400
+
401
+ #### Schema Management Rake Tasks
402
+
403
+ ```bash
404
+ # Generate initial schema from monitored models
405
+ rake lyra:schema:create
406
+
407
+ # Check for schema changes without updating
408
+ rake lyra:schema:verify
409
+
410
+ # Create new schema version (after migrations)
411
+ rake lyra:schema:update
412
+
413
+ # Display model → event mappings
414
+ rake lyra:schema:report
415
+
416
+ # Show schema version history
417
+ rake lyra:schema:history
418
+
419
+ # Compare two schema versions
420
+ rake lyra:schema:diff[1,2]
421
+ ```
422
+
423
+ #### Schema Validation Workflow
424
+
425
+ 1. **Development**: Run `rake lyra:schema:create` to generate initial schema
426
+ 2. **After migrations**: Run `rake lyra:schema:verify` to detect changes
427
+ 3. **If changes detected**: Run `rake lyra:schema:update` to create new version
428
+ 4. **Production**: With `strict_schema = true`, app fails to start if schema changes
429
+
430
+ #### Schema Change Severity Levels
431
+
432
+ | Severity | Changes | Impact |
433
+ |----------|---------|--------|
434
+ | **BREAKING** | model_removed, column_removed, column_type_changed | Requires new schema version |
435
+ | **WARNING** | column_nullable_changed, pii_field_added | Review recommended |
436
+ | **INFO** | model_added, column_added | Documentation update |
437
+
438
+ ### User Tracking (metadata_proc)
439
+
440
+ Lyra can capture custom metadata with each event, such as the current user, for audit trails and GDPR compliance.
441
+
442
+ #### Configuration
443
+
444
+ ```ruby
445
+ # config/initializers/lyra.rb
446
+ Lyra.configure do |config|
447
+ config.mode = :monitor
448
+ config.event_backend = :rails_event_store
449
+
450
+ # Custom metadata proc - called for every event
451
+ # Signature: ->(record, operation) { Hash }
452
+ config.metadata_proc = lambda do |record, operation|
453
+ {
454
+ user_id: Current.user&.id,
455
+ user_email: Current.user&.email,
456
+ ip_address: Current.request&.remote_ip,
457
+ source: 'my_app'
458
+ }
459
+ end
460
+ end
461
+ ```
462
+
463
+ #### Using with Rails CurrentAttributes
464
+
465
+ Rails 5.2+ provides `CurrentAttributes` for request-scoped state:
466
+
467
+ ```ruby
468
+ # app/models/current.rb
469
+ class Current < ActiveSupport::CurrentAttributes
470
+ attribute :user, :request_id, :request
471
+ end
472
+
473
+ # app/controllers/application_controller.rb
474
+ class ApplicationController < ActionController::Base
475
+ before_action :set_current_attributes
476
+
477
+ private
478
+
479
+ def set_current_attributes
480
+ Current.user = current_user
481
+ Current.request_id = request.request_id
482
+ Current.request = request
483
+ end
484
+ end
485
+ ```
486
+
487
+ #### Using with Devise/Warden
488
+
489
+ For Devise-based authentication:
490
+
491
+ ```ruby
492
+ config.metadata_proc = lambda do |record, operation|
493
+ user = if defined?(Warden) && Thread.current[:request_env]
494
+ Warden::Proxy.new(Thread.current[:request_env], Warden::Manager.new(nil)).user
495
+ end
496
+
497
+ { user_id: user&.id, user_email: user&.email }
498
+ end
499
+ ```
500
+
501
+ #### Using with Rails Engines (Solidus, Spree, etc.)
502
+
503
+ Many Rails Engines provide their own `Current` class:
504
+
505
+ ```ruby
506
+ config.metadata_proc = lambda do |record, operation|
507
+ user_id = nil
508
+
509
+ # Try standard Current
510
+ user_id ||= Current.user&.id if defined?(Current)
511
+
512
+ # Try Spree/Solidus Current
513
+ user_id ||= Spree::Current.user&.id if defined?(Spree::Current)
514
+
515
+ { user_id: user_id }
516
+ end
517
+ ```
518
+
519
+ #### Metadata in Events
520
+
521
+ The custom metadata is merged with Lyra's built-in metadata:
522
+
523
+ ```ruby
524
+ event = Lyra.event_store.read.last
525
+ event.metadata
526
+ # => {
527
+ # user_id: 123,
528
+ # user_email: "admin@example.com",
529
+ # ip_address: "127.0.0.1",
530
+ # source: "my_app",
531
+ # request_id: "abc-123", # Built-in from Current
532
+ # correlation_id: "corr-456", # Built-in from Correlation context
533
+ # causation_id: "cause-789" # Built-in from Causation context
534
+ # }
535
+ ```
536
+
537
+ ### Advanced Configuration
538
+
539
+ Use custom event names and aggregates:
540
+
541
+ ```ruby
542
+ class Order < ApplicationRecord
543
+ monitor_with_lyra(
544
+ event_prefix: 'Order',
545
+ aggregate_class: OrderAggregate
546
+ )
547
+ end
548
+
549
+ class OrderAggregate < Lyra::Aggregate
550
+ def total
551
+ get_state(:total)
552
+ end
553
+
554
+ private
555
+
556
+ def apply_order_created(event)
557
+ @id = event.model_id
558
+ set_state(:total, event.attributes['total'])
559
+ set_state(:status, 'pending')
560
+ end
561
+
562
+ def apply_order_updated(event)
563
+ event.changes.each { |k, (old, new)| set_state(k.to_sym, new) }
564
+ end
565
+ end
566
+ ```
567
+
568
+ ### Event Capture Behavior
569
+
570
+ Lyra uses ActiveRecord `after_commit` callbacks to capture events. This means **all** operations that go through ActiveRecord are captured, regardless of source:
571
+
572
+ | Source | Captured |
573
+ |--------|----------|
574
+ | Web requests | ✓ |
575
+ | Rails console (`rails c`) | ✓ |
576
+ | Background jobs (Sidekiq, etc.) | ✓ |
577
+ | Rake tasks | ✓ |
578
+ | Rails runner scripts | ✓ |
579
+ | Seeds (`db:seed`) | ✓ |
580
+
581
+ **Operations NOT captured** (bypass ActiveRecord callbacks):
582
+
583
+ | Operation | Captured | Alternative |
584
+ |-----------|----------|-------------|
585
+ | `update_columns` / `update_column` | ✗ | Use `update!` |
586
+ | `update_all` / `delete_all` | ✗ | Iterate with `find_each` |
587
+ | `insert_all` / `upsert_all` | ✗ | Use `create!` |
588
+ | Raw SQL (`connection.execute`) | ✗ | Use ActiveRecord methods |
589
+ | `touch` with no callbacks | ✗ | Use `update!` |
590
+
591
+ ### Strict Data Access Mode
592
+
593
+ To prevent inconsistencies between CRUD state and event store, enable strict mode to raise errors on callback-bypassing operations:
594
+
595
+ ```ruby
596
+ # config/initializers/lyra.rb
597
+ Lyra.configure do |config|
598
+ config.strict_data_access = true # Raises on update_columns, etc.
599
+ # Or only in specific environments:
600
+ config.strict_data_access = Rails.env.development? || Rails.env.test?
601
+ end
602
+ ```
603
+
604
+ When enabled, monitored models will raise `Lyra::StrictDataAccessViolation` if you attempt:
605
+
606
+ | Operation | Alternative | Scope |
607
+ |-----------|-------------|-------|
608
+ | `update_columns` | `update!` | Instance |
609
+ | `update_column` | `update!` | Instance |
610
+ | `delete` | `destroy` | Instance |
611
+ | `update_all` | `find_each { \|r\| r.update!(...) }` | Relation |
612
+ | `delete_all` | `find_each(&:destroy)` | Relation |
613
+ | `insert_all` | `records.each { \|attrs\| create!(attrs) }` | Class |
614
+ | `upsert_all` | `find_or_create_by!(...).update!(...)` | Class |
615
+
616
+ ```ruby
617
+ user.update_columns(name: "New")
618
+ # => raises Lyra::StrictDataAccessViolation:
619
+ # "update_columns bypasses callbacks and won't be captured by Lyra.
620
+ # Use update! instead. Disable strict_data_access mode if this is intentional."
621
+
622
+ Registration.where(status: "pending").update_all(status: "expired")
623
+ # => raises Lyra::StrictDataAccessViolation:
624
+ # "update_all bypasses callbacks. Use find_each { |r| r.update!(...) } instead."
625
+ ```
626
+
627
+ #### Bypassing Strict Mode
628
+
629
+ For legitimate bulk operations in migrations, seeds, or admin tasks, use `Lyra.without_strict_access`:
630
+
631
+ ```ruby
632
+ # Temporarily bypass strict mode for bulk operations
633
+ Lyra.without_strict_access do
634
+ User.where(active: false).delete_all # No error raised
635
+ end
636
+ ```
637
+
638
+ **Note:** Rails association operations (like `dependent: :nullify`) are automatically allowed since they're internal framework operations.
639
+
640
+ ### Dual View Analysis
641
+
642
+ Compare CRUD state with event-sourced state:
643
+
644
+ ```ruby
645
+ # Single record comparison
646
+ comparison = Lyra::DualView.new(Order, order_id).compare
647
+
648
+ puts comparison[:crud_view]
649
+ # => { exists: true, attributes: {...} }
650
+
651
+ puts comparison[:event_sourced_view]
652
+ # => { exists: true, state: {...}, events_count: 5 }
653
+
654
+ puts comparison[:differences]
655
+ # => { no_differences: true } or differences hash
656
+
657
+ # Audit trail
658
+ audit = Lyra::DualView.new(Order, order_id).audit_trail
659
+ # => Array of all operations with timestamps and changes
660
+ ```
661
+
662
+ ### Batch Analysis
663
+
664
+ Find discrepancies across all records:
665
+
666
+ ```ruby
667
+ discrepancies = Lyra::DualView.find_discrepancies(Order)
668
+ # => Returns all orders where CRUD state != Event-sourced state
669
+
670
+ analysis = Lyra::StateAnalyzer.analyze(Order, order_id)
671
+ puts analysis[:recommendations]
672
+ # => Actionable recommendations based on state comparison
673
+ ```
674
+
675
+ ### Switching to Hijack Mode
676
+
677
+ After analyzing in monitor mode, switch to full event sourcing:
678
+
679
+ ```ruby
680
+ # In config/initializers/lyra.rb
681
+ Lyra.configure do |config|
682
+ config.enable_hijack!
683
+ end
684
+ ```
685
+
686
+ Now CRUD operations are intercepted and routed through event sourcing:
687
+
688
+ ```ruby
689
+ order = Order.create!(total: 100, customer: customer)
690
+ # => CreateCommand processed
691
+ # => OrderCreated event published
692
+ # => Aggregate updated
693
+ # => Database record created with event-sourced ID
694
+ ```
695
+
696
+ ### Dashboard
697
+
698
+ Lyra provides a web dashboard for monitoring and analyzing event-sourced data.
699
+
700
+ #### Mounting the Dashboard
701
+
702
+ Add to your `config/routes.rb`:
703
+
704
+ ```ruby
705
+ Rails.application.routes.draw do
706
+ mount Lyra::Engine, at: "/lyra"
707
+ # ... rest of your routes
708
+ end
709
+ ```
710
+
711
+ #### Available Routes
712
+
713
+ | Route | Description |
714
+ |-------|-------------|
715
+ | `/lyra/dashboard` | Main dashboard with monitored models overview |
716
+ | `/lyra/dashboard/model/:class` | Model-specific overview (e.g., `/lyra/dashboard/model/Order`) |
717
+ | `/lyra/dashboard/compare/:class/:id` | Dual View - Compare CRUD state vs Event-sourced state |
718
+ | `/lyra/dashboard/discrepancies/:class` | List records with state discrepancies |
719
+
720
+ **Event Flow Routes:**
721
+
722
+ | Route | Description |
723
+ |-------|-------------|
724
+ | `/lyra/flow/timeline` | Global event timeline |
725
+ | `/lyra/flow/event_chain/:class/:id` | Event chain for a specific record |
726
+ | `/lyra/flow/crud_mapping` | CRUD operation to event type mapping |
727
+ | `/lyra/flow/correlation/:correlation_id` | Events by correlation ID |
728
+ | `/lyra/flow/user_actions/:user_id` | Events by user |
729
+
730
+ **Visualization Routes:**
731
+
732
+ | Route | Description |
733
+ |-------|-------------|
734
+ | `/lyra/visualizations/event_graph` | Interactive event graph (HTML + Mermaid) |
735
+ | `/lyra/visualizations/event_graph.json` | Event graph data with filters |
736
+ | `/lyra/visualizations/entity_graph/:class/:id.json` | Entity lifecycle graph |
737
+ | `/lyra/visualizations/heatmap` | Activity heatmap view |
738
+ | `/lyra/visualizations/heatmap.json` | Heatmap data for time period |
739
+ | `/lyra/visualizations/event_list.json` | List of entities with event counts |
740
+
741
+ **Event Graph Features:**
742
+
743
+ The event graph provides an interactive visualization of entity lifecycles:
744
+
745
+ - **Entity Picker**: Filter by model class, select specific entities to view
746
+ - **Changed Fields**: Each event node displays which fields were modified (📝 prefix)
747
+ - **Link Types**:
748
+ - Solid lines → Same entity lifecycle (chronological order)
749
+ - Dashed lines → Correlated events (same transaction/request)
750
+ - **Node Details**: Includes operation type, timestamp, and changed field names
751
+
752
+ Example node display:
753
+ ```
754
+ ┌─────────────────────┐
755
+ │ UPDATED │
756
+ │ 14:30:45 │
757
+ │ 📝 status, amount │
758
+ └─────────────────────┘
759
+ ```
760
+
761
+ Timestamp fields (`*_at`) are automatically excluded from the changed fields display.
762
+
763
+ **Schema Management Routes:**
764
+
765
+ | Route | Description |
766
+ |-------|-------------|
767
+ | `/lyra/dashboard/schema` | Current schema with pending changes |
768
+ | `/lyra/dashboard/schema/history` | Schema version history |
769
+ | `/lyra/dashboard/schema/:version` | View specific schema version |
770
+
771
+ **Formal Verification Routes (requires PetriFlow):**
772
+
773
+ | Route | Description |
774
+ |-------|-------------|
775
+ | `/lyra/verification` | Verification dashboard |
776
+ | `/lyra/verification.json` | Verification results (JSON) |
777
+
778
+ **Privacy & GDPR Routes:**
779
+
780
+ | Route | Description |
781
+ |-------|-------------|
782
+ | `/lyra/privacy/pii_detection` | Automatic PII field detection |
783
+ | `/lyra/privacy/gdpr_report/:type/:id` | GDPR Article 15 compliant report |
784
+ | `/lyra/privacy/subject/:type/:id` | View all data for a subject |
785
+
786
+ #### Securing Dashboard Access
787
+
788
+ **IMPORTANT**: The Lyra dashboard exposes sensitive data including PII fields, event history, and audit trails. Always restrict access in production.
789
+
790
+ ##### Option 1: Authentication Constraint (Recommended)
791
+
792
+ ```ruby
793
+ # config/routes.rb
794
+ Rails.application.routes.draw do
795
+ # Restrict to authenticated admin users
796
+ authenticate :user, ->(u) { u.admin? } do
797
+ mount Lyra::Engine, at: "/lyra"
798
+ end
799
+ end
800
+ ```
801
+
802
+ ##### Option 2: Basic HTTP Authentication
803
+
804
+ ```ruby
805
+ # config/routes.rb
806
+ Rails.application.routes.draw do
807
+ mount Lyra::Engine, at: "/lyra", constraints: ->(req) {
808
+ Rack::Auth::Basic::Request.new(req.env).provided? &&
809
+ Rack::Auth::Basic::Request.new(req.env).credentials ==
810
+ [ENV['LYRA_USER'], ENV['LYRA_PASSWORD']]
811
+ }
812
+ end
813
+ ```
814
+
815
+ ##### Option 3: IP Whitelist
816
+
817
+ ```ruby
818
+ # config/routes.rb
819
+ Rails.application.routes.draw do
820
+ constraints ->(req) { ['127.0.0.1', '::1'].include?(req.remote_ip) } do
821
+ mount Lyra::Engine, at: "/lyra"
822
+ end
823
+ end
824
+ ```
825
+
826
+ ##### Option 4: Custom Middleware
827
+
828
+ ```ruby
829
+ # lib/lyra_auth_middleware.rb
830
+ class LyraAuthMiddleware
831
+ def initialize(app)
832
+ @app = app
833
+ end
834
+
835
+ def call(env)
836
+ if env['PATH_INFO'].start_with?('/lyra')
837
+ # Your authentication logic here
838
+ return [403, {}, ['Forbidden']] unless authorized?(env)
839
+ end
840
+ @app.call(env)
841
+ end
842
+
843
+ private
844
+
845
+ def authorized?(env)
846
+ # Implement your authorization logic
847
+ env['warden']&.user&.admin?
848
+ end
849
+ end
850
+
851
+ # config/application.rb
852
+ config.middleware.use LyraAuthMiddleware
853
+ ```
854
+
855
+ ##### Option 5: Disable in Production
856
+
857
+ ```ruby
858
+ # config/routes.rb
859
+ Rails.application.routes.draw do
860
+ unless Rails.env.production?
861
+ mount Lyra::Engine, at: "/lyra"
862
+ end
863
+ end
864
+ ```
865
+
866
+ #### Environment-Based Configuration
867
+
868
+ ```ruby
869
+ # config/routes.rb
870
+ Rails.application.routes.draw do
871
+ case Rails.env
872
+ when 'development'
873
+ # Open access in development
874
+ mount Lyra::Engine, at: "/lyra"
875
+ when 'staging'
876
+ # Basic auth in staging
877
+ mount Lyra::Engine, at: "/lyra", constraints: LyraBasicAuth
878
+ when 'production'
879
+ # Full authentication in production
880
+ authenticate :user, ->(u) { u.admin? } do
881
+ mount Lyra::Engine, at: "/lyra"
882
+ end
883
+ end
884
+ end
885
+ ```
886
+
887
+ ### Custom Event Mappers
888
+
889
+ Create custom event mapping logic:
890
+
891
+ ```ruby
892
+ class OrderEventMapper < Lyra::EventMapper
893
+ def event_data
894
+ super.merge(
895
+ business_context: {
896
+ total: data[:attributes]['total'],
897
+ items_count: data[:attributes]['items_count']
898
+ }
899
+ )
900
+ end
901
+ end
902
+
903
+ Lyra::EventMapper.register_mapper(Order, OrderEventMapper)
904
+ ```
905
+
906
+ ### State Reconstruction
907
+
908
+ Rebuild current state from events:
909
+
910
+ ```ruby
911
+ # Using projection
912
+ state = Lyra::StateProjection.rebuild_state(Order, order_id)
913
+ # => { total: 150, status: "confirmed", ... }
914
+
915
+ # Using aggregate
916
+ aggregate = OrderAggregate.load(order_id)
917
+ aggregate.total # => 150
918
+ aggregate.status # => "confirmed"
919
+ ```
920
+
921
+ ### Pluggable Backends
922
+
923
+ Implement custom event storage:
924
+
925
+ ```ruby
926
+ class MyEventStore < Lyra::CustomEventStoreAdapter
927
+ def publish(event, stream_name:)
928
+ # Custom implementation (e.g., Kafka, EventStoreDB)
929
+ end
930
+
931
+ def read_stream(stream_name)
932
+ # Custom implementation
933
+ end
934
+ end
935
+
936
+ Lyra.configure do |config|
937
+ config.event_backend = :custom
938
+ config.event_store = MyEventStore.new
939
+ end
940
+ ```
941
+
942
+ ---
943
+
944
+ ## Example Applications
945
+
946
+ ### Aegean E-Pay Testbed (Comprehensive)
947
+
948
+ A full-featured university payment system testbed is included in `examples/aegean_epay_testbed/`. This real-world example demonstrates:
949
+
950
+ - **CRUD Operations** - Registrations, payments, refunds with automatic event generation
951
+ - **Dual-View Comparison** - Compare CRUD state vs event-sourced state
952
+ - **Privacy Policy Enforcement** - PAM DSL integration for GDPR compliance
953
+ - **Audit Trail Generation** - Complete history from immutable events
954
+ - **State Machine Workflows** - Refund request lifecycle with events
955
+ - **Performance Benchmarking** - Compare overhead with/without Lyra
956
+
957
+ #### Running the Testbed
958
+
959
+ ```bash
960
+ cd examples/aegean_epay_testbed
961
+ bundle install
962
+ rails db:create db:migrate db:seed
963
+
964
+ # Run integration tests
965
+ ruby test_lyra_integration.rb
966
+
967
+ # Or with performance benchmarks
968
+ ruby test_lyra_integration.rb --performance
969
+ ```
970
+
971
+ [Explore the Aegean E-Pay testbed →](examples/aegean_epay_testbed/README.md)
972
+
973
+ ### Blog App (Getting Started)
974
+
975
+ A simpler example for learning Lyra basics is in `examples/blog_app/`:
976
+
977
+ ```bash
978
+ cd examples/blog_app
979
+ bundle install
980
+ rails db:create db:migrate db:seed
981
+ rails console
982
+ ```
983
+
984
+ [Explore the blog example →](examples/blog_app/README.md)
985
+
986
+ ---
987
+
988
+ ## Benefits
989
+
990
+ ### For Research
991
+ - **Orthogonal Analysis**: Compare static vs. dynamic views of system state
992
+ - **Behavioral Analysis**: Understand system evolution over time
993
+ - **Migration Patterns**: Study CRUD-to-ES transformation strategies
994
+ - **Formal Verification**: Prove correctness using Petri net theory
995
+ - **Privacy Compliance**: Research privacy-preserving event sourcing patterns
996
+
997
+ ### For Development
998
+ - **Zero Downtime Migration**: Gradually transition to event sourcing
999
+ - **Audit Trail**: Complete history of all state changes
1000
+ - **Temporal Queries**: Query state at any point in time
1001
+ - **Debugging**: Replay events to understand issues
1002
+ - **CQRS Support**: Natural separation of commands and queries
1003
+
1004
+ ### For Operations
1005
+ - **Non-intrusive**: Deploy without code changes
1006
+ - **Rollback Safety**: Keep CRUD as safety net during transition
1007
+ - **Real-time Monitoring**: Compare CRUD vs event-sourced state
1008
+ - **Validation**: Verify event sourcing correctness before full migration
1009
+ - **Performance Analysis**: Measure overhead before committing
1010
+
1011
+ ---
1012
+
1013
+ ## Documentation
1014
+
1015
+ ### Core Documentation
1016
+ - **[Getting Started Guide](docs/GETTING_STARTED.md)** - Installation and first steps
1017
+ - **[Architecture Overview](docs/ARCHITECTURE.md)** - System design and components
1018
+ - **[Monorepo Structure](docs/MONOREPO.md)** - Repository organization
1019
+
1020
+ ### Theoretical Foundation
1021
+ - **[ORFEAS Framework Overview](docs/ORFEAS_FRAMEWORK_OVERVIEW.md)** - Complete framework description
1022
+ - **[Petri Nets Model](gems/petri_flow/docs/THEORETICAL_MODEL_PETRI_NETS.md)** - P/T nets for verification, CPNs for data modeling
1023
+ - **[Matrix Analysis Model](gems/petri_flow/docs/THEORETICAL_MODEL_MATRICES.md)** - Linear algebra approach
1024
+
1025
+ ### Privacy & Compliance
1026
+ - **[PAM DSL Integration](gems/pam_dsl/docs/PAM_DSL_INTEGRATION.md)** - Privacy policy DSL guide
1027
+ - **[Privacy Compliance](docs/PRIVACY_COMPLIANCE.md)** - GDPR compliance details
1028
+
1029
+ ### Components
1030
+ - **[PetriFlow Export](gems/petri_flow/docs/PETRIFLOW_EXPORT.md)** - Export formats and integration
1031
+ - **[PetriFlow Gem](gems/petri_flow/README.md)** - Petri net library documentation
1032
+ - **[PAM DSL Gem](gems/pam_dsl/README.md)** - Privacy DSL documentation
1033
+
1034
+ ### Development
1035
+ - **[Testing Guide](docs/TESTING.md)** - Testing strategy and setup
1036
+
1037
+ ---
1038
+
1039
+ ## Research Foundation
1040
+
1041
+ ORFEAS and Lyra are grounded in peer-reviewed research:
1042
+
1043
+ ### Published Papers
1044
+
1045
+ **Pantelelis, M., & Kalloniatis, C. (2022).** *Mapping CRUD to Events: Towards an object to event-sourcing framework.*
1046
+ 26th Pan-Hellenic Conference on Informatics (PCI 2022).
1047
+ DOI: [10.1145/3575879.3576006](https://doi.org/10.1145/3575879.3576006)
1048
+
1049
+ ### Research Areas
1050
+
1051
+ - **Event Sourcing Patterns**: Formal models for CRUD-to-event transformation
1052
+ - **Privacy-Preserving Systems**: GDPR compliance in event-driven architectures
1053
+ - **Petri Net Theory**: P/T nets for workflow verification, CPNs for advanced data modeling
1054
+ - **Matrix Analysis**: Linear algebra approaches to causation and lineage
1055
+ - **Software Architecture**: Gradual migration strategies for legacy systems
1056
+
1057
+ ---
1058
+
1059
+ ## Development Methodology
1060
+
1061
+ This proof-of-concept was developed using **AI-assisted code generation** to accelerate implementation while maintaining focus on theoretical contributions.
1062
+
1063
+ ### AI Tools Used
1064
+
1065
+ - **Claude Code** (Anthropic's agentic coding tool) - Primary development assistant for code implementation, testing, and documentation
1066
+ - **Claude** (Anthropic) - For architectural discussions and design decisions
1067
+
1068
+ **Important**: All architectural decisions, design patterns, and theoretical foundations were specified by the researcher. AI assistance was used for:
1069
+ - Code implementation following defined specifications
1070
+ - Test generation based on requirements
1071
+ - Documentation formatting and organization
1072
+ - Code review and refactoring
1073
+
1074
+ This methodology enabled rapid prototyping while ensuring the theoretical rigor required for academic research.
1075
+
1076
+ ---
1077
+
1078
+ ## Contributing
1079
+
1080
+ Lyra is research software for the ORFEAS framework. Contributions and feedback are welcome!
1081
+
1082
+ ### Ways to Contribute
1083
+
1084
+ - **Bug Reports**: Submit issues on GitHub
1085
+ - **Feature Requests**: Suggest improvements or new features
1086
+ - **Research Collaboration**: Collaborate on research extensions
1087
+ - **Documentation**: Improve documentation and examples
1088
+ - **Testing**: Add test cases and improve coverage
1089
+
1090
+ ### Development Setup
1091
+
1092
+ ```bash
1093
+ # Clone the repository
1094
+ git clone https://github.com/mpantel/lyra-engine.git lyra
1095
+ cd lyra
1096
+
1097
+ # Install dependencies
1098
+ bundle install
1099
+
1100
+ # Run tests
1101
+ rake test
1102
+
1103
+ # Build gems
1104
+ cd gems/petri_flow && rake build
1105
+ cd gems/pam_dsl && rake build
1106
+ ```
1107
+
1108
+ ---
1109
+
1110
+ ## Citation
1111
+
1112
+ If you use this software in academic research, please cite:
1113
+
1114
+ ### Software Citation
1115
+
1116
+ ```bibtex
1117
+ @software{lyra2026,
1118
+ title={Lyra: CRUD to Event Sourcing Transformation Engine},
1119
+ author={Pantelelis, Michail},
1120
+ year={2026},
1121
+ note={Part of ORFEAS Framework},
1122
+ url={https://github.com/mpantel/lyra-engine}
1123
+ }
1124
+ ```
1125
+
1126
+ ### Research Paper Citation
1127
+
1128
+ ```bibtex
1129
+ @inproceedings{pantelelis2022mapping,
1130
+ title={Mapping CRUD to Events: Towards an object to event-sourcing framework},
1131
+ author={Pantelelis, Michail and Kalloniatis, Christos},
1132
+ booktitle={26th Pan-Hellenic Conference on Informatics (PCI 2022)},
1133
+ year={2022},
1134
+ doi={10.1145/3575879.3576006}
1135
+ }
1136
+ ```
1137
+
1138
+ ### References
1139
+
1140
+ - [Rails Event Store](https://railseventstore.org/) - Event Store implementation
1141
+ - [Event Sourcing Pattern](https://martinfowler.com/eaaDev/EventSourcing.html) - Martin Fowler
1142
+ - [CQRS](https://martinfowler.com/bliki/CQRS.html) - Command Query Responsibility Segregation
1143
+ - [Petri Net Theory](http://www.informatik.uni-hamburg.de/TGI/PetriNets/) - Formal foundation
1144
+ - [GDPR Compliance](https://gdpr.eu/) - Privacy regulation
1145
+
1146
+ ---
1147
+
1148
+ ## Support
1149
+
1150
+ For questions, issues, and collaboration:
1151
+
1152
+ - **Email**: mpantel@aegean.gr
1153
+ - **GitHub Issues**: [Repository Issues](https://github.com/mpantel/lyra-engine/issues)
1154
+ - **Institution**: University of the Aegean, Department of Information and Communication Systems Engineering
1155
+
1156
+ ---
1157
+
1158
+ ## License
1159
+
1160
+ MIT License - see [LICENSE](LICENSE) file for details.
1161
+
1162
+ ---
1163
+
1164
+ **Built with Ruby, Petri Net Theory, and Formal Methods**
1165
+ **Part of the ORFEAS PhD Research Project**