Module: Leakless::Cli::Reporter
- Defined in:
- lib/leakless/reporter.rb
Overview
Formats findings for terminal output and gates high-severity secrets.
Constant Summary collapse
- GREEN =
"\e[32m"- YELLOW =
"\e[33m"- RESET =
"\e[0m"- VERDICT_LABELS =
{ "true_positive" => "likely real", "false_positive" => "likely placeholder", "uncertain" => "unclear" }.freeze
Class Method Summary collapse
-
.format_line(finding) ⇒ Object
Data.define objects deconstruct into a Hash for free, so
incan match directly on the fields we care about — no case/when + manual field access. - .gate!(findings, force:) ⇒ Object
- .print_findings(findings) ⇒ Object
- .report(findings, force: false) ⇒ Object
Class Method Details
.format_line(finding) ⇒ Object
Data.define objects deconstruct into a Hash for free, so in can match
directly on the fields we care about — no case/when + manual field access.
The untriaged branch comes first, so a nil verdict never reaches the
formatting that assumes one.
41 42 43 44 45 46 47 48 49 50 |
# File 'lib/leakless/reporter.rb', line 41 def format_line(finding) case finding in { verdict: nil, file:, line:, rule:, preview: } "#{file}:#{line} [#{rule}] #{preview}" in { verdict:, confidence:, rationale:, file:, line:, rule:, preview: } "#{file}:#{line} [#{rule}] #{preview}\n" \ " → #{VERDICT_LABELS.fetch(verdict, verdict)} " \ "(#{(confidence * 100).round}% confident) #{rationale}" end end |
.gate!(findings, force:) ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/leakless/reporter.rb', line 52 def gate!(findings, force:) high = findings.select(&:high?) return if high.empty? || force raise Error, "Secrets export blocked: #{high.size} high-severity finding(s) detected. " \ "Review and remove secrets, or re-run with --force to override." end |
.print_findings(findings) ⇒ Object
27 28 29 30 31 32 33 34 35 |
# File 'lib/leakless/reporter.rb', line 27 def print_findings(findings) puts "#{YELLOW}\n ⚠ Secret patterns detected:#{RESET}" findings.each { |finding| puts "#{YELLOW} #{format_line(finding)}#{RESET}" } puts "#{YELLOW}\n ⚠ Review and redact secrets before pushing to a public repository.#{RESET}" if findings.any?(&:triaged?) puts "#{YELLOW} ⚠ AI verdicts are advisory: the high-severity gate ignores them.#{RESET}" end puts "" end |