{"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-0d228f3ee2905fc8", "name": "Possibly dead Python function: upgrade", "shortDescription": {"text": "Possibly dead Python function: upgrade"}, "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-7ce23d3e38ecc6ac", "name": "Possibly dead Python function: downgrade", "shortDescription": {"text": "Possibly dead Python function: downgrade"}, "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-d43c710924d50823", "name": "Possibly dead Python function: verify_password", "shortDescription": {"text": "Possibly dead Python function: verify_password"}, "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-b2e4875c92edafc8", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/Badges.jsx:49", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/Badges.jsx:49"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-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-8987d6d1c30c7202", "name": "Docker base image is tag-pinned but not digest-pinned: node:20-alpine", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: node:20-alpine"}, "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-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-aa5acaa49eb8315b", "name": "Containers defined but no K8s/orchestration manifest found", "shortDescription": {"text": "Containers defined but no K8s/orchestration manifest found"}, "fullDescription": {"text": "Repo has Dockerfiles/compose but no Kubernetes/Nomad manifests. If the target deployment is K8s, the manifests may live in a separate ops repo."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-72a2eef05773017b", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/screenshots.mjs:31", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/screenshots.mjs:31"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ff937cec43748d3c", "name": "Possible secret in backend/auth.py", "shortDescription": {"text": "Possible secret in backend/auth.py"}, "fullDescription": {"text": "Detected pattern matching password_literal. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "3 test file(s) for 43 source file(s) (ratio 0.07). 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-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-9b8a5dc084e33246", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/scripts/screenshots.mjs:27", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/scripts/screenshots.mjs:27"}, "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-70bfa91e8c87ff16", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/api.js:56", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/api.js:56"}, "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-b334d875f2339fa1", "name": "5 env vars used in code but missing from .env.example", "shortDescription": {"text": "5 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `DATABASE_PATH`, `DATABASE_URL`, `GROQ_MODEL`, `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6313f8369242e5de", "name": "Frontend route `/product/:id` has no Link/navigate to it \u2014 frontend/src/main.jsx", "shortDescription": {"text": "Frontend route `/product/:id` has no Link/navigate to it \u2014 frontend/src/main.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-cb44fac3cdd65bb4", "name": "FastAPI POST `demo_login` without auth dependency \u2014 backend/auth.py:65", "shortDescription": {"text": "FastAPI POST `demo_login` without auth dependency \u2014 backend/auth.py:65"}, "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-b9edad8ae4f2faeb", "name": "Dangling fetch: POST /api/auth/demo (frontend/scripts/screenshots.mjs:27)", "shortDescription": {"text": "Dangling fetch: POST /api/auth/demo (frontend/scripts/screenshots.mjs:27)"}, "fullDescription": {"text": "`frontend/scripts/screenshots.mjs:27` calls `POST /api/auth/demo` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/auth/demo`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-019f89a12641e77e", "name": "Unused endpoint: POST /demo", "shortDescription": {"text": "Unused endpoint: POST /demo"}, "fullDescription": {"text": "`backend/auth.py` declares `POST /demo` 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-cca7583916efd86a", "name": "Unused endpoint: POST /products", "shortDescription": {"text": "Unused endpoint: POST /products"}, "fullDescription": {"text": "`backend/routes_products.py` declares `POST /products` 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-742eba07086df4e1", "name": "Unused endpoint: GET /products/{product_id}/history", "shortDescription": {"text": "Unused endpoint: GET /products/{product_id}/history"}, "fullDescription": {"text": "`backend/routes_products.py` declares `GET /products/{product_id}/history` 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-cdb40a850d729bbe", "name": "Unused endpoint: DELETE /products/{product_id}", "shortDescription": {"text": "Unused endpoint: DELETE /products/{product_id}"}, "fullDescription": {"text": "`backend/routes_products.py` declares `DELETE /products/{product_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-ab8b3c68308c92da", "name": "Unused endpoint: POST /scrape", "shortDescription": {"text": "Unused endpoint: POST /scrape"}, "fullDescription": {"text": "`backend/routes_products.py` declares `POST /scrape` 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-b3f41c5c6da1ef81", "name": "Unused endpoint: GET /products/{product_id}/insight", "shortDescription": {"text": "Unused endpoint: GET /products/{product_id}/insight"}, "fullDescription": {"text": "`backend/routes_products.py` declares `GET /products/{product_id}/insight` 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-af4de720f651079e", "name": "Unused endpoint: POST /extract", "shortDescription": {"text": "Unused endpoint: POST /extract"}, "fullDescription": {"text": "`backend/routes_extract.py` declares `POST /extract` 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-4756b4c4da7d2088", "name": "Unused endpoint: GET /api/health", "shortDescription": {"text": "Unused endpoint: GET /api/health"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/health` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-91786ec9e40e27ca", "name": "Unused endpoint: GET /{path:path}", "shortDescription": {"text": "Unused endpoint: GET /{path:path}"}, "fullDescription": {"text": "`backend/main.py` declares `GET /{path: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}}]}}, "automationDetails": {"id": "repobility/21586"}, "properties": {"repository": "tpsyyyyyl/price-monitor", "repoUrl": "https://github.com/tpsyyyyyl/price-monitor", "branch": "main"}, "results": [{"ruleId": "scanner-0d228f3ee2905fc8", "level": "note", "message": {"text": "Possibly dead Python function: upgrade"}, "properties": {"repobilityId": "cf0b8e5e6e2f8bc4", "scanner": "scanner-primary", "fingerprint": "0d228f3ee2905fc8", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "alembic/versions/0001_initial.py:21"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-7ce23d3e38ecc6ac", "level": "note", "message": {"text": "Possibly dead Python function: downgrade"}, "properties": {"repobilityId": "c03debbf11efa0c5", "scanner": "scanner-primary", "fingerprint": "7ce23d3e38ecc6ac", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "alembic/versions/0001_initial.py:55"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d43c710924d50823", "level": "note", "message": {"text": "Possibly dead Python function: verify_password"}, "properties": {"repobilityId": "db0091ab19f6dc78", "scanner": "scanner-primary", "fingerprint": "d43c710924d50823", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/auth.py:29"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-b2e4875c92edafc8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/Badges.jsx:49"}, "properties": {"repobilityId": "9d01088cac0ea4af", "scanner": "scanner-primary", "fingerprint": "b2e4875c92edafc8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"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-8987d6d1c30c7202", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:20-alpine"}, "properties": {"repobilityId": "e42410be9a4b7ce5", "scanner": "scanner-primary", "fingerprint": "8987d6d1c30c7202", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 2}}}]}, {"ruleId": "scanner-de3c1f217d72a063", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim"}, "properties": {"repobilityId": "61dee16174687f59", "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": 10}}}]}, {"ruleId": "scanner-aa5acaa49eb8315b", "level": "note", "message": {"text": "Containers defined but no K8s/orchestration manifest found"}, "properties": {"repobilityId": "b230ea9b68736081", "scanner": "scanner-primary", "fingerprint": "aa5acaa49eb8315b", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["coverage", "deployment"]}}, {"ruleId": "scanner-72a2eef05773017b", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/screenshots.mjs:31"}, "properties": {"repobilityId": "eeffaef881e5e5dd", "scanner": "scanner-primary", "fingerprint": "72a2eef05773017b", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/screenshots.mjs"}, "region": {"startLine": 31}}}]}, {"ruleId": "scanner-ff937cec43748d3c", "level": "error", "message": {"text": "Possible secret in backend/auth.py"}, "properties": {"repobilityId": "d7bdaf706727f337", "scanner": "scanner-primary", "fingerprint": "ff937cec43748d3c", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/auth.py"}, "region": {"startLine": 20}}}]}, {"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": "18436f7389467774", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "ec635d7e86dca983", "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": "c4ebe90aa47398e8", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-9b8a5dc084e33246", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/scripts/screenshots.mjs:27"}, "properties": {"repobilityId": "4305a4654e3e3511", "scanner": "scanner-primary", "fingerprint": "9b8a5dc084e33246", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-70bfa91e8c87ff16", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/api.js:56"}, "properties": {"repobilityId": "c8a507223c03de34", "scanner": "scanner-primary", "fingerprint": "70bfa91e8c87ff16", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-b334d875f2339fa1", "level": "note", "message": {"text": "5 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "faa38682016f5d53", "scanner": "scanner-primary", "fingerprint": "b334d875f2339fa1", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-6313f8369242e5de", "level": "warning", "message": {"text": "Frontend route `/product/:id` has no Link/navigate to it \u2014 frontend/src/main.jsx"}, "properties": {"repobilityId": "aee7a82d677814a1", "scanner": "scanner-primary", "fingerprint": "6313f8369242e5de", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-cb44fac3cdd65bb4", "level": "error", "message": {"text": "FastAPI POST `demo_login` without auth dependency \u2014 backend/auth.py:65"}, "properties": {"repobilityId": "e9e3e62b53910f92", "scanner": "scanner-primary", "fingerprint": "cb44fac3cdd65bb4", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/auth.py"}, "region": {"startLine": 65}}}]}, {"ruleId": "scanner-b9edad8ae4f2faeb", "level": "error", "message": {"text": "Dangling fetch: POST /api/auth/demo (frontend/scripts/screenshots.mjs:27)"}, "properties": {"repobilityId": "bc8a81a7f0bf40af", "scanner": "scanner-primary", "fingerprint": "b9edad8ae4f2faeb", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-019f89a12641e77e", "level": "note", "message": {"text": "Unused endpoint: POST /demo"}, "properties": {"repobilityId": "0e3a3048f55caa1b", "scanner": "scanner-primary", "fingerprint": "019f89a12641e77e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cca7583916efd86a", "level": "note", "message": {"text": "Unused endpoint: POST /products"}, "properties": {"repobilityId": "0e17a6ae2587e559", "scanner": "scanner-primary", "fingerprint": "cca7583916efd86a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-742eba07086df4e1", "level": "note", "message": {"text": "Unused endpoint: GET /products/{product_id}/history"}, "properties": {"repobilityId": "bba9e6e7300fc3bf", "scanner": "scanner-primary", "fingerprint": "742eba07086df4e1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cdb40a850d729bbe", "level": "note", "message": {"text": "Unused endpoint: DELETE /products/{product_id}"}, "properties": {"repobilityId": "4ce01201e7f3876a", "scanner": "scanner-primary", "fingerprint": "cdb40a850d729bbe", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ab8b3c68308c92da", "level": "note", "message": {"text": "Unused endpoint: POST /scrape"}, "properties": {"repobilityId": "c22dcb0e7cf74ca9", "scanner": "scanner-primary", "fingerprint": "ab8b3c68308c92da", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b3f41c5c6da1ef81", "level": "note", "message": {"text": "Unused endpoint: GET /products/{product_id}/insight"}, "properties": {"repobilityId": "427da753d9532aa6", "scanner": "scanner-primary", "fingerprint": "b3f41c5c6da1ef81", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-af4de720f651079e", "level": "note", "message": {"text": "Unused endpoint: POST /extract"}, "properties": {"repobilityId": "d173f31e78979c56", "scanner": "scanner-primary", "fingerprint": "af4de720f651079e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4756b4c4da7d2088", "level": "note", "message": {"text": "Unused endpoint: GET /api/health"}, "properties": {"repobilityId": "3c95aa69206af894", "scanner": "scanner-primary", "fingerprint": "4756b4c4da7d2088", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-91786ec9e40e27ca", "level": "note", "message": {"text": "Unused endpoint: GET /{path:path}"}, "properties": {"repobilityId": "d16dde372d94e98f", "scanner": "scanner-primary", "fingerprint": "91786ec9e40e27ca", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}