{"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-51ce0e59d73cdfb7", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/breadcrumb-nav.tsx:117", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/breadcrumb-nav.tsx:117"}, "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-5b0bd2e879da9c7b", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/profile-sheet.tsx:50", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/profile-sheet.tsx:50"}, "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-9e76b176e7ef75da", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/sidebar.tsx:59", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/sidebar.tsx:59"}, "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-2a2feec2857781d3", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/branch-switcher.tsx:103", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/branch-switcher.tsx:103"}, "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-b2df08f3581898be", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/impersonation-banner.tsx:26", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/impersonation-banner.tsx:26"}, "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-9df7c905e65a430e", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/schedule/schedule-repair-panel.tsx:199", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/schedule/schedule-repair-panel.tsx:199"}, "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-cfecb4fab596c8f9", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/help/help-article-renderer.tsx:186", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/help/help-article-renderer.tsx:186"}, "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-b2d309bf3d6804aa", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/ai/ai-placeholder-card.tsx:25", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/ai/ai-placeholder-card.tsx:25"}, "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-883dc6f28fb61045", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/ui/page-ui.tsx:49", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/ui/page-ui.tsx: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-2eb68ed37014dbc3", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/onboarding-checklist.tsx:130", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/onboarding-checklist.tsx:130"}, "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-1205ea443726ca57", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/vice-principal-", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/vice-principal-welcome.tsx:53"}, "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-23f9cff9322cb4ae", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/parent-welcome.", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/parent-welcome.tsx: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-7bd21cdca8334c39", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/student-welcome", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/student-welcome.tsx: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-1b8a18d116a864ef", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/director-welcom", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/director-welcome.tsx:54"}, "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-d9c30b03eea3664e", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/teacher-welcome", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/teacher-welcome.tsx:53"}, "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-a2122332647e1bf3", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/branch-admin-we", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/branch-admin-welcome.tsx: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-aa41092e79c53b70", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/students/parent-link-modal.tsx:162", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/students/parent-link-modal.tsx:162"}, "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-e2fcc8ea7d01a051", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/finance/treasury-panel.tsx:188", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/finance/treasury-panel.tsx:188"}, "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-0bb895225db3ad2e", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/setup-wizard/steps/step-generate.tsx:1", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/setup-wizard/steps/step-generate.tsx:171"}, "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-514c33af441fa4bb", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/setup-wizard/steps/step-teaching-loads", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/setup-wizard/steps/step-teaching-loads.tsx:186"}, "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-b8d6cc3cf7f20125", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/right-panel.tsx:112", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/right-panel.tsx:112"}, "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-a924d4104899f3d9", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/activity-stream.tsx", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/activity-stream.tsx:235"}, "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-385dfbad94b29486", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/branch-health-map.t", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/branch-health-map.tsx:133"}, "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-84b5ec43faf670f6", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/intelligence-feed.t", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/intelligence-feed.tsx:286"}, "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-a42dc36c3beea6d5", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/entity-panel.tsx:134", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/entity-panel.tsx:134"}, "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-1a881b78d83be9d6", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/command-palette.tsx:2", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/command-palette.tsx:266"}, "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-be6cc9a32076709c", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/workspace-shell.tsx:1", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/workspace-shell.tsx:107"}, "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-14e848c2018af572", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/workspace-helpers.tsx", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/workspace-helpers.tsx:82"}, "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-2c9e848859d68783", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/display/[schoolSlug]/page.tsx:99", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/display/[schoolSlug]/page.tsx:99"}, "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-8915dce241990674", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx:343", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx:343"}, "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-c2c9915df7e23dd1", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/we", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/weekly-grid.tsx:112"}, "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-db391cd9f1a541a9", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/sc", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/schedule-workspace.tsx:1161"}, "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-041818ae4184b029", "name": "\"active\" state uses light bg in a dark theme \u2014 apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/schedule", "shortDescription": {"text": "\"active\" state uses light bg in a dark theme \u2014 apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/schedule-workspace.tsx:317"}, "fullDescription": {"text": "A ternary like `active ? 'bg-white' : '...'` (or bg-gray-100/200) on a dark theme produces jarring white pills. Use a dark-emphasized active state instead \u2014 border + ring or slightly brighter dark bg. Example: `active ? 'bg-gray-800 border-gray-500 ring-1 ring-blue-500/30' : '\u2026'`.\n\nWhy: P-E in CHECKLIST.md \u2014 light bg in a dark theme is a class of regression.\nRule id: fq.active-light-bg"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9d31eeab106a2be8", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/student/page.tsx:340", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/student/page.tsx:340"}, "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-0f73ec12e0661488", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/student/shop/page.tsx:1", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/student/shop/page.tsx:190"}, "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-f9ffa04b6ad985c3", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/coins/page.tsx:90", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/coins/page.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-14b4e55c2eb101dc", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/users/page.tsx:488", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/users/page.tsx:488"}, "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-e075487409c63deb", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/users/link-parent/page.", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/users/link-parent/page.tsx:393"}, "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-7a7968df871f727a", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/meetings/page.tsx:242", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/meetings/page.tsx:242"}, "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-4548b28800a3b280", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/teacher-substitutions/_", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/teacher-substitutions/_components/teacher-substitutions-workspace.tsx:275"}, "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-797bae9829c07dbb", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/exams/[id]/page.tsx:129", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/exams/[id]/page.tsx:1292"}, "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-9ae4d4b1d55c4778", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/exams/_components/exams", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/exams/_components/exams-workspace.tsx:817"}, "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-a646c13c3c1dc417", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/parent/page.tsx:995", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/parent/page.tsx:995"}, "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-867526ce646f6680", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/export-center/_componen", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/export-center/_components/export-job-detail.tsx:152"}, "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-5517100ea6eeba98", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/staff/_components/staff", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/staff/_components/staff-workspace.tsx:230"}, "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-575656e6b543902a", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/fee-structures/page.tsx", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/fee-structures/page.tsx:392"}, "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-965472e57e899ca4", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/audit-log/page.tsx:106", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/audit-log/page.tsx:106"}, "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-711ba40f4d325860", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/leave-requests/_compone", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/leave-requests/_components/leave-requests-workspace.tsx:459"}, "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-8e8a6b78e2eecf08", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/grades/page.tsx:885", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/grades/page.tsx:885"}, "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-ae5e8ed854795dcd", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/insights/page.tsx:224", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/insights/page.tsx:224"}, "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-dd4c98f70f973512", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/insights/calibration/pa", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/insights/calibration/page.tsx:115"}, "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-ae5667944ec094c0", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/students/[id]/page.tsx:", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/students/[id]/page.tsx:445"}, "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-716953c541048ae4", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/students/_components/st", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/students/_components/students-workspace.tsx:184"}, "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-e1c5fa4b59a3526a", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/homework/page.tsx:709", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/homework/page.tsx:709"}, "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-3aa86843933f7f54", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/finance/page.tsx:106", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/finance/page.tsx:106"}, "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-4c6bdd81c08b9d93", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/classes/[id]/page.tsx:2", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/classes/[id]/page.tsx:271"}, "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-d8999e97484a8bce", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/classes/_components/cla", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/classes/_components/classes-workspace.tsx:381"}, "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-888c68797ff48408", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/kpi/page.tsx:152", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/kpi/page.tsx:152"}, "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-3132c2dac010fd7e", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/kpi/metrics/[id]/page.t", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/kpi/metrics/[id]/page.tsx:357"}, "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-d12fc686d6ecb81d", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/payroll/page.tsx:758", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/payroll/page.tsx:758"}, "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-97a6babb24c13b81", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/discipline/_components/", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/discipline/_components/discipline-workspace.tsx:306"}, "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-5d1185774c756b03", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/alerts/page.tsx:581", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/alerts/page.tsx:581"}, "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-7494b56925ff7c33", "name": "\"active\" state uses light bg in a dark theme \u2014 apps/frontend/src/app/(dashboard)/dashboard/alerts/page.tsx:504", "shortDescription": {"text": "\"active\" state uses light bg in a dark theme \u2014 apps/frontend/src/app/(dashboard)/dashboard/alerts/page.tsx:504"}, "fullDescription": {"text": "A ternary like `active ? 'bg-white' : '...'` (or bg-gray-100/200) on a dark theme produces jarring white pills. Use a dark-emphasized active state instead \u2014 border + ring or slightly brighter dark bg. Example: `active ? 'bg-gray-800 border-gray-500 ring-1 ring-blue-500/30' : '\u2026'`.\n\nWhy: P-E in CHECKLIST.md \u2014 light bg in a dark theme is a class of regression.\nRule id: fq.active-light-bg"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a3333272e62979d4", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/subjects/_components/su", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/subjects/_components/subjects-workspace.tsx:481"}, "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-7b8d1409d386b389", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/attendance/bulk/page.ts", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/attendance/bulk/page.tsx:188"}, "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-57946de4966510c6", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/attendance/_components/", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/attendance/_components/attendance-workspace.tsx:506"}, "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-8189b523e1896346", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/approvals/page.tsx:448", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/approvals/page.tsx:448"}, "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-4397a299816f6cbd", "name": "\"active\" state uses light bg in a dark theme \u2014 apps/frontend/src/app/(dashboard)/dashboard/approvals/page.tsx:383", "shortDescription": {"text": "\"active\" state uses light bg in a dark theme \u2014 apps/frontend/src/app/(dashboard)/dashboard/approvals/page.tsx:383"}, "fullDescription": {"text": "A ternary like `active ? 'bg-white' : '...'` (or bg-gray-100/200) on a dark theme produces jarring white pills. Use a dark-emphasized active state instead \u2014 border + ring or slightly brighter dark bg. Example: `active ? 'bg-gray-800 border-gray-500 ring-1 ring-blue-500/30' : '\u2026'`.\n\nWhy: P-E in CHECKLIST.md \u2014 light bg in a dark theme is a class of regression.\nRule id: fq.active-light-bg"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-74850c5e623aa240", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/messages/page.tsx:493", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/messages/page.tsx:493"}, "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-9db9451398e417f1", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/payments/_components/pa", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/payments/_components/payments-workspace.tsx:325"}, "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-3810316eb400ca5e", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/demo-requests/_componen", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/demo-requests/_components/demo-requests-panel.tsx:133"}, "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-c0cf36866250e3e3", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/crm/page.tsx:118", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/crm/page.tsx:118"}, "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-a4e9f786ee58cc06", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/my-class/page.tsx:410", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/my-class/page.tsx:410"}, "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-583ed57fc5887560", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/branches/page.tsx:416", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/branches/page.tsx:416"}, "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-c1c91f172d970c63", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/reports/_components/rep", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/reports/_components/reports-workspace.tsx:116"}, "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-1668f4fb49db57ae", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/clubs/page.tsx:351", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/clubs/page.tsx:351"}, "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-5975db44e8d3f66a", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/setup/page.tsx:377", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/setup/page.tsx:377"}, "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-6708a0783f70972e", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/academic-calendar/page.", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/academic-calendar/page.tsx:227"}, "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-7622c86fdf2bdcf2", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/branch-admi", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/branch-admin-dashboard.tsx:178"}, "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-f0d50e5a0d370292", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/director-da", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/director-dashboard.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-9076432984994a49", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/shared-widg", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/shared-widgets.tsx:241"}, "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-495c66b183406c55", "name": "Stray `console.log` in TS/JS \u2014 apps/frontend/src/hooks/use-socket.ts:68", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/frontend/src/hooks/use-socket.ts:68"}, "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-f41853b0c2188535", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/backfill-main-campus.ts:15", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/backfill-main-campus.ts:15"}, "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-694db5c063a5095a", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/audit-permissions.ts:162", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/audit-permissions.ts:162"}, "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-d0e4f4be0d56660a", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/validate-demo.ts:55", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/validate-demo.ts:55"}, "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-8b96e77a66e879ff", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/recover-access.ts:32", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/recover-access.ts:32"}, "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-bd6b4c537035be25", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/normalize-emails.ts:30", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/normalize-emails.ts:30"}, "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-287e672b3fd1e097", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/audit-routes.ts:76", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/audit-routes.ts:76"}, "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-89dfbc7f84bd35a9", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed-risk-test.ts:194", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed-risk-test.ts:194"}, "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-d10f811bbde3140b", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed.ts:19", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed.ts:19"}, "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-a49ae4f4790fb23e", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed-specific-users.ts:12", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed-specific-users.ts:12"}, "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-3dee18695270209e", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed-demo.ts:108", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed-demo.ts:108"}, "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-64f78d8cff8447ea", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/src/modules/schedule/advanced-solver.service.spec.ts:532", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/src/modules/schedule/advanced-solver.service.spec.ts:532"}, "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-00af1a079b79526a", "name": "Stray `console.log` in TS/JS \u2014 apps/backend/src/modules/schedule/schedule.service.benchmark.spec.ts:235", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/src/modules/schedule/schedule.service.benchmark.spec.ts:235"}, "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-fdc161a19b8970a4", "name": "TODO/FIXME marker in shipping code \u2014 apps/backend/src/modules/ai/provider/openai.provider.ts:8", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 apps/backend/src/modules/ai/provider/openai.provider.ts:8"}, "fullDescription": {"text": "Track in /reviews or /issues, not as a code comment that rots.\n\nWhy: Drift control \u2014 shouldn't be the same as Quality TODO scanner.\nRule id: fq.todo-marker"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-9360e50090e9efda", "name": "TODO/FIXME marker in shipping code \u2014 apps/backend/src/modules/payments/payments.service.ts:596", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 apps/backend/src/modules/payments/payments.service.ts:596"}, "fullDescription": {"text": "Track in /reviews or /issues, not as a code comment that rots.\n\nWhy: Drift control \u2014 shouldn't be the same as Quality TODO scanner.\nRule id: fq.todo-marker"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e607cc7999825e99", "name": "Stray `console.log` in TS/JS \u2014 scripts/audit-branch-admin-escalation.js:22", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/audit-branch-admin-escalation.js:22"}, "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-23a7b68e0c8e0239", "name": "Stray `console.log` in TS/JS \u2014 scripts/cleanup-class-branchid.ts:25", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/cleanup-class-branchid.ts:25"}, "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-2fc45f4330be1076", "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-9b93146e8746d43a", "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-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-6fa20478a49b34e3", "name": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx", "shortDescription": {"text": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx"}, "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-401e774a559a5b7c", "name": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/classes/[id]/page.tsx", "shortDescription": {"text": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/classes/[id]/page.tsx"}, "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-afd2bff3676776e4", "name": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/profile/page.tsx", "shortDescription": {"text": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/profile/page.tsx"}, "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-b29ad09bdb2a5961", "name": "Possible secret in apps/frontend/src/app/(auth)/reset-password/page.tsx", "shortDescription": {"text": "Possible secret in apps/frontend/src/app/(auth)/reset-password/page.tsx"}, "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-2ab341707a2c6f8e", "name": "Possible secret in apps/frontend/src/app/(auth)/first-login/page.tsx", "shortDescription": {"text": "Possible secret in apps/frontend/src/app/(auth)/first-login/page.tsx"}, "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-4455c503fa90662a", "name": "Possible secret in apps/frontend/src/app/(auth)/accept-invite/page.tsx", "shortDescription": {"text": "Possible secret in apps/frontend/src/app/(auth)/accept-invite/page.tsx"}, "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-de1dcdfe3d11cd2a", "name": "Insecure pattern 'document_write' in apps/frontend/src/hooks/use-print.ts:96", "shortDescription": {"text": "Insecure pattern 'document_write' in apps/frontend/src/hooks/use-print.ts:96"}, "fullDescription": {"text": "Found a known-risky pattern (document_write). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "low", "confidence": 1.0}}, {"id": "scanner-36cbb13749c81331", "name": "Possible secret in apps/backend/prisma/seed.ts", "shortDescription": {"text": "Possible secret in apps/backend/prisma/seed.ts"}, "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-371ebb2123bc494b", "name": "Possible secret in apps/backend/prisma/seed-specific-users.ts", "shortDescription": {"text": "Possible secret in apps/backend/prisma/seed-specific-users.ts"}, "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-6c7f4a639e5df36a", "name": "Possible secret in apps/backend/prisma/seed-demo.ts", "shortDescription": {"text": "Possible secret in apps/backend/prisma/seed-demo.ts"}, "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-79d38226e5691ff3", "name": "Possible secret in apps/backend/src/modules/users/users.service.spec.ts", "shortDescription": {"text": "Possible secret in apps/backend/src/modules/users/users.service.spec.ts"}, "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-96ebf8f05c45f5ec", "name": "Possible secret in apps/backend/src/modules/users/users.controller.spec.ts", "shortDescription": {"text": "Possible secret in apps/backend/src/modules/users/users.controller.spec.ts"}, "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-e816c1a1f8b6e36a", "name": "Possible secret in apps/backend/src/modules/auth/auth.service.spec.ts", "shortDescription": {"text": "Possible secret in apps/backend/src/modules/auth/auth.service.spec.ts"}, "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-e57dd4ed85e1c25d", "name": "Possible secret in apps/backend/src/modules/students/students.service.spec.ts", "shortDescription": {"text": "Possible secret in apps/backend/src/modules/students/students.service.spec.ts"}, "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-9a27c00720c85853", "name": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/schedule-workspace.tsx (1362 lines)", "shortDescription": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/schedule-workspace.tsx (1362 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-1dcec2547271f034", "name": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/users/page.tsx (1241 lines)", "shortDescription": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/users/page.tsx (1241 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-132e9164b3be57fe", "name": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/exams/[id]/page.tsx (1378 lines)", "shortDescription": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/exams/[id]/page.tsx (1378 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-24af8fac4b8f6184", "name": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/exams/_components/exams-workspace.tsx (1570 lines)", "shortDescription": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/exams/_components/exams-workspace.tsx (1570 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-a1f24533117631b8", "name": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/parent/page.tsx (1091 lines)", "shortDescription": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/parent/page.tsx (1091 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-67a433aa74b3cd17", "name": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/grades/page.tsx (1219 lines)", "shortDescription": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/grades/page.tsx (1219 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-b7c711efb77cead3", "name": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/payroll/page.tsx (1747 lines)", "shortDescription": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/payroll/page.tsx (1747 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-e9dadca4ab56b9b7", "name": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/crm/page.tsx (1670 lines)", "shortDescription": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/crm/page.tsx (1670 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-a5f975d32977be71", "name": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/reports/_components/reports-workspace.tsx (1300 lines)", "shortDescription": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/reports/_components/reports-workspace.tsx (1300 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-3bc2f37ae78c225b", "name": "Very large file: apps/backend/src/modules/payroll/payroll.service.ts (1409 lines)", "shortDescription": {"text": "Very large file: apps/backend/src/modules/payroll/payroll.service.ts (1409 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": "15 test file(s) for 731 source file(s) (ratio 0.02). 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-3f02143ce17b7bf9", "name": "Node manifest has dependencies but no lockfile: apps/frontend/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: apps/frontend/package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-53a7af2536f80bd8", "name": "Node manifest has dependencies but no lockfile: apps/backend/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: apps/backend/package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cb3e52667c84fb86", "name": "Node manifest has dependencies but no lockfile: packages/types/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: packages/types/package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "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 175 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 358 placeholder/mock markers across 84 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-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, lockfile. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license, lockfile. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-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-d541d3e5ae110df5", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/frontend/src/app/(dashboard)/dashboard/system-health/page.tsx:124", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/frontend/src/app/(dashboard)/dashboard/system-health/page.tsx:124"}, "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-a1444816c80bc345", "name": "Legacy-named symbol `daysOld` in apps/frontend/src/app/(dashboard)/dashboard/alerts/page.tsx:140", "shortDescription": {"text": "Legacy-named symbol `daysOld` in apps/frontend/src/app/(dashboard)/dashboard/alerts/page.tsx:140"}, "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-0d16d50f11e911a9", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/shared-widgets.tsx", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/shared-widgets.tsx:806"}, "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-c6f925489bed0737", "name": "Commented-code block (6 lines) in apps/frontend/src/app/(auth)/first-login/page.tsx:18", "shortDescription": {"text": "Commented-code block (6 lines) in apps/frontend/src/app/(auth)/first-login/page.tsx:18"}, "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-854903cd46c796b6", "name": "Commented-code block (7 lines) in apps/backend/prisma/seed-risk-test.ts:204", "shortDescription": {"text": "Commented-code block (7 lines) in apps/backend/prisma/seed-risk-test.ts:204"}, "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-6f80d9f1604a9bf9", "name": "Commented-code block (5 lines) in apps/backend/src/modules/leads/leads.service.ts:362", "shortDescription": {"text": "Commented-code block (5 lines) in apps/backend/src/modules/leads/leads.service.ts:362"}, "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-04d68fc75dfc3f5e", "name": "Commented-code block (9 lines) in apps/backend/src/modules/import/import.service.ts:217", "shortDescription": {"text": "Commented-code block (9 lines) in apps/backend/src/modules/import/import.service.ts:217"}, "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-8958210de209898b", "name": "Commented-code block (6 lines) in apps/backend/src/modules/payments/payments.service.ts:592", "shortDescription": {"text": "Commented-code block (6 lines) in apps/backend/src/modules/payments/payments.service.ts:592"}, "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-d1a26d5df86ba873", "name": "Commented-code block (5 lines) in apps/backend/src/modules/super-admin/super-admin.service.ts:335", "shortDescription": {"text": "Commented-code block (5 lines) in apps/backend/src/modules/super-admin/super-admin.service.ts:335"}, "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-319e66a630e14977", "name": "2 env vars used in code but missing from .env.example", "shortDescription": {"text": "2 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `TEST_EMAIL`, `TEST_PASSWORD`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-40f503e51fc9f4b4", "name": "Unused endpoint: GET /super-admin/stats", "shortDescription": {"text": "Unused endpoint: GET /super-admin/stats"}, "fullDescription": {"text": "`apps/frontend/src/app/(dashboard)/dashboard/system-health/page.tsx` declares `GET /super-admin/stats` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7f31228dddd0186f", "name": "Unused endpoint: GET /notifications/queue-stats", "shortDescription": {"text": "Unused endpoint: GET /notifications/queue-stats"}, "fullDescription": {"text": "`apps/frontend/src/app/(dashboard)/dashboard/system-health/page.tsx` declares `GET /notifications/queue-stats` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5b72a3b090f06a9a", "name": "Unused endpoint: DELETE /notifications/queue-failed", "shortDescription": {"text": "Unused endpoint: DELETE /notifications/queue-failed"}, "fullDescription": {"text": "`apps/frontend/src/app/(dashboard)/dashboard/system-health/page.tsx` declares `DELETE /notifications/queue-failed` 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-fad44267fd33eb41", "name": "Unused endpoint: POST /upload/document", "shortDescription": {"text": "Unused endpoint: POST /upload/document"}, "fullDescription": {"text": "`apps/frontend/src/app/(dashboard)/dashboard/homework/page.tsx` declares `POST /upload/document` 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-686b777e7e236fa3", "name": "Unused endpoint: GET /library/stats", "shortDescription": {"text": "Unused endpoint: GET /library/stats"}, "fullDescription": {"text": "`apps/frontend/src/app/(dashboard)/dashboard/_components/librarian-dashboard.tsx` declares `GET /library/stats` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-58000dd1677359e6", "name": "Unused endpoint: GET /library/loans", "shortDescription": {"text": "Unused endpoint: GET /library/loans"}, "fullDescription": {"text": "`apps/frontend/src/app/(dashboard)/dashboard/_components/librarian-dashboard.tsx` declares `GET /library/loans` 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-c059f57186114027", "name": "Unused endpoint: POST /auth/logout", "shortDescription": {"text": "Unused endpoint: POST /auth/logout"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/auth.ts` declares `POST /auth/logout` 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-e2fe5b92648ca462", "name": "Unused endpoint: POST /auth/forgot-password", "shortDescription": {"text": "Unused endpoint: POST /auth/forgot-password"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/auth.ts` declares `POST /auth/forgot-password` 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-deb8df763a50c73a", "name": "Unused endpoint: POST /auth/reset-password", "shortDescription": {"text": "Unused endpoint: POST /auth/reset-password"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/auth.ts` declares `POST /auth/reset-password` 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-e1ceb256e9656751", "name": "Unused endpoint: GET /fee-structures", "shortDescription": {"text": "Unused endpoint: GET /fee-structures"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/fee-structures.ts` declares `GET /fee-structures` 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-7f639a8df9c90de8", "name": "Unused endpoint: POST /fee-structures", "shortDescription": {"text": "Unused endpoint: POST /fee-structures"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/fee-structures.ts` declares `POST /fee-structures` 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-988356d1631079b2", "name": "Unused endpoint: GET /teaching-loads", "shortDescription": {"text": "Unused endpoint: GET /teaching-loads"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/teaching-load.ts` declares `GET /teaching-loads` 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-f1bc81afb6632a67", "name": "Unused endpoint: POST /teaching-loads", "shortDescription": {"text": "Unused endpoint: POST /teaching-loads"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/teaching-load.ts` declares `POST /teaching-loads` 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-cdbcda95e98c0e78", "name": "Unused endpoint: POST /teaching-loads/import/preview", "shortDescription": {"text": "Unused endpoint: POST /teaching-loads/import/preview"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/teaching-load.ts` declares `POST /teaching-loads/import/preview` 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-89d5c1a64eecb42e", "name": "Unused endpoint: POST /teaching-loads/import/commit", "shortDescription": {"text": "Unused endpoint: POST /teaching-loads/import/commit"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/teaching-load.ts` declares `POST /teaching-loads/import/commit` 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-c9163dc1f64fcaed", "name": "Unused endpoint: GET /teaching-loads/workload/summary", "shortDescription": {"text": "Unused endpoint: GET /teaching-loads/workload/summary"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/teaching-load.ts` declares `GET /teaching-loads/workload/summary` 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-0cef062647605739", "name": "Unused endpoint: GET /teaching-loads/workload/teachers", "shortDescription": {"text": "Unused endpoint: GET /teaching-loads/workload/teachers"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/teaching-load.ts` declares `GET /teaching-loads/workload/teachers` 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-2883ad056dbafd27", "name": "Unused endpoint: GET /reports/analytics/pulse", "shortDescription": {"text": "Unused endpoint: GET /reports/analytics/pulse"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/analytics.ts` declares `GET /reports/analytics/pulse` 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-ef190451c695da48", "name": "Unused endpoint: GET /reports/analytics/finance", "shortDescription": {"text": "Unused endpoint: GET /reports/analytics/finance"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/analytics.ts` declares `GET /reports/analytics/finance` 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-c459e09dbe8a6b5d", "name": "Unused endpoint: GET /reports/analytics/branch-comparison", "shortDescription": {"text": "Unused endpoint: GET /reports/analytics/branch-comparison"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/analytics.ts` declares `GET /reports/analytics/branch-comparison` 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-cf5e93311e93fe1f", "name": "Unused endpoint: GET /reports/analytics/marketing-roi", "shortDescription": {"text": "Unused endpoint: GET /reports/analytics/marketing-roi"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/analytics.ts` declares `GET /reports/analytics/marketing-roi` 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-44e47e0ee86d27d1", "name": "Unused endpoint: GET /reports/analytics/alerts", "shortDescription": {"text": "Unused endpoint: GET /reports/analytics/alerts"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/analytics.ts` declares `GET /reports/analytics/alerts` 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-9c4a1b7533f1c9a8", "name": "Unused endpoint: GET /reports/export/excel", "shortDescription": {"text": "Unused endpoint: GET /reports/export/excel"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/analytics.ts` declares `GET /reports/export/excel` 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-1bca8100a44f7f25", "name": "Unused endpoint: POST /users", "shortDescription": {"text": "Unused endpoint: POST /users"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/users.ts` declares `POST /users` 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-984cc1c6d33f9dd2", "name": "Unused endpoint: PUT /users/me/password", "shortDescription": {"text": "Unused endpoint: PUT /users/me/password"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/users.ts` declares `PUT /users/me/password` 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-60bc5c330890659a", "name": "Unused endpoint: PUT /users/me/avatar", "shortDescription": {"text": "Unused endpoint: PUT /users/me/avatar"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/users.ts` declares `PUT /users/me/avatar` 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-eab66eb495182352", "name": "Unused endpoint: POST /users/import/csv", "shortDescription": {"text": "Unused endpoint: POST /users/import/csv"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/users.ts` declares `POST /users/import/csv` 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-0bcaf69bd2ba9d81", "name": "Unused endpoint: GET /users/check-email", "shortDescription": {"text": "Unused endpoint: GET /users/check-email"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/users.ts` declares `GET /users/check-email` 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-a6f226130b2c66e7", "name": "Unused endpoint: GET /invitations", "shortDescription": {"text": "Unused endpoint: GET /invitations"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/invitations.ts` declares `GET /invitations` 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-246ef886fef7811e", "name": "Unused endpoint: GET /discipline", "shortDescription": {"text": "Unused endpoint: GET /discipline"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/discipline.ts` declares `GET /discipline` 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-5ced322e159b28a0", "name": "Unused endpoint: POST /discipline", "shortDescription": {"text": "Unused endpoint: POST /discipline"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/discipline.ts` declares `POST /discipline` 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-0c5f096bdc9451a1", "name": "Unused endpoint: GET /discipline/stats", "shortDescription": {"text": "Unused endpoint: GET /discipline/stats"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/discipline.ts` declares `GET /discipline/stats` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-27e1326288dcbfb2", "name": "Unused endpoint: POST /import/students/parse", "shortDescription": {"text": "Unused endpoint: POST /import/students/parse"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/import.ts` declares `POST /import/students/parse` 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-63b8c95a23e9b752", "name": "Unused endpoint: POST /import/users/parse", "shortDescription": {"text": "Unused endpoint: POST /import/users/parse"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/import.ts` declares `POST /import/users/parse` 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-ab632b2266155f89", "name": "Unused endpoint: POST /import/schedule/parse", "shortDescription": {"text": "Unused endpoint: POST /import/schedule/parse"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/import.ts` declares `POST /import/schedule/parse` 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-945774972da6105a", "name": "Unused endpoint: POST /import/grades/parse", "shortDescription": {"text": "Unused endpoint: POST /import/grades/parse"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/import.ts` declares `POST /import/grades/parse` 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-e650eb5c299e753f", "name": "Unused endpoint: POST /import/attendance/parse", "shortDescription": {"text": "Unused endpoint: POST /import/attendance/parse"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/import.ts` declares `POST /import/attendance/parse` 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-326de6a461d3556a", "name": "Unused endpoint: POST /import/students/commit", "shortDescription": {"text": "Unused endpoint: POST /import/students/commit"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/import.ts` declares `POST /import/students/commit` 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-a1cb92ecf008fd2f", "name": "Unused endpoint: POST /import/users/commit", "shortDescription": {"text": "Unused endpoint: POST /import/users/commit"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/import.ts` declares `POST /import/users/commit` 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-07a0d90efb786baf", "name": "Unused endpoint: POST /import/schedule/commit", "shortDescription": {"text": "Unused endpoint: POST /import/schedule/commit"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/import.ts` declares `POST /import/schedule/commit` 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-7db8577ec9c402c5", "name": "Unused endpoint: POST /import/grades/commit", "shortDescription": {"text": "Unused endpoint: POST /import/grades/commit"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/import.ts` declares `POST /import/grades/commit` 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-2f4d00a371c781c8", "name": "Unused endpoint: POST /import/attendance/commit", "shortDescription": {"text": "Unused endpoint: POST /import/attendance/commit"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/import.ts` declares `POST /import/attendance/commit` 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-f29aade19ceaa61c", "name": "Unused endpoint: POST /leave-requests", "shortDescription": {"text": "Unused endpoint: POST /leave-requests"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/leave-requests.ts` declares `POST /leave-requests` 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-0701294795ef9045", "name": "Unused endpoint: GET /leave-requests", "shortDescription": {"text": "Unused endpoint: GET /leave-requests"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/leave-requests.ts` declares `GET /leave-requests` 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-3af64e805d88ef35", "name": "Unused endpoint: GET /notifications", "shortDescription": {"text": "Unused endpoint: GET /notifications"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/notifications.ts` declares `GET /notifications` 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-6a23aeabb1f0c4d3", "name": "Unused endpoint: PUT /notifications/read-all", "shortDescription": {"text": "Unused endpoint: PUT /notifications/read-all"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/notifications.ts` declares `PUT /notifications/read-all` 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-d15d3333c9f27817", "name": "Unused endpoint: POST /notifications", "shortDescription": {"text": "Unused endpoint: POST /notifications"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/notifications.ts` declares `POST /notifications` 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-8206e0572124202c", "name": "Unused endpoint: POST /notifications/broadcast", "shortDescription": {"text": "Unused endpoint: POST /notifications/broadcast"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/notifications.ts` declares `POST /notifications/broadcast` 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-999dff0ea581b4b8", "name": "Unused endpoint: GET /notifications/preferences", "shortDescription": {"text": "Unused endpoint: GET /notifications/preferences"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/notifications.ts` declares `GET /notifications/preferences` 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-067dcceb02ca4757", "name": "Unused endpoint: PATCH /notifications/preferences", "shortDescription": {"text": "Unused endpoint: PATCH /notifications/preferences"}, "fullDescription": {"text": "`apps/frontend/src/lib/api/notifications.ts` declares `PATCH /notifications/preferences` 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/23071"}, "properties": {"repository": "Xronuz/Xedu_managment", "repoUrl": "https://github.com/Xronuz/Xedu_managment", "branch": "main"}, "results": [{"ruleId": "scanner-51ce0e59d73cdfb7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/breadcrumb-nav.tsx:117"}, "properties": {"repobilityId": "0686bd87fc3c047c", "scanner": "scanner-primary", "fingerprint": "51ce0e59d73cdfb7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5b0bd2e879da9c7b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/profile-sheet.tsx:50"}, "properties": {"repobilityId": "c8ed206d7dda3a71", "scanner": "scanner-primary", "fingerprint": "5b0bd2e879da9c7b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9e76b176e7ef75da", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/sidebar.tsx:59"}, "properties": {"repobilityId": "c176bd14c6e148b8", "scanner": "scanner-primary", "fingerprint": "9e76b176e7ef75da", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2a2feec2857781d3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/branch-switcher.tsx:103"}, "properties": {"repobilityId": "e4745bf565ab013e", "scanner": "scanner-primary", "fingerprint": "2a2feec2857781d3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b2df08f3581898be", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/layout/impersonation-banner.tsx:26"}, "properties": {"repobilityId": "00da637583dba865", "scanner": "scanner-primary", "fingerprint": "b2df08f3581898be", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9df7c905e65a430e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/schedule/schedule-repair-panel.tsx:199"}, "properties": {"repobilityId": "f14107a0e9aaeeb8", "scanner": "scanner-primary", "fingerprint": "9df7c905e65a430e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cfecb4fab596c8f9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/help/help-article-renderer.tsx:186"}, "properties": {"repobilityId": "cc5a619fec4eb78f", "scanner": "scanner-primary", "fingerprint": "cfecb4fab596c8f9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b2d309bf3d6804aa", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/ai/ai-placeholder-card.tsx:25"}, "properties": {"repobilityId": "7b750849b50c0278", "scanner": "scanner-primary", "fingerprint": "b2d309bf3d6804aa", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-883dc6f28fb61045", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/ui/page-ui.tsx:49"}, "properties": {"repobilityId": "a5474f0bfc1ceb5b", "scanner": "scanner-primary", "fingerprint": "883dc6f28fb61045", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2eb68ed37014dbc3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/onboarding-checklist.tsx:130"}, "properties": {"repobilityId": "9fcd1f5900ec2fe4", "scanner": "scanner-primary", "fingerprint": "2eb68ed37014dbc3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1205ea443726ca57", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/vice-principal-welcome.tsx:53"}, "properties": {"repobilityId": "b3e8f94e29bf3688", "scanner": "scanner-primary", "fingerprint": "1205ea443726ca57", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-23f9cff9322cb4ae", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/parent-welcome.tsx:49"}, "properties": {"repobilityId": "c9b1ba6b089916d3", "scanner": "scanner-primary", "fingerprint": "23f9cff9322cb4ae", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7bd21cdca8334c39", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/student-welcome.tsx:49"}, "properties": {"repobilityId": "6f35f51808f02de4", "scanner": "scanner-primary", "fingerprint": "7bd21cdca8334c39", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1b8a18d116a864ef", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/director-welcome.tsx:54"}, "properties": {"repobilityId": "140b0f56b74546ab", "scanner": "scanner-primary", "fingerprint": "1b8a18d116a864ef", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d9c30b03eea3664e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/teacher-welcome.tsx:53"}, "properties": {"repobilityId": "2766f246be37b9dc", "scanner": "scanner-primary", "fingerprint": "d9c30b03eea3664e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a2122332647e1bf3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/dashboard/role-welcome/branch-admin-welcome.tsx:49"}, "properties": {"repobilityId": "4b2d8b8d86fed337", "scanner": "scanner-primary", "fingerprint": "a2122332647e1bf3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-aa41092e79c53b70", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/students/parent-link-modal.tsx:162"}, "properties": {"repobilityId": "cf19ce64fd208776", "scanner": "scanner-primary", "fingerprint": "aa41092e79c53b70", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e2fcc8ea7d01a051", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/finance/treasury-panel.tsx:188"}, "properties": {"repobilityId": "eefb46b790f96b43", "scanner": "scanner-primary", "fingerprint": "e2fcc8ea7d01a051", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0bb895225db3ad2e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/setup-wizard/steps/step-generate.tsx:171"}, "properties": {"repobilityId": "f44baee716fac3d2", "scanner": "scanner-primary", "fingerprint": "0bb895225db3ad2e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-514c33af441fa4bb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/setup-wizard/steps/step-teaching-loads.tsx:186"}, "properties": {"repobilityId": "e39df297d5ea96d5", "scanner": "scanner-primary", "fingerprint": "514c33af441fa4bb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b8d6cc3cf7f20125", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/right-panel.tsx:112"}, "properties": {"repobilityId": "b0827ec1e631e2a1", "scanner": "scanner-primary", "fingerprint": "b8d6cc3cf7f20125", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a924d4104899f3d9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/activity-stream.tsx:235"}, "properties": {"repobilityId": "daafe3d0510e4dd2", "scanner": "scanner-primary", "fingerprint": "a924d4104899f3d9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-385dfbad94b29486", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/branch-health-map.tsx:133"}, "properties": {"repobilityId": "bf063c5c24635d41", "scanner": "scanner-primary", "fingerprint": "385dfbad94b29486", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-84b5ec43faf670f6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/director-workspace/intelligence-feed.tsx:286"}, "properties": {"repobilityId": "7985f9698d363807", "scanner": "scanner-primary", "fingerprint": "84b5ec43faf670f6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a42dc36c3beea6d5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/entity-panel.tsx:134"}, "properties": {"repobilityId": "19d013cbad662ad5", "scanner": "scanner-primary", "fingerprint": "a42dc36c3beea6d5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1a881b78d83be9d6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/command-palette.tsx:266"}, "properties": {"repobilityId": "49eb1c889df0dc1a", "scanner": "scanner-primary", "fingerprint": "1a881b78d83be9d6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-be6cc9a32076709c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/workspace-shell.tsx:107"}, "properties": {"repobilityId": "c0e7133eaecd1b43", "scanner": "scanner-primary", "fingerprint": "be6cc9a32076709c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-14e848c2018af572", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/components/workspace-system/workspace-helpers.tsx:82"}, "properties": {"repobilityId": "5da3c709f7013548", "scanner": "scanner-primary", "fingerprint": "14e848c2018af572", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2c9e848859d68783", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/display/[schoolSlug]/page.tsx:99"}, "properties": {"repobilityId": "c35f9182aa7eac51", "scanner": "scanner-primary", "fingerprint": "2c9e848859d68783", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8915dce241990674", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx:343"}, "properties": {"repobilityId": "6cfe003d1063a708", "scanner": "scanner-primary", "fingerprint": "8915dce241990674", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c2c9915df7e23dd1", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/weekly-grid.tsx:112"}, "properties": {"repobilityId": "10ba7bcd705e8f47", "scanner": "scanner-primary", "fingerprint": "c2c9915df7e23dd1", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-db391cd9f1a541a9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/schedule-workspace.tsx:1161"}, "properties": {"repobilityId": "a22b08205b807da1", "scanner": "scanner-primary", "fingerprint": "db391cd9f1a541a9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-041818ae4184b029", "level": "note", "message": {"text": "\"active\" state uses light bg in a dark theme \u2014 apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/schedule-workspace.tsx:317"}, "properties": {"repobilityId": "f3551760e06c1377", "scanner": "scanner-primary", "fingerprint": "041818ae4184b029", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.active-light-bg"]}}, {"ruleId": "scanner-9d31eeab106a2be8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/student/page.tsx:340"}, "properties": {"repobilityId": "ac8db48eb6ccec05", "scanner": "scanner-primary", "fingerprint": "9d31eeab106a2be8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0f73ec12e0661488", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/student/shop/page.tsx:190"}, "properties": {"repobilityId": "89a0dbdc76b78e88", "scanner": "scanner-primary", "fingerprint": "0f73ec12e0661488", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f9ffa04b6ad985c3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/coins/page.tsx:90"}, "properties": {"repobilityId": "90deeb53970bafde", "scanner": "scanner-primary", "fingerprint": "f9ffa04b6ad985c3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-14b4e55c2eb101dc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/users/page.tsx:488"}, "properties": {"repobilityId": "264441268a01892f", "scanner": "scanner-primary", "fingerprint": "14b4e55c2eb101dc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e075487409c63deb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/users/link-parent/page.tsx:393"}, "properties": {"repobilityId": "a39a0a70d38d3c1c", "scanner": "scanner-primary", "fingerprint": "e075487409c63deb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7a7968df871f727a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/meetings/page.tsx:242"}, "properties": {"repobilityId": "4fce6e51c57bc4de", "scanner": "scanner-primary", "fingerprint": "7a7968df871f727a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4548b28800a3b280", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/teacher-substitutions/_components/teacher-substitutions-workspace.tsx:275"}, "properties": {"repobilityId": "37731a08ea232dbb", "scanner": "scanner-primary", "fingerprint": "4548b28800a3b280", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-797bae9829c07dbb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/exams/[id]/page.tsx:1292"}, "properties": {"repobilityId": "911655e768610008", "scanner": "scanner-primary", "fingerprint": "797bae9829c07dbb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9ae4d4b1d55c4778", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/exams/_components/exams-workspace.tsx:817"}, "properties": {"repobilityId": "7b6faa8a237384ea", "scanner": "scanner-primary", "fingerprint": "9ae4d4b1d55c4778", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a646c13c3c1dc417", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/parent/page.tsx:995"}, "properties": {"repobilityId": "5b553aa8d5a27c8d", "scanner": "scanner-primary", "fingerprint": "a646c13c3c1dc417", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-867526ce646f6680", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/export-center/_components/export-job-detail.tsx:152"}, "properties": {"repobilityId": "93535f79fd9a9ed2", "scanner": "scanner-primary", "fingerprint": "867526ce646f6680", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5517100ea6eeba98", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/staff/_components/staff-workspace.tsx:230"}, "properties": {"repobilityId": "157ce19077ced88a", "scanner": "scanner-primary", "fingerprint": "5517100ea6eeba98", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-575656e6b543902a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/fee-structures/page.tsx:392"}, "properties": {"repobilityId": "f27d06bc5f129df3", "scanner": "scanner-primary", "fingerprint": "575656e6b543902a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-965472e57e899ca4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/audit-log/page.tsx:106"}, "properties": {"repobilityId": "6583af407606b183", "scanner": "scanner-primary", "fingerprint": "965472e57e899ca4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-711ba40f4d325860", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/leave-requests/_components/leave-requests-workspace.tsx:459"}, "properties": {"repobilityId": "b98162c08fe7e4c8", "scanner": "scanner-primary", "fingerprint": "711ba40f4d325860", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8e8a6b78e2eecf08", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/grades/page.tsx:885"}, "properties": {"repobilityId": "5a6c1b3d9c5973c9", "scanner": "scanner-primary", "fingerprint": "8e8a6b78e2eecf08", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ae5e8ed854795dcd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/insights/page.tsx:224"}, "properties": {"repobilityId": "0d66f4bac88a7fee", "scanner": "scanner-primary", "fingerprint": "ae5e8ed854795dcd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-dd4c98f70f973512", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/insights/calibration/page.tsx:115"}, "properties": {"repobilityId": "83021e7e954f30a1", "scanner": "scanner-primary", "fingerprint": "dd4c98f70f973512", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ae5667944ec094c0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/students/[id]/page.tsx:445"}, "properties": {"repobilityId": "127e7cca5b3d1929", "scanner": "scanner-primary", "fingerprint": "ae5667944ec094c0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-716953c541048ae4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/students/_components/students-workspace.tsx:184"}, "properties": {"repobilityId": "c22447c16d78271d", "scanner": "scanner-primary", "fingerprint": "716953c541048ae4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e1c5fa4b59a3526a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/homework/page.tsx:709"}, "properties": {"repobilityId": "776db8a7a480d39c", "scanner": "scanner-primary", "fingerprint": "e1c5fa4b59a3526a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3aa86843933f7f54", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/finance/page.tsx:106"}, "properties": {"repobilityId": "dbdeaebe077b5d97", "scanner": "scanner-primary", "fingerprint": "3aa86843933f7f54", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4c6bdd81c08b9d93", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/classes/[id]/page.tsx:271"}, "properties": {"repobilityId": "32c4094acaa8410c", "scanner": "scanner-primary", "fingerprint": "4c6bdd81c08b9d93", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d8999e97484a8bce", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/classes/_components/classes-workspace.tsx:381"}, "properties": {"repobilityId": "8d4086bc5eb97b55", "scanner": "scanner-primary", "fingerprint": "d8999e97484a8bce", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-888c68797ff48408", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/kpi/page.tsx:152"}, "properties": {"repobilityId": "5d90eea213a78514", "scanner": "scanner-primary", "fingerprint": "888c68797ff48408", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3132c2dac010fd7e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/kpi/metrics/[id]/page.tsx:357"}, "properties": {"repobilityId": "1377fa4d30e64c37", "scanner": "scanner-primary", "fingerprint": "3132c2dac010fd7e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d12fc686d6ecb81d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/payroll/page.tsx:758"}, "properties": {"repobilityId": "de0ec2735215fe98", "scanner": "scanner-primary", "fingerprint": "d12fc686d6ecb81d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-97a6babb24c13b81", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/discipline/_components/discipline-workspace.tsx:306"}, "properties": {"repobilityId": "870795918d9fd604", "scanner": "scanner-primary", "fingerprint": "97a6babb24c13b81", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5d1185774c756b03", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/alerts/page.tsx:581"}, "properties": {"repobilityId": "4f8c9ef446b7c4b7", "scanner": "scanner-primary", "fingerprint": "5d1185774c756b03", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7494b56925ff7c33", "level": "note", "message": {"text": "\"active\" state uses light bg in a dark theme \u2014 apps/frontend/src/app/(dashboard)/dashboard/alerts/page.tsx:504"}, "properties": {"repobilityId": "5aaf2c442df8b026", "scanner": "scanner-primary", "fingerprint": "7494b56925ff7c33", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.active-light-bg"]}}, {"ruleId": "scanner-a3333272e62979d4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/subjects/_components/subjects-workspace.tsx:481"}, "properties": {"repobilityId": "76af172c09a8f037", "scanner": "scanner-primary", "fingerprint": "a3333272e62979d4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7b8d1409d386b389", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/attendance/bulk/page.tsx:188"}, "properties": {"repobilityId": "cd75706fe99fd535", "scanner": "scanner-primary", "fingerprint": "7b8d1409d386b389", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-57946de4966510c6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/attendance/_components/attendance-workspace.tsx:506"}, "properties": {"repobilityId": "d486a62b75447253", "scanner": "scanner-primary", "fingerprint": "57946de4966510c6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8189b523e1896346", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/approvals/page.tsx:448"}, "properties": {"repobilityId": "dbffcce7cbba3062", "scanner": "scanner-primary", "fingerprint": "8189b523e1896346", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4397a299816f6cbd", "level": "note", "message": {"text": "\"active\" state uses light bg in a dark theme \u2014 apps/frontend/src/app/(dashboard)/dashboard/approvals/page.tsx:383"}, "properties": {"repobilityId": "18000f92d4b40a90", "scanner": "scanner-primary", "fingerprint": "4397a299816f6cbd", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.active-light-bg"]}}, {"ruleId": "scanner-74850c5e623aa240", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/messages/page.tsx:493"}, "properties": {"repobilityId": "e173ba1cc5d473d3", "scanner": "scanner-primary", "fingerprint": "74850c5e623aa240", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9db9451398e417f1", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/payments/_components/payments-workspace.tsx:325"}, "properties": {"repobilityId": "1d42ed73079f3e79", "scanner": "scanner-primary", "fingerprint": "9db9451398e417f1", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3810316eb400ca5e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/demo-requests/_components/demo-requests-panel.tsx:133"}, "properties": {"repobilityId": "0618624d3059bfb7", "scanner": "scanner-primary", "fingerprint": "3810316eb400ca5e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c0cf36866250e3e3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/crm/page.tsx:118"}, "properties": {"repobilityId": "33981b6ac292e691", "scanner": "scanner-primary", "fingerprint": "c0cf36866250e3e3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a4e9f786ee58cc06", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/my-class/page.tsx:410"}, "properties": {"repobilityId": "7bd09a244904fec0", "scanner": "scanner-primary", "fingerprint": "a4e9f786ee58cc06", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-583ed57fc5887560", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/branches/page.tsx:416"}, "properties": {"repobilityId": "632ab414da1fe246", "scanner": "scanner-primary", "fingerprint": "583ed57fc5887560", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c1c91f172d970c63", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/reports/_components/reports-workspace.tsx:116"}, "properties": {"repobilityId": "2eb5d58142e024ea", "scanner": "scanner-primary", "fingerprint": "c1c91f172d970c63", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1668f4fb49db57ae", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/clubs/page.tsx:351"}, "properties": {"repobilityId": "d773ec4ba32df314", "scanner": "scanner-primary", "fingerprint": "1668f4fb49db57ae", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5975db44e8d3f66a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/setup/page.tsx:377"}, "properties": {"repobilityId": "654ebac957270a00", "scanner": "scanner-primary", "fingerprint": "5975db44e8d3f66a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6708a0783f70972e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/academic-calendar/page.tsx:227"}, "properties": {"repobilityId": "85e874625ea19b7c", "scanner": "scanner-primary", "fingerprint": "6708a0783f70972e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7622c86fdf2bdcf2", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/branch-admin-dashboard.tsx:178"}, "properties": {"repobilityId": "9779eecf5de18909", "scanner": "scanner-primary", "fingerprint": "7622c86fdf2bdcf2", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f0d50e5a0d370292", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/director-dashboard.tsx:305"}, "properties": {"repobilityId": "8e9bbeb35ca6c48d", "scanner": "scanner-primary", "fingerprint": "f0d50e5a0d370292", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9076432984994a49", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/shared-widgets.tsx:241"}, "properties": {"repobilityId": "41be31681159ea09", "scanner": "scanner-primary", "fingerprint": "9076432984994a49", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-495c66b183406c55", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/frontend/src/hooks/use-socket.ts:68"}, "properties": {"repobilityId": "f57012af559f52f3", "scanner": "scanner-primary", "fingerprint": "495c66b183406c55", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-f41853b0c2188535", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/backfill-main-campus.ts:15"}, "properties": {"repobilityId": "d2b9fa8e9953d69d", "scanner": "scanner-primary", "fingerprint": "f41853b0c2188535", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-694db5c063a5095a", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/audit-permissions.ts:162"}, "properties": {"repobilityId": "df2359d0ebe40a6a", "scanner": "scanner-primary", "fingerprint": "694db5c063a5095a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-d0e4f4be0d56660a", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/validate-demo.ts:55"}, "properties": {"repobilityId": "f3268c74d87697f3", "scanner": "scanner-primary", "fingerprint": "d0e4f4be0d56660a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-8b96e77a66e879ff", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/recover-access.ts:32"}, "properties": {"repobilityId": "1141638ebe19b960", "scanner": "scanner-primary", "fingerprint": "8b96e77a66e879ff", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-bd6b4c537035be25", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/normalize-emails.ts:30"}, "properties": {"repobilityId": "57f76d362bd6b829", "scanner": "scanner-primary", "fingerprint": "bd6b4c537035be25", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-287e672b3fd1e097", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/scripts/audit-routes.ts:76"}, "properties": {"repobilityId": "2f5ae1a9ed30395e", "scanner": "scanner-primary", "fingerprint": "287e672b3fd1e097", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-89dfbc7f84bd35a9", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed-risk-test.ts:194"}, "properties": {"repobilityId": "5d8466b649ba240f", "scanner": "scanner-primary", "fingerprint": "89dfbc7f84bd35a9", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-d10f811bbde3140b", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed.ts:19"}, "properties": {"repobilityId": "418f71b13c11ab60", "scanner": "scanner-primary", "fingerprint": "d10f811bbde3140b", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-a49ae4f4790fb23e", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed-specific-users.ts:12"}, "properties": {"repobilityId": "61823e08c96bf1aa", "scanner": "scanner-primary", "fingerprint": "a49ae4f4790fb23e", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-3dee18695270209e", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/prisma/seed-demo.ts:108"}, "properties": {"repobilityId": "0f0fd655ee1373dd", "scanner": "scanner-primary", "fingerprint": "3dee18695270209e", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-64f78d8cff8447ea", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/src/modules/schedule/advanced-solver.service.spec.ts:532"}, "properties": {"repobilityId": "00565e6b6bd2a0c8", "scanner": "scanner-primary", "fingerprint": "64f78d8cff8447ea", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-00af1a079b79526a", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/backend/src/modules/schedule/schedule.service.benchmark.spec.ts:235"}, "properties": {"repobilityId": "3f666bd9a35ea2eb", "scanner": "scanner-primary", "fingerprint": "00af1a079b79526a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-fdc161a19b8970a4", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 apps/backend/src/modules/ai/provider/openai.provider.ts:8"}, "properties": {"repobilityId": "dadf96ab3d8cd32e", "scanner": "scanner-primary", "fingerprint": "fdc161a19b8970a4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-9360e50090e9efda", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 apps/backend/src/modules/payments/payments.service.ts:596"}, "properties": {"repobilityId": "9d392c7b31a71fad", "scanner": "scanner-primary", "fingerprint": "9360e50090e9efda", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-e607cc7999825e99", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/audit-branch-admin-escalation.js:22"}, "properties": {"repobilityId": "22be063f5ffe56a4", "scanner": "scanner-primary", "fingerprint": "e607cc7999825e99", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-23a7b68e0c8e0239", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/cleanup-class-branchid.ts:25"}, "properties": {"repobilityId": "1679603ef00fef06", "scanner": "scanner-primary", "fingerprint": "23a7b68e0c8e0239", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-2fc45f4330be1076", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:20-alpine"}, "properties": {"repobilityId": "5aff9c127b537749", "scanner": "scanner-primary", "fingerprint": "2fc45f4330be1076", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/Dockerfile"}, "region": {"startLine": 2}}}]}, {"ruleId": "scanner-2fc45f4330be1076", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:20-alpine"}, "properties": {"repobilityId": "61507f7545adc94f", "scanner": "scanner-primary", "fingerprint": "2fc45f4330be1076", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/Dockerfile"}, "region": {"startLine": 43}}}]}, {"ruleId": "scanner-9b93146e8746d43a", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:20-alpine"}, "properties": {"repobilityId": "29bd8525a6a818c9", "scanner": "scanner-primary", "fingerprint": "9b93146e8746d43a", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/Dockerfile"}, "region": {"startLine": 2}}}]}, {"ruleId": "scanner-9b93146e8746d43a", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:20-alpine"}, "properties": {"repobilityId": "3d4245b653b4866c", "scanner": "scanner-primary", "fingerprint": "9b93146e8746d43a", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/Dockerfile"}, "region": {"startLine": 37}}}]}, {"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-6fa20478a49b34e3", "level": "error", "message": {"text": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx"}, "properties": {"repobilityId": "edafcc35d4e8a3bf", "scanner": "scanner-primary", "fingerprint": "6fa20478a49b34e3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx"}, "region": {"startLine": 262}}}]}, {"ruleId": "scanner-6fa20478a49b34e3", "level": "error", "message": {"text": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx"}, "properties": {"repobilityId": "edafcc35d4e8a3bf", "scanner": "scanner-primary", "fingerprint": "6fa20478a49b34e3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx"}, "region": {"startLine": 263}}}]}, {"ruleId": "scanner-6fa20478a49b34e3", "level": "error", "message": {"text": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx"}, "properties": {"repobilityId": "edafcc35d4e8a3bf", "scanner": "scanner-primary", "fingerprint": "6fa20478a49b34e3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/app/(dashboard)/dashboard/settings/page.tsx"}, "region": {"startLine": 264}}}]}, {"ruleId": "scanner-401e774a559a5b7c", "level": "error", "message": {"text": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/classes/[id]/page.tsx"}, "properties": {"repobilityId": "24c43323661ad2fc", "scanner": "scanner-primary", "fingerprint": "401e774a559a5b7c", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/app/(dashboard)/dashboard/classes/[id]/page.tsx"}, "region": {"startLine": 104}}}]}, {"ruleId": "scanner-afd2bff3676776e4", "level": "error", "message": {"text": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/profile/page.tsx"}, "properties": {"repobilityId": "10c7ce8bd48c816a", "scanner": "scanner-primary", "fingerprint": "afd2bff3676776e4", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/app/(dashboard)/dashboard/profile/page.tsx"}, "region": {"startLine": 92}}}]}, {"ruleId": "scanner-afd2bff3676776e4", "level": "error", "message": {"text": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/profile/page.tsx"}, "properties": {"repobilityId": "10c7ce8bd48c816a", "scanner": "scanner-primary", "fingerprint": "afd2bff3676776e4", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/app/(dashboard)/dashboard/profile/page.tsx"}, "region": {"startLine": 93}}}]}, {"ruleId": "scanner-afd2bff3676776e4", "level": "error", "message": {"text": "Possible secret in apps/frontend/src/app/(dashboard)/dashboard/profile/page.tsx"}, "properties": {"repobilityId": "10c7ce8bd48c816a", "scanner": "scanner-primary", "fingerprint": "afd2bff3676776e4", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/app/(dashboard)/dashboard/profile/page.tsx"}, "region": {"startLine": 94}}}]}, {"ruleId": "scanner-b29ad09bdb2a5961", "level": "error", "message": {"text": "Possible secret in apps/frontend/src/app/(auth)/reset-password/page.tsx"}, "properties": {"repobilityId": "83e4365542d7eb22", "scanner": "scanner-primary", "fingerprint": "b29ad09bdb2a5961", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/app/(auth)/reset-password/page.tsx"}, "region": {"startLine": 116}}}]}, {"ruleId": "scanner-2ab341707a2c6f8e", "level": "error", "message": {"text": "Possible secret in apps/frontend/src/app/(auth)/first-login/page.tsx"}, "properties": {"repobilityId": "f916c52375d4e5e8", "scanner": "scanner-primary", "fingerprint": "2ab341707a2c6f8e", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/app/(auth)/first-login/page.tsx"}, "region": {"startLine": 84}}}]}, {"ruleId": "scanner-4455c503fa90662a", "level": "error", "message": {"text": "Possible secret in apps/frontend/src/app/(auth)/accept-invite/page.tsx"}, "properties": {"repobilityId": "7eb0ba2f24d31b53", "scanner": "scanner-primary", "fingerprint": "4455c503fa90662a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/app/(auth)/accept-invite/page.tsx"}, "region": {"startLine": 89}}}]}, {"ruleId": "scanner-de1dcdfe3d11cd2a", "level": "note", "message": {"text": "Insecure pattern 'document_write' in apps/frontend/src/hooks/use-print.ts:96"}, "properties": {"repobilityId": "858e241733bab421", "scanner": "scanner-primary", "fingerprint": "de1dcdfe3d11cd2a", "layer": "security", "severity": "low", "confidence": 1.0, "tags": ["owasp", "document_write"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/src/hooks/use-print.ts"}, "region": {"startLine": 96}}}]}, {"ruleId": "scanner-36cbb13749c81331", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed.ts"}, "properties": {"repobilityId": "9f4a35f3b556f5e5", "scanner": "scanner-primary", "fingerprint": "36cbb13749c81331", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed.ts"}, "region": {"startLine": 86}}}]}, {"ruleId": "scanner-36cbb13749c81331", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed.ts"}, "properties": {"repobilityId": "9f4a35f3b556f5e5", "scanner": "scanner-primary", "fingerprint": "36cbb13749c81331", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed.ts"}, "region": {"startLine": 95}}}]}, {"ruleId": "scanner-36cbb13749c81331", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed.ts"}, "properties": {"repobilityId": "9f4a35f3b556f5e5", "scanner": "scanner-primary", "fingerprint": "36cbb13749c81331", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed.ts"}, "region": {"startLine": 104}}}]}, {"ruleId": "scanner-36cbb13749c81331", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed.ts"}, "properties": {"repobilityId": "9f4a35f3b556f5e5", "scanner": "scanner-primary", "fingerprint": "36cbb13749c81331", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed.ts"}, "region": {"startLine": 113}}}]}, {"ruleId": "scanner-36cbb13749c81331", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed.ts"}, "properties": {"repobilityId": "9f4a35f3b556f5e5", "scanner": "scanner-primary", "fingerprint": "36cbb13749c81331", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed.ts"}, "region": {"startLine": 122}}}]}, {"ruleId": "scanner-36cbb13749c81331", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed.ts"}, "properties": {"repobilityId": "9f4a35f3b556f5e5", "scanner": "scanner-primary", "fingerprint": "36cbb13749c81331", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed.ts"}, "region": {"startLine": 131}}}]}, {"ruleId": "scanner-36cbb13749c81331", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed.ts"}, "properties": {"repobilityId": "9f4a35f3b556f5e5", "scanner": "scanner-primary", "fingerprint": "36cbb13749c81331", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed.ts"}, "region": {"startLine": 140}}}]}, {"ruleId": "scanner-36cbb13749c81331", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed.ts"}, "properties": {"repobilityId": "9f4a35f3b556f5e5", "scanner": "scanner-primary", "fingerprint": "36cbb13749c81331", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed.ts"}, "region": {"startLine": 149}}}]}, {"ruleId": "scanner-36cbb13749c81331", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed.ts"}, "properties": {"repobilityId": "9f4a35f3b556f5e5", "scanner": "scanner-primary", "fingerprint": "36cbb13749c81331", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed.ts"}, "region": {"startLine": 158}}}]}, {"ruleId": "scanner-371ebb2123bc494b", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-specific-users.ts"}, "properties": {"repobilityId": "c2252ffcb61e70d0", "scanner": "scanner-primary", "fingerprint": "371ebb2123bc494b", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-specific-users.ts"}, "region": {"startLine": 50}}}]}, {"ruleId": "scanner-371ebb2123bc494b", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-specific-users.ts"}, "properties": {"repobilityId": "c2252ffcb61e70d0", "scanner": "scanner-primary", "fingerprint": "371ebb2123bc494b", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-specific-users.ts"}, "region": {"startLine": 51}}}]}, {"ruleId": "scanner-371ebb2123bc494b", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-specific-users.ts"}, "properties": {"repobilityId": "c2252ffcb61e70d0", "scanner": "scanner-primary", "fingerprint": "371ebb2123bc494b", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-specific-users.ts"}, "region": {"startLine": 52}}}]}, {"ruleId": "scanner-371ebb2123bc494b", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-specific-users.ts"}, "properties": {"repobilityId": "c2252ffcb61e70d0", "scanner": "scanner-primary", "fingerprint": "371ebb2123bc494b", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-specific-users.ts"}, "region": {"startLine": 53}}}]}, {"ruleId": "scanner-371ebb2123bc494b", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-specific-users.ts"}, "properties": {"repobilityId": "c2252ffcb61e70d0", "scanner": "scanner-primary", "fingerprint": "371ebb2123bc494b", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-specific-users.ts"}, "region": {"startLine": 54}}}]}, {"ruleId": "scanner-371ebb2123bc494b", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-specific-users.ts"}, "properties": {"repobilityId": "c2252ffcb61e70d0", "scanner": "scanner-primary", "fingerprint": "371ebb2123bc494b", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-specific-users.ts"}, "region": {"startLine": 55}}}]}, {"ruleId": "scanner-371ebb2123bc494b", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-specific-users.ts"}, "properties": {"repobilityId": "c2252ffcb61e70d0", "scanner": "scanner-primary", "fingerprint": "371ebb2123bc494b", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-specific-users.ts"}, "region": {"startLine": 56}}}]}, {"ruleId": "scanner-371ebb2123bc494b", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-specific-users.ts"}, "properties": {"repobilityId": "c2252ffcb61e70d0", "scanner": "scanner-primary", "fingerprint": "371ebb2123bc494b", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-specific-users.ts"}, "region": {"startLine": 57}}}]}, {"ruleId": "scanner-371ebb2123bc494b", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-specific-users.ts"}, "properties": {"repobilityId": "c2252ffcb61e70d0", "scanner": "scanner-primary", "fingerprint": "371ebb2123bc494b", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-specific-users.ts"}, "region": {"startLine": 58}}}]}, {"ruleId": "scanner-6c7f4a639e5df36a", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-demo.ts"}, "properties": {"repobilityId": "4718175be051cdfa", "scanner": "scanner-primary", "fingerprint": "6c7f4a639e5df36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-demo.ts"}, "region": {"startLine": 183}}}]}, {"ruleId": "scanner-6c7f4a639e5df36a", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-demo.ts"}, "properties": {"repobilityId": "4718175be051cdfa", "scanner": "scanner-primary", "fingerprint": "6c7f4a639e5df36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-demo.ts"}, "region": {"startLine": 184}}}]}, {"ruleId": "scanner-6c7f4a639e5df36a", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-demo.ts"}, "properties": {"repobilityId": "4718175be051cdfa", "scanner": "scanner-primary", "fingerprint": "6c7f4a639e5df36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-demo.ts"}, "region": {"startLine": 185}}}]}, {"ruleId": "scanner-6c7f4a639e5df36a", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-demo.ts"}, "properties": {"repobilityId": "4718175be051cdfa", "scanner": "scanner-primary", "fingerprint": "6c7f4a639e5df36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-demo.ts"}, "region": {"startLine": 186}}}]}, {"ruleId": "scanner-6c7f4a639e5df36a", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-demo.ts"}, "properties": {"repobilityId": "4718175be051cdfa", "scanner": "scanner-primary", "fingerprint": "6c7f4a639e5df36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-demo.ts"}, "region": {"startLine": 187}}}]}, {"ruleId": "scanner-6c7f4a639e5df36a", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-demo.ts"}, "properties": {"repobilityId": "4718175be051cdfa", "scanner": "scanner-primary", "fingerprint": "6c7f4a639e5df36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-demo.ts"}, "region": {"startLine": 188}}}]}, {"ruleId": "scanner-6c7f4a639e5df36a", "level": "error", "message": {"text": "Possible secret in apps/backend/prisma/seed-demo.ts"}, "properties": {"repobilityId": "4718175be051cdfa", "scanner": "scanner-primary", "fingerprint": "6c7f4a639e5df36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/prisma/seed-demo.ts"}, "region": {"startLine": 189}}}]}, {"ruleId": "scanner-79d38226e5691ff3", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/users/users.service.spec.ts"}, "properties": {"repobilityId": "ca1bc931cbac12e7", "scanner": "scanner-primary", "fingerprint": "79d38226e5691ff3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/users/users.service.spec.ts"}, "region": {"startLine": 66}}}]}, {"ruleId": "scanner-79d38226e5691ff3", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/users/users.service.spec.ts"}, "properties": {"repobilityId": "ca1bc931cbac12e7", "scanner": "scanner-primary", "fingerprint": "79d38226e5691ff3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/users/users.service.spec.ts"}, "region": {"startLine": 139}}}]}, {"ruleId": "scanner-79d38226e5691ff3", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/users/users.service.spec.ts"}, "properties": {"repobilityId": "ca1bc931cbac12e7", "scanner": "scanner-primary", "fingerprint": "79d38226e5691ff3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/users/users.service.spec.ts"}, "region": {"startLine": 185}}}]}, {"ruleId": "scanner-79d38226e5691ff3", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/users/users.service.spec.ts"}, "properties": {"repobilityId": "ca1bc931cbac12e7", "scanner": "scanner-primary", "fingerprint": "79d38226e5691ff3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/users/users.service.spec.ts"}, "region": {"startLine": 223}}}]}, {"ruleId": "scanner-79d38226e5691ff3", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/users/users.service.spec.ts"}, "properties": {"repobilityId": "ca1bc931cbac12e7", "scanner": "scanner-primary", "fingerprint": "79d38226e5691ff3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/users/users.service.spec.ts"}, "region": {"startLine": 330}}}]}, {"ruleId": "scanner-96ebf8f05c45f5ec", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/users/users.controller.spec.ts"}, "properties": {"repobilityId": "feb6a68ecbe2eb61", "scanner": "scanner-primary", "fingerprint": "96ebf8f05c45f5ec", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/users/users.controller.spec.ts"}, "region": {"startLine": 76}}}]}, {"ruleId": "scanner-96ebf8f05c45f5ec", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/users/users.controller.spec.ts"}, "properties": {"repobilityId": "feb6a68ecbe2eb61", "scanner": "scanner-primary", "fingerprint": "96ebf8f05c45f5ec", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/users/users.controller.spec.ts"}, "region": {"startLine": 97}}}]}, {"ruleId": "scanner-96ebf8f05c45f5ec", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/users/users.controller.spec.ts"}, "properties": {"repobilityId": "feb6a68ecbe2eb61", "scanner": "scanner-primary", "fingerprint": "96ebf8f05c45f5ec", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/users/users.controller.spec.ts"}, "region": {"startLine": 136}}}]}, {"ruleId": "scanner-e816c1a1f8b6e36a", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/auth/auth.service.spec.ts"}, "properties": {"repobilityId": "3a7072bee2557d7c", "scanner": "scanner-primary", "fingerprint": "e816c1a1f8b6e36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/auth/auth.service.spec.ts"}, "region": {"startLine": 101}}}]}, {"ruleId": "scanner-e816c1a1f8b6e36a", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/auth/auth.service.spec.ts"}, "properties": {"repobilityId": "3a7072bee2557d7c", "scanner": "scanner-primary", "fingerprint": "e816c1a1f8b6e36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/auth/auth.service.spec.ts"}, "region": {"startLine": 118}}}]}, {"ruleId": "scanner-e816c1a1f8b6e36a", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/auth/auth.service.spec.ts"}, "properties": {"repobilityId": "3a7072bee2557d7c", "scanner": "scanner-primary", "fingerprint": "e816c1a1f8b6e36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/auth/auth.service.spec.ts"}, "region": {"startLine": 137}}}]}, {"ruleId": "scanner-e816c1a1f8b6e36a", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/auth/auth.service.spec.ts"}, "properties": {"repobilityId": "3a7072bee2557d7c", "scanner": "scanner-primary", "fingerprint": "e816c1a1f8b6e36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/auth/auth.service.spec.ts"}, "region": {"startLine": 228}}}]}, {"ruleId": "scanner-e816c1a1f8b6e36a", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/auth/auth.service.spec.ts"}, "properties": {"repobilityId": "3a7072bee2557d7c", "scanner": "scanner-primary", "fingerprint": "e816c1a1f8b6e36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/auth/auth.service.spec.ts"}, "region": {"startLine": 312}}}]}, {"ruleId": "scanner-e816c1a1f8b6e36a", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/auth/auth.service.spec.ts"}, "properties": {"repobilityId": "3a7072bee2557d7c", "scanner": "scanner-primary", "fingerprint": "e816c1a1f8b6e36a", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/auth/auth.service.spec.ts"}, "region": {"startLine": 318}}}]}, {"ruleId": "scanner-e57dd4ed85e1c25d", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/students/students.service.spec.ts"}, "properties": {"repobilityId": "25a5811605fae7e4", "scanner": "scanner-primary", "fingerprint": "e57dd4ed85e1c25d", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/students/students.service.spec.ts"}, "region": {"startLine": 70}}}]}, {"ruleId": "scanner-e57dd4ed85e1c25d", "level": "error", "message": {"text": "Possible secret in apps/backend/src/modules/students/students.service.spec.ts"}, "properties": {"repobilityId": "25a5811605fae7e4", "scanner": "scanner-primary", "fingerprint": "e57dd4ed85e1c25d", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/src/modules/students/students.service.spec.ts"}, "region": {"startLine": 218}}}]}, {"ruleId": "scanner-9a27c00720c85853", "level": "note", "message": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/schedule/_components/schedule-workspace.tsx (1362 lines)"}, "properties": {"repobilityId": "f0aa18d35fdc7cd7", "scanner": "scanner-primary", "fingerprint": "9a27c00720c85853", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-1dcec2547271f034", "level": "note", "message": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/users/page.tsx (1241 lines)"}, "properties": {"repobilityId": "f5a0a0cd8fad9875", "scanner": "scanner-primary", "fingerprint": "1dcec2547271f034", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-132e9164b3be57fe", "level": "note", "message": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/exams/[id]/page.tsx (1378 lines)"}, "properties": {"repobilityId": "17efc1629385599f", "scanner": "scanner-primary", "fingerprint": "132e9164b3be57fe", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-24af8fac4b8f6184", "level": "note", "message": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/exams/_components/exams-workspace.tsx (1570 lines)"}, "properties": {"repobilityId": "c3d39e9d2061192b", "scanner": "scanner-primary", "fingerprint": "24af8fac4b8f6184", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-a1f24533117631b8", "level": "note", "message": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/parent/page.tsx (1091 lines)"}, "properties": {"repobilityId": "b62996a6cf408fd6", "scanner": "scanner-primary", "fingerprint": "a1f24533117631b8", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-67a433aa74b3cd17", "level": "note", "message": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/grades/page.tsx (1219 lines)"}, "properties": {"repobilityId": "cfa9e7c753b1a1fb", "scanner": "scanner-primary", "fingerprint": "67a433aa74b3cd17", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-b7c711efb77cead3", "level": "note", "message": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/payroll/page.tsx (1747 lines)"}, "properties": {"repobilityId": "344c3e4360794054", "scanner": "scanner-primary", "fingerprint": "b7c711efb77cead3", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-e9dadca4ab56b9b7", "level": "note", "message": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/crm/page.tsx (1670 lines)"}, "properties": {"repobilityId": "133e66680b7746ac", "scanner": "scanner-primary", "fingerprint": "e9dadca4ab56b9b7", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-a5f975d32977be71", "level": "note", "message": {"text": "Very large file: apps/frontend/src/app/(dashboard)/dashboard/reports/_components/reports-workspace.tsx (1300 lines)"}, "properties": {"repobilityId": "468da37fd505b4c7", "scanner": "scanner-primary", "fingerprint": "a5f975d32977be71", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-3bc2f37ae78c225b", "level": "note", "message": {"text": "Very large file: apps/backend/src/modules/payroll/payroll.service.ts (1409 lines)"}, "properties": {"repobilityId": "533508e0a1f4f3ae", "scanner": "scanner-primary", "fingerprint": "3bc2f37ae78c225b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-6893a6c8b0861585", "level": "warning", "message": {"text": "Very low test-to-source ratio"}, "properties": {"repobilityId": "54a7de3f06314bf0", "scanner": "scanner-primary", "fingerprint": "6893a6c8b0861585", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "coverage"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "fd5c9a60c199e213", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3f02143ce17b7bf9", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: apps/frontend/package.json"}, "properties": {"repobilityId": "8293ac8b769dc370", "scanner": "scanner-primary", "fingerprint": "3f02143ce17b7bf9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/frontend/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-53a7af2536f80bd8", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: apps/backend/package.json"}, "properties": {"repobilityId": "637f248c83215574", "scanner": "scanner-primary", "fingerprint": "53a7af2536f80bd8", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/backend/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-cb3e52667c84fb86", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: packages/types/package.json"}, "properties": {"repobilityId": "b5e2784f829944e6", "scanner": "scanner-primary", "fingerprint": "cb3e52667c84fb86", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "packages/types/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "4dcbdf1cf8031d56", "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": "24cf6a5b735c120a", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "006c85f9ddeeca74", "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": "ad41a084751ef51b", "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": "df2b6e649fa94717", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "52e3d068d45c0dff", "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": "49ca5b5dc8464b27", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "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-d541d3e5ae110df5", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/frontend/src/app/(dashboard)/dashboard/system-health/page.tsx:124"}, "properties": {"repobilityId": "44bb8a71556fc880", "scanner": "scanner-primary", "fingerprint": "d541d3e5ae110df5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-a1444816c80bc345", "level": "note", "message": {"text": "Legacy-named symbol `daysOld` in apps/frontend/src/app/(dashboard)/dashboard/alerts/page.tsx:140"}, "properties": {"repobilityId": "f8d0126528eb38bc", "scanner": "scanner-primary", "fingerprint": "a1444816c80bc345", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-0d16d50f11e911a9", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/frontend/src/app/(dashboard)/dashboard/_components/shared-widgets.tsx:806"}, "properties": {"repobilityId": "afb113abecc748a6", "scanner": "scanner-primary", "fingerprint": "0d16d50f11e911a9", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c6f925489bed0737", "level": "none", "message": {"text": "Commented-code block (6 lines) in apps/frontend/src/app/(auth)/first-login/page.tsx:18"}, "properties": {"repobilityId": "9a656cc1df28bc0c", "scanner": "scanner-primary", "fingerprint": "c6f925489bed0737", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-854903cd46c796b6", "level": "none", "message": {"text": "Commented-code block (7 lines) in apps/backend/prisma/seed-risk-test.ts:204"}, "properties": {"repobilityId": "483326f4b0ef7a97", "scanner": "scanner-primary", "fingerprint": "854903cd46c796b6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-6f80d9f1604a9bf9", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/backend/src/modules/leads/leads.service.ts:362"}, "properties": {"repobilityId": "9a1a17857874b029", "scanner": "scanner-primary", "fingerprint": "6f80d9f1604a9bf9", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-04d68fc75dfc3f5e", "level": "none", "message": {"text": "Commented-code block (9 lines) in apps/backend/src/modules/import/import.service.ts:217"}, "properties": {"repobilityId": "b2623d2f5fb5cc74", "scanner": "scanner-primary", "fingerprint": "04d68fc75dfc3f5e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8958210de209898b", "level": "none", "message": {"text": "Commented-code block (6 lines) in apps/backend/src/modules/payments/payments.service.ts:592"}, "properties": {"repobilityId": "c2bffde5861a7274", "scanner": "scanner-primary", "fingerprint": "8958210de209898b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-d1a26d5df86ba873", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/backend/src/modules/super-admin/super-admin.service.ts:335"}, "properties": {"repobilityId": "4e4bb55523a11cd7", "scanner": "scanner-primary", "fingerprint": "d1a26d5df86ba873", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-319e66a630e14977", "level": "none", "message": {"text": "2 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "d838d1fc5d8231c9", "scanner": "scanner-primary", "fingerprint": "319e66a630e14977", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-40f503e51fc9f4b4", "level": "note", "message": {"text": "Unused endpoint: GET /super-admin/stats"}, "properties": {"repobilityId": "6b4ef92137f4c49c", "scanner": "scanner-primary", "fingerprint": "40f503e51fc9f4b4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7f31228dddd0186f", "level": "note", "message": {"text": "Unused endpoint: GET /notifications/queue-stats"}, "properties": {"repobilityId": "a2371f762b6aa5c5", "scanner": "scanner-primary", "fingerprint": "7f31228dddd0186f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5b72a3b090f06a9a", "level": "note", "message": {"text": "Unused endpoint: DELETE /notifications/queue-failed"}, "properties": {"repobilityId": "453a7b8448439ccc", "scanner": "scanner-primary", "fingerprint": "5b72a3b090f06a9a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fad44267fd33eb41", "level": "note", "message": {"text": "Unused endpoint: POST /upload/document"}, "properties": {"repobilityId": "6183c0f64ef9ae8e", "scanner": "scanner-primary", "fingerprint": "fad44267fd33eb41", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-686b777e7e236fa3", "level": "note", "message": {"text": "Unused endpoint: GET /library/stats"}, "properties": {"repobilityId": "7fd7af22364385b4", "scanner": "scanner-primary", "fingerprint": "686b777e7e236fa3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-58000dd1677359e6", "level": "note", "message": {"text": "Unused endpoint: GET /library/loans"}, "properties": {"repobilityId": "1ab5414961a49024", "scanner": "scanner-primary", "fingerprint": "58000dd1677359e6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c059f57186114027", "level": "note", "message": {"text": "Unused endpoint: POST /auth/logout"}, "properties": {"repobilityId": "e3c4284e8f8f3cb9", "scanner": "scanner-primary", "fingerprint": "c059f57186114027", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e2fe5b92648ca462", "level": "note", "message": {"text": "Unused endpoint: POST /auth/forgot-password"}, "properties": {"repobilityId": "d0560ec429952b67", "scanner": "scanner-primary", "fingerprint": "e2fe5b92648ca462", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-deb8df763a50c73a", "level": "note", "message": {"text": "Unused endpoint: POST /auth/reset-password"}, "properties": {"repobilityId": "727de5684a777667", "scanner": "scanner-primary", "fingerprint": "deb8df763a50c73a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e1ceb256e9656751", "level": "note", "message": {"text": "Unused endpoint: GET /fee-structures"}, "properties": {"repobilityId": "c1acc65a123aa1c0", "scanner": "scanner-primary", "fingerprint": "e1ceb256e9656751", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7f639a8df9c90de8", "level": "note", "message": {"text": "Unused endpoint: POST /fee-structures"}, "properties": {"repobilityId": "aedc5364f8725b66", "scanner": "scanner-primary", "fingerprint": "7f639a8df9c90de8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-988356d1631079b2", "level": "note", "message": {"text": "Unused endpoint: GET /teaching-loads"}, "properties": {"repobilityId": "fe5d389d93ed298d", "scanner": "scanner-primary", "fingerprint": "988356d1631079b2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f1bc81afb6632a67", "level": "note", "message": {"text": "Unused endpoint: POST /teaching-loads"}, "properties": {"repobilityId": "e9c18f502944ef36", "scanner": "scanner-primary", "fingerprint": "f1bc81afb6632a67", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cdbcda95e98c0e78", "level": "note", "message": {"text": "Unused endpoint: POST /teaching-loads/import/preview"}, "properties": {"repobilityId": "319e49c84439f1d3", "scanner": "scanner-primary", "fingerprint": "cdbcda95e98c0e78", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-89d5c1a64eecb42e", "level": "note", "message": {"text": "Unused endpoint: POST /teaching-loads/import/commit"}, "properties": {"repobilityId": "8c8d9b96cec7e8a8", "scanner": "scanner-primary", "fingerprint": "89d5c1a64eecb42e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c9163dc1f64fcaed", "level": "note", "message": {"text": "Unused endpoint: GET /teaching-loads/workload/summary"}, "properties": {"repobilityId": "e80d5a72106c42bb", "scanner": "scanner-primary", "fingerprint": "c9163dc1f64fcaed", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0cef062647605739", "level": "note", "message": {"text": "Unused endpoint: GET /teaching-loads/workload/teachers"}, "properties": {"repobilityId": "b53c5d3b7a14180f", "scanner": "scanner-primary", "fingerprint": "0cef062647605739", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2883ad056dbafd27", "level": "note", "message": {"text": "Unused endpoint: GET /reports/analytics/pulse"}, "properties": {"repobilityId": "68f072ca5c781d20", "scanner": "scanner-primary", "fingerprint": "2883ad056dbafd27", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ef190451c695da48", "level": "note", "message": {"text": "Unused endpoint: GET /reports/analytics/finance"}, "properties": {"repobilityId": "99869746dd183610", "scanner": "scanner-primary", "fingerprint": "ef190451c695da48", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c459e09dbe8a6b5d", "level": "note", "message": {"text": "Unused endpoint: GET /reports/analytics/branch-comparison"}, "properties": {"repobilityId": "724295283f0957f7", "scanner": "scanner-primary", "fingerprint": "c459e09dbe8a6b5d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cf5e93311e93fe1f", "level": "note", "message": {"text": "Unused endpoint: GET /reports/analytics/marketing-roi"}, "properties": {"repobilityId": "65c651744884c9fa", "scanner": "scanner-primary", "fingerprint": "cf5e93311e93fe1f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-44e47e0ee86d27d1", "level": "note", "message": {"text": "Unused endpoint: GET /reports/analytics/alerts"}, "properties": {"repobilityId": "57ef1cbbd076ca07", "scanner": "scanner-primary", "fingerprint": "44e47e0ee86d27d1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9c4a1b7533f1c9a8", "level": "note", "message": {"text": "Unused endpoint: GET /reports/export/excel"}, "properties": {"repobilityId": "e038ccb8a4186a61", "scanner": "scanner-primary", "fingerprint": "9c4a1b7533f1c9a8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1bca8100a44f7f25", "level": "note", "message": {"text": "Unused endpoint: POST /users"}, "properties": {"repobilityId": "9b5581d965590ad4", "scanner": "scanner-primary", "fingerprint": "1bca8100a44f7f25", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-984cc1c6d33f9dd2", "level": "note", "message": {"text": "Unused endpoint: PUT /users/me/password"}, "properties": {"repobilityId": "f2363452ddfa311b", "scanner": "scanner-primary", "fingerprint": "984cc1c6d33f9dd2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-60bc5c330890659a", "level": "note", "message": {"text": "Unused endpoint: PUT /users/me/avatar"}, "properties": {"repobilityId": "81f1b02507431e83", "scanner": "scanner-primary", "fingerprint": "60bc5c330890659a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-eab66eb495182352", "level": "note", "message": {"text": "Unused endpoint: POST /users/import/csv"}, "properties": {"repobilityId": "979153f8bf5b33ef", "scanner": "scanner-primary", "fingerprint": "eab66eb495182352", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0bcaf69bd2ba9d81", "level": "note", "message": {"text": "Unused endpoint: GET /users/check-email"}, "properties": {"repobilityId": "c33a1bd0e1b44792", "scanner": "scanner-primary", "fingerprint": "0bcaf69bd2ba9d81", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a6f226130b2c66e7", "level": "note", "message": {"text": "Unused endpoint: GET /invitations"}, "properties": {"repobilityId": "e9e7a23e7d0612da", "scanner": "scanner-primary", "fingerprint": "a6f226130b2c66e7", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-246ef886fef7811e", "level": "note", "message": {"text": "Unused endpoint: GET /discipline"}, "properties": {"repobilityId": "12cccb2a8e1e7c6a", "scanner": "scanner-primary", "fingerprint": "246ef886fef7811e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5ced322e159b28a0", "level": "note", "message": {"text": "Unused endpoint: POST /discipline"}, "properties": {"repobilityId": "ea059536a6005a33", "scanner": "scanner-primary", "fingerprint": "5ced322e159b28a0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0c5f096bdc9451a1", "level": "note", "message": {"text": "Unused endpoint: GET /discipline/stats"}, "properties": {"repobilityId": "fc3c39f162906cf8", "scanner": "scanner-primary", "fingerprint": "0c5f096bdc9451a1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-27e1326288dcbfb2", "level": "note", "message": {"text": "Unused endpoint: POST /import/students/parse"}, "properties": {"repobilityId": "866e6b6ea044200b", "scanner": "scanner-primary", "fingerprint": "27e1326288dcbfb2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-63b8c95a23e9b752", "level": "note", "message": {"text": "Unused endpoint: POST /import/users/parse"}, "properties": {"repobilityId": "a1590908ec200a75", "scanner": "scanner-primary", "fingerprint": "63b8c95a23e9b752", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ab632b2266155f89", "level": "note", "message": {"text": "Unused endpoint: POST /import/schedule/parse"}, "properties": {"repobilityId": "84cec3f35fa8dc65", "scanner": "scanner-primary", "fingerprint": "ab632b2266155f89", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-945774972da6105a", "level": "note", "message": {"text": "Unused endpoint: POST /import/grades/parse"}, "properties": {"repobilityId": "64946d8cd3cfc161", "scanner": "scanner-primary", "fingerprint": "945774972da6105a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e650eb5c299e753f", "level": "note", "message": {"text": "Unused endpoint: POST /import/attendance/parse"}, "properties": {"repobilityId": "82788605897e702c", "scanner": "scanner-primary", "fingerprint": "e650eb5c299e753f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-326de6a461d3556a", "level": "note", "message": {"text": "Unused endpoint: POST /import/students/commit"}, "properties": {"repobilityId": "9aef199cb36d925a", "scanner": "scanner-primary", "fingerprint": "326de6a461d3556a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a1cb92ecf008fd2f", "level": "note", "message": {"text": "Unused endpoint: POST /import/users/commit"}, "properties": {"repobilityId": "c9edd9d78e19ea5f", "scanner": "scanner-primary", "fingerprint": "a1cb92ecf008fd2f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-07a0d90efb786baf", "level": "note", "message": {"text": "Unused endpoint: POST /import/schedule/commit"}, "properties": {"repobilityId": "05c34c91b88c41ed", "scanner": "scanner-primary", "fingerprint": "07a0d90efb786baf", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7db8577ec9c402c5", "level": "note", "message": {"text": "Unused endpoint: POST /import/grades/commit"}, "properties": {"repobilityId": "41889fd452c44c60", "scanner": "scanner-primary", "fingerprint": "7db8577ec9c402c5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2f4d00a371c781c8", "level": "note", "message": {"text": "Unused endpoint: POST /import/attendance/commit"}, "properties": {"repobilityId": "135225d83a1d6642", "scanner": "scanner-primary", "fingerprint": "2f4d00a371c781c8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f29aade19ceaa61c", "level": "note", "message": {"text": "Unused endpoint: POST /leave-requests"}, "properties": {"repobilityId": "4542cfc3b53742e2", "scanner": "scanner-primary", "fingerprint": "f29aade19ceaa61c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0701294795ef9045", "level": "note", "message": {"text": "Unused endpoint: GET /leave-requests"}, "properties": {"repobilityId": "81ac7ea81e50de8c", "scanner": "scanner-primary", "fingerprint": "0701294795ef9045", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3af64e805d88ef35", "level": "note", "message": {"text": "Unused endpoint: GET /notifications"}, "properties": {"repobilityId": "4c80121be6f14f65", "scanner": "scanner-primary", "fingerprint": "3af64e805d88ef35", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6a23aeabb1f0c4d3", "level": "note", "message": {"text": "Unused endpoint: PUT /notifications/read-all"}, "properties": {"repobilityId": "b49be8cb81ae4f37", "scanner": "scanner-primary", "fingerprint": "6a23aeabb1f0c4d3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d15d3333c9f27817", "level": "note", "message": {"text": "Unused endpoint: POST /notifications"}, "properties": {"repobilityId": "3e20a7df6aa4c94b", "scanner": "scanner-primary", "fingerprint": "d15d3333c9f27817", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8206e0572124202c", "level": "note", "message": {"text": "Unused endpoint: POST /notifications/broadcast"}, "properties": {"repobilityId": "fe52f4a2939fd9a7", "scanner": "scanner-primary", "fingerprint": "8206e0572124202c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-999dff0ea581b4b8", "level": "note", "message": {"text": "Unused endpoint: GET /notifications/preferences"}, "properties": {"repobilityId": "60fa4c0303c54038", "scanner": "scanner-primary", "fingerprint": "999dff0ea581b4b8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-067dcceb02ca4757", "level": "note", "message": {"text": "Unused endpoint: PATCH /notifications/preferences"}, "properties": {"repobilityId": "c7984d39e3a10051", "scanner": "scanner-primary", "fingerprint": "067dcceb02ca4757", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}