Module: StillActive::StatusHelper
Overview
Collapses a gem's several maintenance signals into one categorical verdict, so a machine/LLM consumer (or another tool's report) can display and threshold a single value instead of re-deriving it from activity_level + archived + vulnerability_count. This is deliberately NOT a numeric composite: an earlier 0-100 score was removed because a weighted average let missing data read as "perfect health". Here, :unknown stays :unknown -- absence of data is never rendered as :ok.
Constant Summary collapse
- SEVERITY =
Worst-first lifecycle verdict. The key distinction (from the "done gems" critique and validated against the maintenance-tooling landscape): a clean, long-dormant gem is :legacy ("done", low risk), NOT a problem -- whereas a dormant or archived gem carrying an unpatched advisory is :dead (no one is going to fix it, migrate). :unknown is least severe -- an absence, not a finding -- so missing data never reads as :ok.
[:unknown, :ok, :legacy, :stale, :archived, :vulnerable, :dead].freeze
Instance Method Summary collapse
-
#gem_status(gem_data) ⇒ Object
Returns :dead, :vulnerable, :archived, :legacy, :stale, :ok, or :unknown.
-
#project_status(result, ruby_info: nil) ⇒ Object
The single worst gem status across the audit.
Instance Method Details
#gem_status(gem_data) ⇒ Object
Returns :dead, :vulnerable, :archived, :legacy, :stale, :ok, or :unknown.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/helpers/status_helper.rb', line 25 def gem_status(gem_data) vulnerable = gem_data[:vulnerability_count].to_i.positive? # A pinned version the registry can't resolve (yanked, typo, or nonexistent) # has no version-specific data to judge, so package-level health must not read # it as :ok. Absence of data is :unknown, never a false all-clear. Guarded on # `!vulnerable` so a detected advisory always wins, in case a future source # ever attaches one to an otherwise-unresolved version. return :unknown if gem_data[:version_unresolved] && !vulnerable level = ActivityHelper.activity_level(gem_data) if vulnerable # A vulnerability in a dormant or archived gem won't be patched -> :dead; # in an actively-released gem a fix is plausible -> :vulnerable. return [:critical, :archived].include?(level) ? :dead : :vulnerable end case level when :archived # archived != EOL: a repo archived while the gem still publishes recent # releases (development moved to a monorepo) isn't dead -- let the # releases speak, but keep :stale so the archived repo stays a yellow flag. ActivityHelper.release_recency_level(gem_data) == :ok ? :stale : :archived when :critical then :legacy # long-dormant but clean: feature-complete, not a fire else level # :stale / :ok / :unknown end end |
#project_status(result, ruby_info: nil) ⇒ Object
The single worst gem status across the audit. An EOL Ruby floors the project at :vulnerable (the runtime itself is a live, actionable risk). :unknown only wins when nothing better is known.
57 58 59 60 61 62 63 64 65 66 |
# File 'lib/helpers/status_helper.rb', line 57 def project_status(result, ruby_info: nil) statuses = result.each_value.map { |data| gem_status(data) } statuses << :vulnerable if ruby_info&.dig(:eol) == true return :unknown if statuses.empty? # Every value gem_status returns is in SEVERITY today; if a future status # isn't, rank it most-severe so it surfaces in the rollup rather than being # silently masked by a milder finding. statuses.max_by { |status| SEVERITY.index(status) || SEVERITY.length } end |