Module: Foam::Otel::Redaction
- Defined in:
- lib/foam/otel/redaction.rb
Overview
Central redaction engine — the ONE place sensitive keys are stripped. Case-insensitive key match; deep-redacts nested structures with a depth guard; values become the literal "[REDACTED]".
Class Method Summary collapse
-
.redact(raw, keys) ⇒ Object
Redacts a raw string: JSON payloads are deep-redacted; non-JSON strings pass through unchanged.
-
.redact_query(query, keys) ⇒ Object
Per-key query-string redaction ('a=1&token=x' form), mirroring the other cores: split on '&', split each pair on the FIRST '=', URL-decode the key for matching ONLY, emit the RAW key + '=[REDACTED]' (matched) or the raw pair unchanged — never re-encode, never leak on failure.
- .redact_value(obj, keys, depth = 0) ⇒ Object
Class Method Details
.redact(raw, keys) ⇒ Object
Redacts a raw string: JSON payloads are deep-redacted; non-JSON strings pass through unchanged.
37 38 39 40 41 42 |
# File 'lib/foam/otel/redaction.rb', line 37 def redact(raw, keys) parsed = JSON.parse(raw) JSON.generate(redact_value(parsed, keys)) rescue StandardError raw end |
.redact_query(query, keys) ⇒ Object
Per-key query-string redaction ('a=1&token=x' form), mirroring the other cores: split on '&', split each pair on the FIRST '=', URL-decode the key for matching ONLY, emit the RAW key + '=[REDACTED]' (matched) or the raw pair unchanged — never re-encode, never leak on failure.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/foam/otel/redaction.rb', line 48 def redact_query(query, keys) return query if query.nil? || query.empty? query.split("&", -1).map do |pair| eq = pair.index("=") next pair if eq.nil? raw_key = pair[0...eq] decoded_key = URI.decode_www_form_component(raw_key) if keys.include?(decoded_key.downcase) "#{raw_key}=[REDACTED]" else pair end end.join("&") rescue StandardError "" end |
.redact_value(obj, keys, depth = 0) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/foam/otel/redaction.rb', line 16 def redact_value(obj, keys, depth = 0) return "[depth limit]" if depth > MAX_REDACT_DEPTH case obj when Array obj.map { |item| redact_value(item, keys, depth + 1) } when Hash obj.each_with_object({}) do |(key, val), result| if key.is_a?(String) && keys.include?(key.downcase) result[key] = "[REDACTED]" else result[key] = redact_value(val, keys, depth + 1) end end else obj end end |