legionio 1.7.19 → 1.7.21
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/.rubocop.yml +3 -0
- data/CHANGELOG.md +32 -0
- data/CLAUDE.md +1 -1
- data/README.md +4 -4
- data/lib/legion/api/default_settings.rb +1 -1
- data/lib/legion/api/identity_audit.rb +46 -0
- data/lib/legion/api/settings.rb +1 -1
- data/lib/legion/api.rb +2 -0
- data/lib/legion/cli/doctor/api_bind_check.rb +56 -0
- data/lib/legion/cli/doctor/mode_check.rb +40 -0
- data/lib/legion/cli/doctor_command.rb +4 -0
- data/lib/legion/extensions.rb +57 -1
- data/lib/legion/identity/broker.rb +159 -0
- data/lib/legion/identity/lease.rb +63 -0
- data/lib/legion/identity/lease_renewer.rb +82 -0
- data/lib/legion/identity/middleware.rb +79 -0
- data/lib/legion/identity/process.rb +121 -0
- data/lib/legion/identity/request.rb +71 -0
- data/lib/legion/mode.rb +76 -0
- data/lib/legion/process_role.rb +4 -2
- data/lib/legion/readiness.rb +16 -6
- data/lib/legion/service.rb +215 -8
- data/lib/legion/version.rb +1 -1
- data/lib/legion.rb +7 -0
- metadata +11 -1
data/lib/legion/service.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'timeout'
|
|
4
4
|
require 'legion/logging'
|
|
5
5
|
require_relative 'readiness'
|
|
6
|
+
require_relative 'mode'
|
|
6
7
|
require_relative 'process_role'
|
|
7
8
|
|
|
8
9
|
module Legion
|
|
@@ -101,7 +102,11 @@ module Legion
|
|
|
101
102
|
end
|
|
102
103
|
end
|
|
103
104
|
|
|
104
|
-
|
|
105
|
+
if data
|
|
106
|
+
setup_rbac
|
|
107
|
+
else
|
|
108
|
+
Legion::Readiness.mark_skipped(:rbac)
|
|
109
|
+
end
|
|
105
110
|
setup_cluster if data
|
|
106
111
|
|
|
107
112
|
if llm
|
|
@@ -111,9 +116,13 @@ module Legion
|
|
|
111
116
|
rescue LoadError => e
|
|
112
117
|
handle_exception(e, level: :debug, operation: 'service.initialize.llm', availability: 'missing')
|
|
113
118
|
log.info 'Legion::LLM gem is not installed'
|
|
119
|
+
Legion::Readiness.mark_skipped(:llm)
|
|
114
120
|
rescue StandardError => e
|
|
115
121
|
handle_exception(e, level: :warn, operation: 'service.initialize.llm')
|
|
122
|
+
Legion::Readiness.mark_skipped(:llm)
|
|
116
123
|
end
|
|
124
|
+
else
|
|
125
|
+
Legion::Readiness.mark_skipped(:llm)
|
|
117
126
|
end
|
|
118
127
|
|
|
119
128
|
begin
|
|
@@ -122,8 +131,10 @@ module Legion
|
|
|
122
131
|
rescue LoadError => e
|
|
123
132
|
handle_exception(e, level: :debug, operation: 'service.initialize.apollo', availability: 'missing')
|
|
124
133
|
log.info 'Legion::Apollo gem is not installed, starting without Apollo'
|
|
134
|
+
Legion::Readiness.mark_skipped(:apollo)
|
|
125
135
|
rescue StandardError => e
|
|
126
136
|
handle_exception(e, level: :warn, operation: 'service.initialize.apollo')
|
|
137
|
+
Legion::Readiness.mark_skipped(:apollo)
|
|
127
138
|
end
|
|
128
139
|
|
|
129
140
|
if gaia
|
|
@@ -133,9 +144,13 @@ module Legion
|
|
|
133
144
|
rescue LoadError => e
|
|
134
145
|
handle_exception(e, level: :debug, operation: 'service.initialize.gaia', availability: 'missing')
|
|
135
146
|
log.info 'Legion::Gaia gem is not installed'
|
|
147
|
+
Legion::Readiness.mark_skipped(:gaia)
|
|
136
148
|
rescue StandardError => e
|
|
137
149
|
handle_exception(e, level: :warn, operation: 'service.initialize.gaia')
|
|
150
|
+
Legion::Readiness.mark_skipped(:gaia)
|
|
138
151
|
end
|
|
152
|
+
else
|
|
153
|
+
Legion::Readiness.mark_skipped(:gaia)
|
|
139
154
|
end
|
|
140
155
|
|
|
141
156
|
setup_telemetry
|
|
@@ -149,6 +164,9 @@ module Legion
|
|
|
149
164
|
setup_generated_functions
|
|
150
165
|
end
|
|
151
166
|
|
|
167
|
+
# Identity resolution — after extensions so lex-identity-* providers are loaded
|
|
168
|
+
setup_identity if transport
|
|
169
|
+
|
|
152
170
|
register_core_tools
|
|
153
171
|
|
|
154
172
|
Legion::Gaia.registry&.rediscover if gaia && defined?(Legion::Gaia) && Legion::Gaia.started?
|
|
@@ -174,6 +192,7 @@ module Legion
|
|
|
174
192
|
require 'legion/api/default_settings'
|
|
175
193
|
api_settings = Legion::Settings[:api]
|
|
176
194
|
@api_enabled = api && api_settings[:enabled]
|
|
195
|
+
setup_apm if @api_enabled
|
|
177
196
|
setup_api if @api_enabled
|
|
178
197
|
setup_network_watchdog
|
|
179
198
|
Legion::Settings[:client][:ready] = true
|
|
@@ -204,8 +223,7 @@ module Legion
|
|
|
204
223
|
end
|
|
205
224
|
|
|
206
225
|
def lite_mode?
|
|
207
|
-
|
|
208
|
-
Legion::Settings[:mode].to_s == 'lite'
|
|
226
|
+
Legion::Mode.lite?
|
|
209
227
|
end
|
|
210
228
|
|
|
211
229
|
def setup_data
|
|
@@ -229,8 +247,10 @@ module Legion
|
|
|
229
247
|
rescue LoadError => e
|
|
230
248
|
handle_exception(e, level: :debug, operation: 'service.setup_rbac', availability: 'missing')
|
|
231
249
|
log.debug 'Legion::Rbac gem is not installed, starting without RBAC'
|
|
250
|
+
Legion::Readiness.mark_skipped(:rbac)
|
|
232
251
|
rescue StandardError => e
|
|
233
252
|
handle_exception(e, level: :warn, operation: 'service.setup_rbac')
|
|
253
|
+
Legion::Readiness.mark_skipped(:rbac)
|
|
234
254
|
end
|
|
235
255
|
|
|
236
256
|
def setup_cluster
|
|
@@ -306,6 +326,42 @@ module Legion
|
|
|
306
326
|
)
|
|
307
327
|
end
|
|
308
328
|
|
|
329
|
+
def setup_apm
|
|
330
|
+
apm_settings = Legion::Settings[:apm] || {}
|
|
331
|
+
return unless apm_settings[:enabled]
|
|
332
|
+
|
|
333
|
+
require 'elastic-apm'
|
|
334
|
+
|
|
335
|
+
config = {
|
|
336
|
+
service_name: apm_settings[:service_name] || "legion-#{Legion::Settings[:client][:name]}",
|
|
337
|
+
server_url: apm_settings[:server_url] || 'http://localhost:8200',
|
|
338
|
+
environment: apm_settings[:environment] || Legion::Settings[:environment] || 'development',
|
|
339
|
+
secret_token: apm_settings[:secret_token],
|
|
340
|
+
api_key: apm_settings[:api_key],
|
|
341
|
+
log_level: apm_settings[:log_level]&.to_sym || Logger::WARN,
|
|
342
|
+
transaction_sample_rate: apm_settings[:sample_rate] || 1.0
|
|
343
|
+
}.compact
|
|
344
|
+
|
|
345
|
+
ElasticAPM.start(**config)
|
|
346
|
+
@apm_running = true
|
|
347
|
+
log.info "Elastic APM started: server=#{config[:server_url]} service=#{config[:service_name]}"
|
|
348
|
+
rescue LoadError => e
|
|
349
|
+
handle_exception(e, level: :debug, operation: 'service.setup_apm', availability: 'missing')
|
|
350
|
+
log.info 'elastic-apm gem is not installed, starting without APM'
|
|
351
|
+
rescue StandardError => e
|
|
352
|
+
handle_exception(e, level: :warn, operation: 'service.setup_apm')
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def shutdown_apm
|
|
356
|
+
return unless @apm_running
|
|
357
|
+
|
|
358
|
+
ElasticAPM.stop if defined?(ElasticAPM) && ElasticAPM.running?
|
|
359
|
+
@apm_running = false
|
|
360
|
+
log.info 'Elastic APM stopped'
|
|
361
|
+
rescue StandardError => e
|
|
362
|
+
handle_exception(e, level: :warn, operation: 'service.shutdown_apm')
|
|
363
|
+
end
|
|
364
|
+
|
|
309
365
|
def setup_api # rubocop:disable Metrics/MethodLength
|
|
310
366
|
if @api_thread&.alive?
|
|
311
367
|
log.warn 'API already running, skipping duplicate setup_api call'
|
|
@@ -344,6 +400,12 @@ module Legion
|
|
|
344
400
|
log.info "Starting Legion API on #{bind}:#{port}"
|
|
345
401
|
end
|
|
346
402
|
|
|
403
|
+
# Mount identity middleware — bridges legion.auth to legion.principal
|
|
404
|
+
if defined?(Legion::Identity::Middleware)
|
|
405
|
+
require_auth = Legion::Identity::Middleware.require_auth?(bind: bind, mode: Legion::Mode.current)
|
|
406
|
+
Legion::API.use Legion::Identity::Middleware, require_auth: require_auth
|
|
407
|
+
end
|
|
408
|
+
|
|
347
409
|
@api_thread = Thread.new do
|
|
348
410
|
retries = 0
|
|
349
411
|
max_retries = api_settings[:bind_retries]
|
|
@@ -427,6 +489,45 @@ module Legion
|
|
|
427
489
|
log.info 'Legion::Transport connected'
|
|
428
490
|
end
|
|
429
491
|
|
|
492
|
+
def setup_identity
|
|
493
|
+
require_relative 'identity/process'
|
|
494
|
+
require_relative 'identity/broker'
|
|
495
|
+
require_relative 'identity/lease'
|
|
496
|
+
require_relative 'identity/lease_renewer'
|
|
497
|
+
require_relative 'identity/request'
|
|
498
|
+
require_relative 'identity/middleware'
|
|
499
|
+
|
|
500
|
+
# Resolve identity from available providers (Phase 4 adds real providers)
|
|
501
|
+
resolved = resolve_identity_providers
|
|
502
|
+
unless resolved
|
|
503
|
+
Legion::Identity::Process.bind_fallback!
|
|
504
|
+
log.info "[Identity] fallback identity: #{Legion::Identity::Process.canonical_name}"
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
# Re-resolve secrets for any identity-scoped lease:// refs (task 2.25)
|
|
508
|
+
Legion::Settings.resolve_secrets! if Legion::Settings.respond_to?(:resolve_secrets!)
|
|
509
|
+
|
|
510
|
+
# Fire-and-forget JWKS prefetch
|
|
511
|
+
jwks_url = Legion::Settings.dig(:identity, :jwks_endpoint) || Legion::Settings.dig(:crypt, :jwt, :jwks_endpoint)
|
|
512
|
+
if jwks_url && defined?(Legion::Crypt::JwksClient)
|
|
513
|
+
Legion::Crypt::JwksClient.prefetch!(jwks_url)
|
|
514
|
+
Legion::Crypt::JwksClient.start_background_refresh!(jwks_url)
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
log.info "[Identity] resolved=#{Legion::Identity::Process.resolved?} mode=#{Legion::Mode.current} queue_prefix=#{Legion::Identity::Process.queue_prefix}"
|
|
518
|
+
rescue StandardError => e
|
|
519
|
+
handle_exception(e, level: :warn, operation: 'service.setup_identity')
|
|
520
|
+
Legion::Identity::Process.bind_fallback! if defined?(Legion::Identity::Process) && !Legion::Identity::Process.resolved?
|
|
521
|
+
ensure
|
|
522
|
+
Legion::Readiness.mark_ready(:identity)
|
|
523
|
+
begin
|
|
524
|
+
Legion::Extensions.flush_pending_registrations! if defined?(Legion::Extensions) &&
|
|
525
|
+
Legion::Extensions.respond_to?(:flush_pending_registrations!)
|
|
526
|
+
rescue StandardError => e
|
|
527
|
+
handle_exception(e, level: :warn, operation: 'service.setup_identity.flush_pending_registrations')
|
|
528
|
+
end
|
|
529
|
+
end
|
|
530
|
+
|
|
430
531
|
def setup_logging_transport # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
|
431
532
|
return unless defined?(Legion::Transport::Connection)
|
|
432
533
|
return unless Legion::Transport::Connection.session_open?
|
|
@@ -610,7 +711,7 @@ module Legion
|
|
|
610
711
|
handle_exception(e, level: :warn, operation: 'service.shutdown_api')
|
|
611
712
|
end
|
|
612
713
|
|
|
613
|
-
def shutdown # rubocop:disable Metrics/CyclomaticComplexity
|
|
714
|
+
def shutdown # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
614
715
|
log.info('Legion::Service.shutdown was called')
|
|
615
716
|
@shutdown = true
|
|
616
717
|
Legion::Settings[:client][:shutting_down] = true
|
|
@@ -619,6 +720,7 @@ module Legion
|
|
|
619
720
|
shutdown_network_watchdog
|
|
620
721
|
shutdown_audit_archiver
|
|
621
722
|
shutdown_api
|
|
723
|
+
shutdown_apm
|
|
622
724
|
|
|
623
725
|
Legion::Metrics.reset! if defined?(Legion::Metrics)
|
|
624
726
|
|
|
@@ -658,6 +760,17 @@ module Legion
|
|
|
658
760
|
shutdown_component('Cache') { Legion::Cache.shutdown }
|
|
659
761
|
Legion::Readiness.mark_not_ready(:cache)
|
|
660
762
|
|
|
763
|
+
# Identity: cooperative shutdown of Broker (stops all LeaseRenewer threads)
|
|
764
|
+
if defined?(Legion::Identity::Broker)
|
|
765
|
+
shutdown_component('Identity::Broker') { Legion::Identity::Broker.shutdown }
|
|
766
|
+
Legion::Readiness.mark_not_ready(:identity)
|
|
767
|
+
end
|
|
768
|
+
|
|
769
|
+
# Stop JWKS background refresh
|
|
770
|
+
if defined?(Legion::Crypt::JwksClient) && Legion::Crypt::JwksClient.respond_to?(:stop_background_refresh!)
|
|
771
|
+
Legion::Crypt::JwksClient.stop_background_refresh!
|
|
772
|
+
end
|
|
773
|
+
|
|
661
774
|
teardown_logging_transport
|
|
662
775
|
shutdown_component('Transport') { Legion::Transport::Connection.shutdown }
|
|
663
776
|
Legion::Readiness.mark_not_ready(:transport)
|
|
@@ -679,6 +792,7 @@ module Legion
|
|
|
679
792
|
|
|
680
793
|
shutdown_network_watchdog
|
|
681
794
|
shutdown_api
|
|
795
|
+
shutdown_apm
|
|
682
796
|
|
|
683
797
|
if defined?(Legion::Gaia) && Legion::Gaia.respond_to?(:started?) && Legion::Gaia.started?
|
|
684
798
|
shutdown_component('Gaia') { Legion::Gaia.shutdown }
|
|
@@ -718,6 +832,8 @@ module Legion
|
|
|
718
832
|
teardown_logging_transport
|
|
719
833
|
setup_logging_transport
|
|
720
834
|
|
|
835
|
+
Legion::Identity::Process.refresh_credentials if defined?(Legion::Identity::Process)
|
|
836
|
+
|
|
721
837
|
require 'legion/cache' unless defined?(Legion::Cache)
|
|
722
838
|
Legion::Cache.setup
|
|
723
839
|
Legion::Readiness.mark_ready(:cache)
|
|
@@ -725,19 +841,44 @@ module Legion
|
|
|
725
841
|
setup_data
|
|
726
842
|
Legion::Readiness.mark_ready(:data)
|
|
727
843
|
|
|
728
|
-
|
|
729
|
-
|
|
844
|
+
if defined?(Legion::Rbac)
|
|
845
|
+
setup_rbac
|
|
846
|
+
else
|
|
847
|
+
Legion::Readiness.mark_skipped(:rbac)
|
|
848
|
+
end
|
|
730
849
|
|
|
731
|
-
|
|
732
|
-
|
|
850
|
+
if defined?(Legion::LLM)
|
|
851
|
+
setup_llm
|
|
852
|
+
else
|
|
853
|
+
Legion::Readiness.mark_skipped(:llm)
|
|
854
|
+
end
|
|
855
|
+
|
|
856
|
+
if defined?(Legion::Apollo)
|
|
857
|
+
setup_apollo
|
|
858
|
+
Legion::Readiness.mark_ready(:apollo)
|
|
859
|
+
else
|
|
860
|
+
Legion::Readiness.mark_skipped(:apollo)
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
if defined?(Legion::Gaia)
|
|
864
|
+
setup_gaia
|
|
865
|
+
Legion::Readiness.mark_ready(:gaia)
|
|
866
|
+
else
|
|
867
|
+
Legion::Readiness.mark_skipped(:gaia)
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
Legion::Readiness.mark_ready(:identity)
|
|
733
871
|
|
|
734
872
|
setup_supervision
|
|
735
873
|
load_extensions
|
|
736
874
|
Legion::Readiness.mark_ready(:extensions)
|
|
737
875
|
|
|
876
|
+
Legion::Extensions.flush_pending_registrations! if defined?(Legion::Extensions) && Legion::Extensions.respond_to?(:flush_pending_registrations!)
|
|
877
|
+
|
|
738
878
|
register_core_tools
|
|
739
879
|
|
|
740
880
|
Legion::Crypt.cs
|
|
881
|
+
setup_apm if @api_enabled
|
|
741
882
|
setup_api if @api_enabled
|
|
742
883
|
|
|
743
884
|
if defined?(Legion::MCP)
|
|
@@ -895,6 +1036,72 @@ module Legion
|
|
|
895
1036
|
|
|
896
1037
|
private
|
|
897
1038
|
|
|
1039
|
+
def resolve_identity_providers
|
|
1040
|
+
# Phase 4 adds lex-identity-* providers. For now, check if any are loaded.
|
|
1041
|
+
return false unless defined?(Legion::Extensions)
|
|
1042
|
+
|
|
1043
|
+
providers = find_identity_providers
|
|
1044
|
+
return false if providers.empty?
|
|
1045
|
+
|
|
1046
|
+
# Parallel resolution with 5s per-provider timeout (NO Timeout.timeout — uses future.value)
|
|
1047
|
+
pool = Concurrent::FixedThreadPool.new([providers.size, 4].min)
|
|
1048
|
+
futures = providers.map do |provider|
|
|
1049
|
+
Concurrent::Promises.future_on(pool, provider, &:resolve)
|
|
1050
|
+
end
|
|
1051
|
+
|
|
1052
|
+
winner_pair = providers.zip(futures).find do |_provider, future|
|
|
1053
|
+
result = begin
|
|
1054
|
+
future.value(5) # 5s timeout per provider
|
|
1055
|
+
rescue StandardError => e
|
|
1056
|
+
handle_exception(e, level: :debug, operation: 'service.resolve_identity_providers.future')
|
|
1057
|
+
nil
|
|
1058
|
+
end
|
|
1059
|
+
result.is_a?(Hash) && result[:canonical_name]
|
|
1060
|
+
end
|
|
1061
|
+
|
|
1062
|
+
if winner_pair
|
|
1063
|
+
provider, future = winner_pair
|
|
1064
|
+
identity = future.value
|
|
1065
|
+
Legion::Identity::Process.bind!(provider, identity)
|
|
1066
|
+
log.info "[Identity] resolved via #{provider.class.name}: #{identity[:canonical_name]}"
|
|
1067
|
+
true
|
|
1068
|
+
else
|
|
1069
|
+
false
|
|
1070
|
+
end
|
|
1071
|
+
rescue StandardError => e
|
|
1072
|
+
handle_exception(e, level: :warn, operation: 'service.resolve_identity_providers')
|
|
1073
|
+
false
|
|
1074
|
+
ensure
|
|
1075
|
+
pool&.shutdown
|
|
1076
|
+
pool&.kill unless pool&.wait_for_termination(2)
|
|
1077
|
+
end
|
|
1078
|
+
|
|
1079
|
+
def find_identity_providers
|
|
1080
|
+
return [] unless defined?(Legion::Extensions)
|
|
1081
|
+
|
|
1082
|
+
collect_identity_providers(Legion::Extensions)
|
|
1083
|
+
end
|
|
1084
|
+
|
|
1085
|
+
def collect_identity_providers(namespace, visited = Set.new)
|
|
1086
|
+
return [] unless namespace.is_a?(Module)
|
|
1087
|
+
return [] if visited.include?(namespace.object_id)
|
|
1088
|
+
|
|
1089
|
+
visited.add(namespace.object_id)
|
|
1090
|
+
providers = []
|
|
1091
|
+
|
|
1092
|
+
namespace.constants(false).each do |const_name|
|
|
1093
|
+
mod = namespace.const_get(const_name, false)
|
|
1094
|
+
next unless mod.is_a?(Module)
|
|
1095
|
+
|
|
1096
|
+
providers << mod if mod.respond_to?(:resolve) && mod.respond_to?(:provider_name)
|
|
1097
|
+
providers.concat(collect_identity_providers(mod, visited))
|
|
1098
|
+
rescue StandardError
|
|
1099
|
+
next
|
|
1100
|
+
end
|
|
1101
|
+
|
|
1102
|
+
providers
|
|
1103
|
+
end
|
|
1104
|
+
|
|
898
1105
|
def bootstrap_log_level(cli_level)
|
|
899
1106
|
cli_level = nil if cli_level.respond_to?(:empty?) && cli_level.empty?
|
|
900
1107
|
return cli_level if cli_level
|
data/lib/legion/version.rb
CHANGED
data/lib/legion.rb
CHANGED
|
@@ -6,6 +6,7 @@ require 'securerandom'
|
|
|
6
6
|
require 'legion/version'
|
|
7
7
|
require 'legion/logging'
|
|
8
8
|
require 'legion/events'
|
|
9
|
+
require 'legion/mode'
|
|
9
10
|
require 'legion/ingress'
|
|
10
11
|
require 'legion/process'
|
|
11
12
|
require 'legion/service'
|
|
@@ -18,6 +19,12 @@ module Legion
|
|
|
18
19
|
autoload :Leader, 'legion/leader'
|
|
19
20
|
autoload :Prompts, 'legion/prompts'
|
|
20
21
|
|
|
22
|
+
@instance_id = ENV.fetch('LEGIONIO_INSTANCE_ID') { SecureRandom.uuid }.downcase.strip.gsub(/[^a-z0-9-]/, '')
|
|
23
|
+
|
|
24
|
+
def self.instance_id
|
|
25
|
+
@instance_id
|
|
26
|
+
end
|
|
27
|
+
|
|
21
28
|
attr_reader :service
|
|
22
29
|
|
|
23
30
|
def self.start
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: legionio
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.7.
|
|
4
|
+
version: 1.7.21
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -490,6 +490,7 @@ files:
|
|
|
490
490
|
- lib/legion/api/graphql/types/task_type.rb
|
|
491
491
|
- lib/legion/api/graphql/types/worker_type.rb
|
|
492
492
|
- lib/legion/api/helpers.rb
|
|
493
|
+
- lib/legion/api/identity_audit.rb
|
|
493
494
|
- lib/legion/api/inbound_webhooks.rb
|
|
494
495
|
- lib/legion/api/knowledge.rb
|
|
495
496
|
- lib/legion/api/lex_dispatch.rb
|
|
@@ -641,11 +642,13 @@ files:
|
|
|
641
642
|
- lib/legion/cli/do_command.rb
|
|
642
643
|
- lib/legion/cli/docs_command.rb
|
|
643
644
|
- lib/legion/cli/doctor.rb
|
|
645
|
+
- lib/legion/cli/doctor/api_bind_check.rb
|
|
644
646
|
- lib/legion/cli/doctor/bundle_check.rb
|
|
645
647
|
- lib/legion/cli/doctor/cache_check.rb
|
|
646
648
|
- lib/legion/cli/doctor/config_check.rb
|
|
647
649
|
- lib/legion/cli/doctor/database_check.rb
|
|
648
650
|
- lib/legion/cli/doctor/extensions_check.rb
|
|
651
|
+
- lib/legion/cli/doctor/mode_check.rb
|
|
649
652
|
- lib/legion/cli/doctor/permissions_check.rb
|
|
650
653
|
- lib/legion/cli/doctor/pid_check.rb
|
|
651
654
|
- lib/legion/cli/doctor/rabbitmq_check.rb
|
|
@@ -841,6 +844,12 @@ files:
|
|
|
841
844
|
- lib/legion/graph/exporter.rb
|
|
842
845
|
- lib/legion/guardrails.rb
|
|
843
846
|
- lib/legion/helpers/context.rb
|
|
847
|
+
- lib/legion/identity/broker.rb
|
|
848
|
+
- lib/legion/identity/lease.rb
|
|
849
|
+
- lib/legion/identity/lease_renewer.rb
|
|
850
|
+
- lib/legion/identity/middleware.rb
|
|
851
|
+
- lib/legion/identity/process.rb
|
|
852
|
+
- lib/legion/identity/request.rb
|
|
844
853
|
- lib/legion/ingress.rb
|
|
845
854
|
- lib/legion/isolation.rb
|
|
846
855
|
- lib/legion/leader.rb
|
|
@@ -848,6 +857,7 @@ files:
|
|
|
848
857
|
- lib/legion/lock.rb
|
|
849
858
|
- lib/legion/memory/consolidator.rb
|
|
850
859
|
- lib/legion/metrics.rb
|
|
860
|
+
- lib/legion/mode.rb
|
|
851
861
|
- lib/legion/notebook/generator.rb
|
|
852
862
|
- lib/legion/notebook/parser.rb
|
|
853
863
|
- lib/legion/notebook/renderer.rb
|