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

Class Method Details

.algorithmObject



91
92
93
# File 'lib/legion/llm/fleet/token_issuer.rb', line 91

def algorithm
  auth_setting(:algorithm, default: ALGORITHM)
end

.audienceObject



87
88
89
# File 'lib/legion/llm/fleet/token_issuer.rb', line 87

def audience
  auth_setting(:audience, default: AUDIENCE)
end

.auth_setting(key, default:) ⇒ Object



95
96
97
98
# File 'lib/legion/llm/fleet/token_issuer.rb', line 95

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.message}"
end

.issuerObject



83
84
85
# File 'lib/legion/llm/fleet/token_issuer.rb', line 83

def issuer
  auth_setting(:issuer, default: ISSUER)
end

.jwt_moduleObject

Raises:



111
112
113
114
115
116
# File 'lib/legion/llm/fleet/token_issuer.rb', line 111

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

Raises:



118
119
120
121
122
# File 'lib/legion/llm/fleet/token_issuer.rb', line 118

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
# 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
  execution_contract = payload[:execution_contract]
  unless execution_contract.nil?
    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 marker present)' unless offering_id.is_a?(String) && !offering_id.strip.empty?

    claims[:execution_contract] = execution_contract
    claims[:offering_id] = offering_id
  end
  claims
end

.signing_keyObject



100
101
102
103
104
105
106
107
108
109
# File 'lib/legion/llm/fleet/token_issuer.rb', line 100

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.message}"
end

.symbolize_keys(hash) ⇒ Object



124
125
126
127
128
# File 'lib/legion/llm/fleet/token_issuer.rb', line 124

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_secondsObject



79
80
81
# File 'lib/legion/llm/fleet/token_issuer.rb', line 79

def token_ttl_seconds
  Integer(Legion::Settings[:llm][:fleet][:dispatch][:token_ttl_seconds])
end