legion-data 1.7.4 → 1.8.1

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +66 -13
  3. data/CHANGELOG.md +24 -0
  4. data/CLAUDE.md +44 -307
  5. data/README.md +100 -6
  6. data/lib/legion/data/migrations/077_create_llm_conversations.rb +32 -0
  7. data/lib/legion/data/migrations/078_create_llm_messages.rb +33 -0
  8. data/lib/legion/data/migrations/079_create_llm_message_inference_requests.rb +47 -0
  9. data/lib/legion/data/migrations/080_create_llm_message_inference_responses.rb +39 -0
  10. data/lib/legion/data/migrations/081_add_llm_message_inference_foreign_keys.rb +17 -0
  11. data/lib/legion/data/migrations/082_create_llm_route_attempts.rb +31 -0
  12. data/lib/legion/data/migrations/083_create_llm_message_inference_metrics.rb +36 -0
  13. data/lib/legion/data/migrations/084_create_llm_tool_calls.rb +32 -0
  14. data/lib/legion/data/migrations/085_add_llm_message_tool_call_foreign_key.rb +15 -0
  15. data/lib/legion/data/migrations/086_create_llm_tool_call_attempts.rb +30 -0
  16. data/lib/legion/data/migrations/087_create_llm_conversation_compactions.rb +31 -0
  17. data/lib/legion/data/migrations/088_create_llm_policy_evaluations.rb +33 -0
  18. data/lib/legion/data/migrations/089_create_llm_security_events.rb +33 -0
  19. data/lib/legion/data/migrations/090_create_llm_registry_events.rb +23 -0
  20. data/lib/legion/data/migrations/091_create_portable_identity_providers.rb +35 -0
  21. data/lib/legion/data/migrations/092_create_portable_identity_principals.rb +25 -0
  22. data/lib/legion/data/migrations/093_create_portable_identities.rb +31 -0
  23. data/lib/legion/data/migrations/094_create_portable_identity_groups.rb +21 -0
  24. data/lib/legion/data/migrations/095_create_portable_identity_group_memberships.rb +25 -0
  25. data/lib/legion/data/migrations/096_create_portable_identity_audit_log.rb +26 -0
  26. data/lib/legion/data/migrations/097_add_llm_dispatch_fields.rb +16 -0
  27. data/lib/legion/data/model.rb +11 -1
  28. data/lib/legion/data/models/apollo/access_log.rb +17 -0
  29. data/lib/legion/data/models/apollo/entries.rb +22 -0
  30. data/lib/legion/data/models/apollo/expertise.rb +16 -0
  31. data/lib/legion/data/models/apollo/model_helpers.rb +17 -0
  32. data/lib/legion/data/models/apollo/operation.rb +16 -0
  33. data/lib/legion/data/models/apollo/relation.rb +18 -0
  34. data/lib/legion/data/models/function.rb +1 -0
  35. data/lib/legion/data/models/identity/audit_log.rb +20 -0
  36. data/lib/legion/data/models/identity/group.rb +28 -0
  37. data/lib/legion/data/models/identity/group_memberships.rb +28 -0
  38. data/lib/legion/data/models/identity/identity.rb +24 -0
  39. data/lib/legion/data/models/identity/model_helpers.rb +86 -0
  40. data/lib/legion/data/models/identity/principal.rb +37 -0
  41. data/lib/legion/data/models/identity/providers.rb +34 -0
  42. data/lib/legion/data/models/identity.rb +7 -0
  43. data/lib/legion/data/models/identity_group.rb +13 -0
  44. data/lib/legion/data/models/identity_provider.rb +8 -0
  45. data/lib/legion/data/models/llm/conversation.rb +25 -0
  46. data/lib/legion/data/models/llm/conversation_compaction.rb +22 -0
  47. data/lib/legion/data/models/llm/message.rb +105 -0
  48. data/lib/legion/data/models/llm/message_inference_metric.rb +46 -0
  49. data/lib/legion/data/models/llm/message_inference_request.rb +80 -0
  50. data/lib/legion/data/models/llm/message_inference_response.rb +23 -0
  51. data/lib/legion/data/models/llm/model_helpers.rb +18 -0
  52. data/lib/legion/data/models/llm/policy_evaluation.rb +20 -0
  53. data/lib/legion/data/models/llm/registry_event.rb +15 -0
  54. data/lib/legion/data/models/llm/route_attempt.rb +18 -0
  55. data/lib/legion/data/models/llm/security_event.rb +66 -0
  56. data/lib/legion/data/models/llm/tool_call.rb +21 -0
  57. data/lib/legion/data/models/llm/tool_call_attempt.rb +18 -0
  58. data/lib/legion/data/models/node.rb +2 -1
  59. data/lib/legion/data/models/principal.rb +13 -0
  60. data/lib/legion/data/models/rbac/cross_team_grants.rb +25 -0
  61. data/lib/legion/data/models/rbac/model_helpers.rb +25 -0
  62. data/lib/legion/data/models/rbac/role_assignments.rb +25 -0
  63. data/lib/legion/data/models/rbac/runner_grants.rb +23 -0
  64. data/lib/legion/data/models/relationship.rb +1 -0
  65. data/lib/legion/data/models/runner.rb +24 -2
  66. data/lib/legion/data/models/task.rb +4 -0
  67. data/lib/legion/data/version.rb +1 -1
  68. metadata +52 -1
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ change do
5
+ create_table(:portable_identity_principals) do
6
+ primary_key :id
7
+ String :uuid, size: 36, null: false, unique: true
8
+ String :canonical_name, size: 255, null: false
9
+ String :kind, size: 64, null: false
10
+ String :employee_key, size: 255
11
+ String :display_name, size: 255
12
+ TrueClass :active, null: false, default: true
13
+ DateTime :last_seen_at
14
+ DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
15
+ DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
16
+
17
+ unique %i[canonical_name kind]
18
+ index :uuid
19
+ index :canonical_name
20
+ index :kind
21
+ index :employee_key
22
+ index :active
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ change do
5
+ create_table(:portable_identities) do
6
+ primary_key :id
7
+ String :uuid, size: 36, null: false, unique: true
8
+ foreign_key :principal_id, :portable_identity_principals, null: false, on_delete: :cascade
9
+ foreign_key :provider_id, :portable_identity_providers, null: false, on_delete: :cascade
10
+ String :provider_identity_key, size: 255, null: false
11
+ String :profile_ciphertext, text: true
12
+ TrueClass :active, null: false, default: true
13
+ DateTime :last_authenticated_at
14
+ String :account_type, size: 64, null: false, default: 'primary'
15
+ String :qualifier, size: 255
16
+ TrueClass :is_default, null: false, default: false
17
+ String :link_evidence, text: true
18
+ DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
19
+ DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
20
+
21
+ unique %i[principal_id provider_id provider_identity_key]
22
+ index :uuid
23
+ index :principal_id
24
+ index :provider_id
25
+ index :provider_identity_key
26
+ index %i[provider_id provider_identity_key]
27
+ index :active
28
+ index :is_default
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ change do
5
+ create_table(:portable_identity_groups) do
6
+ primary_key :id
7
+ String :uuid, size: 36, null: false, unique: true
8
+ String :name, size: 255, null: false, unique: true
9
+ String :source, size: 64, null: false, default: 'ldap'
10
+ String :description, text: true
11
+ TrueClass :active, null: false, default: true
12
+ DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
13
+ DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
14
+
15
+ index :uuid
16
+ index :name
17
+ index :source
18
+ index :active
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ change do
5
+ create_table(:portable_identity_group_memberships) do
6
+ primary_key :id
7
+ String :uuid, size: 36, null: false, unique: true
8
+ foreign_key :principal_id, :portable_identity_principals, null: false, on_delete: :cascade
9
+ foreign_key :group_id, :portable_identity_groups, null: false, on_delete: :cascade
10
+ String :status, size: 32, null: false, default: 'active'
11
+ String :discovered_by, size: 255, null: false
12
+ Integer :trust_weight, null: false, default: 50
13
+ DateTime :expires_at
14
+ DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
15
+ DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
16
+
17
+ unique %i[principal_id group_id discovered_by]
18
+ index :uuid
19
+ index :principal_id
20
+ index :group_id
21
+ index :status
22
+ index %i[principal_id status]
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ change do
5
+ create_table(:portable_identity_audit_log) do
6
+ primary_key :id
7
+ String :uuid, size: 36, null: false, unique: true
8
+ foreign_key :principal_id, :portable_identity_principals, on_delete: :set_null
9
+ foreign_key :identity_id, :portable_identities, on_delete: :set_null
10
+ String :provider_name, size: 255, null: false
11
+ String :event_type, size: 128, null: false
12
+ String :trust_level, size: 64
13
+ String :detail_payload, text: true
14
+ String :node_ref, size: 255
15
+ String :session_ref, size: 255
16
+ DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
17
+
18
+ index :uuid
19
+ index :principal_id
20
+ index :identity_id
21
+ index :event_type
22
+ index :created_at
23
+ index %i[principal_id event_type created_at]
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ change do
5
+ alter_table(:llm_message_inference_requests) do
6
+ add_column :operation, String, size: 64, null: false, default: 'chat'
7
+ add_column :correlation_id, String, size: 64
8
+ add_column :idempotency_key, String, size: 128
9
+ end
10
+
11
+ alter_table(:llm_message_inference_responses) do
12
+ add_column :provider_instance, String, size: 128
13
+ add_column :dispatch_path, String, size: 32
14
+ end
15
+ end
16
+ end
@@ -14,7 +14,17 @@ module Legion
14
14
  %w[extension function relationship chain task runner node setting digital_worker
15
15
  apollo_entry apollo_relation apollo_expertise apollo_access_log audit_log
16
16
  audit_record identity_provider principal identity identity_group
17
- identity_group_membership identity_audit_log extract_step_timing]
17
+ identity_group_membership identity_audit_log extract_step_timing
18
+ identity/identity identity/principal identity/providers identity/group
19
+ identity/group_memberships identity/audit_log
20
+ apollo/entries apollo/relation apollo/access_log apollo/expertise
21
+ apollo/operation
22
+ rbac/role_assignments rbac/runner_grants rbac/cross_team_grants
23
+ llm/conversation llm/message llm/message_inference_request
24
+ llm/message_inference_response llm/route_attempt
25
+ llm/message_inference_metric llm/tool_call llm/tool_call_attempt
26
+ llm/conversation_compaction llm/policy_evaluation
27
+ llm/security_event llm/registry_event]
18
28
  end
19
29
 
20
30
  def load
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Apollo::ModelHelpers.table_available?(:apollo_access_log)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ module Apollo
11
+ class AccessLog < Sequel::Model(:apollo_access_log)
12
+ many_to_one :entry, class: 'Legion::Data::Model::Apollo::Entry', key: :entry_id
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Apollo::ModelHelpers.table_available?(:apollo_entries)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ module Apollo
11
+ class Entry < Sequel::Model(:apollo_entries)
12
+ one_to_many :outgoing_relations, class: 'Legion::Data::Model::Apollo::Relation',
13
+ key: :from_entry_id
14
+ one_to_many :incoming_relations, class: 'Legion::Data::Model::Apollo::Relation',
15
+ key: :to_entry_id
16
+ one_to_many :access_logs, class: 'Legion::Data::Model::Apollo::AccessLog',
17
+ key: :entry_id
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Apollo::ModelHelpers.table_available?(:apollo_expertise)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ module Apollo
11
+ class Expertise < Sequel::Model(:apollo_expertise)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Data
5
+ module Model
6
+ module Apollo
7
+ module ModelHelpers
8
+ def self.table_available?(table_name)
9
+ Legion::Data::Connection.sequel&.table_exists?(table_name)
10
+ rescue StandardError
11
+ false
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Apollo::ModelHelpers.table_available?(:apollo_operations)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ module Apollo
11
+ class Operation < Sequel::Model(:apollo_operations)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Apollo::ModelHelpers.table_available?(:apollo_relations)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ module Apollo
11
+ class Relation < Sequel::Model(:apollo_relations)
12
+ many_to_one :from_entry, class: 'Legion::Data::Model::Apollo::Entry', key: :from_entry_id
13
+ many_to_one :to_entry, class: 'Legion::Data::Model::Apollo::Entry', key: :to_entry_id
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -11,6 +11,7 @@ module Legion
11
11
  many_to_one :runner
12
12
  one_to_many :trigger_relationships, class: 'Legion::Data::Model::Relationship', key: :trigger_id
13
13
  one_to_many :action_relationships, class: 'Legion::Data::Model::Relationship', key: :action_id
14
+ one_to_many :tasks
14
15
 
15
16
  def embedding_vector
16
17
  return nil unless embedding
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Identity::ModelHelpers.table_available?(:portable_identity_audit_log)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ class Identity
11
+ class AuditLog < Sequel::Model(:portable_identity_audit_log)
12
+ include ModelHelpers
13
+
14
+ many_to_one :principal, class: 'Legion::Data::Model::Identity::Principal'
15
+ many_to_one :identity, class: 'Legion::Data::Model::Identity::Identity'
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Identity::ModelHelpers.table_available?(:portable_identity_groups)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ class Identity
11
+ class Group < Sequel::Model(:portable_identity_groups)
12
+ include ModelHelpers
13
+
14
+ one_to_many :memberships, class: 'Legion::Data::Model::Identity::GroupMembership', key: :group_id
15
+ many_to_many :principals,
16
+ class: 'Legion::Data::Model::Identity::Principal',
17
+ join_table: :portable_identity_group_memberships,
18
+ left_key: :group_id,
19
+ right_key: :principal_id
20
+
21
+ def self.lookup_columns
22
+ %i[id uuid name]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Identity::ModelHelpers.table_available?(:portable_identity_group_memberships)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ class Identity
11
+ class GroupMembership < Sequel::Model(:portable_identity_group_memberships)
12
+ include ModelHelpers
13
+
14
+ many_to_one :principal, class: 'Legion::Data::Model::Identity::Principal'
15
+ many_to_one :group, class: 'Legion::Data::Model::Identity::Group'
16
+
17
+ def expired?
18
+ status == 'expired' || (expires_at && Time.now >= expires_at)
19
+ end
20
+
21
+ def stale?
22
+ status == 'stale'
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Identity::ModelHelpers.table_available?(:portable_identities)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ class Identity
11
+ class Identity < Sequel::Model(:portable_identities)
12
+ include ModelHelpers
13
+
14
+ many_to_one :principal, class: 'Legion::Data::Model::Identity::Principal'
15
+ many_to_one :provider, class: 'Legion::Data::Model::Identity::Provider', key: :provider_id
16
+
17
+ def self.lookup_columns
18
+ %i[id uuid provider_identity_key]
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Data
7
+ module Model
8
+ class Identity
9
+ module ModelHelpers
10
+ def self.included(model)
11
+ model.extend(ClassMethods)
12
+ end
13
+
14
+ def self.table_available?(table_name)
15
+ Legion::Data::Connection.sequel&.table_exists?(table_name)
16
+ rescue StandardError
17
+ false
18
+ end
19
+
20
+ module ClassMethods
21
+ def lookup(value)
22
+ lookup_by_columns(value, lookup_columns)
23
+ end
24
+
25
+ def lookup_by_columns(value, lookup_columns)
26
+ normalized = normalize_lookup_value(value)
27
+ return if normalized.nil?
28
+
29
+ lookup_columns.each do |column|
30
+ next unless columns.include?(column)
31
+
32
+ query_value = lookup_query_value(column, normalized)
33
+ next if query_value == :skip
34
+
35
+ record = where(column => query_value).first
36
+ return record if record
37
+ end
38
+
39
+ nil
40
+ end
41
+
42
+ private
43
+
44
+ def lookup_columns
45
+ %i[id uuid name]
46
+ end
47
+
48
+ def normalize_lookup_value(value)
49
+ normalized = value.is_a?(String) ? value.strip : value
50
+ return if normalized.respond_to?(:empty?) && normalized.empty?
51
+
52
+ normalized
53
+ end
54
+
55
+ def lookup_query_value(column, value)
56
+ case column
57
+ when :id
58
+ return value.to_i if integer_lookup_value?(value)
59
+ return value.to_s if uuid_lookup_value?(value) && !columns.include?(:uuid)
60
+
61
+ :skip
62
+ when :uuid
63
+ uuid_lookup_value?(value) ? value.to_s : :skip
64
+ else
65
+ value.to_s
66
+ end
67
+ end
68
+
69
+ def integer_lookup_value?(value)
70
+ value.is_a?(Integer) || value.to_s.match?(/\A\d+\z/)
71
+ end
72
+
73
+ def uuid_lookup_value?(value)
74
+ value.to_s.match?(/\A[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\z/i)
75
+ end
76
+ end
77
+
78
+ def before_create
79
+ self[:uuid] ||= SecureRandom.uuid if self.class.columns.include?(:uuid)
80
+ super
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Identity::ModelHelpers.table_available?(:portable_identity_principals)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ class Identity
11
+ class Principal < Sequel::Model(:portable_identity_principals)
12
+ include ModelHelpers
13
+
14
+ one_to_many :identities, class: 'Legion::Data::Model::Identity::Identity'
15
+ one_to_many :group_memberships, class: 'Legion::Data::Model::Identity::GroupMembership'
16
+ many_to_many :groups,
17
+ class: 'Legion::Data::Model::Identity::Group',
18
+ join_table: :portable_identity_group_memberships,
19
+ left_key: :principal_id,
20
+ right_key: :group_id
21
+
22
+ def self.lookup_columns
23
+ %i[id uuid canonical_name employee_key]
24
+ end
25
+
26
+ def active_groups
27
+ group_memberships_dataset
28
+ .where(status: 'active')
29
+ .eager(:group)
30
+ .all
31
+ .map(&:group)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ return unless Legion::Data::Model::Identity::ModelHelpers.table_available?(:portable_identity_providers)
6
+
7
+ module Legion
8
+ module Data
9
+ module Model
10
+ class Identity
11
+ class Provider < Sequel::Model(:portable_identity_providers)
12
+ include ModelHelpers
13
+
14
+ one_to_many :identities, class: 'Legion::Data::Model::Identity::Identity', key: :provider_id
15
+ one_to_many :capabilities,
16
+ class: 'Legion::Data::Model::Identity::ProviderCapability',
17
+ key: :provider_id
18
+
19
+ def self.lookup_columns
20
+ %i[id uuid name]
21
+ end
22
+
23
+ def parsed_capabilities
24
+ capabilities_dataset.select_map(:capability_key)
25
+ end
26
+ end
27
+
28
+ class ProviderCapability < Sequel::Model(:portable_identity_provider_capabilities)
29
+ many_to_one :provider, class: 'Legion::Data::Model::Identity::Provider'
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -6,9 +6,16 @@ module Legion
6
6
  module Data
7
7
  module Model
8
8
  class Identity < Sequel::Model(:identities)
9
+ require_relative 'identity/model_helpers'
10
+ include ModelHelpers
11
+
9
12
  many_to_one :principal, class: 'Legion::Data::Model::Principal'
10
13
  many_to_one :provider, class: 'Legion::Data::Model::IdentityProvider', key: :provider_id
11
14
 
15
+ def self.lookup_columns
16
+ %i[id uuid provider_identity_key provider_identity]
17
+ end
18
+
12
19
  if defined?(Legion::Data::Encryption::SequelPlugin)
13
20
  plugin Legion::Data::Encryption::SequelPlugin
14
21
  encrypted_column :profile
@@ -1,12 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'identity/model_helpers'
4
+
3
5
  return unless Legion::Data::Connection.adapter == :postgres
4
6
 
5
7
  module Legion
6
8
  module Data
7
9
  module Model
8
10
  class IdentityGroup < Sequel::Model(:identity_groups)
11
+ include Identity::ModelHelpers
12
+
9
13
  one_to_many :memberships, class: 'Legion::Data::Model::IdentityGroupMembership', key: :group_id
14
+ many_to_many :principals,
15
+ class: 'Legion::Data::Model::Principal',
16
+ join_table: :identity_group_memberships,
17
+ left_key: :group_id,
18
+ right_key: :principal_id
19
+
20
+ def self.lookup_columns
21
+ %i[id uuid name]
22
+ end
10
23
  end
11
24
  end
12
25
  end
@@ -1,13 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'identity/model_helpers'
4
+
3
5
  return unless Legion::Data::Connection.adapter == :postgres
4
6
 
5
7
  module Legion
6
8
  module Data
7
9
  module Model
8
10
  class IdentityProvider < Sequel::Model(:identity_providers)
11
+ include Identity::ModelHelpers
12
+
9
13
  one_to_many :identities, class: 'Legion::Data::Model::Identity'
10
14
 
15
+ def self.lookup_columns
16
+ %i[id uuid name]
17
+ end
18
+
11
19
  def parsed_capabilities
12
20
  Array(capabilities)
13
21
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ module Legion
6
+ module Data
7
+ module Models
8
+ module LLM
9
+ class Conversation < Sequel::Model(:llm_conversations)
10
+ include ModelHelpers
11
+
12
+ one_to_many :messages
13
+ one_to_many :message_inference_requests
14
+ one_to_many :conversation_compactions
15
+ one_to_many :policy_evaluations
16
+ one_to_many :security_events
17
+
18
+ def security_incident_lineage
19
+ SecurityEvent.lineage_for_conversation(self)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model_helpers'
4
+
5
+ module Legion
6
+ module Data
7
+ module Models
8
+ module LLM
9
+ class ConversationCompaction < Sequel::Model(:llm_conversation_compactions)
10
+ include ModelHelpers
11
+
12
+ many_to_one :conversation
13
+ many_to_one :triggered_by_message_inference_request,
14
+ class: 'Legion::Data::Models::LLM::MessageInferenceRequest',
15
+ key: :triggered_by_message_inference_request_id
16
+ many_to_one :replaces_message_from, class: 'Legion::Data::Models::LLM::Message', key: :replaces_message_from_id
17
+ many_to_one :replaces_message_to, class: 'Legion::Data::Models::LLM::Message', key: :replaces_message_to_id
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end