{"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-3e36c9029de4ef5a", "name": "Possibly dead Python function: feature_card", "shortDescription": {"text": "Possibly dead Python function: feature_card"}, "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-c5771fcb7db4a73e", "name": "`truncate` class without `title=` for hover reveal \u2014 web/components/FrequencyView.tsx:2041", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/components/FrequencyView.tsx:2041"}, "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-3b48e329f91f8b9c", "name": "`truncate` class without `title=` for hover reveal \u2014 web/components/MapPage.tsx:600", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/components/MapPage.tsx:600"}, "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-853ad2fdec68c8a8", "name": "`truncate` class without `title=` for hover reveal \u2014 web/components/StationHeader.tsx:39", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/components/StationHeader.tsx:39"}, "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-9ca8054931a1878c", "name": "`truncate` class without `title=` for hover reveal \u2014 web/components/CompareView.tsx:259", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/components/CompareView.tsx:259"}, "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-64753ff62fd873c2", "name": "Dockerfile runs as root: ffa-service/Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: ffa-service/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-d1c56668fe2c1380", "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-6372cebde0220094", "name": "No auth library detected", "shortDescription": {"text": "No auth library detected"}, "fullDescription": {"text": "The scanner did not find any standard auth library (JWT, OAuth, NextAuth, Auth0, etc.). The repo has auth/admin/session surface indicators, so auth may live in custom code, in a separate service, or be missing."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4a67bbda0877bbee", "name": "Very large file: web/components/FrequencyView.tsx (2068 lines)", "shortDescription": {"text": "Very large file: web/components/FrequencyView.tsx (2068 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "0 test file(s) for 49 source file(s) (ratio 0.00). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 7 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-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: ci, tests. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing ci, tests. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2c5f98b152cddb6d", "name": "Agent authority lacks a verifier contract: .claude/launch.json", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/launch.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-a78e5de2b750736b", "name": "Commented-code block (6 lines) in make_logo.py:26", "shortDescription": {"text": "Commented-code block (6 lines) in make_logo.py:26"}, "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-5a2e3e628b4aaf94", "name": "Commented-code block (5 lines) in ffa-service/app/ffa.py:55", "shortDescription": {"text": "Commented-code block (5 lines) in ffa-service/app/ffa.py:55"}, "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-77420cdc5ff76751", "name": "Commented-code block (5 lines) in web/components/HistoricDataView.tsx:407", "shortDescription": {"text": "Commented-code block (5 lines) in web/components/HistoricDataView.tsx:407"}, "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-cf959b9882496d47", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/components/FrequencyView.tsx:498", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/components/FrequencyView.tsx:498"}, "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-bea7d65eb41c9314", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/components/ReportView.tsx:142", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/components/ReportView.tsx:142"}, "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-4ab5129cc3ffb061", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/components/CompareView.tsx:73", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/components/CompareView.tsx:73"}, "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-a91233e636c5931a", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/lib/ogc.ts:14", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/lib/ogc.ts:14"}, "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-3fc5253c00c17823", "name": "FastAPI POST `flood_frequency` without auth dependency \u2014 ffa-service/app/main.py:32", "shortDescription": {"text": "FastAPI POST `flood_frequency` without auth dependency \u2014 ffa-service/app/main.py:32"}, "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-7224519fc83d075c", "name": "Dangling fetch: GET /api/stations/${stationId}/daily?variable=${v} (web/components/HistoricDataView.tsx:87)", "shortDescription": {"text": "Dangling fetch: GET /api/stations/${stationId}/daily?variable=${v} (web/components/HistoricDataView.tsx:87)"}, "fullDescription": {"text": "`web/components/HistoricDataView.tsx:87` calls `GET /api/stations/${stationId}/daily?variable=${v}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>/daily`\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-e12d7696ec21778d", "name": "Dangling fetch: GET /api/stations/${stationId}/peaks (web/components/FrequencyView.tsx:223)", "shortDescription": {"text": "Dangling fetch: GET /api/stations/${stationId}/peaks (web/components/FrequencyView.tsx:223)"}, "fullDescription": {"text": "`web/components/FrequencyView.tsx:223` calls `GET /api/stations/${stationId}/peaks` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>/peaks`\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-08a08fb74720a995", "name": "Dangling fetch: GET /api/stations/${stationId}/daily?variable=discharge (web/components/FrequencyView.tsx:239)", "shortDescription": {"text": "Dangling fetch: GET /api/stations/${stationId}/daily?variable=discharge (web/components/FrequencyView.tsx:239)"}, "fullDescription": {"text": "`web/components/FrequencyView.tsx:239` calls `GET /api/stations/${stationId}/daily?variable=discharge` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>/daily`\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-7d88d7664894eb14", "name": "Dangling fetch: GET /api/stations/${stationId} (web/components/FrequencyView.tsx:252)", "shortDescription": {"text": "Dangling fetch: GET /api/stations/${stationId} (web/components/FrequencyView.tsx:252)"}, "fullDescription": {"text": "`web/components/FrequencyView.tsx:252` calls `GET /api/stations/${stationId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>`\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-33f937df6db0d7c5", "name": "Dangling fetch: GET /api/stations (web/components/FrequencyView.tsx:254)", "shortDescription": {"text": "Dangling fetch: GET /api/stations (web/components/FrequencyView.tsx:254)"}, "fullDescription": {"text": "`web/components/FrequencyView.tsx:254` calls `GET /api/stations` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations`\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-38446414e7bde95d", "name": "Dangling fetch: POST /api/stations/${stationId}/frequency (web/components/FrequencyView.tsx:498)", "shortDescription": {"text": "Dangling fetch: POST /api/stations/${stationId}/frequency (web/components/FrequencyView.tsx:498)"}, "fullDescription": {"text": "`web/components/FrequencyView.tsx:498` calls `POST /api/stations/${stationId}/frequency` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>/frequency`\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-7b8f00a068b3d8c6", "name": "Dangling fetch: GET /api/stations/${stationId}/daily?variable=discharge (web/components/ReportView.tsx:142)", "shortDescription": {"text": "Dangling fetch: GET /api/stations/${stationId}/daily?variable=discharge (web/components/ReportView.tsx:142)"}, "fullDescription": {"text": "`web/components/ReportView.tsx:142` calls `GET /api/stations/${stationId}/daily?variable=discharge` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>/daily`\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-35c89fdb134a1197", "name": "Dangling fetch: GET /api/stations/${stationId}/peaks (web/components/ReportView.tsx:144)", "shortDescription": {"text": "Dangling fetch: GET /api/stations/${stationId}/peaks (web/components/ReportView.tsx:144)"}, "fullDescription": {"text": "`web/components/ReportView.tsx:144` calls `GET /api/stations/${stationId}/peaks` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>/peaks`\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-0f3c2abde6977bfc", "name": "Dangling fetch: POST /api/stations/${stationId}/frequency (web/components/ReportView.tsx:146)", "shortDescription": {"text": "Dangling fetch: POST /api/stations/${stationId}/frequency (web/components/ReportView.tsx:146)"}, "fullDescription": {"text": "`web/components/ReportView.tsx:146` calls `POST /api/stations/${stationId}/frequency` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>/frequency`\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-a1a39ddcf494ab81", "name": "Dangling fetch: GET /api/stations/${id}/daily?variable=discharge (web/components/CompareView.tsx:73)", "shortDescription": {"text": "Dangling fetch: GET /api/stations/${id}/daily?variable=discharge (web/components/CompareView.tsx:73)"}, "fullDescription": {"text": "`web/components/CompareView.tsx:73` calls `GET /api/stations/${id}/daily?variable=discharge` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>/daily`\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-24352ac2bd9df790", "name": "Dangling fetch: GET /api/stations/${id}/peaks (web/components/CompareView.tsx:75)", "shortDescription": {"text": "Dangling fetch: GET /api/stations/${id}/peaks (web/components/CompareView.tsx:75)"}, "fullDescription": {"text": "`web/components/CompareView.tsx:75` calls `GET /api/stations/${id}/peaks` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>/peaks`\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-3e85050ac1f19f81", "name": "Dangling fetch: POST /api/stations/${s.id}/frequency (web/components/CompareView.tsx:160)", "shortDescription": {"text": "Dangling fetch: POST /api/stations/${s.id}/frequency (web/components/CompareView.tsx:160)"}, "fullDescription": {"text": "`web/components/CompareView.tsx:160` calls `POST /api/stations/${s.id}/frequency` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/stations/<p>/frequency`\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-9da5b38054cafd56", "name": "Unused endpoint: POST /api/v1/flood-frequency", "shortDescription": {"text": "Unused endpoint: POST /api/v1/flood-frequency"}, "fullDescription": {"text": "`ffa-service/app/main.py` declares `POST /api/v1/flood-frequency` 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/23900"}, "properties": {"repository": "adilch/WSCprep", "repoUrl": "https://github.com/adilch/WSCprep", "branch": "main"}, "results": [{"ruleId": "scanner-3e36c9029de4ef5a", "level": "note", "message": {"text": "Possibly dead Python function: feature_card"}, "properties": {"repobilityId": "f8cac4374c52de9e", "scanner": "scanner-primary", "fingerprint": "3e36c9029de4ef5a", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "make_presentation.py:96"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-c5771fcb7db4a73e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/components/FrequencyView.tsx:2041"}, "properties": {"repobilityId": "b0c4991653ee7089", "scanner": "scanner-primary", "fingerprint": "c5771fcb7db4a73e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3b48e329f91f8b9c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/components/MapPage.tsx:600"}, "properties": {"repobilityId": "30bf4e761739aeb9", "scanner": "scanner-primary", "fingerprint": "3b48e329f91f8b9c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-853ad2fdec68c8a8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/components/StationHeader.tsx:39"}, "properties": {"repobilityId": "99b911e7fadd45f5", "scanner": "scanner-primary", "fingerprint": "853ad2fdec68c8a8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9ca8054931a1878c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/components/CompareView.tsx:259"}, "properties": {"repobilityId": "b0e2396fc1b66c4e", "scanner": "scanner-primary", "fingerprint": "9ca8054931a1878c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-64753ff62fd873c2", "level": "warning", "message": {"text": "Dockerfile runs as root: ffa-service/Dockerfile"}, "properties": {"repobilityId": "09b2c6e75842c534", "scanner": "scanner-primary", "fingerprint": "64753ff62fd873c2", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-d1c56668fe2c1380", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim"}, "properties": {"repobilityId": "ee6cccf940cfef96", "scanner": "scanner-primary", "fingerprint": "d1c56668fe2c1380", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ffa-service/Dockerfile"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6372cebde0220094", "level": "warning", "message": {"text": "No auth library detected"}, "properties": {"repobilityId": "a5b6035a5bbf8054", "scanner": "scanner-primary", "fingerprint": "6372cebde0220094", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["coverage", "auth"]}}, {"ruleId": "scanner-4a67bbda0877bbee", "level": "note", "message": {"text": "Very large file: web/components/FrequencyView.tsx (2068 lines)"}, "properties": {"repobilityId": "c50d4ebe55384ea8", "scanner": "scanner-primary", "fingerprint": "4a67bbda0877bbee", "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-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "92a6da22a3e7a8b7", "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": "7b23a4b32af7a639", "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": "5d8623c20ddc3e0d", "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": "3082a02d0a8961be", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-2c5f98b152cddb6d", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/launch.json"}, "properties": {"repobilityId": "0de48c0f4ab303d8", "scanner": "scanner-primary", "fingerprint": "2c5f98b152cddb6d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/launch.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-a78e5de2b750736b", "level": "none", "message": {"text": "Commented-code block (6 lines) in make_logo.py:26"}, "properties": {"repobilityId": "08baf1d8bf33f63b", "scanner": "scanner-primary", "fingerprint": "a78e5de2b750736b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-5a2e3e628b4aaf94", "level": "none", "message": {"text": "Commented-code block (5 lines) in ffa-service/app/ffa.py:55"}, "properties": {"repobilityId": "0226d1b45ccb10ac", "scanner": "scanner-primary", "fingerprint": "5a2e3e628b4aaf94", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-77420cdc5ff76751", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/components/HistoricDataView.tsx:407"}, "properties": {"repobilityId": "0649168c165a5068", "scanner": "scanner-primary", "fingerprint": "77420cdc5ff76751", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-cf959b9882496d47", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/components/FrequencyView.tsx:498"}, "properties": {"repobilityId": "5783bb298604cdea", "scanner": "scanner-primary", "fingerprint": "cf959b9882496d47", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-bea7d65eb41c9314", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/components/ReportView.tsx:142"}, "properties": {"repobilityId": "3c82f1cc062a136a", "scanner": "scanner-primary", "fingerprint": "bea7d65eb41c9314", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-4ab5129cc3ffb061", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/components/CompareView.tsx:73"}, "properties": {"repobilityId": "363960d972856e7a", "scanner": "scanner-primary", "fingerprint": "4ab5129cc3ffb061", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-a91233e636c5931a", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/lib/ogc.ts:14"}, "properties": {"repobilityId": "4d577977cdb39a10", "scanner": "scanner-primary", "fingerprint": "a91233e636c5931a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3fc5253c00c17823", "level": "error", "message": {"text": "FastAPI POST `flood_frequency` without auth dependency \u2014 ffa-service/app/main.py:32"}, "properties": {"repobilityId": "6b9ca135ea3c0815", "scanner": "scanner-primary", "fingerprint": "3fc5253c00c17823", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ffa-service/app/main.py"}, "region": {"startLine": 32}}}]}, {"ruleId": "scanner-7224519fc83d075c", "level": "error", "message": {"text": "Dangling fetch: GET /api/stations/${stationId}/daily?variable=${v} (web/components/HistoricDataView.tsx:87)"}, "properties": {"repobilityId": "943d65cc96a87f9a", "scanner": "scanner-primary", "fingerprint": "7224519fc83d075c", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-e12d7696ec21778d", "level": "error", "message": {"text": "Dangling fetch: GET /api/stations/${stationId}/peaks (web/components/FrequencyView.tsx:223)"}, "properties": {"repobilityId": "ccc11579aa3ec64f", "scanner": "scanner-primary", "fingerprint": "e12d7696ec21778d", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-08a08fb74720a995", "level": "error", "message": {"text": "Dangling fetch: GET /api/stations/${stationId}/daily?variable=discharge (web/components/FrequencyView.tsx:239)"}, "properties": {"repobilityId": "44078080f7eab21d", "scanner": "scanner-primary", "fingerprint": "08a08fb74720a995", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-7d88d7664894eb14", "level": "error", "message": {"text": "Dangling fetch: GET /api/stations/${stationId} (web/components/FrequencyView.tsx:252)"}, "properties": {"repobilityId": "ad685fe8d05af41b", "scanner": "scanner-primary", "fingerprint": "7d88d7664894eb14", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-33f937df6db0d7c5", "level": "error", "message": {"text": "Dangling fetch: GET /api/stations (web/components/FrequencyView.tsx:254)"}, "properties": {"repobilityId": "7c91352f62daebd7", "scanner": "scanner-primary", "fingerprint": "33f937df6db0d7c5", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-38446414e7bde95d", "level": "error", "message": {"text": "Dangling fetch: POST /api/stations/${stationId}/frequency (web/components/FrequencyView.tsx:498)"}, "properties": {"repobilityId": "186b33e5fb6c2954", "scanner": "scanner-primary", "fingerprint": "38446414e7bde95d", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-7b8f00a068b3d8c6", "level": "error", "message": {"text": "Dangling fetch: GET /api/stations/${stationId}/daily?variable=discharge (web/components/ReportView.tsx:142)"}, "properties": {"repobilityId": "78ea73f79599985b", "scanner": "scanner-primary", "fingerprint": "7b8f00a068b3d8c6", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-35c89fdb134a1197", "level": "error", "message": {"text": "Dangling fetch: GET /api/stations/${stationId}/peaks (web/components/ReportView.tsx:144)"}, "properties": {"repobilityId": "8a044ee6530f3a62", "scanner": "scanner-primary", "fingerprint": "35c89fdb134a1197", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-0f3c2abde6977bfc", "level": "error", "message": {"text": "Dangling fetch: POST /api/stations/${stationId}/frequency (web/components/ReportView.tsx:146)"}, "properties": {"repobilityId": "b1d3330146c04ede", "scanner": "scanner-primary", "fingerprint": "0f3c2abde6977bfc", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-a1a39ddcf494ab81", "level": "error", "message": {"text": "Dangling fetch: GET /api/stations/${id}/daily?variable=discharge (web/components/CompareView.tsx:73)"}, "properties": {"repobilityId": "be9613ab7b00ce37", "scanner": "scanner-primary", "fingerprint": "a1a39ddcf494ab81", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-24352ac2bd9df790", "level": "error", "message": {"text": "Dangling fetch: GET /api/stations/${id}/peaks (web/components/CompareView.tsx:75)"}, "properties": {"repobilityId": "4c98f26b6fd8e51d", "scanner": "scanner-primary", "fingerprint": "24352ac2bd9df790", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-3e85050ac1f19f81", "level": "error", "message": {"text": "Dangling fetch: POST /api/stations/${s.id}/frequency (web/components/CompareView.tsx:160)"}, "properties": {"repobilityId": "54604a6658a74c74", "scanner": "scanner-primary", "fingerprint": "3e85050ac1f19f81", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-9da5b38054cafd56", "level": "note", "message": {"text": "Unused endpoint: POST /api/v1/flood-frequency"}, "properties": {"repobilityId": "478ac0f69ae5662e", "scanner": "scanner-primary", "fingerprint": "9da5b38054cafd56", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}