{"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-166dff3c3df6a10e", "name": "ORM models found but no DB engine detected", "shortDescription": {"text": "ORM models found but no DB engine detected"}, "fullDescription": {"text": "The repo defines tables/models but no DB connection string was found. Likely lives in env vars or a config file the scanner didn't read."}, "properties": {"scanner": "scanner-primary", "layer": "data", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9710c8d059e53154", "name": "No frontend routes/components detected", "shortDescription": {"text": "No frontend routes/components detected"}, "fullDescription": {"text": "No React/Vue/Next routes were found. This is fine for backend-only repos."}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "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-dfea91fc6bcad315", "name": "Very large file: ui/main.py (1894 lines)", "shortDescription": {"text": "Very large file: ui/main.py (1894 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "1 test file(s) for 17 source file(s) (ratio 0.06). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-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: license, ci. 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 license, ci. 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-cc55229a7a3c078d", "name": "Agent authority lacks a verifier contract: .mcp.json", "shortDescription": {"text": "Agent authority lacks a verifier contract: .mcp.json"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e74855e1600fb3e9", "name": "Network/subprocess call without timeout or try/except \u2014 ui/main.py:184", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 ui/main.py:184"}, "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-83ba39c59458d381", "name": "Legacy-named symbol `002_migrate_v2` in utils/db_migrations.py:21", "shortDescription": {"text": "Legacy-named symbol `002_migrate_v2` in utils/db_migrations.py:21"}, "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-2f659627c04c63f1", "name": "FastAPI POST `save_oauth_credentials` without auth dependency \u2014 ui/main.py:1514", "shortDescription": {"text": "FastAPI POST `save_oauth_credentials` without auth dependency \u2014 ui/main.py:1514"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-65277f946df6f92f", "name": "FastAPI POST `confirm_token` without auth dependency \u2014 ui/main.py:1610", "shortDescription": {"text": "FastAPI POST `confirm_token` without auth dependency \u2014 ui/main.py:1610"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-a220291e1126e787", "name": "FastAPI POST `run_etl` without auth dependency \u2014 ui/main.py:1625", "shortDescription": {"text": "FastAPI POST `run_etl` without auth dependency \u2014 ui/main.py:1625"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-96f48b3142a43be0", "name": "FastAPI POST `run_order` without auth dependency \u2014 ui/main.py:1641", "shortDescription": {"text": "FastAPI POST `run_order` without auth dependency \u2014 ui/main.py:1641"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-14ef3c10d2d25bfd", "name": "FastAPI POST `cancel_run` without auth dependency \u2014 ui/main.py:1658", "shortDescription": {"text": "FastAPI POST `cancel_run` without auth dependency \u2014 ui/main.py:1658"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-9f2636a42a0b5dc8", "name": "FastAPI POST `pause_scheduler` without auth dependency \u2014 ui/main.py:1675", "shortDescription": {"text": "FastAPI POST `pause_scheduler` without auth dependency \u2014 ui/main.py:1675"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-a65e7b138eb41394", "name": "FastAPI POST `resume_scheduler` without auth dependency \u2014 ui/main.py:1682", "shortDescription": {"text": "FastAPI POST `resume_scheduler` without auth dependency \u2014 ui/main.py:1682"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-1717af21e8c91b38", "name": "FastAPI POST `save_shopify` without auth dependency \u2014 ui/main.py:1690", "shortDescription": {"text": "FastAPI POST `save_shopify` without auth dependency \u2014 ui/main.py:1690"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-2acd3ba462ecf5b7", "name": "FastAPI POST `save_sql` without auth dependency \u2014 ui/main.py:1711", "shortDescription": {"text": "FastAPI POST `save_sql` without auth dependency \u2014 ui/main.py:1711"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-7280e487c24323bf", "name": "FastAPI POST `test_shopify` without auth dependency \u2014 ui/main.py:1732", "shortDescription": {"text": "FastAPI POST `test_shopify` without auth dependency \u2014 ui/main.py:1732"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-0ec463c9e1c36ca7", "name": "FastAPI POST `test_sql` without auth dependency \u2014 ui/main.py:1755", "shortDescription": {"text": "FastAPI POST `test_sql` without auth dependency \u2014 ui/main.py:1755"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-bb0304f3866bfb4f", "name": "FastAPI POST `save_schedules_api` without auth dependency \u2014 ui/main.py:1805", "shortDescription": {"text": "FastAPI POST `save_schedules_api` without auth dependency \u2014 ui/main.py:1805"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-5baa8971ebe192a1", "name": "Unused endpoint: GET /", "shortDescription": {"text": "Unused endpoint: GET /"}, "fullDescription": {"text": "`ui/main.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-d86afd7dd2beb431", "name": "Unused endpoint: GET /setup", "shortDescription": {"text": "Unused endpoint: GET /setup"}, "fullDescription": {"text": "`ui/main.py` declares `GET /setup` 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-35ec8f7061e5b6ef", "name": "Unused endpoint: POST /api/setup/oauth-credentials", "shortDescription": {"text": "Unused endpoint: POST /api/setup/oauth-credentials"}, "fullDescription": {"text": "`ui/main.py` declares `POST /api/setup/oauth-credentials` 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-53c2b72cad164662", "name": "Unused endpoint: GET /shopify/install", "shortDescription": {"text": "Unused endpoint: GET /shopify/install"}, "fullDescription": {"text": "`ui/main.py` declares `GET /shopify/install` 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-6fb9bff9ac099b6b", "name": "Unused endpoint: GET /shopify/callback", "shortDescription": {"text": "Unused endpoint: GET /shopify/callback"}, "fullDescription": {"text": "`ui/main.py` declares `GET /shopify/callback` 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-eb506296b722524c", "name": "Unused endpoint: POST /api/setup/confirm-token", "shortDescription": {"text": "Unused endpoint: POST /api/setup/confirm-token"}, "fullDescription": {"text": "`ui/main.py` declares `POST /api/setup/confirm-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-01b99da652895201", "name": "Unused endpoint: POST /run-etl", "shortDescription": {"text": "Unused endpoint: POST /run-etl"}, "fullDescription": {"text": "`ui/main.py` declares `POST /run-etl` 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-b8a2cab6e0a49c8a", "name": "Unused endpoint: POST /run-order", "shortDescription": {"text": "Unused endpoint: POST /run-order"}, "fullDescription": {"text": "`ui/main.py` declares `POST /run-order` 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-37c5e8b4b3110797", "name": "Unused endpoint: POST /api/runs/cancel", "shortDescription": {"text": "Unused endpoint: POST /api/runs/cancel"}, "fullDescription": {"text": "`ui/main.py` declares `POST /api/runs/cancel` 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-cf64b72b7c1dcc0c", "name": "Unused endpoint: POST /api/scheduler/pause", "shortDescription": {"text": "Unused endpoint: POST /api/scheduler/pause"}, "fullDescription": {"text": "`ui/main.py` declares `POST /api/scheduler/pause` 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-4601884d6eef6dc7", "name": "Unused endpoint: POST /api/scheduler/resume", "shortDescription": {"text": "Unused endpoint: POST /api/scheduler/resume"}, "fullDescription": {"text": "`ui/main.py` declares `POST /api/scheduler/resume` 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-46a8d2e803aa3e21", "name": "Unused endpoint: POST /api/setup/shopify", "shortDescription": {"text": "Unused endpoint: POST /api/setup/shopify"}, "fullDescription": {"text": "`ui/main.py` declares `POST /api/setup/shopify` 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-d61bb0987f538077", "name": "Unused endpoint: POST /api/setup/sql", "shortDescription": {"text": "Unused endpoint: POST /api/setup/sql"}, "fullDescription": {"text": "`ui/main.py` declares `POST /api/setup/sql` 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-a3ea4d10e1ad1ab5", "name": "Unused endpoint: POST /api/setup/test-shopify", "shortDescription": {"text": "Unused endpoint: POST /api/setup/test-shopify"}, "fullDescription": {"text": "`ui/main.py` declares `POST /api/setup/test-shopify` 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-b1b337b05d9e7f05", "name": "Unused endpoint: POST /api/setup/test-sql", "shortDescription": {"text": "Unused endpoint: POST /api/setup/test-sql"}, "fullDescription": {"text": "`ui/main.py` declares `POST /api/setup/test-sql` 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-3a752ed7cd6869b6", "name": "Unused endpoint: GET /api/schedules", "shortDescription": {"text": "Unused endpoint: GET /api/schedules"}, "fullDescription": {"text": "`ui/main.py` declares `GET /api/schedules` 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-ac73623d29f8c1e0", "name": "Unused endpoint: POST /api/schedules", "shortDescription": {"text": "Unused endpoint: POST /api/schedules"}, "fullDescription": {"text": "`ui/main.py` declares `POST /api/schedules` 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-3b37265900e79a8a", "name": "Unused endpoint: GET /api/stats", "shortDescription": {"text": "Unused endpoint: GET /api/stats"}, "fullDescription": {"text": "`ui/main.py` declares `GET /api/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-ca0ee8c086b37844", "name": "Unused endpoint: GET /api/runs", "shortDescription": {"text": "Unused endpoint: GET /api/runs"}, "fullDescription": {"text": "`ui/main.py` declares `GET /api/runs` 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-d944c223f021a4ff", "name": "Unused endpoint: GET /api/stats/chart", "shortDescription": {"text": "Unused endpoint: GET /api/stats/chart"}, "fullDescription": {"text": "`ui/main.py` declares `GET /api/stats/chart` 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-b8c606acd376c4d5", "name": "Unused endpoint: GET /api/config-changes", "shortDescription": {"text": "Unused endpoint: GET /api/config-changes"}, "fullDescription": {"text": "`ui/main.py` declares `GET /api/config-changes` 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-f3bf72f059406b13", "name": "Unused endpoint: GET /api/logs", "shortDescription": {"text": "Unused endpoint: GET /api/logs"}, "fullDescription": {"text": "`ui/main.py` declares `GET /api/logs` 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/22646"}, "properties": {"repository": "wendelvinter/shopify-etl", "repoUrl": "https://github.com/wendelvinter/shopify-etl", "branch": "main"}, "results": [{"ruleId": "scanner-166dff3c3df6a10e", "level": "warning", "message": {"text": "ORM models found but no DB engine detected"}, "properties": {"repobilityId": "cda36de65e114635", "scanner": "scanner-primary", "fingerprint": "166dff3c3df6a10e", "layer": "data", "severity": "medium", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-9710c8d059e53154", "level": "none", "message": {"text": "No frontend routes/components detected"}, "properties": {"repobilityId": "44ca61485762e494", "scanner": "scanner-primary", "fingerprint": "9710c8d059e53154", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["coverage"]}}, {"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-dfea91fc6bcad315", "level": "note", "message": {"text": "Very large file: ui/main.py (1894 lines)"}, "properties": {"repobilityId": "4848a9862fb86b20", "scanner": "scanner-primary", "fingerprint": "dfea91fc6bcad315", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-6893a6c8b0861585", "level": "warning", "message": {"text": "Very low test-to-source ratio"}, "properties": {"repobilityId": "54a7de3f06314bf0", "scanner": "scanner-primary", "fingerprint": "6893a6c8b0861585", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "coverage"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "abc243ca20449277", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "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": "a35b1586661ec7c2", "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": "923787400ec76141", "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": "648f30a9b5fbdbed", "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": "71cc774c8efe4320", "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": "795bfab7912157dc", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-cc55229a7a3c078d", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .mcp.json"}, "properties": {"repobilityId": "51942fb3d5b8b5b4", "scanner": "scanner-primary", "fingerprint": "cc55229a7a3c078d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "mcp_config"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".mcp.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-e74855e1600fb3e9", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 ui/main.py:184"}, "properties": {"repobilityId": "78c3f14060642a84", "scanner": "scanner-primary", "fingerprint": "e74855e1600fb3e9", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-83ba39c59458d381", "level": "note", "message": {"text": "Legacy-named symbol `002_migrate_v2` in utils/db_migrations.py:21"}, "properties": {"repobilityId": "f6103ddbb9e3c57b", "scanner": "scanner-primary", "fingerprint": "83ba39c59458d381", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-2f659627c04c63f1", "level": "error", "message": {"text": "FastAPI POST `save_oauth_credentials` without auth dependency \u2014 ui/main.py:1514"}, "properties": {"repobilityId": "aac820d9633fa9b0", "scanner": "scanner-primary", "fingerprint": "2f659627c04c63f1", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1514}}}]}, {"ruleId": "scanner-65277f946df6f92f", "level": "error", "message": {"text": "FastAPI POST `confirm_token` without auth dependency \u2014 ui/main.py:1610"}, "properties": {"repobilityId": "191e61ee778d8fd0", "scanner": "scanner-primary", "fingerprint": "65277f946df6f92f", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1610}}}]}, {"ruleId": "scanner-a220291e1126e787", "level": "error", "message": {"text": "FastAPI POST `run_etl` without auth dependency \u2014 ui/main.py:1625"}, "properties": {"repobilityId": "a203289c4ff3a160", "scanner": "scanner-primary", "fingerprint": "a220291e1126e787", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1625}}}]}, {"ruleId": "scanner-96f48b3142a43be0", "level": "error", "message": {"text": "FastAPI POST `run_order` without auth dependency \u2014 ui/main.py:1641"}, "properties": {"repobilityId": "0fd6438ece4188ce", "scanner": "scanner-primary", "fingerprint": "96f48b3142a43be0", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1641}}}]}, {"ruleId": "scanner-14ef3c10d2d25bfd", "level": "error", "message": {"text": "FastAPI POST `cancel_run` without auth dependency \u2014 ui/main.py:1658"}, "properties": {"repobilityId": "2db032ce9096170d", "scanner": "scanner-primary", "fingerprint": "14ef3c10d2d25bfd", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1658}}}]}, {"ruleId": "scanner-9f2636a42a0b5dc8", "level": "error", "message": {"text": "FastAPI POST `pause_scheduler` without auth dependency \u2014 ui/main.py:1675"}, "properties": {"repobilityId": "7c75df7c2317cb94", "scanner": "scanner-primary", "fingerprint": "9f2636a42a0b5dc8", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1675}}}]}, {"ruleId": "scanner-a65e7b138eb41394", "level": "error", "message": {"text": "FastAPI POST `resume_scheduler` without auth dependency \u2014 ui/main.py:1682"}, "properties": {"repobilityId": "a5a5c286edf37eae", "scanner": "scanner-primary", "fingerprint": "a65e7b138eb41394", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1682}}}]}, {"ruleId": "scanner-1717af21e8c91b38", "level": "error", "message": {"text": "FastAPI POST `save_shopify` without auth dependency \u2014 ui/main.py:1690"}, "properties": {"repobilityId": "4f10c1cefc696181", "scanner": "scanner-primary", "fingerprint": "1717af21e8c91b38", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1690}}}]}, {"ruleId": "scanner-2acd3ba462ecf5b7", "level": "error", "message": {"text": "FastAPI POST `save_sql` without auth dependency \u2014 ui/main.py:1711"}, "properties": {"repobilityId": "e3c951d420df5e8c", "scanner": "scanner-primary", "fingerprint": "2acd3ba462ecf5b7", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1711}}}]}, {"ruleId": "scanner-7280e487c24323bf", "level": "error", "message": {"text": "FastAPI POST `test_shopify` without auth dependency \u2014 ui/main.py:1732"}, "properties": {"repobilityId": "22243136db9b4c3e", "scanner": "scanner-primary", "fingerprint": "7280e487c24323bf", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1732}}}]}, {"ruleId": "scanner-0ec463c9e1c36ca7", "level": "error", "message": {"text": "FastAPI POST `test_sql` without auth dependency \u2014 ui/main.py:1755"}, "properties": {"repobilityId": "296f6f9b37909b4d", "scanner": "scanner-primary", "fingerprint": "0ec463c9e1c36ca7", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1755}}}]}, {"ruleId": "scanner-bb0304f3866bfb4f", "level": "error", "message": {"text": "FastAPI POST `save_schedules_api` without auth dependency \u2014 ui/main.py:1805"}, "properties": {"repobilityId": "181393a3b43728b2", "scanner": "scanner-primary", "fingerprint": "bb0304f3866bfb4f", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ui/main.py"}, "region": {"startLine": 1805}}}]}, {"ruleId": "scanner-5baa8971ebe192a1", "level": "note", "message": {"text": "Unused endpoint: GET /"}, "properties": {"repobilityId": "1ac0f76b70a90119", "scanner": "scanner-primary", "fingerprint": "5baa8971ebe192a1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d86afd7dd2beb431", "level": "note", "message": {"text": "Unused endpoint: GET /setup"}, "properties": {"repobilityId": "4a73880472512940", "scanner": "scanner-primary", "fingerprint": "d86afd7dd2beb431", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-35ec8f7061e5b6ef", "level": "note", "message": {"text": "Unused endpoint: POST /api/setup/oauth-credentials"}, "properties": {"repobilityId": "0475b9abc4aa0680", "scanner": "scanner-primary", "fingerprint": "35ec8f7061e5b6ef", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-53c2b72cad164662", "level": "note", "message": {"text": "Unused endpoint: GET /shopify/install"}, "properties": {"repobilityId": "062ec030fbbecb05", "scanner": "scanner-primary", "fingerprint": "53c2b72cad164662", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6fb9bff9ac099b6b", "level": "note", "message": {"text": "Unused endpoint: GET /shopify/callback"}, "properties": {"repobilityId": "da39ea7f83f99569", "scanner": "scanner-primary", "fingerprint": "6fb9bff9ac099b6b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-eb506296b722524c", "level": "note", "message": {"text": "Unused endpoint: POST /api/setup/confirm-token"}, "properties": {"repobilityId": "01c42ba559701186", "scanner": "scanner-primary", "fingerprint": "eb506296b722524c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-01b99da652895201", "level": "note", "message": {"text": "Unused endpoint: POST /run-etl"}, "properties": {"repobilityId": "87efe40f41d795c5", "scanner": "scanner-primary", "fingerprint": "01b99da652895201", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b8a2cab6e0a49c8a", "level": "note", "message": {"text": "Unused endpoint: POST /run-order"}, "properties": {"repobilityId": "4c413e46906af00f", "scanner": "scanner-primary", "fingerprint": "b8a2cab6e0a49c8a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-37c5e8b4b3110797", "level": "note", "message": {"text": "Unused endpoint: POST /api/runs/cancel"}, "properties": {"repobilityId": "e45d0bb4c870c1a4", "scanner": "scanner-primary", "fingerprint": "37c5e8b4b3110797", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cf64b72b7c1dcc0c", "level": "note", "message": {"text": "Unused endpoint: POST /api/scheduler/pause"}, "properties": {"repobilityId": "215b0ddb5f992671", "scanner": "scanner-primary", "fingerprint": "cf64b72b7c1dcc0c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4601884d6eef6dc7", "level": "note", "message": {"text": "Unused endpoint: POST /api/scheduler/resume"}, "properties": {"repobilityId": "7935650d283b7366", "scanner": "scanner-primary", "fingerprint": "4601884d6eef6dc7", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-46a8d2e803aa3e21", "level": "note", "message": {"text": "Unused endpoint: POST /api/setup/shopify"}, "properties": {"repobilityId": "186d3e0c3007b9a0", "scanner": "scanner-primary", "fingerprint": "46a8d2e803aa3e21", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d61bb0987f538077", "level": "note", "message": {"text": "Unused endpoint: POST /api/setup/sql"}, "properties": {"repobilityId": "4a705754c9019f05", "scanner": "scanner-primary", "fingerprint": "d61bb0987f538077", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a3ea4d10e1ad1ab5", "level": "note", "message": {"text": "Unused endpoint: POST /api/setup/test-shopify"}, "properties": {"repobilityId": "03ea5dfe0c471201", "scanner": "scanner-primary", "fingerprint": "a3ea4d10e1ad1ab5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b1b337b05d9e7f05", "level": "note", "message": {"text": "Unused endpoint: POST /api/setup/test-sql"}, "properties": {"repobilityId": "9da24dfe8cf1b7d3", "scanner": "scanner-primary", "fingerprint": "b1b337b05d9e7f05", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3a752ed7cd6869b6", "level": "note", "message": {"text": "Unused endpoint: GET /api/schedules"}, "properties": {"repobilityId": "98f79c50afe7fa08", "scanner": "scanner-primary", "fingerprint": "3a752ed7cd6869b6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ac73623d29f8c1e0", "level": "note", "message": {"text": "Unused endpoint: POST /api/schedules"}, "properties": {"repobilityId": "7f0c5c92a847310b", "scanner": "scanner-primary", "fingerprint": "ac73623d29f8c1e0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3b37265900e79a8a", "level": "note", "message": {"text": "Unused endpoint: GET /api/stats"}, "properties": {"repobilityId": "db8df40606a5888a", "scanner": "scanner-primary", "fingerprint": "3b37265900e79a8a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ca0ee8c086b37844", "level": "note", "message": {"text": "Unused endpoint: GET /api/runs"}, "properties": {"repobilityId": "640ba380aef62d1a", "scanner": "scanner-primary", "fingerprint": "ca0ee8c086b37844", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d944c223f021a4ff", "level": "note", "message": {"text": "Unused endpoint: GET /api/stats/chart"}, "properties": {"repobilityId": "dec0c76a1da19580", "scanner": "scanner-primary", "fingerprint": "d944c223f021a4ff", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b8c606acd376c4d5", "level": "note", "message": {"text": "Unused endpoint: GET /api/config-changes"}, "properties": {"repobilityId": "4594654648914b5e", "scanner": "scanner-primary", "fingerprint": "b8c606acd376c4d5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f3bf72f059406b13", "level": "note", "message": {"text": "Unused endpoint: GET /api/logs"}, "properties": {"repobilityId": "2d700b1bcd07a756", "scanner": "scanner-primary", "fingerprint": "f3bf72f059406b13", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}