Module: RailVerdict::Fingerprint

Defined in:
lib/rail_verdict/fingerprint.rb

Defined Under Namespace

Classes: IncompatibleError

Constant Summary collapse

VERSION =
1
ALGORITHM =
"sha256"
PAYLOAD_SCHEMA =
"https://railverdict.dev/fingerprint-payload/v1"
LEGACY_PAYLOAD_SCHEMA =
"https://railverdict.dev/fingerprint-payload/v0.1"
FINGERPRINT_PATTERN =
/\Asha256:[0-9a-f]{64}\z/

Class Method Summary collapse

Class Method Details

.canonical_json(analyzer:, rule_id:, path:, message:) ⇒ Object



34
35
36
37
38
# File 'lib/rail_verdict/fingerprint.rb', line 34

def canonical_json(analyzer:, rule_id:, path:, message:)
  payload = canonical_payload(analyzer: analyzer, rule_id: rule_id, path: path, message: message)
  sorted = payload.keys.sort.to_h { |key| [key, payload.fetch(key)] }
  JSON.generate(sorted)
end

.canonical_payload(analyzer:, rule_id:, path:, message:) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/rail_verdict/fingerprint.rb', line 18

def canonical_payload(analyzer:, rule_id:, path:, message:)
  analyzer = normalize_field(analyzer, "analyzer")
  rule_id = normalize_field(rule_id, "rule_id")
  path = normalize_path(path)
  message = normalize_message(message)
  {
    "payload_schema" => PAYLOAD_SCHEMA,
    "fingerprint_version" => VERSION,
    "algorithm" => ALGORITHM,
    "analyzer" => analyzer,
    "rule_id" => rule_id,
    "path" => path,
    "message" => message
  }
end

.hexdigest(analyzer:, rule_id:, path:, message:) ⇒ Object



40
41
42
# File 'lib/rail_verdict/fingerprint.rb', line 40

def hexdigest(analyzer:, rule_id:, path:, message:)
  "sha256:#{Digest::SHA256.hexdigest(canonical_json(analyzer: analyzer, rule_id: rule_id, path: path, message: message))}"
end

.valid?(fingerprint) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/rail_verdict/fingerprint.rb', line 44

def valid?(fingerprint)
  fingerprint.is_a?(String) && fingerprint.match?(FINGERPRINT_PATTERN)
end