{"version": "2.1.0", "$schema": "https://json.schemastore.org/sarif-2.1.0.json", "runs": [{"tool": {"driver": {"name": "Repobility", "informationUri": "https://repobility.com", "rules": [{"id": "scanner-b0f7cab5b852d48b", "name": "Possibly dead Python function: fetch_artist_albums", "shortDescription": {"text": "Possibly dead Python function: fetch_artist_albums"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-319c6e57a4b33432", "name": "Possibly dead Python function: deeper_cut_items", "shortDescription": {"text": "Possibly dead Python function: deeper_cut_items"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0ddd0d46f9c9e79e", "name": "Possibly dead Python function: grab", "shortDescription": {"text": "Possibly dead Python function: grab"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-76281044d6341f5d", "name": "Possibly dead Python function: job", "shortDescription": {"text": "Possibly dead Python function: job"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-dc4b7ba0776ea9e2", "name": "Possibly dead Python function: stop", "shortDescription": {"text": "Possibly dead Python function: stop"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-075d860677a0f171", "name": "Possibly dead Python function: handle_button", "shortDescription": {"text": "Possibly dead Python function: handle_button"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e213e1f8c4bbc059", "name": "Very large file: server.py (1492 lines)", "shortDescription": {"text": "Very large file: server.py (1492 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "0 test file(s) for 4 source file(s) (ratio 0.00). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 42 console/debugger/print-style debug statements in non-test source. This is a common fast-generation residue before production cleanup."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, ci, tests. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1e67c2856e1ebd8d", "name": "Legacy-named symbol `playing_state_too_old` in server.py:810", "shortDescription": {"text": "Legacy-named symbol `playing_state_too_old` in server.py:810"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-dcc35cacb8e97b29", "name": "Commented-code block (5 lines) in wled_sync.py:569", "shortDescription": {"text": "Commented-code block (5 lines) in wled_sync.py:569"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-2c04133e54348533", "name": "Near-duplicate function bodies in 2 places", "shortDescription": {"text": "Near-duplicate function bodies in 2 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nserver.py:crate_payload, server.py:crate\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-be46ea126aa5d8dc", "name": "Near-duplicate function bodies in 3 places", "shortDescription": {"text": "Near-duplicate function bodies in 3 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nserver.py:control_playback_local, server.py:control_playback, server.py:control\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-af4d71590efeaf1f", "name": "Flask mutation route `control` without `@login_required` \u2014 server.py:1149", "shortDescription": {"text": "Flask mutation route `control` without `@login_required` \u2014 server.py:1149"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-90df9adaeace5959", "name": "Flask mutation route `control_seek` without `@login_required` \u2014 server.py:1161", "shortDescription": {"text": "Flask mutation route `control_seek` without `@login_required` \u2014 server.py:1161"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-308a52918a024cdc", "name": "Flask mutation route `control_volume` without `@login_required` \u2014 server.py:1183", "shortDescription": {"text": "Flask mutation route `control_volume` without `@login_required` \u2014 server.py:1183"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-0a8d3423fa643c67", "name": "Flask mutation route `idle_play` without `@login_required` \u2014 server.py:1231", "shortDescription": {"text": "Flask mutation route `idle_play` without `@login_required` \u2014 server.py:1231"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-3b6c1fd6cfb9a9c6", "name": "Flask mutation route `wled_devices_update` without `@login_required` \u2014 server.py:1420", "shortDescription": {"text": "Flask mutation route `wled_devices_update` without `@login_required` \u2014 server.py:1420"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/28300"}, "properties": {"repository": "nonlineartom/spotify-circular-display", "repoUrl": "https://github.com/nonlineartom/spotify-circular-display", "branch": "main"}, "results": [{"ruleId": "scanner-b0f7cab5b852d48b", "level": "note", "message": {"text": "Possibly dead Python function: fetch_artist_albums"}, "properties": {"repobilityId": "e4bad302d84ec1ca", "scanner": "scanner-primary", "fingerprint": "b0f7cab5b852d48b", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server.py:377"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-319c6e57a4b33432", "level": "note", "message": {"text": "Possibly dead Python function: deeper_cut_items"}, "properties": {"repobilityId": "177cb8af52bce2e1", "scanner": "scanner-primary", "fingerprint": "319c6e57a4b33432", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server.py:419"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-0ddd0d46f9c9e79e", "level": "note", "message": {"text": "Possibly dead Python function: grab"}, "properties": {"repobilityId": "257c68fdb7719edf", "scanner": "scanner-primary", "fingerprint": "0ddd0d46f9c9e79e", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server.py:463"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-76281044d6341f5d", "level": "note", "message": {"text": "Possibly dead Python function: job"}, "properties": {"repobilityId": "134e4133852d2744", "scanner": "scanner-primary", "fingerprint": "76281044d6341f5d", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server.py:504"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-dc4b7ba0776ea9e2", "level": "note", "message": {"text": "Possibly dead Python function: stop"}, "properties": {"repobilityId": "ba22d90d343a0bd9", "scanner": "scanner-primary", "fingerprint": "dc4b7ba0776ea9e2", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "wled_sync.py:484"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-075d860677a0f171", "level": "note", "message": {"text": "Possibly dead Python function: handle_button"}, "properties": {"repobilityId": "e7fcb8a236dd302c", "scanner": "scanner-primary", "fingerprint": "075d860677a0f171", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "gpio_buttons.py:52"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-e213e1f8c4bbc059", "level": "note", "message": {"text": "Very large file: server.py (1492 lines)"}, "properties": {"repobilityId": "61d8058d744c856e", "scanner": "scanner-primary", "fingerprint": "e213e1f8c4bbc059", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-6893a6c8b0861585", "level": "warning", "message": {"text": "Very low test-to-source ratio"}, "properties": {"repobilityId": "54a7de3f06314bf0", "scanner": "scanner-primary", "fingerprint": "6893a6c8b0861585", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "coverage"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "4b01be472aa5043d", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "d0d2e92571a4bb8f", "scanner": "scanner-primary", "fingerprint": "3ab5d313dda8e5f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["debug", "cleanup", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "warning", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "d65ab4dd391918e3", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-1e67c2856e1ebd8d", "level": "note", "message": {"text": "Legacy-named symbol `playing_state_too_old` in server.py:810"}, "properties": {"repobilityId": "c6a7f2c989b8aa1f", "scanner": "scanner-primary", "fingerprint": "1e67c2856e1ebd8d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-dcc35cacb8e97b29", "level": "none", "message": {"text": "Commented-code block (5 lines) in wled_sync.py:569"}, "properties": {"repobilityId": "3684b52f6c40a7a9", "scanner": "scanner-primary", "fingerprint": "dcc35cacb8e97b29", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "2f1e9d174c7bfb9e", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "d71d71c27b075f03", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "955065227e91a175", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-af4d71590efeaf1f", "level": "error", "message": {"text": "Flask mutation route `control` without `@login_required` \u2014 server.py:1149"}, "properties": {"repobilityId": "3b189af18a943590", "scanner": "scanner-primary", "fingerprint": "af4d71590efeaf1f", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server.py"}, "region": {"startLine": 1149}}}]}, {"ruleId": "scanner-90df9adaeace5959", "level": "error", "message": {"text": "Flask mutation route `control_seek` without `@login_required` \u2014 server.py:1161"}, "properties": {"repobilityId": "b823ccc7c31a51db", "scanner": "scanner-primary", "fingerprint": "90df9adaeace5959", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server.py"}, "region": {"startLine": 1161}}}]}, {"ruleId": "scanner-308a52918a024cdc", "level": "error", "message": {"text": "Flask mutation route `control_volume` without `@login_required` \u2014 server.py:1183"}, "properties": {"repobilityId": "b6441884877d7ccf", "scanner": "scanner-primary", "fingerprint": "308a52918a024cdc", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server.py"}, "region": {"startLine": 1183}}}]}, {"ruleId": "scanner-0a8d3423fa643c67", "level": "error", "message": {"text": "Flask mutation route `idle_play` without `@login_required` \u2014 server.py:1231"}, "properties": {"repobilityId": "dce862a3dbb6c9c6", "scanner": "scanner-primary", "fingerprint": "0a8d3423fa643c67", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server.py"}, "region": {"startLine": 1231}}}]}, {"ruleId": "scanner-3b6c1fd6cfb9a9c6", "level": "error", "message": {"text": "Flask mutation route `wled_devices_update` without `@login_required` \u2014 server.py:1420"}, "properties": {"repobilityId": "34be5c97cceae852", "scanner": "scanner-primary", "fingerprint": "3b6c1fd6cfb9a9c6", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server.py"}, "region": {"startLine": 1420}}}]}]}]}