legion-data 1.6.15 → 1.6.17
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/.github/workflows/ci.yml +36 -2
- data/.rubocop.yml +15 -45
- data/CHANGELOG.md +20 -0
- data/Gemfile +1 -1
- data/lib/legion/data/extract/handlers/base.rb +2 -2
- data/lib/legion/data/extract/handlers/xlsx.rb +2 -2
- data/lib/legion/data/extract.rb +2 -1
- data/lib/legion/data/migrations/019_add_audit_hash_chain.rb +40 -11
- data/lib/legion/data/migrations/020_add_webhooks.rb +6 -0
- data/lib/legion/data/migrations/060_add_knowledge_tiers.rb +38 -0
- data/lib/legion/data/settings.rb +1 -1
- data/lib/legion/data/version.rb +1 -1
- 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: 751fcaf222628502475f1d3fd7563f1162836d7de4e3a2949724c2324387890e
|
|
4
|
+
data.tar.gz: c6787226b1fce54751d250bf27fecb4ada9538f7c2d466bb9215d4386ae607b8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1b52c53a9993f31862973c3b4117b985c21aa5a344979083dcd69b912c00be6c42461e45a5e583970dfe9ae2824841e869a89d4cdf3eab46fb15f6a66d698e91
|
|
7
|
+
data.tar.gz: f35cbc4955c14f93a4c5fea5188fd766cf8b09061467d9764de56835ff7a2f95ada6c5e976c3fcf6e41b2af69f850dbf0e6e53d66d98be6ded80db6894cc8cf3
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -10,6 +10,40 @@ jobs:
|
|
|
10
10
|
ci:
|
|
11
11
|
uses: LegionIO/.github/.github/workflows/ci.yml@main
|
|
12
12
|
|
|
13
|
+
ci-postgres:
|
|
14
|
+
name: "RSpec (PostgreSQL)"
|
|
15
|
+
timeout-minutes: 15
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
services:
|
|
18
|
+
postgres:
|
|
19
|
+
image: postgres:16-alpine
|
|
20
|
+
env:
|
|
21
|
+
POSTGRES_USER: legion
|
|
22
|
+
POSTGRES_PASSWORD: legion
|
|
23
|
+
POSTGRES_DB: legionio
|
|
24
|
+
ports:
|
|
25
|
+
- 5432:5432
|
|
26
|
+
options: >-
|
|
27
|
+
--health-cmd pg_isready
|
|
28
|
+
--health-interval 10s
|
|
29
|
+
--health-timeout 5s
|
|
30
|
+
--health-retries 5
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
- uses: ruby/setup-ruby@v1
|
|
34
|
+
with:
|
|
35
|
+
ruby-version: '3.4'
|
|
36
|
+
bundler-cache: true
|
|
37
|
+
- name: Run RSpec (PostgreSQL adapter)
|
|
38
|
+
env:
|
|
39
|
+
LEGION_DATA_ADAPTER: postgres
|
|
40
|
+
LEGION_DATA_HOST: 127.0.0.1
|
|
41
|
+
LEGION_DATA_PORT: 5432
|
|
42
|
+
LEGION_DATA_USER: legion
|
|
43
|
+
LEGION_DATA_PASSWORD: legion
|
|
44
|
+
LEGION_DATA_DATABASE: legionio
|
|
45
|
+
run: bundle exec rspec
|
|
46
|
+
|
|
13
47
|
lint:
|
|
14
48
|
uses: LegionIO/.github/.github/workflows/lint-patterns.yml@main
|
|
15
49
|
|
|
@@ -27,8 +61,8 @@ jobs:
|
|
|
27
61
|
uses: LegionIO/.github/.github/workflows/stale.yml@main
|
|
28
62
|
|
|
29
63
|
release:
|
|
30
|
-
needs: [ci, lint]
|
|
64
|
+
needs: [ci, ci-postgres, lint]
|
|
31
65
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
32
66
|
uses: LegionIO/.github/.github/workflows/release.yml@main
|
|
33
67
|
secrets:
|
|
34
|
-
rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
|
|
68
|
+
rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
|
data/.rubocop.yml
CHANGED
|
@@ -1,26 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
NewCops: enable
|
|
4
|
-
SuggestExtensions: false
|
|
1
|
+
inherit_gem:
|
|
2
|
+
rubocop-legion: config/core.yml
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
Max:
|
|
8
|
-
|
|
9
|
-
Layout/SpaceAroundEqualsInParameterDefault:
|
|
10
|
-
EnforcedStyle: space
|
|
11
|
-
|
|
12
|
-
Layout/HashAlignment:
|
|
13
|
-
EnforcedHashRocketStyle: table
|
|
14
|
-
EnforcedColonStyle: table
|
|
15
|
-
|
|
16
|
-
Metrics/MethodLength:
|
|
17
|
-
Max: 50
|
|
18
|
-
|
|
19
|
-
Metrics/ClassLength:
|
|
20
|
-
Max: 1500
|
|
21
|
-
|
|
22
|
-
Metrics/ModuleLength:
|
|
23
|
-
Max: 1500
|
|
4
|
+
Metrics/ParameterLists:
|
|
5
|
+
Max: 8
|
|
24
6
|
|
|
25
7
|
Metrics/BlockLength:
|
|
26
8
|
Max: 40
|
|
@@ -28,34 +10,22 @@ Metrics/BlockLength:
|
|
|
28
10
|
- 'spec/**/*'
|
|
29
11
|
- 'lib/legion/data/migrations/**/*'
|
|
30
12
|
|
|
31
|
-
|
|
32
|
-
Max: 60
|
|
33
|
-
|
|
34
|
-
Metrics/CyclomaticComplexity:
|
|
35
|
-
Max: 15
|
|
36
|
-
|
|
37
|
-
Metrics/PerceivedComplexity:
|
|
38
|
-
Max: 17
|
|
39
|
-
|
|
40
|
-
Style/Documentation:
|
|
13
|
+
Naming/VariableNumber:
|
|
41
14
|
Enabled: false
|
|
42
15
|
|
|
43
|
-
Style/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Style/FrozenStringLiteralComment:
|
|
47
|
-
Enabled: true
|
|
48
|
-
EnforcedStyle: always
|
|
16
|
+
Style/FileOpen:
|
|
17
|
+
Exclude:
|
|
18
|
+
- 'lib/legion/data/connection.rb'
|
|
49
19
|
|
|
50
|
-
|
|
20
|
+
# Pre-existing patterns — suppress until addressed in a dedicated cleanup PR
|
|
21
|
+
ThreadSafety/ClassInstanceVariable:
|
|
51
22
|
Enabled: false
|
|
52
23
|
|
|
53
|
-
|
|
24
|
+
ThreadSafety/ClassAndModuleAttributes:
|
|
54
25
|
Enabled: false
|
|
55
26
|
|
|
56
|
-
|
|
57
|
-
|
|
27
|
+
Legion/RescueLogging/NoCapture:
|
|
28
|
+
Enabled: false
|
|
58
29
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- 'lib/legion/data/connection.rb'
|
|
30
|
+
Legion/Framework/EagerSequelModel:
|
|
31
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.6.17] - 2026-03-30
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Migration 060: L0/L1 summary columns on `apollo_entries` (`summary_l0` VARCHAR 500, `summary_l1` TEXT, `knowledge_tier` VARCHAR 4 default 'L2', `parent_entry_id` UUID, `l0_generated_at` timestamptz, `l1_generated_at` timestamptz) — postgres only
|
|
9
|
+
- Migration 060: named indexes `idx_apollo_knowledge_tier` and `idx_apollo_parent_entry` on `apollo_entries`
|
|
10
|
+
- Spec for migration 060 covering column presence, types, nullability, defaults, indexes, and idempotency
|
|
11
|
+
|
|
12
|
+
## [1.6.16] - 2026-03-30
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- Migration 019: widen `record_hash` column to size 255 via `set_column_type` (column added in migration 017)
|
|
16
|
+
- Migration 019: rename `prev_hash` to `previous_hash` via `rename_column` instead of adding a duplicate column
|
|
17
|
+
- Migration 019: decouple index creation from column existence checks so indexes are always guarded by their own `idxs.key?` check
|
|
18
|
+
- Migration 019: `down` no longer drops `record_hash` (owned by migration 017, not 019)
|
|
19
|
+
- Migration 019: replace `db.indexes` with bare `indexes()` — inside a `Sequel.migration` block `self` is the DB object, so `db` is undefined
|
|
20
|
+
- Updated to rubocop-legion (`inherit_gem: config/core.yml`) for shared LegionIO cop configuration
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- Migration 019 spec: 8 examples covering column presence, defaults, indexes, idempotency, and rollback
|
|
24
|
+
|
|
5
25
|
## [1.6.15] - 2026-03-29
|
|
6
26
|
|
|
7
27
|
### Added
|
data/Gemfile
CHANGED
|
@@ -5,7 +5,7 @@ module Legion
|
|
|
5
5
|
module Extract
|
|
6
6
|
module Handlers
|
|
7
7
|
class Base
|
|
8
|
-
@registry = {}
|
|
8
|
+
@registry = {}.freeze
|
|
9
9
|
|
|
10
10
|
class << self
|
|
11
11
|
attr_reader :registry
|
|
@@ -22,7 +22,7 @@ module Legion
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def register(handler_class)
|
|
25
|
-
@registry
|
|
25
|
+
@registry = @registry.merge(handler_class.type => handler_class).freeze
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def for_type(type)
|
|
@@ -16,11 +16,11 @@ module Legion
|
|
|
16
16
|
workbook = ::RubyXL::Parser.parse(source)
|
|
17
17
|
sheets = []
|
|
18
18
|
workbook.worksheets.each do |sheet|
|
|
19
|
-
rows = sheet.each.
|
|
19
|
+
rows = sheet.each.filter_map do |row|
|
|
20
20
|
next unless row
|
|
21
21
|
|
|
22
22
|
row.cells.map { |c| c&.value.to_s }.join(', ')
|
|
23
|
-
end
|
|
23
|
+
end
|
|
24
24
|
sheets << "Sheet: #{sheet.sheet_name}\n#{rows.join("\n")}" unless rows.empty?
|
|
25
25
|
end
|
|
26
26
|
text = sheets.join("\n\n")
|
data/lib/legion/data/extract.rb
CHANGED
|
@@ -4,15 +4,32 @@ Sequel.migration do
|
|
|
4
4
|
up do
|
|
5
5
|
return unless table_exists?(:audit_log)
|
|
6
6
|
|
|
7
|
-
cols
|
|
7
|
+
cols = schema(:audit_log).map(&:first)
|
|
8
|
+
idxs = indexes(:audit_log)
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
add_index :retention_tier, if_not_exists: true
|
|
10
|
+
# record_hash exists from migration 017 at size 64; widen to 255 if needed.
|
|
11
|
+
if cols.include?(:record_hash)
|
|
12
|
+
set_column_type :audit_log, :record_hash, String, size: 255
|
|
13
|
+
else
|
|
14
|
+
alter_table(:audit_log) { add_column :record_hash, String, size: 255 }
|
|
15
15
|
end
|
|
16
|
+
|
|
17
|
+
add_index :audit_log, :record_hash unless idxs.key?(:audit_log_record_hash_index)
|
|
18
|
+
|
|
19
|
+
# Rename prev_hash (introduced in migration 017) to previous_hash for clarity,
|
|
20
|
+
# then widen it to 255 to match record_hash.
|
|
21
|
+
if cols.include?(:prev_hash) && !cols.include?(:previous_hash)
|
|
22
|
+
rename_column :audit_log, :prev_hash, :previous_hash
|
|
23
|
+
set_column_type :audit_log, :previous_hash, String, size: 255
|
|
24
|
+
elsif !cols.include?(:previous_hash)
|
|
25
|
+
alter_table(:audit_log) { add_column :previous_hash, String, size: 255 }
|
|
26
|
+
elsif cols.include?(:previous_hash)
|
|
27
|
+
set_column_type :audit_log, :previous_hash, String, size: 255
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
alter_table(:audit_log) { add_column :retention_tier, String, size: 10, default: 'hot' } unless cols.include?(:retention_tier)
|
|
31
|
+
|
|
32
|
+
add_index :audit_log, :retention_tier unless idxs.key?(:audit_log_retention_tier_index)
|
|
16
33
|
end
|
|
17
34
|
|
|
18
35
|
down do
|
|
@@ -20,10 +37,22 @@ Sequel.migration do
|
|
|
20
37
|
|
|
21
38
|
cols = schema(:audit_log).map(&:first)
|
|
22
39
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
drop_index :audit_log, :record_hash, if_exists: true
|
|
41
|
+
|
|
42
|
+
# Restore record_hash to its original size (64 from migration 017).
|
|
43
|
+
set_column_type :audit_log, :record_hash, String, size: 64 if cols.include?(:record_hash)
|
|
44
|
+
|
|
45
|
+
# Rename previous_hash back to prev_hash (reverse of the up rename) and restore size to 64.
|
|
46
|
+
if cols.include?(:previous_hash) && !cols.include?(:prev_hash)
|
|
47
|
+
rename_column :audit_log, :previous_hash, :prev_hash
|
|
48
|
+
set_column_type :audit_log, :prev_hash, String, size: 64
|
|
49
|
+
elsif cols.include?(:previous_hash)
|
|
50
|
+
alter_table(:audit_log) { drop_column :previous_hash }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if cols.include?(:retention_tier)
|
|
54
|
+
drop_index :audit_log, :retention_tier, if_exists: true
|
|
55
|
+
alter_table(:audit_log) { drop_column :retention_tier }
|
|
27
56
|
end
|
|
28
57
|
end
|
|
29
58
|
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
up do
|
|
5
|
+
next unless adapter_scheme == :postgres
|
|
6
|
+
next unless table_exists?(:apollo_entries)
|
|
7
|
+
|
|
8
|
+
existing_columns = schema(:apollo_entries).map(&:first)
|
|
9
|
+
|
|
10
|
+
alter_table(:apollo_entries) do
|
|
11
|
+
add_column :summary_l0, String, size: 500, null: true unless existing_columns.include?(:summary_l0)
|
|
12
|
+
add_column :summary_l1, :text, null: true unless existing_columns.include?(:summary_l1)
|
|
13
|
+
add_column :knowledge_tier, String, size: 4, null: false, default: 'L2' unless existing_columns.include?(:knowledge_tier)
|
|
14
|
+
add_column :parent_entry_id, :uuid, null: true unless existing_columns.include?(:parent_entry_id)
|
|
15
|
+
add_column :l0_generated_at, :timestamptz, null: true unless existing_columns.include?(:l0_generated_at)
|
|
16
|
+
add_column :l1_generated_at, :timestamptz, null: true unless existing_columns.include?(:l1_generated_at)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
add_index :apollo_entries, :knowledge_tier, name: :idx_apollo_knowledge_tier, if_not_exists: true
|
|
20
|
+
add_index :apollo_entries, :parent_entry_id, name: :idx_apollo_parent_entry, if_not_exists: true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
down do
|
|
24
|
+
next unless adapter_scheme == :postgres
|
|
25
|
+
next unless table_exists?(:apollo_entries)
|
|
26
|
+
|
|
27
|
+
existing_columns = schema(:apollo_entries).map(&:first)
|
|
28
|
+
|
|
29
|
+
alter_table(:apollo_entries) do
|
|
30
|
+
drop_column :summary_l0 if existing_columns.include?(:summary_l0)
|
|
31
|
+
drop_column :summary_l1 if existing_columns.include?(:summary_l1)
|
|
32
|
+
drop_column :knowledge_tier if existing_columns.include?(:knowledge_tier)
|
|
33
|
+
drop_column :parent_entry_id if existing_columns.include?(:parent_entry_id)
|
|
34
|
+
drop_column :l0_generated_at if existing_columns.include?(:l0_generated_at)
|
|
35
|
+
drop_column :l1_generated_at if existing_columns.include?(:l1_generated_at)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/lib/legion/data/settings.rb
CHANGED
|
@@ -128,7 +128,7 @@ module Legion
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
begin
|
|
131
|
-
Legion::Settings.merge_settings('data', Legion::Data::Settings.default) if Legion.const_defined?('Settings')
|
|
131
|
+
Legion::Settings.merge_settings('data', Legion::Data::Settings.default) if Legion.const_defined?('Settings', false)
|
|
132
132
|
rescue StandardError => e
|
|
133
133
|
Legion::Logging.fatal(e.message) if Legion::Logging.method_defined?(:fatal)
|
|
134
134
|
end
|
data/lib/legion/data/version.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.6.
|
|
4
|
+
version: 1.6.17
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -189,6 +189,7 @@ files:
|
|
|
189
189
|
- lib/legion/data/migrations/057_add_routing_key_to_runners.rb
|
|
190
190
|
- lib/legion/data/migrations/058_add_audit_records.rb
|
|
191
191
|
- lib/legion/data/migrations/059_create_chains.rb
|
|
192
|
+
- lib/legion/data/migrations/060_add_knowledge_tiers.rb
|
|
192
193
|
- lib/legion/data/model.rb
|
|
193
194
|
- lib/legion/data/models/apollo_access_log.rb
|
|
194
195
|
- lib/legion/data/models/apollo_entry.rb
|