Netflix-Skunkworks/Scumblr
Web framework that allows performing periodic syncs of data sources and performing analysis on the identified results
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓8 active contributors
- ✓Apache-2.0 licensed
- ✓CI configured
Show 3 more →Show less
- ✓Tests present
- ⚠Stale — last commit 6y ago
- ⚠Concentrated ownership — top contributor handles 71% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/netflix-skunkworks/scumblr)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/netflix-skunkworks/scumblr on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: Netflix-Skunkworks/Scumblr
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Netflix-Skunkworks/Scumblr shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 8 active contributors
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 6y ago
- ⚠ Concentrated ownership — top contributor handles 71% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live Netflix-Skunkworks/Scumblr
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/Netflix-Skunkworks/Scumblr.
What it runs against: a local clone of Netflix-Skunkworks/Scumblr — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in Netflix-Skunkworks/Scumblr | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 2342 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Netflix-Skunkworks/Scumblr. If you don't
# have one yet, run these first:
#
# git clone https://github.com/Netflix-Skunkworks/Scumblr.git
# cd Scumblr
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of Netflix-Skunkworks/Scumblr and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Netflix-Skunkworks/Scumblr(\\.git)?\\b" \\
&& ok "origin remote is Netflix-Skunkworks/Scumblr" \\
|| miss "origin remote is not Netflix-Skunkworks/Scumblr (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "app/models/task.rb" \\
&& ok "app/models/task.rb" \\
|| miss "missing critical file: app/models/task.rb"
test -f "app/models/result.rb" \\
&& ok "app/models/result.rb" \\
|| miss "missing critical file: app/models/result.rb"
test -f "app/controllers/application_controller.rb" \\
&& ok "app/controllers/application_controller.rb" \\
|| miss "missing critical file: app/controllers/application_controller.rb"
test -f "app/models/ability.rb" \\
&& ok "app/models/ability.rb" \\
|| miss "missing critical file: app/models/ability.rb"
test -f "config/routes.rb" \\
&& ok "config/routes.rb" \\
|| miss "missing critical file: config/routes.rb"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 2342 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~2312d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Netflix-Skunkworks/Scumblr"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Scumblr is a Rails-based web framework for performing periodic syncs of external data sources (GitHub repos, Route53 DNS, manual uploads) and running asynchronous security analysis tasks (static code analysis with Brakeman/Bandit, GitHub secret searching, curl-based vulnerability checks) on the collected results. It provides centralized vulnerability tracking, metadata storage, event auditing, and workflow automation to streamline proactive security scanning at scale. Monolithic Rails 4+ application: app/models contain database entities (Result, Task, Event, SavedFilter), app/controllers handle web requests, app/assets contain CoffeeScript event handlers (events.js.coffee, results.js.coffee, searches.js.coffee) wired to Foundation UI, and lib/ likely contains sync and analysis task classes. Workflowable gem manages state machines for results across their lifecycle.
👥Who it's for
Security engineers and DevSecOps teams at enterprises who need to automate periodic scans across multiple data sources, correlate findings, and track remediation workflows—especially those running GitHub-heavy or AWS-integrated environments requiring scheduled, auditable security checks.
🌱Maturity & risk
Archived/unmaintained as of August 2018; the README explicitly states Netflix is no longer actively developing it and is looking for maintainers. While it has a full Rails app with CI (Travis), database migrations, and asset pipeline setup, there are no recent commits, no active issue resolution, and no test coverage visible in the file structure. Not production-ready for new deployments.
Critical risk: project is explicitly unmaintained and Netflix is not addressing PRs or issues. Single-maintainer dependency (Scott Behrens) with no active handoff. Likely has outdated Ruby/Rails dependencies (no Gemfile.lock visible in top 60 files, but Rails footnotes suggests Rails 3.x/4.x era). No visible test suite despite complexity, making refactoring dangerous. High risk for production use without full audit and dependency updates.
Active areas of work
Nothing—project is archived. Last activity was the August 2018 deprecation notice. No active branches, PRs, or milestones are being worked on. If deployed, it would only receive bug fixes from external maintainers, not the original Netflix team.
🚀Get running
git clone https://github.com/Netflix/Scumblr.git && cd Scumblr && bundle install (Ruby/Bundler required; Ruby version in .ruby-version). Then rails db:migrate && rails server to start the Rails dev server on localhost:3000. Note: Likely requires external services (GitHub API key, Route53 credentials, optional Bandit/Brakeman installations) to function fully.
Daily commands: bundle install && rails db:migrate && rails server (visits http://localhost:3000). External services must be configured: GitHub token for GitHub sync tasks, AWS credentials for Route53 sync, Python environment for Bandit, Ruby environment for Brakeman if using those tasks.
🗺️Map of the codebase
app/models/task.rb— Core Task model orchestrating periodic syncs and analysis workflows; fundamental to understanding Scumblr's data pipeline.app/models/result.rb— Central Result model storing sync outputs and analysis findings; schema foundation for the entire application.app/controllers/application_controller.rb— Base controller handling authentication, authorization (via ability.rb), and shared request logic across all endpoints.app/models/ability.rb— CanCan authorization rules defining role-based access control for Tasks, Results, Flags, and other resources.config/routes.rb— Rails routing configuration mapping HTTP endpoints to controllers; necessary to understand API surface.Gemfile— Dependency declarations including ActiveRecord, CanCan, Devise, and custom gems; critical for understanding external libraries.
🛠️How to make changes
Add a new analysis result type (custom Result subclass)
- Create a new model inheriting from Result in app/models/my_analysis_result.rb with custom attributes and validations. (
app/models/my_analysis_result.rb) - Add a migration to create the my_analysis_results table with task_id foreign key and analysis-specific columns. (
db/migrate/XXX_create_my_analysis_results.rb) - Update Task.rb to instantiate your result type in the sync/analysis workflow (e.g., in a before_save or callback). (
app/models/task.rb) - Add a view partial in app/views/results/_my_analysis_result.html.erb to render custom result fields. (
app/views/results/_my_analysis_result.html.erb) - Update ability.rb to grant appropriate permissions for your result type (read, update, flag). (
app/models/ability.rb)
Add a new saved filter or search criterion
- Update the SavedFilter model or create a UserSavedFilter variant if per-user filtering is needed. (
app/models/saved_filter.rb) - Add filter parameters to the ResultsController search action to parse and apply the new criterion in the database query. (
app/controllers/results_controller.rb) - Update the results view to include a UI control (dropdown, text field) for the new filter in app/views/results/index.html.erb. (
app/views/results/index.html.erb) - Add client-side JavaScript in app/assets/javascripts/results.js.coffee to wire up interactivity (autocomplete, form submission). (
app/assets/javascripts/results.js.coffee)
Add a new task type or data source integration
- Create a new Task subclass (e.g., app/models/github_repo_task.rb) with source-specific configuration fields and validation. (
app/models/github_repo_task.rb) - Implement the sync logic (fetch data from GitHub API, S3, etc.) in a library or Delayed Job handler called from Task#execute. (
lib/tasks/github_sync_handler.rb) - Add a migration to extend the tasks table with source-specific columns (github_url, branch, credentials_ref, etc.). (
db/migrate/XXX_add_github_fields_to_tasks.rb) - Create a form partial in app/views/tasks/_github_repo_form.html.erb for configuration UI in the task creation flow. (
app/views/tasks/_github_repo_form.html.erb) - Update TasksController to route to the new form partial and persist the new task type. (
app/controllers/tasks_controller.rb)
Add a new notification or email alert
- Add a new mailer method in app/mailers/notification_mailer.rb or summary_mailer.rb that formats and renders the alert email. (
app/mailers/notification_mailer.rb) - Create an email template (view) in app/views/notification_mailer/ to define the email body and styling. (
app/views/notification_mailer/my_alert.html.erb) - Hook the mailer call into Task#execute or Event creation callbacks to trigger the email on task completion or new findings. (
app/models/task.rb) - Update Subscriber model or create a subscription preference record to control which users receive the new alert. (
app/models/subscriber.rb)
🔧Why these technologies
- Rails ActiveRecord + PostgreSQL — Mature ORM for relational data (Tasks, Results, Flags, Events); PostgreSQL supports JSON fields for flexible result metadata.
- CanCan authorization gem — Declarative role-based access control rules in ability.rb; simplifies permission checks across controllers.
- Delayed Job gem — Background job queue for async task execution; prevents long-running syncs from blocking HTTP requests.
- Foundation CSS framework — Responsive, accessibility-focused UI toolkit for admin dashboard; pre-built components reduce custom CSS.
- Devise gem — Standard Rails authentication library; manages user login, sessions, and password resets.
⚖️Trade-offs already made
-
Polymorphic Result model vs. dedicated tables per analysis type
- Why: Polymorphic design (single results table with type discriminator) simplifies unified result browsing and tagging.
- Consequence: Increases query complexity and N+1 risk; requires eager loading of polymorphic associations. Alternative (separate tables) would improve query performance but fragment the unified result interface.
-
Synchronous task scheduling (manual trigger via UI) vs. cron-like periodic execution
- Why: UI-driven scheduling is simpler and allows granular per-task control; users can execute on-demand.
- Consequence: Requires human intervention; no automatic background syncs. Users must remember to trigger tasks. A cron-based alternative (Rufus, Whenever gem) would automate but reduce user visibility and control.
-
Delaying emails in queue vs. synchronous send
- Why: Async mailers prevent HTTP timeout risks and improve responsiveness.
- Consequence:
🪤Traps & gotchas
No visible test suite (no spec/ or test/ in top 60 files)—difficult to refactor safely. Workflowable gem dependency is custom Netflix package; if removed from rubygems, build breaks. CoffeeScript assets require coffee-rails gem; transpilation failures are common on modern Node/Ruby versions. GitHub/AWS sync tasks require external API credentials; missing keys fail silently in scheduled jobs. No visible database.yml or secrets management in top 60 files—expect config/database.yml and config/secrets.yml to be gitignored and manually set. Asset pipeline (d3.js, nvd3.min.js, select2x2.png) bundled inline—no package.json for JS dependency mgmt suggests old Rails 3.2 asset behavior.
🏗️Architecture
💡Concepts to learn
- Asynchronous Job Scheduling & Task Chaining — Scumblr runs periodic syncs and analysis tasks in the background (not blocking HTTP requests); understanding Rails background job frameworks (Sidekiq, Delayed Job) and how they are chained (sync GitHub → run Brakeman → send alerts) is core to modifying the automation pipeline.
- State Machine Workflows (Workflowable) — Result entities move through states (new → reviewed → resolved → remediated); the Workflowable gem models these transitions and enforces valid state changes; critical for understanding how Scumblr tracks vulnerability lifecycle.
- Rails Asset Pipeline (CoffeeScript, SCSS, JavaScript Bundling) — All frontend code is in app/assets/; CoffeeScript files (.js.coffee) compile to JavaScript, SCSS stylesheets are minified, and vendor libraries (d3.js, nvd3.min.js) are sprockets-managed; Rails version determines whether Webpacker or Sprockets is used.
- Metadata Storage & Advanced Filtering — Scumblr stores arbitrary key-value metadata on Results (e.g., CVSS score, repository path, finding date) and provides SavedFilter entities to enable reusable, shareable queries without code changes; understanding this design allows adding new result attributes and filter logic.
- Event Sourcing / Audit Trail Pattern — Every change to a Result (status update, triage decision, remediation note) creates an Event entity with timestamp and user; enables compliance auditing and change tracking without modifying Result itself; common security automation requirement.
- OAuth / API Integration (GitHub, Route53, Search APIs) — Scumblr syncs data by calling external APIs (GitHub GraphQL or REST, AWS Route53, Google Search, Twitter, etc.); understanding rate limiting, token refresh, error handling, and credential management is essential for adding new sync sources or debugging integration failures.
- Foundation CSS Framework & Responsive Design — UI is built with Foundation (CSS grid, form components, responsive breakpoints); app/assets/stylesheets contains Foundation overrides; modifying layout or adding new pages requires understanding Foundation patterns.
🔗Related repos
Netflix/Workflowable— Dependency of Scumblr; provides the state machine workflow framework used by Result entities to track scan progress and remediation.rails/rails— Core framework; Scumblr is a Rails 4 monolith; understanding Rails routing, ActiveRecord, asset pipeline, and generator commands is essential.ankane/shorts— Alternative Ruby security scanning orchestration tool if evaluating replacements for Scumblr's deprecated pipeline.DefectDojo/django-DefectDojo— Similar vulnerability management and aggregation platform (Python/Django); useful reference for modern architecture if forking Scumblr or building alternatives.aquasecurity/Trivy— Modern containerized scanning tool; represents the direction post-Scumblr security automation moved toward, replacing the custom task framework.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add RSpec tests for Results and Flags controllers
The repo has .rspec configured and Rakefile present, indicating test infrastructure exists, but there's no visible spec/ directory in the file structure. The Results and Flags controllers handle critical data processing and analysis functionality. Adding comprehensive controller specs would improve reliability and make the codebase more maintainable for new contributors.
- [ ] Create spec/controllers/results_controller_spec.rb with tests for index, show, and filtering actions
- [ ] Create spec/controllers/flags_controller_spec.rb with tests for CRUD operations and flag state transitions
- [ ] Add factory_bot fixtures in spec/factories/ for Result and Flag models
- [ ] Run
bundle exec rspecto verify tests pass and add to .travis.yml if not already running
Refactor and document the Tasks/TaskTypes architecture
The file structure shows both tasks_controller.rb and task_types_controller.rb, suggesting a complex jobs/scheduling system for 'periodic syncs of data sources' mentioned in the README. This core feature lacks visible documentation. Adding clear documentation with examples would help new maintainers understand the data sync pipeline.
- [ ] Create docs/ARCHITECTURE.md with a section explaining Tasks and TaskTypes relationships
- [ ] Document the periodic sync workflow with sequence diagrams or pseudo-code referencing app/controllers/tasks_controller.rb
- [ ] Add inline code comments to app/controllers/tasks_controller.rb and app/controllers/task_types_controller.rb explaining the sync lifecycle
- [ ] Add an example of creating a custom TaskType in CONTRIBUTING.md
Add JavaScript unit tests for asset pipeline modules
The app has numerous CoffeeScript modules (events.js.coffee, results.js.coffee, searches.js.coffee, etc.) but no visible test infrastructure for frontend code. Adding Jasmine or Jest tests for at least the most critical modules (results.js.coffee, searches.js.coffee) would improve code quality and provide examples for future contributors.
- [ ] Add jasmine gem to Gemfile and create spec/javascripts/support/jasmine.yml
- [ ] Create spec/javascripts/results_spec.coffee with tests for key DOM manipulation functions in app/assets/javascripts/results.js.coffee
- [ ] Create spec/javascripts/searches_spec.coffee with tests for search filter logic
- [ ] Update .travis.yml to run JavaScript tests via
bundle exec rake spec:javascript
🌿Good first issues
- Add RSpec test suite for app/models/result.rb and app/models/task.rb to cover state transitions, validations, and associations—critical for enabling safe refactoring of the unmaintained codebase.
- Document the exact steps to configure GitHub API auth, Route53 credentials, and Bandit/Brakeman environments in a SETUP.md file; README is vague and many new contributors will get stuck on missing API keys.
- Extract sync task classes (GitHub, Route53, manual upload) from lib/tasks/ into app/services/syncs/ using a SyncTask base class to follow Rails conventions and make the codebase navigable for new contributors.
⭐Top contributors
Click to expand
Top contributors
- @sbehrens — 71 commits
- [@Andy Hoernecke](https://github.com/Andy Hoernecke) — 9 commits
- [@Dave King](https://github.com/Dave King) — 8 commits
- [@Madan Sriraman](https://github.com/Madan Sriraman) — 7 commits
- @ahoernecke — 2 commits
📝Recent commits
Click to expand
Recent commits
66ed69a— Merge pull request #252 from Netflix-Skunkworks/bugfix/rails-analyzer (sbehrens)ca0ea77— made section more readable (sbehrens)10be8e3— points analyzer at stash sync object (sbehrens)d6a48b9— Merge pull request #250 from Netflix-Skunkworks/bugfix/vuln-views (sbehrens)6a4b046— fixed partial and added new matcher (sbehrens)b2dcd9e— Create issue_template.md (sbehrens)44be1c9— Update OSSMETADATA (sbehrens)aaa2e16— Update README.md (sbehrens)f27d218— Update README.md (sbehrens)3c71857— Update README.md (sbehrens)
🔒Security observations
- Critical · Deprecated Project - No Active Maintenance —
README.md, Overall Project. The project is officially deprecated as of August 2018 and is actively looking for maintainers. No new features or security patches are being addressed. This means known vulnerabilities will not be fixed, and the project is vulnerable to all emerging threats. Fix: Consider migrating to an actively maintained alternative or fork the project and maintain security patches internally if continued use is required. - High · Missing Dependency Information —
Gemfile, Gemfile.lock. The Gemfile and Gemfile.lock files are not provided in the analysis. This prevents evaluation of Ruby gem dependencies for known vulnerabilities (CVEs). Given the project's age (last maintained in 2018), it likely uses outdated and vulnerable dependencies. Fix: Review all dependencies usingbundle auditand update all gems to their latest secure versions. Consider using Dependabot or similar tools for continuous vulnerability monitoring. - High · Potential SQL Injection Vulnerabilities —
app/controllers/results_controller.rb, app/controllers/searches_controller.rb, app/controllers/tasks_controller.rb. The controllers (results_controller.rb, searches_controller.rb, tasks_controller.rb) likely contain database queries. Without inspecting the code, Rails applications from this era often had SQL injection vulnerabilities, especially when using dynamic query construction. Fix: Review all database queries and ensure parameterized queries/prepared statements are used. Use Rails ORM (ActiveRecord) with proper parameter binding and avoid raw SQL when possible. - High · Potential XSS Vulnerabilities in Views —
app/assets/javascripts/, app/views/ (not shown but implied). The project includes multiple JavaScript files (events.js.coffee, results.js.coffee, searches.js.coffee) and uses CoffeeScript. Legacy Rails applications often lack proper output encoding, making them vulnerable to XSS attacks when rendering user-supplied data. Fix: Ensure all user-supplied data is properly HTML-encoded before rendering. Use Rails helpers likeh()orsanitize(). Review all dynamic content injection points and enable Content Security Policy (CSP) headers. - High · Missing Security Headers Configuration —
app/controllers/application_controller.rb, config/application.rb (not provided). No evidence of security headers configuration (X-Frame-Options, X-Content-Type-Options, Strict-Transport-Security, etc.) in the visible files. Rails applications from 2018 often shipped without these protections. Fix: Configure security headers in the ApplicationController or middleware. Add X-Frame-Options, X-Content-Type-Options, Strict-Transport-Security, and CSP headers. - Medium · Insufficient CSRF Protection Evidence —
app/controllers/application_controller.rb, app/views/ (not shown). While Rails has CSRF protection by default, there's no visible evidence of proper token handling in the file structure. This is a common configuration issue. Fix: Ensureprotect_from_forgery with: :exceptionis enabled in ApplicationController and all forms include CSRF tokens. - Medium · Unencrypted Data in Transit Risk —
config/environments/production.rb (not provided). No visible configuration for enforcing HTTPS or SSL/TLS. The application appears to handle sensitive data (search results, task management) without guaranteed encryption in transit. Fix: Enableconfig.force_ssl = truein production Rails configuration and ensure all traffic is redirected to HTTPS. - Medium · Potential Authentication/Authorization Bypass —
app/models/ability.rb, app/controllers/application_controller.rb. The ability.rb model exists for authorization, but without code inspection, it's unclear if permissions are properly enforced across all controllers. Legacy Rails apps frequently have authorization bypasses. Fix: Implement comprehensive authorization checks in all controllers. Use Pundit or CanCan gem with proper policy enforcement and test authorization rules thoroughly. - Medium · Pry Debugger in Production —
.pryrc. The presence of .pryrc file suggests Pry debugger is configured. If this remains active in production, it could expose a serious attack vector. Fix: undefined
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.