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 +4 -4
- data/CHANGELOG.md +10 -0
- data/CLAUDE.md +23 -6
- data/README.md +11 -1
- data/lib/legion/data/spool.rb +88 -0
- data/lib/legion/data/version.rb +1 -1
- data/lib/legion/data.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cc137f8ac51b46a97a5bc6c82b25e8036536fb5771309b69aa9df35604db7b89
|
|
4
|
+
data.tar.gz: dd10068c7f5b243c0fe6b5d56b572ab06cdfe3a33bcf6449c8758e94e4e17147
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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,
|
|
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 (
|
|
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
|
-
│
|
|
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
|
-
│
|
|
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/` |
|
|
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
|
|
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
|
data/lib/legion/data/version.rb
CHANGED
data/lib/legion/data.rb
CHANGED
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.
|
|
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
|