Module: Legion::LLM::Fleet::Lane
- Defined in:
- lib/legion/llm/fleet/lane.rb
Overview
Builds canonical RabbitMQ routing keys for shared fleet work lanes.
Constant Summary collapse
- FORBIDDEN_DIGEST_KEYS =
%i[ api_key authorization caller credential credentials endpoint endpoint_url filesystem identity messages path prompt reply_to secret secrets token url ].freeze
- FORBIDDEN_DIGEST_KEY_PATTERN =
/ (?:^|[^a-z0-9]) (?:api[-_]?key|key|token|secret|credential|password|passphrase|auth|authorization| cookie|bearer|session|private[-_]?key|client[-_]?secret|refresh[-_]?token| access[-_]?token|signature|jwt|pat) (?:$|[^a-z0-9]) /ix- MAX_PUBLIC_SEGMENT_LENGTH =
64
Class Method Summary collapse
- .eligibility_fingerprint(facts) ⇒ Object
- .forbidden_digest_key?(key) ⇒ Boolean
- .forbidden_keys(value, path = []) ⇒ Object
- .inference?(operation) ⇒ Boolean
- .normalize_facts(value) ⇒ Object
- .offering_key(instance_id:, model:, operation:) ⇒ Object
- .operation_slug(operation) ⇒ Object
- .public_segment(label, value) ⇒ Object
- .routing_key(operation:, model:, context_window: nil, boundary: nil, eligibility_fingerprint: nil) ⇒ Object
- .sanitize_model(model) ⇒ Object
- .sanitize_segment(value) ⇒ Object
- .sensitive_segment?(value) ⇒ Boolean
Class Method Details
.eligibility_fingerprint(facts) ⇒ Object
45 46 47 48 49 50 51 |
# File 'lib/legion/llm/fleet/lane.rb', line 45 def eligibility_fingerprint(facts) normalized = normalize_facts(facts) forbidden = forbidden_keys(normalized) raise ArgumentError, "eligibility facts include sensitive keys: #{forbidden.join(', ')}" if forbidden.any? Digest::SHA256.hexdigest(::JSON.generate(normalized))[0, 16] end |
.forbidden_digest_key?(key) ⇒ Boolean
125 126 127 128 |
# File 'lib/legion/llm/fleet/lane.rb', line 125 def forbidden_digest_key?(key) FORBIDDEN_DIGEST_KEYS.include?(key.to_s.downcase.to_sym) || key.to_s.match?(FORBIDDEN_DIGEST_KEY_PATTERN) end |
.forbidden_keys(value, path = []) ⇒ Object
115 116 117 118 119 120 121 122 123 |
# File 'lib/legion/llm/fleet/lane.rb', line 115 def forbidden_keys(value, path = []) return [] unless value.is_a?(Hash) value.flat_map do |key, val| key_path = path + [key] matches = forbidden_digest_key?(key) ? [key_path.join('.')] : [] matches + forbidden_keys(val, key_path) end end |
.inference?(operation) ⇒ Boolean
62 63 64 |
# File 'lib/legion/llm/fleet/lane.rb', line 62 def inference?(operation) operation_slug(operation) == 'inference' end |
.normalize_facts(value) ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/legion/llm/fleet/lane.rb', line 100 def normalize_facts(value) case value when Hash value.each_with_object({}) do |(key, val), normalized| normalized[key.to_s] = normalize_facts(val) end.sort.to_h when Array value.map { |entry| normalize_facts(entry) }.sort_by(&:to_s) when Symbol value.to_s else value end end |
.offering_key(instance_id:, model:, operation:) ⇒ Object
34 35 36 37 38 39 40 41 42 43 |
# File 'lib/legion/llm/fleet/lane.rb', line 34 def offering_key(instance_id:, model:, operation:) [ 'llm', 'fleet', 'offering', public_segment(:instance_id, instance_id), sanitize_model(model), operation_slug(operation) ].join('.') end |
.operation_slug(operation) ⇒ Object
53 54 55 56 57 58 59 60 |
# File 'lib/legion/llm/fleet/lane.rb', line 53 def operation_slug(operation) case operation.to_s when 'embed', 'embedding', 'embeddings' 'embed' else 'inference' end end |
.public_segment(label, value) ⇒ Object
86 87 88 89 90 91 92 93 94 |
# File 'lib/legion/llm/fleet/lane.rb', line 86 def public_segment(label, value) raise ArgumentError, "#{label} contains sensitive content" if sensitive_segment?(value) segment = sanitize_segment(value) raise ArgumentError, "#{label} is empty after sanitization" if segment.empty? raise ArgumentError, "#{label} exceeds #{MAX_PUBLIC_SEGMENT_LENGTH} characters" if segment.length > MAX_PUBLIC_SEGMENT_LENGTH segment end |
.routing_key(operation:, model:, context_window: nil, boundary: nil, eligibility_fingerprint: nil) ⇒ Object
26 27 28 29 30 31 32 |
# File 'lib/legion/llm/fleet/lane.rb', line 26 def routing_key(operation:, model:, context_window: nil, boundary: nil, eligibility_fingerprint: nil) parts = ['llm', 'fleet', operation_slug(operation), sanitize_model(model)] parts << "ctx#{Integer(context_window)}" if inference?(operation) && context_window parts.push('boundary', public_segment(:boundary, boundary)) if boundary parts.push('elig', public_segment(:eligibility_fingerprint, eligibility_fingerprint)) if eligibility_fingerprint parts.join('.') end |
.sanitize_model(model) ⇒ Object
66 67 68 |
# File 'lib/legion/llm/fleet/lane.rb', line 66 def sanitize_model(model) sanitize_segment(model).tr('.', '-') end |
.sanitize_segment(value) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/legion/llm/fleet/lane.rb', line 70 def sanitize_segment(value) output = +'' previous_dash = true value.to_s.downcase.each_byte do |byte| if byte.between?(97, 122) || byte.between?(48, 57) output << byte previous_dash = false elsif !previous_dash output << '-' previous_dash = true end end output.chop! if output.end_with?('-') output end |
.sensitive_segment?(value) ⇒ Boolean
96 97 98 |
# File 'lib/legion/llm/fleet/lane.rb', line 96 def sensitive_segment?(value) value.to_s.match?(FORBIDDEN_DIGEST_KEY_PATTERN) end |