legion-data 1.8.6 → 1.8.8

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: edd18502b1d95a3863975b1144fa9b53cbc1a51d6306f20d2e02cb6b316d488c
4
- data.tar.gz: eae1da697b4296e99898852da936a7247791e39e11e2d70fa0d64403e02145d6
3
+ metadata.gz: 60b8f26149494282c49455aedc216eebf0db867fa359dea9404ca44d09ad9815
4
+ data.tar.gz: 4da8dfdb277d9ceda6807543f58c2804ae71f938056cff7f8bcd366c4bad9cae
5
5
  SHA512:
6
- metadata.gz: da91b8a4a865c22dc85853f725eddaacbae069b4550ceebb38cf44cc07ec57c8c29fe0bdabccd0b542a677893af2c6622ac12ae43c8fcb395ae955627729e4f8
7
- data.tar.gz: ff3630c3f7f33082ccef8f6b9c30be34e0d0b222c443ad6ff146963b3655d8c4239fa683293954a9fd1f95c8d476a3536b30304289e3c1b476c5c3536ded5297
6
+ metadata.gz: ef647d212100c659d28847879153403ac1dd42c55c0cb9b1529fd1e17d73f029a912d23988f6701e59e4b25d326b8512cd89f0291bcc52a9e492e6fd4c85b055
7
+ data.tar.gz: '018844cceb163d4100cffcfa8ea1ed06b916889ca14111e9ca8398d9c3d2a045c9e9c4d73f735e8c22f681ccc834c23f732d08d68303973251c60085f5013c1b'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Legion::Data Changelog
2
2
 
3
+ ## [1.8.8] - 2026-05-20
4
+
5
+ ### Added
6
+ - `Legion::Data::Connection.reconnect_with_fresh_creds` — updates Sequel's internal connection opts with fresh credentials from `Legion::Settings[:data][:creds]` and reconnects the pool. Called by `LeaseManager#trigger_postgresql_reconnect` after Vault dynamic PostgreSQL lease rotation.
7
+
8
+ ### Fixed
9
+ - Vault dynamic PostgreSQL credential rotation: after lease expiry, connections would fail with `PG::ConnectionBad: role "v-legionio-node-..." does not exist` because Sequel retained the original (revoked) credentials in `@opts`. The legacy fallback (`disconnect` + `test_connection`) was insufficient since it doesn't update stored credentials.
10
+
11
+ ## [1.8.7] - 2026-05-17
12
+
13
+ ### Added
14
+ - Migrations 103-114: adds standardized identity columns (`access_scope`, `identity_principal_id`, `identity_id`, `identity_canonical_name`) to all 12 LLM lifecycle tables. Tables that already carried identity columns under legacy names (`principal_id`/`identity_id` on `llm_conversations`, `caller_principal_id`/`caller_identity_id` on `llm_message_inference_requests`) receive only `access_scope` and `identity_canonical_name` — existing columns are not renamed. Each table is its own migration with full `access_scope` index and partial `identity_principal_id` index.
15
+
3
16
  ## [1.8.6] - 2026-05-15
4
17
 
5
18
  ### Added
@@ -267,6 +267,36 @@ module Legion
267
267
  log.info 'Legion::Data connection closed'
268
268
  end
269
269
 
270
+ def reconnect_with_fresh_creds
271
+ return false unless @sequel
272
+ return false if adapter == :sqlite
273
+
274
+ fresh_creds = Legion::Settings[:data][:creds]
275
+ return false unless fresh_creds.is_a?(Hash)
276
+
277
+ new_user = fresh_creds[:user] || fresh_creds[:username]
278
+ new_pass = fresh_creds[:password]
279
+
280
+ unless new_user && new_pass
281
+ log.error('reconnect_with_fresh_creds: no user/password in Settings[:data][:creds]')
282
+ return false
283
+ end
284
+
285
+ old_user = @sequel.opts[:user]
286
+ @sequel.opts[:user] = new_user
287
+ @sequel.opts[:password] = new_pass
288
+
289
+ @sequel.disconnect
290
+
291
+ @sequel.test_connection
292
+ log.info("reconnect_with_fresh_creds: rotated credentials (#{old_user} → #{new_user})")
293
+ true
294
+ rescue StandardError => e
295
+ handle_exception(e, level: :error, handled: true, operation: :reconnect_with_fresh_creds,
296
+ old_user: old_user, new_user: new_user)
297
+ false
298
+ end
299
+
270
300
  def connect_with_replicas
271
301
  return unless adapter == :postgres
272
302
 
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # llm_conversations already has principal_id and identity_id (077).
4
+ # Add only the two missing standardized columns: access_scope and identity_canonical_name.
5
+ # Existing columns are NOT renamed — they are in active use by lex-llm-ledger.
6
+
7
+ Sequel.migration do
8
+ up do
9
+ alter_table(:llm_conversations) do
10
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
11
+ add_column :identity_canonical_name, String, size: 255, null: true
12
+ add_index :access_scope, name: :idx_conversations_access_scope
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_conversations) do
18
+ drop_index :access_scope, name: :idx_conversations_access_scope
19
+ drop_column :access_scope
20
+ drop_column :identity_canonical_name
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_messages) do
6
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
7
+ add_column :identity_principal_id, Integer, null: true
8
+ add_column :identity_id, Integer, null: true
9
+ add_column :identity_canonical_name, String, size: 255, null: true
10
+ add_index :access_scope, name: :idx_messages_access_scope
11
+ add_index :identity_principal_id, name: :idx_messages_identity_principal_id,
12
+ where: Sequel.negate(identity_principal_id: nil)
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_messages) do
18
+ drop_index :identity_principal_id, name: :idx_messages_identity_principal_id
19
+ drop_index :access_scope, name: :idx_messages_access_scope
20
+ drop_column :access_scope
21
+ drop_column :identity_principal_id
22
+ drop_column :identity_id
23
+ drop_column :identity_canonical_name
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # llm_message_inference_requests already has caller_principal_id and caller_identity_id (079).
4
+ # Add only the two missing standardized columns: access_scope and identity_canonical_name.
5
+ # Existing columns are NOT renamed — they are in active use by lex-llm-ledger.
6
+
7
+ Sequel.migration do
8
+ up do
9
+ alter_table(:llm_message_inference_requests) do
10
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
11
+ add_column :identity_canonical_name, String, size: 255, null: true
12
+ add_index :access_scope, name: :idx_inference_requests_access_scope
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_message_inference_requests) do
18
+ drop_index :access_scope, name: :idx_inference_requests_access_scope
19
+ drop_column :access_scope
20
+ drop_column :identity_canonical_name
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_message_inference_responses) do
6
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
7
+ add_column :identity_principal_id, Integer, null: true
8
+ add_column :identity_id, Integer, null: true
9
+ add_column :identity_canonical_name, String, size: 255, null: true
10
+ add_index :access_scope, name: :idx_message_inference_responses_access_scope
11
+ add_index :identity_principal_id, name: :idx_message_inference_responses_identity_principal_id,
12
+ where: Sequel.negate(identity_principal_id: nil)
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_message_inference_responses) do
18
+ drop_index :identity_principal_id, name: :idx_message_inference_responses_identity_principal_id
19
+ drop_index :access_scope, name: :idx_message_inference_responses_access_scope
20
+ drop_column :access_scope
21
+ drop_column :identity_principal_id
22
+ drop_column :identity_id
23
+ drop_column :identity_canonical_name
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_route_attempts) do
6
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
7
+ add_column :identity_principal_id, Integer, null: true
8
+ add_column :identity_id, Integer, null: true
9
+ add_column :identity_canonical_name, String, size: 255, null: true
10
+ add_index :access_scope, name: :idx_route_attempts_access_scope
11
+ add_index :identity_principal_id, name: :idx_route_attempts_identity_principal_id,
12
+ where: Sequel.negate(identity_principal_id: nil)
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_route_attempts) do
18
+ drop_index :identity_principal_id, name: :idx_route_attempts_identity_principal_id
19
+ drop_index :access_scope, name: :idx_route_attempts_access_scope
20
+ drop_column :access_scope
21
+ drop_column :identity_principal_id
22
+ drop_column :identity_id
23
+ drop_column :identity_canonical_name
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_message_inference_metrics) do
6
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
7
+ add_column :identity_principal_id, Integer, null: true
8
+ add_column :identity_id, Integer, null: true
9
+ add_column :identity_canonical_name, String, size: 255, null: true
10
+ add_index :access_scope, name: :idx_message_inference_metrics_access_scope
11
+ add_index :identity_principal_id, name: :idx_message_inference_metrics_identity_principal_id,
12
+ where: Sequel.negate(identity_principal_id: nil)
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_message_inference_metrics) do
18
+ drop_index :identity_principal_id, name: :idx_message_inference_metrics_identity_principal_id
19
+ drop_index :access_scope, name: :idx_message_inference_metrics_access_scope
20
+ drop_column :access_scope
21
+ drop_column :identity_principal_id
22
+ drop_column :identity_id
23
+ drop_column :identity_canonical_name
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_tool_calls) do
6
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
7
+ add_column :identity_principal_id, Integer, null: true
8
+ add_column :identity_id, Integer, null: true
9
+ add_column :identity_canonical_name, String, size: 255, null: true
10
+ add_index :access_scope, name: :idx_tool_calls_access_scope
11
+ add_index :identity_principal_id, name: :idx_tool_calls_identity_principal_id,
12
+ where: Sequel.negate(identity_principal_id: nil)
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_tool_calls) do
18
+ drop_index :identity_principal_id, name: :idx_tool_calls_identity_principal_id
19
+ drop_index :access_scope, name: :idx_tool_calls_access_scope
20
+ drop_column :access_scope
21
+ drop_column :identity_principal_id
22
+ drop_column :identity_id
23
+ drop_column :identity_canonical_name
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_tool_call_attempts) do
6
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
7
+ add_column :identity_principal_id, Integer, null: true
8
+ add_column :identity_id, Integer, null: true
9
+ add_column :identity_canonical_name, String, size: 255, null: true
10
+ add_index :access_scope, name: :idx_tool_call_attempts_access_scope
11
+ add_index :identity_principal_id, name: :idx_tool_call_attempts_identity_principal_id,
12
+ where: Sequel.negate(identity_principal_id: nil)
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_tool_call_attempts) do
18
+ drop_index :identity_principal_id, name: :idx_tool_call_attempts_identity_principal_id
19
+ drop_index :access_scope, name: :idx_tool_call_attempts_access_scope
20
+ drop_column :access_scope
21
+ drop_column :identity_principal_id
22
+ drop_column :identity_id
23
+ drop_column :identity_canonical_name
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_conversation_compactions) do
6
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
7
+ add_column :identity_principal_id, Integer, null: true
8
+ add_column :identity_id, Integer, null: true
9
+ add_column :identity_canonical_name, String, size: 255, null: true
10
+ add_index :access_scope, name: :idx_conversation_compactions_access_scope
11
+ add_index :identity_principal_id, name: :idx_conversation_compactions_identity_principal_id,
12
+ where: Sequel.negate(identity_principal_id: nil)
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_conversation_compactions) do
18
+ drop_index :identity_principal_id, name: :idx_conversation_compactions_identity_principal_id
19
+ drop_index :access_scope, name: :idx_conversation_compactions_access_scope
20
+ drop_column :access_scope
21
+ drop_column :identity_principal_id
22
+ drop_column :identity_id
23
+ drop_column :identity_canonical_name
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_policy_evaluations) do
6
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
7
+ add_column :identity_principal_id, Integer, null: true
8
+ add_column :identity_id, Integer, null: true
9
+ add_column :identity_canonical_name, String, size: 255, null: true
10
+ add_index :access_scope, name: :idx_policy_evaluations_access_scope
11
+ add_index :identity_principal_id, name: :idx_policy_evaluations_identity_principal_id,
12
+ where: Sequel.negate(identity_principal_id: nil)
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_policy_evaluations) do
18
+ drop_index :identity_principal_id, name: :idx_policy_evaluations_identity_principal_id
19
+ drop_index :access_scope, name: :idx_policy_evaluations_access_scope
20
+ drop_column :access_scope
21
+ drop_column :identity_principal_id
22
+ drop_column :identity_id
23
+ drop_column :identity_canonical_name
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_security_events) do
6
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
7
+ add_column :identity_principal_id, Integer, null: true
8
+ add_column :identity_id, Integer, null: true
9
+ add_column :identity_canonical_name, String, size: 255, null: true
10
+ add_index :access_scope, name: :idx_security_events_access_scope
11
+ add_index :identity_principal_id, name: :idx_security_events_identity_principal_id,
12
+ where: Sequel.negate(identity_principal_id: nil)
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_security_events) do
18
+ drop_index :identity_principal_id, name: :idx_security_events_identity_principal_id
19
+ drop_index :access_scope, name: :idx_security_events_access_scope
20
+ drop_column :access_scope
21
+ drop_column :identity_principal_id
22
+ drop_column :identity_id
23
+ drop_column :identity_canonical_name
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_registry_events) do
6
+ add_column :access_scope, String, size: 20, null: false, default: 'global'
7
+ add_column :identity_principal_id, Integer, null: true
8
+ add_column :identity_id, Integer, null: true
9
+ add_column :identity_canonical_name, String, size: 255, null: true
10
+ add_index :access_scope, name: :idx_registry_events_access_scope
11
+ add_index :identity_principal_id, name: :idx_registry_events_identity_principal_id,
12
+ where: Sequel.negate(identity_principal_id: nil)
13
+ end
14
+ end
15
+
16
+ down do
17
+ alter_table(:llm_registry_events) do
18
+ drop_index :identity_principal_id, name: :idx_registry_events_identity_principal_id
19
+ drop_index :access_scope, name: :idx_registry_events_access_scope
20
+ drop_column :access_scope
21
+ drop_column :identity_principal_id
22
+ drop_column :identity_id
23
+ drop_column :identity_canonical_name
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ up do
5
+ alter_table(:llm_message_inference_requests) do
6
+ add_column :runtime_caller_class, String, size: 255, null: true, index: true
7
+ add_column :runtime_caller_client, String, size: 255, null: true
8
+ end
9
+ end
10
+
11
+ down do
12
+ alter_table(:llm_message_inference_requests) do
13
+ drop_index :runtime_caller_class
14
+ drop_column :runtime_caller_class
15
+ drop_column :runtime_caller_client
16
+ end
17
+ end
18
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Data
5
- VERSION = '1.8.6'
5
+ VERSION = '1.8.8'
6
6
  end
7
7
  end
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.8.6
4
+ version: 1.8.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -249,6 +249,19 @@ files:
249
249
  - lib/legion/data/migrations/100_create_apollo_entries_sqlite.rb
250
250
  - lib/legion/data/migrations/101_add_apollo_identity_and_access_scope.rb
251
251
  - lib/legion/data/migrations/102_add_apollo_access_scope_and_identity_indexes.rb
252
+ - lib/legion/data/migrations/103_add_llm_conversations_identity_columns.rb
253
+ - lib/legion/data/migrations/104_add_llm_messages_identity_columns.rb
254
+ - lib/legion/data/migrations/105_add_llm_message_inference_requests_identity_columns.rb
255
+ - lib/legion/data/migrations/106_add_llm_message_inference_responses_identity_columns.rb
256
+ - lib/legion/data/migrations/107_add_llm_route_attempts_identity_columns.rb
257
+ - lib/legion/data/migrations/108_add_llm_message_inference_metrics_identity_columns.rb
258
+ - lib/legion/data/migrations/109_add_llm_tool_calls_identity_columns.rb
259
+ - lib/legion/data/migrations/110_add_llm_tool_call_attempts_identity_columns.rb
260
+ - lib/legion/data/migrations/111_add_llm_conversation_compactions_identity_columns.rb
261
+ - lib/legion/data/migrations/112_add_llm_policy_evaluations_identity_columns.rb
262
+ - lib/legion/data/migrations/113_add_llm_security_events_identity_columns.rb
263
+ - lib/legion/data/migrations/114_add_llm_registry_events_identity_columns.rb
264
+ - lib/legion/data/migrations/115_add_runtime_caller_columns.rb
252
265
  - lib/legion/data/model.rb
253
266
  - lib/legion/data/models/apollo/access_log.rb
254
267
  - lib/legion/data/models/apollo/entries.rb