{"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-0c75158cf1f1995e", "name": "Possibly dead Python function: run", "shortDescription": {"text": "Possibly dead Python function: run"}, "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-e9fcd030896e7ff3", "name": "Possibly dead Python function: toggle", "shortDescription": {"text": "Possibly dead Python function: toggle"}, "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-04377a128872441f", "name": "Stray `console.log` in TS/JS \u2014 gen-icons.js:44", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 gen-icons.js:44"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-42bef3ea04b829bb", "name": "Icon-only button without accessible name \u2014 kakeibo/app/page.tsx:161", "shortDescription": {"text": "Icon-only button without accessible name \u2014 kakeibo/app/page.tsx:161"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-66e7975bb2e4be69", "name": "`truncate` class without `title=` for hover reveal \u2014 kakeibo/app/components/TransactionList.tsx:209", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 kakeibo/app/components/TransactionList.tsx:209"}, "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-8645ad4db62f90b2", "name": "Icon-only button without accessible name \u2014 kakeibo/app/components/TransactionForm.tsx:83", "shortDescription": {"text": "Icon-only button without accessible name \u2014 kakeibo/app/components/TransactionForm.tsx:83"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f1e7755af3dba7da", "name": "`truncate` class without `title=` for hover reveal \u2014 kakeibo/app/components/CSVImport.tsx:305", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 kakeibo/app/components/CSVImport.tsx:305"}, "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-8d598bcd00cb59f6", "name": "`truncate` class without `title=` for hover reveal \u2014 kakeibo/app/components/Calendar.tsx:110", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 kakeibo/app/components/Calendar.tsx:110"}, "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-034b269e77a327a0", "name": "Icon-only button without accessible name \u2014 earthquake-app/app/components/EarthquakeDetail.tsx:48", "shortDescription": {"text": "Icon-only button without accessible name \u2014 earthquake-app/app/components/EarthquakeDetail.tsx:48"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d441efa6a329ee56", "name": "`truncate` class without `title=` for hover reveal \u2014 earthquake-app/app/components/EarthquakeCard.tsx:36", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 earthquake-app/app/components/EarthquakeCard.tsx:36"}, "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-73c73807b1293c42", "name": "`truncate` class without `title=` for hover reveal \u2014 interest/app/page.tsx:321", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 interest/app/page.tsx:321"}, "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-7e609e1866d0f421", "name": "Icon-only button without accessible name \u2014 inventory/app/page.tsx:443", "shortDescription": {"text": "Icon-only button without accessible name \u2014 inventory/app/page.tsx:443"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f98d59f2e3ad1928", "name": "`truncate` class without `title=` for hover reveal \u2014 inventory/app/page.tsx:347", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 inventory/app/page.tsx:347"}, "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-8f9a87d20f665e71", "name": "Icon-only button without accessible name \u2014 inventory/app/components/ItemForm.tsx:59", "shortDescription": {"text": "Icon-only button without accessible name \u2014 inventory/app/components/ItemForm.tsx:59"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-522d1fad312afe46", "name": "`truncate` class without `title=` for hover reveal \u2014 inventory/app/components/ItemCard.tsx:40", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 inventory/app/components/ItemCard.tsx:40"}, "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-88fe0a37a49f492c", "name": "Icon-only button without accessible name \u2014 todo/app/page.tsx:417", "shortDescription": {"text": "Icon-only button without accessible name \u2014 todo/app/page.tsx:417"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f344512fefba1103", "name": "`truncate` class without `title=` for hover reveal \u2014 todo/app/page.tsx:370", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 todo/app/page.tsx:370"}, "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-b7aec563938e7da7", "name": "`truncate` class without `title=` for hover reveal \u2014 todo/app/components/TaskItem.tsx:90", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 todo/app/components/TaskItem.tsx:90"}, "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-f2f39e3107f6f188", "name": "Icon-only button without accessible name \u2014 todo/app/settings/page.tsx:177", "shortDescription": {"text": "Icon-only button without accessible name \u2014 todo/app/settings/page.tsx:177"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0d15034f30104eef", "name": "`truncate` class without `title=` for hover reveal \u2014 todo/app/settings/page.tsx:126", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 todo/app/settings/page.tsx:126"}, "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-4a80c222428121d6", "name": "`truncate` class without `title=` for hover reveal \u2014 todo/app/calendar/page.tsx:256", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 todo/app/calendar/page.tsx:256"}, "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-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-0b1bc594bb8cdace", "name": "Insecure pattern 'direct_innerhtml_assignment' in todolist.py:131", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in todolist.py:131"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-be074595410d32c3", "name": "Insecure pattern 'python_os_system' in rpg.py:35", "shortDescription": {"text": "Insecure pattern 'python_os_system' in rpg.py:35"}, "fullDescription": {"text": "Found a known-risky pattern (python_os_system). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "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-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "0 test file(s) for 90 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-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 83 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-72b2a6250083a784", "name": "Placeholder or mock-heavy implementation detected", "shortDescription": {"text": "Placeholder or mock-heavy implementation detected"}, "fullDescription": {"text": "Found 41 placeholder/mock markers across 15 source files. This often means the repo looks complete while core flows still use generated scaffolding or fake data."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, 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": "medium", "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, 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-31ad3bbdd2602cea", "name": "Agent authority lacks a verifier contract: kakeibo/CLAUDE.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: kakeibo/CLAUDE.md"}, "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-c4faa7353216fcb6", "name": "`fetch()` without try/.catch or AbortSignal \u2014 earthquake-app/app/lib/api.ts:48", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 earthquake-app/app/lib/api.ts:48"}, "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-68cea50ee2ea8fa9", "name": "`fetch()` without try/.catch or AbortSignal \u2014 earthquake-app/app/lib/typhoonApi.ts:25", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 earthquake-app/app/lib/typhoonApi.ts:25"}, "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-2b86c21e33e4d3a9", "name": "Legacy-named symbol `interest_calc_v1` in interest/app/page.tsx:18", "shortDescription": {"text": "Legacy-named symbol `interest_calc_v1` in interest/app/page.tsx:18"}, "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-2c04133e54348533", "name": "Near-duplicate function bodies in 2 places", "shortDescription": {"text": "Near-duplicate function bodies in 2 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nrpg.py:is_alive, rpg.py:is_alive\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7cf82373e5ffef93", "name": "FastAPI POST `add_todo` without auth dependency \u2014 todolist.py:177", "shortDescription": {"text": "FastAPI POST `add_todo` without auth dependency \u2014 todolist.py:177"}, "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-6167564909aa0a14", "name": "FastAPI PUT `complete_todo` without auth dependency \u2014 todolist.py:185", "shortDescription": {"text": "FastAPI PUT `complete_todo` without auth dependency \u2014 todolist.py:185"}, "fullDescription": {"text": "`@router.put` 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-13225153702b094e", "name": "FastAPI DELETE `delete_todo` without auth dependency \u2014 todolist.py:193", "shortDescription": {"text": "FastAPI DELETE `delete_todo` without auth dependency \u2014 todolist.py:193"}, "fullDescription": {"text": "`@router.delete` 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}}]}}, "automationDetails": {"id": "repobility/24370"}, "properties": {"repository": "atanikumeya2313-dot/my-web-app", "repoUrl": "https://github.com/atanikumeya2313-dot/my-web-app", "branch": "main"}, "results": [{"ruleId": "scanner-0c75158cf1f1995e", "level": "note", "message": {"text": "Possibly dead Python function: run"}, "properties": {"repobilityId": "1dbeb43640a3ab52", "scanner": "scanner-primary", "fingerprint": "0c75158cf1f1995e", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "restaurant-search/main.py:187"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-e9fcd030896e7ff3", "level": "note", "message": {"text": "Possibly dead Python function: toggle"}, "properties": {"repobilityId": "0f9993db32d0ee08", "scanner": "scanner-primary", "fingerprint": "e9fcd030896e7ff3", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "restaurant-search/main.py:279"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-04377a128872441f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 gen-icons.js:44"}, "properties": {"repobilityId": "8e78c63845c10d5d", "scanner": "scanner-primary", "fingerprint": "04377a128872441f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-42bef3ea04b829bb", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 kakeibo/app/page.tsx:161"}, "properties": {"repobilityId": "28c8c5538696e261", "scanner": "scanner-primary", "fingerprint": "42bef3ea04b829bb", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-66e7975bb2e4be69", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 kakeibo/app/components/TransactionList.tsx:209"}, "properties": {"repobilityId": "1672ca3f569afa2e", "scanner": "scanner-primary", "fingerprint": "66e7975bb2e4be69", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8645ad4db62f90b2", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 kakeibo/app/components/TransactionForm.tsx:83"}, "properties": {"repobilityId": "764b0aac9e6ca44d", "scanner": "scanner-primary", "fingerprint": "8645ad4db62f90b2", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-f1e7755af3dba7da", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 kakeibo/app/components/CSVImport.tsx:305"}, "properties": {"repobilityId": "225de0aab074d6c0", "scanner": "scanner-primary", "fingerprint": "f1e7755af3dba7da", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8d598bcd00cb59f6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 kakeibo/app/components/Calendar.tsx:110"}, "properties": {"repobilityId": "382dbe4199e2cce1", "scanner": "scanner-primary", "fingerprint": "8d598bcd00cb59f6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-034b269e77a327a0", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 earthquake-app/app/components/EarthquakeDetail.tsx:48"}, "properties": {"repobilityId": "822669d95315f0bb", "scanner": "scanner-primary", "fingerprint": "034b269e77a327a0", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-d441efa6a329ee56", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 earthquake-app/app/components/EarthquakeCard.tsx:36"}, "properties": {"repobilityId": "b41677ed545bff33", "scanner": "scanner-primary", "fingerprint": "d441efa6a329ee56", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-73c73807b1293c42", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 interest/app/page.tsx:321"}, "properties": {"repobilityId": "97581517197dc3c8", "scanner": "scanner-primary", "fingerprint": "73c73807b1293c42", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7e609e1866d0f421", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 inventory/app/page.tsx:443"}, "properties": {"repobilityId": "a766b6dfd23bdc26", "scanner": "scanner-primary", "fingerprint": "7e609e1866d0f421", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-f98d59f2e3ad1928", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 inventory/app/page.tsx:347"}, "properties": {"repobilityId": "2648882ada0613e3", "scanner": "scanner-primary", "fingerprint": "f98d59f2e3ad1928", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8f9a87d20f665e71", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 inventory/app/components/ItemForm.tsx:59"}, "properties": {"repobilityId": "eedd48814a4b625f", "scanner": "scanner-primary", "fingerprint": "8f9a87d20f665e71", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-522d1fad312afe46", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 inventory/app/components/ItemCard.tsx:40"}, "properties": {"repobilityId": "7b9cd14fda03b080", "scanner": "scanner-primary", "fingerprint": "522d1fad312afe46", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-88fe0a37a49f492c", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 todo/app/page.tsx:417"}, "properties": {"repobilityId": "7552bde425db0428", "scanner": "scanner-primary", "fingerprint": "88fe0a37a49f492c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-f344512fefba1103", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 todo/app/page.tsx:370"}, "properties": {"repobilityId": "43d5cba30257a6d8", "scanner": "scanner-primary", "fingerprint": "f344512fefba1103", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b7aec563938e7da7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 todo/app/components/TaskItem.tsx:90"}, "properties": {"repobilityId": "d73f817bcdfe9e58", "scanner": "scanner-primary", "fingerprint": "b7aec563938e7da7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f2f39e3107f6f188", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 todo/app/settings/page.tsx:177"}, "properties": {"repobilityId": "22e0097945c516d1", "scanner": "scanner-primary", "fingerprint": "f2f39e3107f6f188", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-0d15034f30104eef", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 todo/app/settings/page.tsx:126"}, "properties": {"repobilityId": "e001cc42e68440ca", "scanner": "scanner-primary", "fingerprint": "0d15034f30104eef", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4a80c222428121d6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 todo/app/calendar/page.tsx:256"}, "properties": {"repobilityId": "b1b535cf87f5c4d3", "scanner": "scanner-primary", "fingerprint": "4a80c222428121d6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"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-0b1bc594bb8cdace", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in todolist.py:131"}, "properties": {"repobilityId": "8128a6717dfd5e9f", "scanner": "scanner-primary", "fingerprint": "0b1bc594bb8cdace", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "todolist.py"}, "region": {"startLine": 131}}}]}, {"ruleId": "scanner-be074595410d32c3", "level": "error", "message": {"text": "Insecure pattern 'python_os_system' in rpg.py:35"}, "properties": {"repobilityId": "a313d76cfeee75ad", "scanner": "scanner-primary", "fingerprint": "be074595410d32c3", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["owasp", "python_os_system"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "rpg.py"}, "region": {"startLine": 35}}}]}, {"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-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": "babdd954e89a52ed", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "d3c4c01b1d3921ef", "scanner": "scanner-primary", "fingerprint": "3ab5d313dda8e5f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["debug", "cleanup", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-72b2a6250083a784", "level": "warning", "message": {"text": "Placeholder or mock-heavy implementation detected"}, "properties": {"repobilityId": "e49fb594d0d651ca", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "warning", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "c9f7443f590d889d", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "medium", "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": "35d9668c35dcc302", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-31ad3bbdd2602cea", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: kakeibo/CLAUDE.md"}, "properties": {"repobilityId": "d46f7b8f4dd049ee", "scanner": "scanner-primary", "fingerprint": "31ad3bbdd2602cea", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "kakeibo/CLAUDE.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-c4faa7353216fcb6", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 earthquake-app/app/lib/api.ts:48"}, "properties": {"repobilityId": "e1ab946fa311f463", "scanner": "scanner-primary", "fingerprint": "c4faa7353216fcb6", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-68cea50ee2ea8fa9", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 earthquake-app/app/lib/typhoonApi.ts:25"}, "properties": {"repobilityId": "02909e8036086254", "scanner": "scanner-primary", "fingerprint": "68cea50ee2ea8fa9", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-2b86c21e33e4d3a9", "level": "note", "message": {"text": "Legacy-named symbol `interest_calc_v1` in interest/app/page.tsx:18"}, "properties": {"repobilityId": "ba3eedfe8c523c71", "scanner": "scanner-primary", "fingerprint": "2b86c21e33e4d3a9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "e1058a998634324d", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "3664d0c38c3e7662", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "4039bc6fb4138a33", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-7cf82373e5ffef93", "level": "error", "message": {"text": "FastAPI POST `add_todo` without auth dependency \u2014 todolist.py:177"}, "properties": {"repobilityId": "ad1c0fc0349d2b2d", "scanner": "scanner-primary", "fingerprint": "7cf82373e5ffef93", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "todolist.py"}, "region": {"startLine": 177}}}]}, {"ruleId": "scanner-6167564909aa0a14", "level": "error", "message": {"text": "FastAPI PUT `complete_todo` without auth dependency \u2014 todolist.py:185"}, "properties": {"repobilityId": "e86d8dda1d2afffe", "scanner": "scanner-primary", "fingerprint": "6167564909aa0a14", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "todolist.py"}, "region": {"startLine": 185}}}]}, {"ruleId": "scanner-13225153702b094e", "level": "error", "message": {"text": "FastAPI DELETE `delete_todo` without auth dependency \u2014 todolist.py:193"}, "properties": {"repobilityId": "149b7a00f1c7ea83", "scanner": "scanner-primary", "fingerprint": "13225153702b094e", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "todolist.py"}, "region": {"startLine": 193}}}]}]}]}