legion-data 1.4.2 → 1.4.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eaf37e68acae5015ef50b01e6a5c7a4806e81b80f5cf74f3c71b72e6799f0bd4
4
- data.tar.gz: 81b55083c6e8d59403b51a838935a4146b1d3f39eca8316dfd82ee4d2f6a0b05
3
+ metadata.gz: cc137f8ac51b46a97a5bc6c82b25e8036536fb5771309b69aa9df35604db7b89
4
+ data.tar.gz: dd10068c7f5b243c0fe6b5d56b572ab06cdfe3a33bcf6449c8758e94e4e17147
5
5
  SHA512:
6
- metadata.gz: 4a24d0a86df7d44669ff38d34667c4f0c63036f877d1453df2e1418670b8a8c59ad803f9c245f5895094465d994253e1b4eced1007f0724cd31f53c4ae804d37
7
- data.tar.gz: 830b7fc8203eb8a339a5ad84d334e56dabf0e6e02084be99a3b27a3067b104d7b5ca973437f3f8577050983c0126a302903624bdcf6a2916e267a1e6a8558754
6
+ metadata.gz: 74ca6d37fce4a381b04b9ce35bc50117649a0be3fae11c3231d496aed38aa43a03439dc5262569bcce2c6b037a996fa6b16ac6067c48d2e40cd1b97aa2153241
7
+ data.tar.gz: c7d530da08c104df4f2d633a33ac13171c7eac51516ac75d2b54374b9d938a9075a41a0d37edc0614f204753e349264bd0a96b76ca3ca031ccc63c926f9deebd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Legion::Data Changelog
2
2
 
3
+ ## [Unreleased]
4
+
5
+ ### Added
6
+ - `Legion::Data::Spool`: filesystem-based event buffer at `~/.legionio/data/spool/`
7
+
8
+ ## v1.4.3
9
+
10
+ ### Added
11
+ - `Legion::Data::Spool`: filesystem-based event buffer at `~/.legionio/data/spool/`
12
+
3
13
  ## v1.4.2
4
14
 
5
15
  ### Fixed
data/CLAUDE.md CHANGED
@@ -5,9 +5,10 @@
5
5
 
6
6
  ## Purpose
7
7
 
8
- Manages persistent database storage for the LegionIO framework. Supports SQLite (default), MySQL, and PostgreSQL via Sequel ORM. Provides automatic schema migrations and data models for extensions, functions, runners, nodes, tasks, settings, digital workers, task relationships, and Apollo shared knowledge tables (PostgreSQL only). Also provides a parallel local SQLite database (`Legion::Data::Local`) for agentic cognitive state persistence.
8
+ Manages persistent database storage for the LegionIO framework. Supports SQLite (default), MySQL, and PostgreSQL via Sequel ORM. Provides automatic schema migrations and data models for extensions, functions, runners, nodes, tasks, settings, digital workers, task relationships, Apollo shared knowledge tables (PostgreSQL only), tenants, webhooks, audit log, and archive tables. Also provides a parallel local SQLite database (`Legion::Data::Local`) for agentic cognitive state persistence.
9
9
 
10
10
  **GitHub**: https://github.com/LegionIO/legion-data
11
+ **Version**: 1.4.3
11
12
  **License**: Apache-2.0
12
13
 
13
14
  ## Supported Databases
@@ -45,7 +46,7 @@ Legion::Data (singleton module)
45
46
  │ ├── .shutdown # Close local connection
46
47
  │ └── .reset! # Clear all state (testing)
47
48
 
48
- ├── Migration # Auto-migration system (14 migrations, Sequel DSL)
49
+ ├── Migration # Auto-migration system (25 migrations, Sequel DSL)
49
50
  │ └── migrations/
50
51
  │ ├── 001_add_schema_columns
51
52
  │ ├── 002_add_nodes
@@ -64,7 +65,14 @@ Legion::Data (singleton module)
64
65
  │ ├── 015_add_rbac_tables
65
66
  │ ├── 016_add_worker_health
66
67
  │ ├── 017_add_audit_log
67
- └── 018_add_governance_events # append-only event store with hash chain
68
+ ├── 018_add_governance_events # append-only event store with hash chain
69
+ │ ├── 019_add_audit_hash_chain
70
+ │ ├── 020_add_webhooks
71
+ │ ├── 021_add_archive_tables
72
+ │ ├── 022_add_memory_traces
73
+ │ ├── 023_add_data_archive
74
+ │ ├── 024_add_tenant_partition_columns
75
+ │ └── 025_add_tenants_table
68
76
 
69
77
  ├── Model # Sequel model loader
70
78
  │ └── Models/
@@ -80,7 +88,11 @@ Legion::Data (singleton module)
80
88
  │ ├── ApolloEntry # Apollo knowledge entries — postgres only (pgvector embedding, confidence lifecycle)
81
89
  │ ├── ApolloRelation # Weighted relations between Apollo entries — postgres only
82
90
  │ ├── ApolloExpertise # Per-agent domain expertise tracking — postgres only
83
- └── ApolloAccessLog # Apollo entry access audit log — postgres only
91
+ ├── ApolloAccessLog # Apollo entry access audit log — postgres only
92
+ │ ├── AuditLog # Audit trail entries (AMQP + query layer)
93
+ │ ├── RbacRoleAssignment # RBAC principal -> role mappings
94
+ │ ├── RbacRunnerGrant # RBAC per-runner permission grants
95
+ │ └── RbacCrossTeamGrant # RBAC cross-team access grants
84
96
  │ Note: value_metrics table (migration 010) is accessed via raw Sequel dataset,
85
97
  │ not via a named Sequel::Model subclass.
86
98
  │ Note: Apollo models are guarded with `return unless adapter == :postgres` at load time.
@@ -169,10 +181,10 @@ Per-adapter credential defaults are defined in `Settings::CREDS`:
169
181
  | `lib/legion/data.rb` | Module entry, setup/shutdown lifecycle |
170
182
  | `lib/legion/data/connection.rb` | Sequel database connection (adapter selection) |
171
183
  | `lib/legion/data/migration.rb` | Migration runner |
172
- | `lib/legion/data/migrations/` | 14 numbered migration files (Sequel DSL) |
184
+ | `lib/legion/data/migrations/` | 25 numbered migration files (Sequel DSL) |
173
185
  | `lib/legion/data/model.rb` | Model autoloader |
174
186
  | `lib/legion/data/local.rb` | Local SQLite module for agentic cognitive state |
175
- | `lib/legion/data/models/` | Sequel models (Extension, Function, Runner, Node, Task, TaskLog, Setting, DigitalWorker, Relationship, ApolloEntry, ApolloRelation, ApolloExpertise, ApolloAccessLog) |
187
+ | `lib/legion/data/models/` | Sequel models (Extension, Function, Runner, Node, Task, TaskLog, Setting, DigitalWorker, Relationship, ApolloEntry, ApolloRelation, ApolloExpertise, ApolloAccessLog, AuditLog, RbacRoleAssignment, RbacRunnerGrant, RbacCrossTeamGrant) |
176
188
  | `lib/legion/data/encryption/cipher.rb` | AES-256-GCM encrypt/decrypt with versioned binary format and AAD |
177
189
  | `lib/legion/data/encryption/key_provider.rb` | Vault-backed key derivation with per-tenant scope and local fallback |
178
190
  | `lib/legion/data/encryption/sequel_plugin.rb` | Transparent `encrypted_column` DSL for Sequel models |
@@ -193,6 +205,11 @@ Optional persistent storage initialized during `Legion::Service` startup (after
193
205
  6. Task relationship graph (trigger/action chains)
194
206
  7. Apollo shared knowledge store (PostgreSQL + pgvector only, used by lex-apollo)
195
207
  8. Local SQLite for agentic cognitive state (memory traces, trust scores, dream journals) — always on-node, independent of shared DB
208
+ 9. RBAC assignment tables (migrations 015 — role assignments, runner grants, cross-team grants)
209
+ 10. Audit log with tamper-evident hash chain (migrations 017, 019)
210
+ 11. Governance event store with append-only integrity (migration 018)
211
+ 12. Webhook subscription storage (migration 020)
212
+ 13. Archive, memory traces, and tenant partition tables (migrations 021–025)
196
213
 
197
214
  ---
198
215
 
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Persistent database storage for the [LegionIO](https://github.com/LegionIO/LegionIO) framework. Provides database connectivity via Sequel ORM, automatic schema migrations, and data models for extensions, functions, runners, nodes, tasks, settings, digital workers, task relationships, and Apollo shared knowledge tables.
4
4
 
5
- Version: 1.3.0
5
+ **Version**: 1.4.3
6
6
 
7
7
  ## Supported Databases
8
8
 
@@ -155,6 +155,16 @@ CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
155
155
 
156
156
  Set `enabled: false` to disable local SQLite entirely.
157
157
 
158
+ ### Spool (Filesystem Buffer)
159
+
160
+ `Legion::Data::Spool` provides a filesystem-backed write buffer for extensions. When the database is unavailable, task data can be written to `~/.legionio/data/spool/` and replayed once the connection is restored.
161
+
162
+ ```ruby
163
+ spool = Legion::Data::Spool.for(Legion::Extensions::MyLex)
164
+ spool.write({ task_id: SecureRandom.uuid, data: payload })
165
+ spool.drain { |entry| process(entry) }
166
+ ```
167
+
158
168
  ### Dev Mode Fallback
159
169
 
160
170
  When `dev_mode: true` and a network database (MySQL/PostgreSQL) is unreachable, the shared connection falls back to SQLite automatically instead of raising.
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'fileutils'
5
+ require 'securerandom'
6
+
7
+ module Legion
8
+ module Data
9
+ module Spool
10
+ EXTENSION_PREFIX = 'Legion::Extensions::'
11
+
12
+ class << self
13
+ def root
14
+ @root ||= File.expand_path('~/.legionio/data/spool')
15
+ end
16
+
17
+ attr_writer :root
18
+
19
+ def for(extension_module)
20
+ ScopedSpool.new(extension_module, root)
21
+ end
22
+
23
+ private
24
+
25
+ def extension_path(extension_module)
26
+ name = extension_module.name
27
+ raise ArgumentError, "#{name} is not under Legion::Extensions::" unless name&.start_with?(EXTENSION_PREFIX)
28
+
29
+ name.delete_prefix(EXTENSION_PREFIX).gsub('::', '/').downcase
30
+ end
31
+ end
32
+
33
+ class ScopedSpool
34
+ def initialize(extension_module, spool_root)
35
+ @extension_dir = File.join(spool_root, Spool.send(:extension_path, extension_module))
36
+ end
37
+
38
+ def write(sub_namespace, payload)
39
+ dir = sub_dir(sub_namespace)
40
+ FileUtils.mkdir_p(dir)
41
+ filename = "#{Time.now.strftime('%s%9N')}-#{SecureRandom.uuid}.json"
42
+ path = File.join(dir, filename)
43
+ File.write(path, ::JSON.generate(payload))
44
+ path
45
+ end
46
+
47
+ def read(sub_namespace)
48
+ sorted_files(sub_namespace).map { |f| ::JSON.parse(File.read(f), symbolize_names: true) }
49
+ end
50
+
51
+ def flush(sub_namespace)
52
+ count = 0
53
+ sorted_files(sub_namespace).each do |path|
54
+ event = ::JSON.parse(File.read(path), symbolize_names: true)
55
+ yield event
56
+ File.delete(path)
57
+ count += 1
58
+ end
59
+ count
60
+ end
61
+
62
+ def count(sub_namespace)
63
+ sorted_files(sub_namespace).size
64
+ end
65
+
66
+ def clear(sub_namespace)
67
+ dir = sub_dir(sub_namespace)
68
+ return unless Dir.exist?(dir)
69
+
70
+ Dir[File.join(dir, '*.json')].each { |f| File.delete(f) }
71
+ end
72
+
73
+ private
74
+
75
+ def sub_dir(sub_namespace)
76
+ File.join(@extension_dir, sub_namespace.to_s)
77
+ end
78
+
79
+ def sorted_files(sub_namespace)
80
+ dir = sub_dir(sub_namespace)
81
+ return [] unless Dir.exist?(dir)
82
+
83
+ Dir[File.join(dir, '*.json')]
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Data
5
- VERSION = '1.4.2'
5
+ VERSION = '1.4.3'
6
6
  end
7
7
  end
data/lib/legion/data.rb CHANGED
@@ -8,6 +8,7 @@ require 'legion/data/connection'
8
8
  require 'legion/data/model'
9
9
  require 'legion/data/migration'
10
10
  require_relative 'data/local'
11
+ require_relative 'data/spool'
11
12
 
12
13
  module Legion
13
14
  module Data
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-data
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2
4
+ version: 1.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -140,6 +140,7 @@ files:
140
140
  - lib/legion/data/models/task.rb
141
141
  - lib/legion/data/models/task_log.rb
142
142
  - lib/legion/data/settings.rb
143
+ - lib/legion/data/spool.rb
143
144
  - lib/legion/data/storage_tiers.rb
144
145
  - lib/legion/data/vector.rb
145
146
  - lib/legion/data/version.rb