{"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-fb34e16690026100", "name": "Possibly dead Python function: require_auth", "shortDescription": {"text": "Possibly dead Python function: require_auth"}, "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-7ecfff8d99bbbcc3", "name": "Possibly dead Python function: require_admin", "shortDescription": {"text": "Possibly dead Python function: require_admin"}, "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-978f3c1c0a98ef69", "name": "Possibly dead Python function: cleanup", "shortDescription": {"text": "Possibly dead Python function: cleanup"}, "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-a479a7ddbc3a462c", "name": "Possibly dead Python function: kpa_to_bar", "shortDescription": {"text": "Possibly dead Python function: kpa_to_bar"}, "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-2a2fe1e4a885fed8", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/equipment/AnalyticsCalendarDialog.tsx:331", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/equipment/AnalyticsCalendarDialog.tsx:331"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-c912dc4d6475bc2f", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/map/ObjectsMapPopup.tsx:65", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/map/ObjectsMapPopup.tsx:65"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-77a464701f01cedf", "name": "Possible secret in README.md", "shortDescription": {"text": "Possible secret in README.md"}, "fullDescription": {"text": "Detected pattern matching password_literal. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-c5a0f540290b13dc", "name": "Insecure pattern 'direct_innerhtml_assignment' in frontend/src/components/equipment/history/HistoryChart.tsx:892", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/src/components/equipment/history/HistoryChart.tsx:892"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f8f287a0b7e0669f", "name": "Insecure pattern 'node_child_process' in scripts/start_frontend.js:13", "shortDescription": {"text": "Insecure pattern 'node_child_process' in scripts/start_frontend.js:13"}, "fullDescription": {"text": "Found a known-risky pattern (node_child_process). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-75350d055cd39502", "name": "Insecure pattern 'node_child_process' in scripts/start_backend.js:13", "shortDescription": {"text": "Insecure pattern 'node_child_process' in scripts/start_backend.js:13"}, "fullDescription": {"text": "Found a known-risky pattern (node_child_process). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-817ce3e9a8ea0264", "name": "Insecure pattern 'node_child_process' in .claude/hooks/bump-version.mjs:14", "shortDescription": {"text": "Insecure pattern 'node_child_process' in .claude/hooks/bump-version.mjs:14"}, "fullDescription": {"text": "Found a known-risky pattern (node_child_process). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6372cebde0220094", "name": "No auth library detected", "shortDescription": {"text": "No auth library detected"}, "fullDescription": {"text": "The scanner did not find any standard auth library (JWT, OAuth, NextAuth, Auth0, etc.). The repo has auth/admin/session surface indicators, so auth may live in custom code, in a separate service, or be missing."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4601e3ad3bb28677", "name": "No CI/CD pipelines detected", "shortDescription": {"text": "No CI/CD pipelines detected"}, "fullDescription": {"text": "No GitHub Actions, GitLab CI, or CircleCI configs found. Without CI you can't gate deploys on tests/lints."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "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 139 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-72b2a6250083a784", "name": "Placeholder or mock-heavy implementation detected", "shortDescription": {"text": "Placeholder or mock-heavy implementation detected"}, "fullDescription": {"text": "Found 19 placeholder/mock markers across 8 source files. This often means the repo looks complete while core flows still use generated scaffolding or fake data."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "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: 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": "low", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing ci, tests. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e0a0795d98dbfff2", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/api.ts:49", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/api.ts:49"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "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:\nbackend/app/db/queries/history.py:fetch_history, backend/app/db/queries/history.py:fetch_state_events\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-d17d4b3c9f957504", "name": "Frontend route `/objects/:routerSn` has no Link/navigate to it \u2014 frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `/objects/:routerSn` has no Link/navigate to it \u2014 frontend/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-584eae16f5c7b6b7", "name": "Frontend route `/objects/:routerSn/equipment/:equipType/:panelId` has no Link/navigate to it \u2014 frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `/objects/:routerSn/equipment/:equipType/:panelId` has no Link/navigate to it \u2014 frontend/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4756b4c4da7d2088", "name": "Unused endpoint: GET /api/health", "shortDescription": {"text": "Unused endpoint: GET /api/health"}, "fullDescription": {"text": "`backend/app/main.py` declares `GET /api/health` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7aa4b2518cbbbfa2", "name": "Unused endpoint: GET /api/config", "shortDescription": {"text": "Unused endpoint: GET /api/config"}, "fullDescription": {"text": "`backend/app/main.py` declares `GET /api/config` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cb12316bd076fcf1", "name": "Unused endpoint: GET /{router_sn}/{equip_type}/{panel_id}", "shortDescription": {"text": "Unused endpoint: GET /{router_sn}/{equip_type}/{panel_id}"}, "fullDescription": {"text": "`backend/app/routers/registers.py` declares `GET /{router_sn}/{equip_type}/{panel_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-69d327318617f514", "name": "Unused endpoint: POST /update", "shortDescription": {"text": "Unused endpoint: POST /update"}, "fullDescription": {"text": "`backend/app/routers/admin_proxy.py` declares `POST /update` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-97a9452719d54058", "name": "Unused endpoint: GET /check-update", "shortDescription": {"text": "Unused endpoint: GET /check-update"}, "fullDescription": {"text": "`backend/app/routers/admin_proxy.py` declares `GET /check-update` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5d27bd61937853f5", "name": "Unused endpoint: GET /update-status", "shortDescription": {"text": "Unused endpoint: GET /update-status"}, "fullDescription": {"text": "`backend/app/routers/admin_proxy.py` declares `GET /update-status` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5baa8971ebe192a1", "name": "Unused endpoint: GET /", "shortDescription": {"text": "Unused endpoint: GET /"}, "fullDescription": {"text": "`backend/app/routers/history.py` declares `GET /` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4d0b75c541565cd9", "name": "Unused endpoint: GET /journal", "shortDescription": {"text": "Unused endpoint: GET /journal"}, "fullDescription": {"text": "`backend/app/routers/history.py` declares `GET /journal` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-00bc47191499b910", "name": "Unused endpoint: GET /state-events", "shortDescription": {"text": "Unused endpoint: GET /state-events"}, "fullDescription": {"text": "`backend/app/routers/history.py` declares `GET /state-events` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-592cb4697f2407c3", "name": "Unused endpoint: GET /{z}/{x}/{y}.png", "shortDescription": {"text": "Unused endpoint: GET /{z}/{x}/{y}.png"}, "fullDescription": {"text": "`backend/app/routers/tiles.py` declares `GET /{z}/{x}/{y}.png` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-578b401db4f0fb2b", "name": "Unused endpoint: GET /cache/stats", "shortDescription": {"text": "Unused endpoint: GET /cache/stats"}, "fullDescription": {"text": "`backend/app/routers/tiles.py` declares `GET /cache/stats` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1461946ab835599d", "name": "Unused endpoint: DELETE /cache", "shortDescription": {"text": "Unused endpoint: DELETE /cache"}, "fullDescription": {"text": "`backend/app/routers/tiles.py` declares `DELETE /cache` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-27b0a19caacdf70c", "name": "Unused endpoint: GET /{router_sn}", "shortDescription": {"text": "Unused endpoint: GET /{router_sn}"}, "fullDescription": {"text": "`backend/app/routers/objects.py` declares `GET /{router_sn}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-00e086613d7cbcaf", "name": "Unused endpoint: PATCH /{router_sn}", "shortDescription": {"text": "Unused endpoint: PATCH /{router_sn}"}, "fullDescription": {"text": "`backend/app/routers/objects.py` declares `PATCH /{router_sn}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1cf5015dd556449a", "name": "Unused endpoint: DELETE /{router_sn}", "shortDescription": {"text": "Unused endpoint: DELETE /{router_sn}"}, "fullDescription": {"text": "`backend/app/routers/objects.py` declares `DELETE /{router_sn}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7c3ea82eb37bae8f", "name": "Unused endpoint: GET /machines", "shortDescription": {"text": "Unused endpoint: GET /machines"}, "fullDescription": {"text": "`backend/app/routers/analytics_proxy.py` declares `GET /machines` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-429864bfed5b10cc", "name": "Unused endpoint: GET /machine/{router_sn}/{equip_type}/{panel_id}/segments", "shortDescription": {"text": "Unused endpoint: GET /machine/{router_sn}/{equip_type}/{panel_id}/segments"}, "fullDescription": {"text": "`backend/app/routers/analytics_proxy.py` declares `GET /machine/{router_sn}/{equip_type}/{panel_id}/segments` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b63ba8f75be5d9ef", "name": "Unused endpoint: GET /segment/{seg_id}", "shortDescription": {"text": "Unused endpoint: GET /segment/{seg_id}"}, "fullDescription": {"text": "`backend/app/routers/analytics_proxy.py` declares `GET /segment/{seg_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1826d7e6a428cb0f", "name": "Unused endpoint: GET /view/{token}", "shortDescription": {"text": "Unused endpoint: GET /view/{token}"}, "fullDescription": {"text": "`backend/app/routers/share.py` declares `GET /view/{token}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5c1545494ab6166c", "name": "Unused endpoint: GET /api/me", "shortDescription": {"text": "Unused endpoint: GET /api/me"}, "fullDescription": {"text": "`backend/app/routers/share.py` declares `GET /api/me` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8136b6876213748f", "name": "Unused endpoint: POST /api/share-links", "shortDescription": {"text": "Unused endpoint: POST /api/share-links"}, "fullDescription": {"text": "`backend/app/routers/share.py` declares `POST /api/share-links` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0af75b531f690fdf", "name": "Unused endpoint: GET /api/share-links", "shortDescription": {"text": "Unused endpoint: GET /api/share-links"}, "fullDescription": {"text": "`backend/app/routers/share.py` declares `GET /api/share-links` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c171c61e9ea45199", "name": "Unused endpoint: POST /api/share-links/{link_id}/revoke", "shortDescription": {"text": "Unused endpoint: POST /api/share-links/{link_id}/revoke"}, "fullDescription": {"text": "`backend/app/routers/share.py` declares `POST /api/share-links/{link_id}/revoke` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-65cd00693b44fc80", "name": "Unused endpoint: PATCH /{equip_type}/{panel_id}/name", "shortDescription": {"text": "Unused endpoint: PATCH /{equip_type}/{panel_id}/name"}, "fullDescription": {"text": "`backend/app/routers/equipment.py` declares `PATCH /{equip_type}/{panel_id}/name` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b437172024d687ff", "name": "Unused endpoint: GET /diagnostics", "shortDescription": {"text": "Unused endpoint: GET /diagnostics"}, "fullDescription": {"text": "`backend/app/routers/system.py` declares `GET /diagnostics` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/23594"}, "properties": {"repository": "zergont/UI-telemetry", "repoUrl": "https://github.com/zergont/UI-telemetry", "branch": "main"}, "results": [{"ruleId": "scanner-fb34e16690026100", "level": "note", "message": {"text": "Possibly dead Python function: require_auth"}, "properties": {"repobilityId": "d7855475dea79341", "scanner": "scanner-primary", "fingerprint": "fb34e16690026100", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/auth.py:185"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-7ecfff8d99bbbcc3", "level": "note", "message": {"text": "Possibly dead Python function: require_admin"}, "properties": {"repobilityId": "3c06db2e25566bf7", "scanner": "scanner-primary", "fingerprint": "7ecfff8d99bbbcc3", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/auth.py:210"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-978f3c1c0a98ef69", "level": "note", "message": {"text": "Possibly dead Python function: cleanup"}, "properties": {"repobilityId": "c1cf2fbdf1e262a0", "scanner": "scanner-primary", "fingerprint": "978f3c1c0a98ef69", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/services/rate_limiter.py:43"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-a479a7ddbc3a462c", "level": "note", "message": {"text": "Possibly dead Python function: kpa_to_bar"}, "properties": {"repobilityId": "263bca794d014f38", "scanner": "scanner-primary", "fingerprint": "a479a7ddbc3a462c", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/services/telemetry.py:24"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2a2fe1e4a885fed8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/equipment/AnalyticsCalendarDialog.tsx:331"}, "properties": {"repobilityId": "534180bc9dab6ae2", "scanner": "scanner-primary", "fingerprint": "2a2fe1e4a885fed8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c912dc4d6475bc2f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/map/ObjectsMapPopup.tsx:65"}, "properties": {"repobilityId": "15ff2168b10b1720", "scanner": "scanner-primary", "fingerprint": "c912dc4d6475bc2f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-77a464701f01cedf", "level": "error", "message": {"text": "Possible secret in README.md"}, "properties": {"repobilityId": "03df1be0543b7759", "scanner": "scanner-primary", "fingerprint": "77a464701f01cedf", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "README.md"}, "region": {"startLine": 109}}}]}, {"ruleId": "scanner-77a464701f01cedf", "level": "error", "message": {"text": "Possible secret in README.md"}, "properties": {"repobilityId": "03df1be0543b7759", "scanner": "scanner-primary", "fingerprint": "77a464701f01cedf", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "README.md"}, "region": {"startLine": 111}}}]}, {"ruleId": "scanner-c5a0f540290b13dc", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/src/components/equipment/history/HistoryChart.tsx:892"}, "properties": {"repobilityId": "889ccddc6885a11d", "scanner": "scanner-primary", "fingerprint": "c5a0f540290b13dc", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/equipment/history/HistoryChart.tsx"}, "region": {"startLine": 892}}}]}, {"ruleId": "scanner-f8f287a0b7e0669f", "level": "warning", "message": {"text": "Insecure pattern 'node_child_process' in scripts/start_frontend.js:13"}, "properties": {"repobilityId": "28e848f95382b8e1", "scanner": "scanner-primary", "fingerprint": "f8f287a0b7e0669f", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "node_child_process"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "scripts/start_frontend.js"}, "region": {"startLine": 13}}}]}, {"ruleId": "scanner-75350d055cd39502", "level": "warning", "message": {"text": "Insecure pattern 'node_child_process' in scripts/start_backend.js:13"}, "properties": {"repobilityId": "3d8912bb188e4932", "scanner": "scanner-primary", "fingerprint": "75350d055cd39502", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "node_child_process"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "scripts/start_backend.js"}, "region": {"startLine": 13}}}]}, {"ruleId": "scanner-817ce3e9a8ea0264", "level": "warning", "message": {"text": "Insecure pattern 'node_child_process' in .claude/hooks/bump-version.mjs:14"}, "properties": {"repobilityId": "c66fec596e073b08", "scanner": "scanner-primary", "fingerprint": "817ce3e9a8ea0264", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "node_child_process"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/hooks/bump-version.mjs"}, "region": {"startLine": 14}}}]}, {"ruleId": "scanner-6372cebde0220094", "level": "warning", "message": {"text": "No auth library detected"}, "properties": {"repobilityId": "a5b6035a5bbf8054", "scanner": "scanner-primary", "fingerprint": "6372cebde0220094", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["coverage", "auth"]}}, {"ruleId": "scanner-4601e3ad3bb28677", "level": "warning", "message": {"text": "No CI/CD pipelines detected"}, "properties": {"repobilityId": "c3ee439bce2bc51e", "scanner": "scanner-primary", "fingerprint": "4601e3ad3bb28677", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["coverage"]}}, {"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-72b2a6250083a784", "level": "warning", "message": {"text": "Placeholder or mock-heavy implementation detected"}, "properties": {"repobilityId": "fe9bc273a0a40305", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "5bc17cfc683d48ad", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "note", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "5e4394a476ed0c73", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "68a1f8a1094572a8", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "ddedc1efc2ab0352", "scanner": "scanner-primary", "fingerprint": "ea8f3013f588db25", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-8424db9c75e04ba4", "level": "none", "message": {"text": "Very short observed git history"}, "properties": {"repobilityId": "a5e7623a6433de7a", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-e0a0795d98dbfff2", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/api.ts:49"}, "properties": {"repobilityId": "601ad9ff153d71e4", "scanner": "scanner-primary", "fingerprint": "e0a0795d98dbfff2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "9f07a0471aa56f10", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "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": "6038e38a4103bcd3", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "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": "8d6e92feedaa905a", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-d17d4b3c9f957504", "level": "warning", "message": {"text": "Frontend route `/objects/:routerSn` has no Link/navigate to it \u2014 frontend/src/App.tsx"}, "properties": {"repobilityId": "ae7e15f8e31a0193", "scanner": "scanner-primary", "fingerprint": "d17d4b3c9f957504", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-584eae16f5c7b6b7", "level": "warning", "message": {"text": "Frontend route `/objects/:routerSn/equipment/:equipType/:panelId` has no Link/navigate to it \u2014 frontend/src/App.tsx"}, "properties": {"repobilityId": "e67218ec0cd97da5", "scanner": "scanner-primary", "fingerprint": "584eae16f5c7b6b7", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-4756b4c4da7d2088", "level": "note", "message": {"text": "Unused endpoint: GET /api/health"}, "properties": {"repobilityId": "414de3a0f9ad89dd", "scanner": "scanner-primary", "fingerprint": "4756b4c4da7d2088", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7aa4b2518cbbbfa2", "level": "note", "message": {"text": "Unused endpoint: GET /api/config"}, "properties": {"repobilityId": "396e2ca8e7902141", "scanner": "scanner-primary", "fingerprint": "7aa4b2518cbbbfa2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cb12316bd076fcf1", "level": "note", "message": {"text": "Unused endpoint: GET /{router_sn}/{equip_type}/{panel_id}"}, "properties": {"repobilityId": "f6444f93d49dc460", "scanner": "scanner-primary", "fingerprint": "cb12316bd076fcf1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-69d327318617f514", "level": "note", "message": {"text": "Unused endpoint: POST /update"}, "properties": {"repobilityId": "32090bc2f9a3c78d", "scanner": "scanner-primary", "fingerprint": "69d327318617f514", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-97a9452719d54058", "level": "note", "message": {"text": "Unused endpoint: GET /check-update"}, "properties": {"repobilityId": "6819db09ecb796c9", "scanner": "scanner-primary", "fingerprint": "97a9452719d54058", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5d27bd61937853f5", "level": "note", "message": {"text": "Unused endpoint: GET /update-status"}, "properties": {"repobilityId": "0386194773bfd5ee", "scanner": "scanner-primary", "fingerprint": "5d27bd61937853f5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5baa8971ebe192a1", "level": "note", "message": {"text": "Unused endpoint: GET /"}, "properties": {"repobilityId": "e32e13d86e326fc0", "scanner": "scanner-primary", "fingerprint": "5baa8971ebe192a1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4d0b75c541565cd9", "level": "note", "message": {"text": "Unused endpoint: GET /journal"}, "properties": {"repobilityId": "39029ccfb8c19e77", "scanner": "scanner-primary", "fingerprint": "4d0b75c541565cd9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-00bc47191499b910", "level": "note", "message": {"text": "Unused endpoint: GET /state-events"}, "properties": {"repobilityId": "28c52a2e342791bc", "scanner": "scanner-primary", "fingerprint": "00bc47191499b910", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-592cb4697f2407c3", "level": "note", "message": {"text": "Unused endpoint: GET /{z}/{x}/{y}.png"}, "properties": {"repobilityId": "6fb42408168ad8f2", "scanner": "scanner-primary", "fingerprint": "592cb4697f2407c3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-578b401db4f0fb2b", "level": "note", "message": {"text": "Unused endpoint: GET /cache/stats"}, "properties": {"repobilityId": "896093b31c3df37b", "scanner": "scanner-primary", "fingerprint": "578b401db4f0fb2b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1461946ab835599d", "level": "note", "message": {"text": "Unused endpoint: DELETE /cache"}, "properties": {"repobilityId": "c967f13bb9a3af2e", "scanner": "scanner-primary", "fingerprint": "1461946ab835599d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-27b0a19caacdf70c", "level": "note", "message": {"text": "Unused endpoint: GET /{router_sn}"}, "properties": {"repobilityId": "dfaf9aa8f1401fff", "scanner": "scanner-primary", "fingerprint": "27b0a19caacdf70c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-00e086613d7cbcaf", "level": "note", "message": {"text": "Unused endpoint: PATCH /{router_sn}"}, "properties": {"repobilityId": "f5205b7710617f04", "scanner": "scanner-primary", "fingerprint": "00e086613d7cbcaf", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1cf5015dd556449a", "level": "note", "message": {"text": "Unused endpoint: DELETE /{router_sn}"}, "properties": {"repobilityId": "29df36b8001d1e37", "scanner": "scanner-primary", "fingerprint": "1cf5015dd556449a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7c3ea82eb37bae8f", "level": "note", "message": {"text": "Unused endpoint: GET /machines"}, "properties": {"repobilityId": "acaa1d1d0c67ed8c", "scanner": "scanner-primary", "fingerprint": "7c3ea82eb37bae8f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-429864bfed5b10cc", "level": "note", "message": {"text": "Unused endpoint: GET /machine/{router_sn}/{equip_type}/{panel_id}/segments"}, "properties": {"repobilityId": "9d6b81e2ea86b9cd", "scanner": "scanner-primary", "fingerprint": "429864bfed5b10cc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b63ba8f75be5d9ef", "level": "note", "message": {"text": "Unused endpoint: GET /segment/{seg_id}"}, "properties": {"repobilityId": "c93789e19f4a4bbd", "scanner": "scanner-primary", "fingerprint": "b63ba8f75be5d9ef", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1826d7e6a428cb0f", "level": "note", "message": {"text": "Unused endpoint: GET /view/{token}"}, "properties": {"repobilityId": "222c98ffae45f9bd", "scanner": "scanner-primary", "fingerprint": "1826d7e6a428cb0f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5c1545494ab6166c", "level": "note", "message": {"text": "Unused endpoint: GET /api/me"}, "properties": {"repobilityId": "97c17bcff4ce3b59", "scanner": "scanner-primary", "fingerprint": "5c1545494ab6166c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8136b6876213748f", "level": "note", "message": {"text": "Unused endpoint: POST /api/share-links"}, "properties": {"repobilityId": "ddd4a8d3bd7eb3c3", "scanner": "scanner-primary", "fingerprint": "8136b6876213748f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0af75b531f690fdf", "level": "note", "message": {"text": "Unused endpoint: GET /api/share-links"}, "properties": {"repobilityId": "891424cc35c53d6e", "scanner": "scanner-primary", "fingerprint": "0af75b531f690fdf", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c171c61e9ea45199", "level": "note", "message": {"text": "Unused endpoint: POST /api/share-links/{link_id}/revoke"}, "properties": {"repobilityId": "b6484c386a090ebc", "scanner": "scanner-primary", "fingerprint": "c171c61e9ea45199", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-65cd00693b44fc80", "level": "note", "message": {"text": "Unused endpoint: PATCH /{equip_type}/{panel_id}/name"}, "properties": {"repobilityId": "20a52096ac097972", "scanner": "scanner-primary", "fingerprint": "65cd00693b44fc80", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b437172024d687ff", "level": "note", "message": {"text": "Unused endpoint: GET /diagnostics"}, "properties": {"repobilityId": "50601fbbdeb4645b", "scanner": "scanner-primary", "fingerprint": "b437172024d687ff", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}