Module: Legion::Extensions::Llm::Inventory::RecordSupport

Defined in:
lib/legion/extensions/llm/inventory/records.rb

Overview

Shared normalization/validation used by the immutable inventory and routing records. Kept internal to the records so no record implements a competing validator. See phase-1-lex-llm-additive.md sections 10 and 15.

Constant Summary collapse

SECRET_KEY_TOKENS =
%w[
  credential authorization token secret password apikey prompt endpointurl callable
].freeze
PUBLICATION_SOURCES =
%i[provider_catalog provider_static_catalog provider_control_plane].freeze
WEIGHT_INPUT_KEYS =
%i[instance model_or_offering provider tier].freeze
IDENTITY_WEIGHT_INPUTS =
{
  tier: 100, provider: 100, instance: 100, model_or_offering: 100
}.freeze
IDENTITY_BASE_WEIGHT =
100_000_000

Class Method Summary collapse

Class Method Details

.boolean!(value:, field:) ⇒ Object



106
107
108
109
110
# File 'lib/legion/extensions/llm/inventory/records.rb', line 106

def boolean!(value:, field:)
  return value if [true, false].include?(value)

  raise Errors::ValidationError, "#{field} must be true or false"
end

.check_unknown_kwargs!(kwargs:, members:) ⇒ Object



63
64
65
66
# File 'lib/legion/extensions/llm/inventory/records.rb', line 63

def check_unknown_kwargs!(kwargs:, members:)
  unknown = kwargs.keys - members
  raise Errors::ValidationError, "unknown keyword(s): #{unknown.join(', ')}" unless unknown.empty?
end

.embedding_dimensions_value_evidence!(evidence, field) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/legion/extensions/llm/inventory/records.rb', line 228

def embedding_dimensions_value_evidence!(evidence, field)
  value_evidence!(evidence, field)
  return evidence unless evidence.known?

  dims = evidence.value
  valid = dims.is_a?(::Array) && !dims.empty? &&
          dims.all? { |dim| dim.is_a?(::Integer) && dim.positive? } &&
          dims == dims.uniq && dims == dims.sort
  raise Errors::ValidationError, "known #{field} must be a sorted, unique Array of positive Integers" unless valid

  evidence
end

.frozen_metadata(value:, field: :metadata) ⇒ Object



126
127
128
129
# File 'lib/legion/extensions/llm/inventory/records.rb', line 126

def (value:, field: :metadata)
  reject_secret_keys!(value, field)
  ImmutableValue.copy_and_freeze(value: value, field: field)
end

.model_revision_value_evidence!(evidence, field) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
# File 'lib/legion/extensions/llm/inventory/records.rb', line 241

def model_revision_value_evidence!(evidence, field)
  value_evidence!(evidence, field)
  return evidence unless evidence.known?

  revision = evidence.value
  valid = revision.is_a?(::String) && !revision.strip.empty? &&
          valid_utf8?(revision) && revision.unicode_normalized?(:nfc)
  raise Errors::ValidationError, "known #{field} must be a nonempty NFC String" unless valid

  evidence
end

.nonempty_nfc!(value:, field:) ⇒ Object



269
270
271
272
273
274
# File 'lib/legion/extensions/llm/inventory/records.rb', line 269

def nonempty_nfc!(value:, field:)
  valid = value.is_a?(::String) && !value.strip.empty? && valid_utf8?(value) && value.unicode_normalized?(:nfc)
  raise Errors::ValidationError, "#{field} must be a nonempty NFC String" unless valid

  value
end

.nonnegative_integer(value:, field:) ⇒ Object



96
97
98
99
100
# File 'lib/legion/extensions/llm/inventory/records.rb', line 96

def nonnegative_integer(value:, field:)
  raise Errors::ValidationError, "#{field} must be a nonnegative Integer" unless nonnegative_integer?(value)

  value
end

.nonnegative_integer?(value) ⇒ Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/legion/extensions/llm/inventory/records.rb', line 102

def nonnegative_integer?(value)
  value.is_a?(::Integer) && !value.negative?
end

.normalize_provider_family(value:, field: :provider_family) ⇒ Object



112
113
114
115
116
117
# File 'lib/legion/extensions/llm/inventory/records.rb', line 112

def normalize_provider_family(value:, field: :provider_family)
  text = Identity.normalize_text(value: value, field: field).downcase
  raise Errors::ValidationError, "#{field} must be snake-case ASCII" unless text.match?(/\A[a-z][a-z0-9_]*\z/)

  text.to_sym
end

.optional_sanitized_reason(value:, field:, max_bytes: 1024) ⇒ Object



90
91
92
93
94
# File 'lib/legion/extensions/llm/inventory/records.rb', line 90

def optional_sanitized_reason(value:, field:, max_bytes: 1024)
  return nil if value.nil?

  sanitized_reason(value: value, field: field, max_bytes: max_bytes)
end

.optional_time(value:, field:) ⇒ Object



119
120
121
122
123
124
# File 'lib/legion/extensions/llm/inventory/records.rb', line 119

def optional_time(value:, field:)
  return nil if value.nil?
  raise Errors::ValidationError, "#{field} must be a Time" unless value.is_a?(::Time)

  value.dup.freeze
end

.positive_int_value_evidence!(evidence, field) ⇒ Object



221
222
223
224
225
226
# File 'lib/legion/extensions/llm/inventory/records.rb', line 221

def positive_int_value_evidence!(evidence, field)
  value_evidence!(evidence, field)
  raise Errors::ValidationError, "known #{field} must be a positive Integer" if evidence.known? && !(evidence.value.is_a?(::Integer) && evidence.value.positive?)

  evidence
end

.publication_source!(value:) ⇒ Object



276
277
278
279
280
# File 'lib/legion/extensions/llm/inventory/records.rb', line 276

def publication_source!(value:)
  raise Errors::ValidationError, "publication_source must be one of #{PUBLICATION_SOURCES.inspect}" unless PUBLICATION_SOURCES.include?(value)

  value
end

.reject_secret_keys!(value, field) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/legion/extensions/llm/inventory/records.rb', line 131

def reject_secret_keys!(value, field)
  case value
  when ::Hash
    value.each do |key, nested|
      raise Errors::ValidationError, "#{field} contains a secret-like key" if secret_key?(key)

      reject_secret_keys!(nested, field)
    end
  when ::Array
    value.each { |element| reject_secret_keys!(element, field) }
  end
end

.sanitized_reason(value:, field:, max_bytes: 1024) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/legion/extensions/llm/inventory/records.rb', line 72

def sanitized_reason(value:, field:, max_bytes: 1024)
  raise Errors::ValidationError, "#{field} must be a String" unless value.is_a?(::String)

  # Coerce any source encoding to valid UTF-8 rather than raising: provider
  # error messages can be ASCII-8BIT/binary (raw response bodies, Ruby kernel
  # error messages). A reason is diagnostic text, not operator input to reject —
  # raising here would mask the real dispatch error as an unclassifiable 500 and
  # defeat fail-forward. Undecodable bytes are replaced.
  coerced = value.dup.force_encoding(::Encoding::UTF_8)
  coerced = coerced.scrub('?') unless coerced.valid_encoding?

  trimmed = coerced.strip
  raise Errors::ValidationError, "#{field} must not be empty" if trimmed.empty?
  raise Errors::ValidationError, "#{field} exceeds #{max_bytes} UTF-8 bytes" if trimmed.bytesize > max_bytes

  trimmed.b.dup.force_encoding(::Encoding::UTF_8).freeze
end

.scalar_value_evidences(kwargs) ⇒ Object

Validates and returns the five scalar ValueEvidence fields shared by OfferingDraft, OfferingRecord, and LaneRecord as a member Hash.



201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/legion/extensions/llm/inventory/records.rb', line 201

def scalar_value_evidences(kwargs)
  {
    context_evidence: positive_int_value_evidence!(kwargs[:context_evidence], :context_evidence),
    max_output_evidence: positive_int_value_evidence!(kwargs[:max_output_evidence], :max_output_evidence),
    embedding_dimensions_evidence: embedding_dimensions_value_evidence!(
      kwargs[:embedding_dimensions_evidence], :embedding_dimensions_evidence
    ),
    model_revision_evidence: model_revision_value_evidence!(
      kwargs[:model_revision_evidence], :model_revision_evidence
    ),
    tokenizer_evidence: tokenizer_value_evidence!(kwargs[:tokenizer_evidence], :tokenizer_evidence)
  }
end

.secret_key?(key) ⇒ Boolean

Returns:

  • (Boolean)


144
145
146
147
# File 'lib/legion/extensions/llm/inventory/records.rb', line 144

def secret_key?(key)
  normalized = key.to_s.downcase.gsub(/[^a-z0-9]/, '')
  SECRET_KEY_TOKENS.any? { |token| normalized.include?(token) }
end

.tokenizer_value_evidence!(evidence, field) ⇒ Object



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/legion/extensions/llm/inventory/records.rb', line 253

def tokenizer_value_evidence!(evidence, field)
  value_evidence!(evidence, field)
  return evidence unless evidence.known?

  descriptor = evidence.value
  unless descriptor.is_a?(::Hash) && descriptor.keys.sort == %i[estimator parameters version]
    raise Errors::ValidationError, "known #{field} must be exactly {estimator:, version:, parameters:}"
  end

  nonempty_nfc!(value: descriptor[:estimator], field: "#{field}.estimator")
  nonempty_nfc!(value: descriptor[:version], field: "#{field}.version")
  raise Errors::ValidationError, "#{field}.parameters must be a Hash" unless descriptor[:parameters].is_a?(::Hash)

  evidence
end

.valid_utf8?(string) ⇒ Boolean

Returns:

  • (Boolean)


68
69
70
# File 'lib/legion/extensions/llm/inventory/records.rb', line 68

def valid_utf8?(string)
  [::Encoding::UTF_8, ::Encoding::US_ASCII].include?(string.encoding) && string.valid_encoding?
end

.validate_capability_evidence!(evidence) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/legion/extensions/llm/inventory/records.rb', line 166

def validate_capability_evidence!(evidence)
  raise Errors::ValidationError, 'capability_evidence must be a Hash' unless evidence.is_a?(::Hash)

  normalized = {}
  evidence.each do |key, value|
    cap = Legion::Extensions::Llm::Capabilities.canonical(key)
    raise Errors::ValidationError, "capability_evidence key #{cap} is not canonical" unless Legion::Extensions::Llm::Capabilities::CANONICAL.include?(cap)
    raise Errors::ValidationError, "capability_evidence[#{cap}] must be a CapabilityEvidence" unless value.is_a?(CapabilityEvidence)
    raise Errors::ValidationError, "capability_evidence[#{cap}] capability must match key" unless value.capability == cap
    raise Errors::ValidationError, "duplicate capability_evidence key #{cap}" if normalized.key?(cap)

    normalized[cap] = value
  end
  normalized.freeze
end

.validate_operation_evidence!(evidence) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/legion/extensions/llm/inventory/records.rb', line 149

def validate_operation_evidence!(evidence)
  raise Errors::ValidationError, 'operation_evidence must be a Hash' unless evidence.is_a?(::Hash)

  normalized = {}
  evidence.each do |key, value|
    op = Taxonomies.normalize_operation(value: key, allow_aliases: false)
    raise Errors::ValidationError, "operation_evidence[#{op}] must be an OperationEvidence" unless value.is_a?(OperationEvidence)
    raise Errors::ValidationError, "operation_evidence[#{op}] operation must match key" unless value.operation == op
    raise Errors::ValidationError, "duplicate operation_evidence key #{op}" if normalized.key?(op)

    normalized[op] = value
  end
  raise Errors::ValidationError, 'operation_evidence keys must equal Taxonomies::OPERATIONS exactly' unless normalized.keys.sort == Taxonomies::OPERATIONS.sort

  normalized.freeze
end

.validate_quota_domain_value!(value:, field:) ⇒ Object



193
194
195
196
197
# File 'lib/legion/extensions/llm/inventory/records.rb', line 193

def validate_quota_domain_value!(value:, field:)
  raise Errors::ValidationError, "#{field} must be a nonempty opaque String" unless value.is_a?(::String) && valid_utf8?(value) && !value.strip.empty?

  value.dup.freeze
end

.validate_quota_domains!(quota_domains) ⇒ Object



182
183
184
185
186
187
188
189
190
191
# File 'lib/legion/extensions/llm/inventory/records.rb', line 182

def validate_quota_domains!(quota_domains)
  raise Errors::ValidationError, 'quota_domains must be a Hash' unless quota_domains.is_a?(::Hash)

  normalized = {}
  quota_domains.each do |key, value|
    op = Taxonomies.normalize_operation(value: key, allow_aliases: false)
    normalized[op] = validate_quota_domain_value!(value: value, field: "quota_domains[#{op}]")
  end
  normalized.freeze
end

.validated_weight_pair(weight_inputs:, base_weight:) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/legion/extensions/llm/inventory/records.rb', line 40

def validated_weight_pair(weight_inputs:, base_weight:)
  raise Errors::ValidationError, 'weight_inputs and base_weight must be supplied together' \
    if weight_inputs.nil? != base_weight.nil?

  return [IDENTITY_WEIGHT_INPUTS, IDENTITY_BASE_WEIGHT] if weight_inputs.nil?

  raise Errors::ValidationError, 'weight_inputs must be a Hash' \
    unless weight_inputs.is_a?(::Hash)
  unless weight_inputs.keys.length == WEIGHT_INPUT_KEYS.length &&
         WEIGHT_INPUT_KEYS.all? { |key| weight_inputs.key?(key) }
    raise Errors::ValidationError,
          'weight_inputs must have keys tier/provider/instance/model_or_offering'
  end
  raise Errors::ValidationError, 'weight_inputs values must be Integers >= 0' \
    unless weight_inputs.values.all? { |value| value.is_a?(::Integer) && value >= 0 }
  raise Errors::ValidationError, 'base_weight must be an Integer >= 0' \
    unless base_weight.is_a?(::Integer) && base_weight >= 0
  raise Errors::ValidationError, 'base_weight must equal the product of weight_inputs' \
    unless base_weight == weight_inputs.values.reduce(1, :*)

  [weight_inputs.dup.freeze, base_weight]
end

.value_evidence!(evidence, field) ⇒ Object



215
216
217
218
219
# File 'lib/legion/extensions/llm/inventory/records.rb', line 215

def value_evidence!(evidence, field)
  raise Errors::ValidationError, "#{field} must be a ValueEvidence" unless evidence.is_a?(ValueEvidence)

  evidence
end