{"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-ea92eb634b04c8ea", "name": "Possibly dead Python function: close_db", "shortDescription": {"text": "Possibly dead Python function: close_db"}, "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-2969680393261516", "name": "Privileged port 29 in use", "shortDescription": {"text": "Privileged port 29 in use"}, "fullDescription": {"text": "Port 29 is privileged (<1024). Make sure the service runs with the right caps or front it with a non-privileged port via a load balancer."}, "properties": {"scanner": "scanner-primary", "layer": "network", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d63da3583b14afc0", "name": "Dockerfile runs as root: Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-de3c1f217d72a063", "name": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8264e661f361a579", "name": "Insecure pattern 'direct_innerhtml_assignment' in js/activity.js:58", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in js/activity.js:58"}, "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-2f820416f1d13698", "name": "Insecure pattern 'direct_innerhtml_assignment' in js/app.js:102", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in js/app.js:102"}, "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-5f4c15df2800a29f", "name": "Insecure pattern 'direct_innerhtml_assignment' in js/backlog.js:154", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in js/backlog.js:154"}, "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-382952fbf06903e3", "name": "Insecure pattern 'direct_innerhtml_assignment' in js/kanban.js:135", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in js/kanban.js:135"}, "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-737583d442eabb76", "name": "Insecure pattern 'direct_innerhtml_assignment' in js/admin-sync.js:101", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in js/admin-sync.js:101"}, "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-cef24e87c6156470", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/setup-python@v5 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ee3fca994c12ce1", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "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 75 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-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-e18683ad20364270", "name": "Commented-code block (5 lines) in js/app.js:71", "shortDescription": {"text": "Commented-code block (5 lines) in js/app.js:71"}, "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-3eb22d609b5f9d77", "name": "Commented-code block (5 lines) in js/backlog.js:1", "shortDescription": {"text": "Commented-code block (5 lines) in js/backlog.js:1"}, "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-2bbacfab1c5e0948", "name": "`fetch()` without try/.catch or AbortSignal \u2014 js/backlog.js:81", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 js/backlog.js:81"}, "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-b782a4fab1dfab7e", "name": "Commented-code block (5 lines) in js/kanban.js:1", "shortDescription": {"text": "Commented-code block (5 lines) in js/kanban.js:1"}, "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-fe1a89bf4b659a58", "name": "`fetch()` without try/.catch or AbortSignal \u2014 js/auth.js:37", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 js/auth.js:37"}, "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-0d5e5d37b0f6e456", "name": "Legacy-named symbol `test_migrate_columns_v2_remaps_legacy` in tests/test_database.py:67", "shortDescription": {"text": "Legacy-named symbol `test_migrate_columns_v2_remaps_legacy` in tests/test_database.py:67"}, "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-a84f201431a84bf6", "name": "Commented-code block (6 lines) in scripts/migrate_docs.py:23", "shortDescription": {"text": "Commented-code block (6 lines) in scripts/migrate_docs.py:23"}, "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-ca80c25604d690a2", "name": "Commented-code block (7 lines) in scripts/refresh_metrics.py:615", "shortDescription": {"text": "Commented-code block (7 lines) in scripts/refresh_metrics.py:615"}, "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-e23a6d70e63d6454", "name": "Network/subprocess call without timeout or try/except \u2014 scripts/refresh_metrics.py:213", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 scripts/refresh_metrics.py:213"}, "fullDescription": {"text": "`subprocess.run(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7a3c290e14e3bbe1", "name": "Network/subprocess call without timeout or try/except \u2014 server/sync_runner.py:374", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 server/sync_runner.py:374"}, "fullDescription": {"text": "`subprocess.Popen(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-514db26c220bb339", "name": "Commented-code block (7 lines) in server/yaml_sync.py:176", "shortDescription": {"text": "Commented-code block (7 lines) in server/yaml_sync.py:176"}, "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-81321ca7ed6ebc64", "name": "Legacy-named symbol `_migrate_columns_v2` in server/database.py:118", "shortDescription": {"text": "Legacy-named symbol `_migrate_columns_v2` in server/database.py:118"}, "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-2eafc3188c36bb02", "name": "3 env vars used in code but missing from .env.example", "shortDescription": {"text": "3 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `GITHUB_TOKEN`, `PROJECTS_YAML`, `REFRESH_CACHE`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "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/app.py:update_card, server/app.py:evaluate_card\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-bae05b284ec7abfe", "name": "Flask mutation route `login` without `@login_required` \u2014 server/app.py:584", "shortDescription": {"text": "Flask mutation route `login` without `@login_required` \u2014 server/app.py:584"}, "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-c0bd0f28f104c037", "name": "Flask mutation route `create_card` without `@login_required` \u2014 server/app.py:725", "shortDescription": {"text": "Flask mutation route `create_card` without `@login_required` \u2014 server/app.py:725"}, "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-d0f5df648aeb44d4", "name": "Flask mutation route `update_card` without `@login_required` \u2014 server/app.py:767", "shortDescription": {"text": "Flask mutation route `update_card` without `@login_required` \u2014 server/app.py:767"}, "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-ceb7330289119749", "name": "Flask mutation route `delete_card` without `@login_required` \u2014 server/app.py:799", "shortDescription": {"text": "Flask mutation route `delete_card` without `@login_required` \u2014 server/app.py:799"}, "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-8e06640e251981eb", "name": "Flask mutation route `evaluate_card` without `@login_required` \u2014 server/app.py:841", "shortDescription": {"text": "Flask mutation route `evaluate_card` without `@login_required` \u2014 server/app.py:841"}, "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-e92aede2ee32ba79", "name": "Flask mutation route `upload_screenshot` without `@login_required` \u2014 server/app.py:904", "shortDescription": {"text": "Flask mutation route `upload_screenshot` without `@login_required` \u2014 server/app.py:904"}, "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-1cd67f09a7c70a29", "name": "Flask mutation route `delete_screenshot` without `@login_required` \u2014 server/app.py:988", "shortDescription": {"text": "Flask mutation route `delete_screenshot` without `@login_required` \u2014 server/app.py:988"}, "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-68c6babe40e8528e", "name": "Flask mutation route `api_sync_excluded` without `@login_required` \u2014 server/app.py:1115", "shortDescription": {"text": "Flask mutation route `api_sync_excluded` without `@login_required` \u2014 server/app.py:1115"}, "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-d9d7ecd6c05a84a7", "name": "Flask mutation route `api_sync_apply` without `@login_required` \u2014 server/app.py:1166", "shortDescription": {"text": "Flask mutation route `api_sync_apply` without `@login_required` \u2014 server/app.py:1166"}, "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-94a91e2a26273631", "name": "Flask mutation route `api_sync_run` without `@login_required` \u2014 server/app.py:1191", "shortDescription": {"text": "Flask mutation route `api_sync_run` without `@login_required` \u2014 server/app.py:1191"}, "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-1a6d91f2236825bf", "name": "Unused endpoint: ANY /", "shortDescription": {"text": "Unused endpoint: ANY /"}, "fullDescription": {"text": "`server/app.py` declares `ANY /` 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-80afd703898c84fd", "name": "Unused endpoint: ANY /proposition", "shortDescription": {"text": "Unused endpoint: ANY /proposition"}, "fullDescription": {"text": "`server/app.py` declares `ANY /proposition` 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-778878e7904df7a0", "name": "Unused endpoint: ANY /kanban", "shortDescription": {"text": "Unused endpoint: ANY /kanban"}, "fullDescription": {"text": "`server/app.py` declares `ANY /kanban` 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-10be72019bda2088", "name": "Unused endpoint: ANY /documents", "shortDescription": {"text": "Unused endpoint: ANY /documents"}, "fullDescription": {"text": "`server/app.py` declares `ANY /documents` 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-b5bd69edc53b46b2", "name": "Unused endpoint: ANY /backlog", "shortDescription": {"text": "Unused endpoint: ANY /backlog"}, "fullDescription": {"text": "`server/app.py` declares `ANY /backlog` 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-44c0947053d5a6a2", "name": "Unused endpoint: ANY /projet/<card_id>", "shortDescription": {"text": "Unused endpoint: ANY /projet/<card_id>"}, "fullDescription": {"text": "`server/app.py` declares `ANY /projet/<card_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-78fd9b093a630623", "name": "Unused endpoint: ANY /css/<path:filename>", "shortDescription": {"text": "Unused endpoint: ANY /css/<path:filename>"}, "fullDescription": {"text": "`server/app.py` declares `ANY /css/<path:filename>` 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-ee5e772aa3f7521a", "name": "Unused endpoint: ANY /js/<path:filename>", "shortDescription": {"text": "Unused endpoint: ANY /js/<path:filename>"}, "fullDescription": {"text": "`server/app.py` declares `ANY /js/<path:filename>` 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-ecce81fb7dc26d9b", "name": "Unused endpoint: ANY /docs/<path:filename>", "shortDescription": {"text": "Unused endpoint: ANY /docs/<path:filename>"}, "fullDescription": {"text": "`server/app.py` declares `ANY /docs/<path:filename>` 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-9738ed408a43f4d0", "name": "Unused endpoint: ANY /picto/<path:filename>", "shortDescription": {"text": "Unused endpoint: ANY /picto/<path:filename>"}, "fullDescription": {"text": "`server/app.py` declares `ANY /picto/<path:filename>` 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-2321010846f5b7c2", "name": "Unused endpoint: ANY /docs/view/<slug>", "shortDescription": {"text": "Unused endpoint: ANY /docs/view/<slug>"}, "fullDescription": {"text": "`server/app.py` declares `ANY /docs/view/<slug>` 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-f6bebf7a043f51bb", "name": "Unused endpoint: ANY /docs/export/<slug>.docx", "shortDescription": {"text": "Unused endpoint: ANY /docs/export/<slug>.docx"}, "fullDescription": {"text": "`server/app.py` declares `ANY /docs/export/<slug>.docx` 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-7396d4d1a2374403", "name": "Unused endpoint: ANY /data/screenshots/<path:filename>", "shortDescription": {"text": "Unused endpoint: ANY /data/screenshots/<path:filename>"}, "fullDescription": {"text": "`server/app.py` declares `ANY /data/screenshots/<path:filename>` 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-0bac2999f80dd4ee", "name": "Unused endpoint: ANY /api/auth/login", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/login"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/auth/login` 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-fcaedbb556396417", "name": "Unused endpoint: ANY /api/auth/me", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/me"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/auth/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-45f12f778c386cb9", "name": "Unused endpoint: ANY /api/kanban/cards", "shortDescription": {"text": "Unused endpoint: ANY /api/kanban/cards"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/kanban/cards` 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-2a3ee8a606043226", "name": "Unused endpoint: ANY /api/kanban/cards/<card_id>", "shortDescription": {"text": "Unused endpoint: ANY /api/kanban/cards/<card_id>"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/kanban/cards/<card_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-385c639849437e91", "name": "Unused endpoint: ANY /api/backlog/cards", "shortDescription": {"text": "Unused endpoint: ANY /api/backlog/cards"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/backlog/cards` 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-f49d5dc09d5b5297", "name": "Unused endpoint: ANY /api/kanban/cards/<card_id>/evaluate", "shortDescription": {"text": "Unused endpoint: ANY /api/kanban/cards/<card_id>/evaluate"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/kanban/cards/<card_id>/evaluate` 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-417ed37c4a730b2b", "name": "Unused endpoint: ANY /api/kanban/cards/<card_id>/screenshots", "shortDescription": {"text": "Unused endpoint: ANY /api/kanban/cards/<card_id>/screenshots"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/kanban/cards/<card_id>/screenshots` 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-63216cdfacb79112", "name": "Unused endpoint: ANY /api/github-proxy/<path:repo_path>", "shortDescription": {"text": "Unused endpoint: ANY /api/github-proxy/<path:repo_path>"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/github-proxy/<path:repo_path>` 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-68e9ea1e140f9bad", "name": "Unused endpoint: ANY /api/kanban/cards/<card_id>/screenshots/<screenshot_id>", "shortDescription": {"text": "Unused endpoint: ANY /api/kanban/cards/<card_id>/screenshots/<screenshot_id>"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/kanban/cards/<card_id>/screenshots/<screenshot_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-495d432f2d3f03f4", "name": "Unused endpoint: ANY /admin/sync", "shortDescription": {"text": "Unused endpoint: ANY /admin/sync"}, "fullDescription": {"text": "`server/app.py` declares `ANY /admin/sync` 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-00b49c0c303a582d", "name": "Unused endpoint: ANY /api/sync/excluded", "shortDescription": {"text": "Unused endpoint: ANY /api/sync/excluded"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/sync/excluded` 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-416c6341deea7998", "name": "Unused endpoint: ANY /api/sync/debug", "shortDescription": {"text": "Unused endpoint: ANY /api/sync/debug"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/sync/debug` 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-21b94746f407b1df", "name": "Unused endpoint: ANY /api/activity", "shortDescription": {"text": "Unused endpoint: ANY /api/activity"}, "fullDescription": {"text": "`server/app.py` declares `ANY /api/activity` 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/24643"}, "properties": {"repository": "bmatge/vibe-lab-bercy", "repoUrl": "https://github.com/bmatge/vibe-lab-bercy", "branch": "main"}, "results": [{"ruleId": "scanner-ea92eb634b04c8ea", "level": "note", "message": {"text": "Possibly dead Python function: close_db"}, "properties": {"repobilityId": "c3b06ac4c16e2787", "scanner": "scanner-primary", "fingerprint": "ea92eb634b04c8ea", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/database.py:62"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2969680393261516", "level": "warning", "message": {"text": "Privileged port 29 in use"}, "properties": {"repobilityId": "f09242400239b5a3", "scanner": "scanner-primary", "fingerprint": "2969680393261516", "layer": "network", "severity": "medium", "confidence": 1.0, "tags": ["security", "ports"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "content/stats.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d63da3583b14afc0", "level": "warning", "message": {"text": "Dockerfile runs as root: Dockerfile"}, "properties": {"repobilityId": "a2ed1bd120e507db", "scanner": "scanner-primary", "fingerprint": "d63da3583b14afc0", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-de3c1f217d72a063", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim"}, "properties": {"repobilityId": "1de0ecd007803dbd", "scanner": "scanner-primary", "fingerprint": "de3c1f217d72a063", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-8264e661f361a579", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in js/activity.js:58"}, "properties": {"repobilityId": "ff14181ef21d7994", "scanner": "scanner-primary", "fingerprint": "8264e661f361a579", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "js/activity.js"}, "region": {"startLine": 58}}}]}, {"ruleId": "scanner-2f820416f1d13698", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in js/app.js:102"}, "properties": {"repobilityId": "f12f5fb5c6eb3ec0", "scanner": "scanner-primary", "fingerprint": "2f820416f1d13698", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "js/app.js"}, "region": {"startLine": 102}}}]}, {"ruleId": "scanner-5f4c15df2800a29f", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in js/backlog.js:154"}, "properties": {"repobilityId": "66cfae73ffea6001", "scanner": "scanner-primary", "fingerprint": "5f4c15df2800a29f", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "js/backlog.js"}, "region": {"startLine": 154}}}]}, {"ruleId": "scanner-382952fbf06903e3", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in js/kanban.js:135"}, "properties": {"repobilityId": "2ecdec52c3e0823e", "scanner": "scanner-primary", "fingerprint": "382952fbf06903e3", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "js/kanban.js"}, "region": {"startLine": 135}}}]}, {"ruleId": "scanner-737583d442eabb76", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in js/admin-sync.js:101"}, "properties": {"repobilityId": "3ca32436a3dcb940", "scanner": "scanner-primary", "fingerprint": "737583d442eabb76", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "js/admin-sync.js"}, "region": {"startLine": 101}}}]}, {"ruleId": "scanner-cef24e87c6156470", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "6e07b8c585376343", "scanner": "scanner-primary", "fingerprint": "cef24e87c6156470", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/refresh-content.yml"}, "region": {"startLine": 29}}}]}, {"ruleId": "scanner-cef24e87c6156470", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "7643090d90b582ba", "scanner": "scanner-primary", "fingerprint": "cef24e87c6156470", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/refresh-content.yml"}, "region": {"startLine": 60}}}]}, {"ruleId": "scanner-3ee3fca994c12ce1", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "586df9ffab17c64c", "scanner": "scanner-primary", "fingerprint": "3ee3fca994c12ce1", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/refresh-content.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "5f2b29550fc274c3", "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": "4c60cad10f4c812f", "scanner": "scanner-primary", "fingerprint": "3ab5d313dda8e5f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["debug", "cleanup", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "e52a0d7d2cbca762", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-e18683ad20364270", "level": "none", "message": {"text": "Commented-code block (5 lines) in js/app.js:71"}, "properties": {"repobilityId": "fbe65ab51eff2777", "scanner": "scanner-primary", "fingerprint": "e18683ad20364270", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3eb22d609b5f9d77", "level": "none", "message": {"text": "Commented-code block (5 lines) in js/backlog.js:1"}, "properties": {"repobilityId": "fd8e1c422e968366", "scanner": "scanner-primary", "fingerprint": "3eb22d609b5f9d77", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2bbacfab1c5e0948", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 js/backlog.js:81"}, "properties": {"repobilityId": "e1371904e2f39940", "scanner": "scanner-primary", "fingerprint": "2bbacfab1c5e0948", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-b782a4fab1dfab7e", "level": "none", "message": {"text": "Commented-code block (5 lines) in js/kanban.js:1"}, "properties": {"repobilityId": "3a3c1793ef0f3fb3", "scanner": "scanner-primary", "fingerprint": "b782a4fab1dfab7e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-fe1a89bf4b659a58", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 js/auth.js:37"}, "properties": {"repobilityId": "bfe6ca87c8847240", "scanner": "scanner-primary", "fingerprint": "fe1a89bf4b659a58", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-0d5e5d37b0f6e456", "level": "note", "message": {"text": "Legacy-named symbol `test_migrate_columns_v2_remaps_legacy` in tests/test_database.py:67"}, "properties": {"repobilityId": "bea52a94001f39f2", "scanner": "scanner-primary", "fingerprint": "0d5e5d37b0f6e456", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-a84f201431a84bf6", "level": "none", "message": {"text": "Commented-code block (6 lines) in scripts/migrate_docs.py:23"}, "properties": {"repobilityId": "47193f1395583be4", "scanner": "scanner-primary", "fingerprint": "a84f201431a84bf6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-ca80c25604d690a2", "level": "none", "message": {"text": "Commented-code block (7 lines) in scripts/refresh_metrics.py:615"}, "properties": {"repobilityId": "ad2293ee8d3adbbf", "scanner": "scanner-primary", "fingerprint": "ca80c25604d690a2", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e23a6d70e63d6454", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 scripts/refresh_metrics.py:213"}, "properties": {"repobilityId": "0ebc2700c4c758a6", "scanner": "scanner-primary", "fingerprint": "e23a6d70e63d6454", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-7a3c290e14e3bbe1", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 server/sync_runner.py:374"}, "properties": {"repobilityId": "4bfd930fece21740", "scanner": "scanner-primary", "fingerprint": "7a3c290e14e3bbe1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-514db26c220bb339", "level": "none", "message": {"text": "Commented-code block (7 lines) in server/yaml_sync.py:176"}, "properties": {"repobilityId": "192e228bf7c28868", "scanner": "scanner-primary", "fingerprint": "514db26c220bb339", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-81321ca7ed6ebc64", "level": "note", "message": {"text": "Legacy-named symbol `_migrate_columns_v2` in server/database.py:118"}, "properties": {"repobilityId": "3d795de20478a45e", "scanner": "scanner-primary", "fingerprint": "81321ca7ed6ebc64", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-2eafc3188c36bb02", "level": "none", "message": {"text": "3 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "bd934ba112b02ffa", "scanner": "scanner-primary", "fingerprint": "2eafc3188c36bb02", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "83e2268d1500eff7", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-bae05b284ec7abfe", "level": "error", "message": {"text": "Flask mutation route `login` without `@login_required` \u2014 server/app.py:584"}, "properties": {"repobilityId": "26420ed26292928b", "scanner": "scanner-primary", "fingerprint": "bae05b284ec7abfe", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/app.py"}, "region": {"startLine": 584}}}]}, {"ruleId": "scanner-c0bd0f28f104c037", "level": "error", "message": {"text": "Flask mutation route `create_card` without `@login_required` \u2014 server/app.py:725"}, "properties": {"repobilityId": "52e5114284ab5c83", "scanner": "scanner-primary", "fingerprint": "c0bd0f28f104c037", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/app.py"}, "region": {"startLine": 725}}}]}, {"ruleId": "scanner-d0f5df648aeb44d4", "level": "error", "message": {"text": "Flask mutation route `update_card` without `@login_required` \u2014 server/app.py:767"}, "properties": {"repobilityId": "09d17171779a2a17", "scanner": "scanner-primary", "fingerprint": "d0f5df648aeb44d4", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/app.py"}, "region": {"startLine": 767}}}]}, {"ruleId": "scanner-ceb7330289119749", "level": "error", "message": {"text": "Flask mutation route `delete_card` without `@login_required` \u2014 server/app.py:799"}, "properties": {"repobilityId": "a52cdba8634f7779", "scanner": "scanner-primary", "fingerprint": "ceb7330289119749", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/app.py"}, "region": {"startLine": 799}}}]}, {"ruleId": "scanner-8e06640e251981eb", "level": "error", "message": {"text": "Flask mutation route `evaluate_card` without `@login_required` \u2014 server/app.py:841"}, "properties": {"repobilityId": "3edd9b1732c1cc30", "scanner": "scanner-primary", "fingerprint": "8e06640e251981eb", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/app.py"}, "region": {"startLine": 841}}}]}, {"ruleId": "scanner-e92aede2ee32ba79", "level": "error", "message": {"text": "Flask mutation route `upload_screenshot` without `@login_required` \u2014 server/app.py:904"}, "properties": {"repobilityId": "e3656b78a358509a", "scanner": "scanner-primary", "fingerprint": "e92aede2ee32ba79", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/app.py"}, "region": {"startLine": 904}}}]}, {"ruleId": "scanner-1cd67f09a7c70a29", "level": "error", "message": {"text": "Flask mutation route `delete_screenshot` without `@login_required` \u2014 server/app.py:988"}, "properties": {"repobilityId": "e5f3e9778a3ad2e7", "scanner": "scanner-primary", "fingerprint": "1cd67f09a7c70a29", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/app.py"}, "region": {"startLine": 988}}}]}, {"ruleId": "scanner-68c6babe40e8528e", "level": "error", "message": {"text": "Flask mutation route `api_sync_excluded` without `@login_required` \u2014 server/app.py:1115"}, "properties": {"repobilityId": "1388ec0141e9e527", "scanner": "scanner-primary", "fingerprint": "68c6babe40e8528e", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/app.py"}, "region": {"startLine": 1115}}}]}, {"ruleId": "scanner-d9d7ecd6c05a84a7", "level": "error", "message": {"text": "Flask mutation route `api_sync_apply` without `@login_required` \u2014 server/app.py:1166"}, "properties": {"repobilityId": "cba5ad0804a0873e", "scanner": "scanner-primary", "fingerprint": "d9d7ecd6c05a84a7", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/app.py"}, "region": {"startLine": 1166}}}]}, {"ruleId": "scanner-94a91e2a26273631", "level": "error", "message": {"text": "Flask mutation route `api_sync_run` without `@login_required` \u2014 server/app.py:1191"}, "properties": {"repobilityId": "d77951c2529b0f86", "scanner": "scanner-primary", "fingerprint": "94a91e2a26273631", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/app.py"}, "region": {"startLine": 1191}}}]}, {"ruleId": "scanner-1a6d91f2236825bf", "level": "note", "message": {"text": "Unused endpoint: ANY /"}, "properties": {"repobilityId": "c4a7fd17e3932df9", "scanner": "scanner-primary", "fingerprint": "1a6d91f2236825bf", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-80afd703898c84fd", "level": "note", "message": {"text": "Unused endpoint: ANY /proposition"}, "properties": {"repobilityId": "f33f56e73bb17550", "scanner": "scanner-primary", "fingerprint": "80afd703898c84fd", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-778878e7904df7a0", "level": "note", "message": {"text": "Unused endpoint: ANY /kanban"}, "properties": {"repobilityId": "9192341f0b701c2c", "scanner": "scanner-primary", "fingerprint": "778878e7904df7a0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-10be72019bda2088", "level": "note", "message": {"text": "Unused endpoint: ANY /documents"}, "properties": {"repobilityId": "d0306580dc1b1d16", "scanner": "scanner-primary", "fingerprint": "10be72019bda2088", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b5bd69edc53b46b2", "level": "note", "message": {"text": "Unused endpoint: ANY /backlog"}, "properties": {"repobilityId": "c3d3aa3eea37a791", "scanner": "scanner-primary", "fingerprint": "b5bd69edc53b46b2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-44c0947053d5a6a2", "level": "note", "message": {"text": "Unused endpoint: ANY /projet/<card_id>"}, "properties": {"repobilityId": "bdcb882f69c3dec2", "scanner": "scanner-primary", "fingerprint": "44c0947053d5a6a2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-78fd9b093a630623", "level": "note", "message": {"text": "Unused endpoint: ANY /css/<path:filename>"}, "properties": {"repobilityId": "57c2e1d0977b4bff", "scanner": "scanner-primary", "fingerprint": "78fd9b093a630623", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ee5e772aa3f7521a", "level": "note", "message": {"text": "Unused endpoint: ANY /js/<path:filename>"}, "properties": {"repobilityId": "30fc255bea0428e1", "scanner": "scanner-primary", "fingerprint": "ee5e772aa3f7521a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ecce81fb7dc26d9b", "level": "note", "message": {"text": "Unused endpoint: ANY /docs/<path:filename>"}, "properties": {"repobilityId": "1d0ba829befb7891", "scanner": "scanner-primary", "fingerprint": "ecce81fb7dc26d9b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9738ed408a43f4d0", "level": "note", "message": {"text": "Unused endpoint: ANY /picto/<path:filename>"}, "properties": {"repobilityId": "49f9b6e79ccc58f3", "scanner": "scanner-primary", "fingerprint": "9738ed408a43f4d0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2321010846f5b7c2", "level": "note", "message": {"text": "Unused endpoint: ANY /docs/view/<slug>"}, "properties": {"repobilityId": "82a515559ba195f2", "scanner": "scanner-primary", "fingerprint": "2321010846f5b7c2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f6bebf7a043f51bb", "level": "note", "message": {"text": "Unused endpoint: ANY /docs/export/<slug>.docx"}, "properties": {"repobilityId": "ca3f62ed56bf62a7", "scanner": "scanner-primary", "fingerprint": "f6bebf7a043f51bb", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7396d4d1a2374403", "level": "note", "message": {"text": "Unused endpoint: ANY /data/screenshots/<path:filename>"}, "properties": {"repobilityId": "dcb9ef302a73cd2d", "scanner": "scanner-primary", "fingerprint": "7396d4d1a2374403", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0bac2999f80dd4ee", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/login"}, "properties": {"repobilityId": "9d0cacf18d3dac46", "scanner": "scanner-primary", "fingerprint": "0bac2999f80dd4ee", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fcaedbb556396417", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/me"}, "properties": {"repobilityId": "9c24cfec0ee63e83", "scanner": "scanner-primary", "fingerprint": "fcaedbb556396417", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-45f12f778c386cb9", "level": "note", "message": {"text": "Unused endpoint: ANY /api/kanban/cards"}, "properties": {"repobilityId": "8d4bfb55ec3e75c9", "scanner": "scanner-primary", "fingerprint": "45f12f778c386cb9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2a3ee8a606043226", "level": "note", "message": {"text": "Unused endpoint: ANY /api/kanban/cards/<card_id>"}, "properties": {"repobilityId": "a0efe60a1b9d97b5", "scanner": "scanner-primary", "fingerprint": "2a3ee8a606043226", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-385c639849437e91", "level": "note", "message": {"text": "Unused endpoint: ANY /api/backlog/cards"}, "properties": {"repobilityId": "6e8d311ebef1e0d5", "scanner": "scanner-primary", "fingerprint": "385c639849437e91", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f49d5dc09d5b5297", "level": "note", "message": {"text": "Unused endpoint: ANY /api/kanban/cards/<card_id>/evaluate"}, "properties": {"repobilityId": "e9516ed253693af6", "scanner": "scanner-primary", "fingerprint": "f49d5dc09d5b5297", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-417ed37c4a730b2b", "level": "note", "message": {"text": "Unused endpoint: ANY /api/kanban/cards/<card_id>/screenshots"}, "properties": {"repobilityId": "4aa5ea1590898578", "scanner": "scanner-primary", "fingerprint": "417ed37c4a730b2b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-63216cdfacb79112", "level": "note", "message": {"text": "Unused endpoint: ANY /api/github-proxy/<path:repo_path>"}, "properties": {"repobilityId": "9b0881f218137066", "scanner": "scanner-primary", "fingerprint": "63216cdfacb79112", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-68e9ea1e140f9bad", "level": "note", "message": {"text": "Unused endpoint: ANY /api/kanban/cards/<card_id>/screenshots/<screenshot_id>"}, "properties": {"repobilityId": "794c627adef25d0d", "scanner": "scanner-primary", "fingerprint": "68e9ea1e140f9bad", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-495d432f2d3f03f4", "level": "note", "message": {"text": "Unused endpoint: ANY /admin/sync"}, "properties": {"repobilityId": "400a654fc360b3e3", "scanner": "scanner-primary", "fingerprint": "495d432f2d3f03f4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-00b49c0c303a582d", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sync/excluded"}, "properties": {"repobilityId": "497f674383b0489e", "scanner": "scanner-primary", "fingerprint": "00b49c0c303a582d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-416c6341deea7998", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sync/debug"}, "properties": {"repobilityId": "f16b4315390dea0b", "scanner": "scanner-primary", "fingerprint": "416c6341deea7998", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-21b94746f407b1df", "level": "note", "message": {"text": "Unused endpoint: ANY /api/activity"}, "properties": {"repobilityId": "150c19f8a77683de", "scanner": "scanner-primary", "fingerprint": "21b94746f407b1df", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}