Module: Legion::LLM::Fleet::TokenIssuer
- Defined in:
- lib/legion/llm/fleet/token_issuer.rb
Constant Summary collapse
- ISSUER =
'legion-llm'- AUDIENCE =
'lex-llm-fleet-worker'- ALGORITHM =
'HS256'
Class Method Summary collapse
- .algorithm ⇒ Object
- .audience ⇒ Object
- .auth_setting(key, default:) ⇒ Object
- .issue(payload) ⇒ Object
- .issuer ⇒ Object
- .jwt_module ⇒ Object
- .require_crypt! ⇒ Object
- .required_claims(payload) ⇒ Object
- .signing_key ⇒ Object
- .symbolize_keys(hash) ⇒ Object
- .token_ttl_seconds ⇒ Object
Class Method Details
.algorithm ⇒ Object
96 97 98 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 96 def algorithm auth_setting(:algorithm, default: ALGORITHM) end |
.audience ⇒ Object
92 93 94 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 92 def audience auth_setting(:audience, default: AUDIENCE) end |
.auth_setting(key, default:) ⇒ Object
100 101 102 103 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 100 def auth_setting(key, default:) val = Legion::Settings[:llm][:fleet][:auth][key] val.nil? ? default : val end |
.issue(payload) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 21 def issue(payload) ttl = token_ttl_seconds now = Time.now.to_i claims = required_claims(payload).merge( iss: issuer, aud: audience, iat: now, exp: now + ttl, nbf: now, jti: "fleet-jti-#{SecureRandom.uuid}" ) jwt_module.issue( claims, signing_key: signing_key, ttl: ttl, issuer: issuer, algorithm: algorithm ) rescue TokenError raise rescue StandardError => e raise TokenError, "failed to issue fleet token: #{e.}" end |
.issuer ⇒ Object
88 89 90 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 88 def issuer auth_setting(:issuer, default: ISSUER) end |
.jwt_module ⇒ Object
116 117 118 119 120 121 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 116 def jwt_module require_crypt! return Legion::Crypt::JWT if defined?(Legion::Crypt::JWT) && Legion::Crypt::JWT.respond_to?(:issue) raise TokenError, 'Legion::Crypt::JWT.issue unavailable' end |
.require_crypt! ⇒ Object
123 124 125 126 127 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 123 def require_crypt! return if defined?(Legion::Crypt) raise TokenError, 'Legion::Crypt is required for fleet token issuance' end |
.required_claims(payload) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 46 def required_claims(payload) payload = symbolize_keys(payload || {}) claims = {} %i[ request_id correlation_id idempotency_key operation provider provider_instance model reply_to message_context ].each do |key| value = payload[key] raise TokenError, "missing token claim source: #{key}" if value.nil? claims[key] = value end %i[params caller trace_context timeout_seconds expires_at].each do |key| value = payload[key] raise TokenError, "missing token claim source: #{key}" if value.nil? claims[key] = value end # S3: every request is exact (06 P2) — the exact signed scalar # claims are verified unconditionally on the worker, so they are # issued unconditionally. The marker-absence branch is deleted. execution_contract = payload[:execution_contract] if execution_contract.nil? raise TokenError, 'missing token claim source: execution_contract (fleet protocol v3 is exact-execution only)' end unless execution_contract == ::Legion::Extensions::Llm::Fleet::Protocol::EXACT_EXECUTION_CONTRACT raise TokenError, "unknown fleet execution_contract marker: #{execution_contract.inspect}" end offering_id = payload[:offering_id] raise TokenError, 'missing token claim source: nonempty String offering_id (exact execution)' unless offering_id.is_a?(String) && !offering_id.strip.empty? claims[:execution_contract] = execution_contract claims[:offering_id] = offering_id claims end |
.signing_key ⇒ Object
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 105 def signing_key require_crypt! return Legion::Crypt.cluster_secret if Legion::Crypt.respond_to?(:cluster_secret) raise TokenError, 'no signing key available - Legion::Crypt not initialized' rescue TokenError raise rescue StandardError => e raise TokenError, "no signing key available: #{e.}" end |
.symbolize_keys(hash) ⇒ Object
129 130 131 132 133 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 129 def symbolize_keys(hash) hash.each_with_object({}) do |(key, value), result| result[key.respond_to?(:to_sym) ? key.to_sym : key] = value end end |
.token_ttl_seconds ⇒ Object
84 85 86 |
# File 'lib/legion/llm/fleet/token_issuer.rb', line 84 def token_ttl_seconds Integer(Legion::Settings[:llm][:fleet][:dispatch][:token_ttl_seconds]) end |