{"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-c48073a20c9da3f9", "name": "Possibly dead Python function: build_report_pdf", "shortDescription": {"text": "Possibly dead Python function: build_report_pdf"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-30b1027ef22ab25f", "name": "Possibly dead Python function: build_report_image", "shortDescription": {"text": "Possibly dead Python function: build_report_image"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2933efb86c372873", "name": "Possibly dead Python function: request_with_retry", "shortDescription": {"text": "Possibly dead Python function: request_with_retry"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e1e3e996f53b9889", "name": "Possibly dead Python function: save_and_insert", "shortDescription": {"text": "Possibly dead Python function: save_and_insert"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b52358acf479a1bf", "name": "Possibly dead Python function: zoom_get_zak", "shortDescription": {"text": "Possibly dead Python function: zoom_get_zak"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c98f35dc863edc6e", "name": "Possibly dead Python function: verify_token", "shortDescription": {"text": "Possibly dead Python function: verify_token"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1eee186884b93539", "name": "Possibly dead Python function: login_rate_limit", "shortDescription": {"text": "Possibly dead Python function: login_rate_limit"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-fe76e00d4b7a9cff", "name": "Possibly dead Python function: fetch_students", "shortDescription": {"text": "Possibly dead Python function: fetch_students"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-78e9c3d33b7a269c", "name": "Possibly dead Python function: fetch_subjects", "shortDescription": {"text": "Possibly dead Python function: fetch_subjects"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-bc24447d84a7765d", "name": "Possibly dead Python function: fetch_broadcasts", "shortDescription": {"text": "Possibly dead Python function: fetch_broadcasts"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-517fe1fb4e7f306c", "name": "Possibly dead Python function: fetch_class_ids", "shortDescription": {"text": "Possibly dead Python function: fetch_class_ids"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b0718255478175c8", "name": "Possibly dead Python function: fetch_subs", "shortDescription": {"text": "Possibly dead Python function: fetch_subs"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-002b1240ce921845", "name": "Possibly dead Python function: fetch_studs", "shortDescription": {"text": "Possibly dead Python function: fetch_studs"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-86cb5970badf9030", "name": "Possibly dead Python function: fetch_links", "shortDescription": {"text": "Possibly dead Python function: fetch_links"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-19071fa8a9f40da9", "name": "Possibly dead Python function: fetch_tests_cnt", "shortDescription": {"text": "Possibly dead Python function: fetch_tests_cnt"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ffab1c04c88b0dee", "name": "Possibly dead Python function: fetch_asg", "shortDescription": {"text": "Possibly dead Python function: fetch_asg"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d02f5f0087a97291", "name": "Possibly dead Python function: fetch_lc", "shortDescription": {"text": "Possibly dead Python function: fetch_lc"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7d6433e91ce9ac69", "name": "Possibly dead Python function: fetch_upc_tests", "shortDescription": {"text": "Possibly dead Python function: fetch_upc_tests"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4fe7a6059b707ea4", "name": "Possibly dead Python function: fetch_tests", "shortDescription": {"text": "Possibly dead Python function: fetch_tests"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-253f82c49c9bc1ff", "name": "Possibly dead Python function: fetch_videos", "shortDescription": {"text": "Possibly dead Python function: fetch_videos"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0ca2340179762112", "name": "Possibly dead Python function: fetch_assignments", "shortDescription": {"text": "Possibly dead Python function: fetch_assignments"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ee75a550154d1f0f", "name": "Possibly dead Python function: fetch_live", "shortDescription": {"text": "Possibly dead Python function: fetch_live"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4536f177713a93d4", "name": "Possibly dead Python function: fetch_att_30", "shortDescription": {"text": "Possibly dead Python function: fetch_att_30"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-615d71a135d6eb6b", "name": "Possibly dead Python function: fetch_attempts_30", "shortDescription": {"text": "Possibly dead Python function: fetch_attempts_30"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7c3245c19f6fdcbc", "name": "Possibly dead Python function: fetch_subm_30", "shortDescription": {"text": "Possibly dead Python function: fetch_subm_30"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-30167e1970a2b92b", "name": "Possibly dead Python function: fetch_questions", "shortDescription": {"text": "Possibly dead Python function: fetch_questions"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6b25944e151b7235", "name": "Possibly dead Python function: fetch_test_attempts", "shortDescription": {"text": "Possibly dead Python function: fetch_test_attempts"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-77af0cd041cee449", "name": "Possibly dead Python function: fetch_video_progress", "shortDescription": {"text": "Possibly dead Python function: fetch_video_progress"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3fbaffc9bb5ec657", "name": "Possibly dead Python function: fetch_submissions", "shortDescription": {"text": "Possibly dead Python function: fetch_submissions"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-831f09651693f238", "name": "`truncate` class without `title=` for hover reveal \u2014 lms-v3_9.jsx:338", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 lms-v3_9.jsx:338"}, "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-a8595a0f049109f3", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/student/StudentAssignmentSheet.jsx:165", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/student/StudentAssignmentSheet.jsx:165"}, "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-80b8010bb5d628ea", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/StudentReportCard.jsx:1402", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/StudentReportCard.jsx:1402"}, "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-6c996b65b1d6c8d7", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/SearchPalette.jsx:60", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/SearchPalette.jsx:60"}, "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-fef09a079f12ee6a", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/Sidebar.jsx:43", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/Sidebar.jsx:43"}, "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-505b1e6574b8c596", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/LeaderboardPanel.jsx:113", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/LeaderboardPanel.jsx:113"}, "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-132d32d924563576", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/TopBar.jsx:42", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/TopBar.jsx:42"}, "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-8911715c029ab600", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/NotificationBell.jsx:113", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/NotificationBell.jsx:113"}, "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-5a7ac294db90d252", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/TopNav.jsx:52", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/TopNav.jsx:52"}, "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-c77c4c8479a1f86e", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/ui/index.tsx:239", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/ui/index.tsx:239"}, "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-5bc0027755f490d7", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/cards/PageHeader.jsx:20", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/cards/PageHeader.jsx:20"}, "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-6a11938de1ddf192", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/cards/EventCard.jsx:41", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/cards/EventCard.jsx:41"}, "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-476031e2e0b00065", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/TestResultsSheet.jsx:343", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/TestResultsSheet.jsx: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-4c03d5b2faff0074", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/StudentManageGrid.jsx:51", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/StudentManageGrid.jsx:51"}, "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-42593fa68d0bf394", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/AttendanceStudentCard.jsx:98", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/AttendanceStudentCard.jsx:98"}, "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-88fb5e65f4a46c7b", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/AttendanceTab.jsx:274", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/AttendanceTab.jsx:274"}, "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-dc9f6c9ca3ec41ba", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/LiveClassAttendanceSheet.jsx:58", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/LiveClassAttendanceSheet.jsx:58"}, "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-ee3a968fb65d93ff", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/PerformancePanel.jsx:124", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/PerformancePanel.jsx:124"}, "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-df383dcc563da447", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/BulkImportModal.jsx:276", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/BulkImportModal.jsx:276"}, "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-22d7bc3a11f15e4c", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/NewAssignmentModal.jsx:135", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/NewAssignmentModal.jsx:135"}, "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-9e122896bd8877b2", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/AssignmentSubmissionsSheet.jsx:136", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/AssignmentSubmissionsSheet.jsx:136"}, "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-1d107cc4303e4bcc", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/BroadcastThread.jsx:336", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/BroadcastThread.jsx:336"}, "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-98586d19cb070312", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/Modals.jsx:92", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/Modals.jsx:92"}, "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-de1fffa78abcefa1", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/PendingReattemptsCard.jsx:91", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/PendingReattemptsCard.jsx:91"}, "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-17386cde695c7104", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/LiveAbsenteesCard.jsx:19", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/LiveAbsenteesCard.jsx:19"}, "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-7d03bc3221c9b0dd", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/AssignmentStatusCard.jsx:", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/AssignmentStatusCard.jsx: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-8260642e5e4810e0", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/VideoEngagementCard.jsx:4", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/VideoEngagementCard.jsx:42"}, "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-bbb496b26730c796", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/PerformanceSnapshotCard.j", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/PerformanceSnapshotCard.jsx: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-c39978fd31247e26", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/CopySuspectsCard.jsx:26", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/CopySuspectsCard.jsx: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-49d8221a80bf029e", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/subject/NoteFormModal.jsx:61", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/subject/NoteFormModal.jsx:61"}, "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-f087ecb6e9b26d36", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/subject/VideoViewersModal.jsx:94", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/subject/VideoViewersModal.jsx:94"}, "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-0ff31b4e30e2fc2d", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/subject/NotesSection.jsx:26", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/subject/NotesSection.jsx: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-c8e601c0551f3bcd", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/RecentMessagesTable.jsx:58", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/RecentMessagesTable.jsx:58"}, "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-ca81e8a165d9c19b", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/ClassPicker.jsx:90", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/ClassPicker.jsx: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-babcae604a37e2e3", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/teacher/whatsapp/previewText.jsx:51", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/teacher/whatsapp/previewText.jsx:51"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-38cb1c99f6828539", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/WhatsAppPreview.jsx:18", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/WhatsAppPreview.jsx:18"}, "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-3b74731763c8cd11", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/HistoryTab.jsx:96", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/HistoryTab.jsx:96"}, "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-88c48969e16878eb", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/RecipientPicker.jsx:103", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/RecipientPicker.jsx: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-62e0456da585a09e", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/SendWizard.jsx:301", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/SendWizard.jsx:301"}, "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-3338dff3dc1c1c45", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/TemplatesTab.jsx:111", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/TemplatesTab.jsx:111"}, "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-daa26bc4afeb1047", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/PendingActions.jsx:65", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/PendingActions.jsx:65"}, "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-0b58931d0a854e18", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/InboxTab.jsx:64", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/InboxTab.jsx:64"}, "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-774b45d119a01107", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/AutomationTab.jsx:213", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/AutomationTab.jsx:213"}, "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-80e740c6ee96bc76", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/Composer.jsx:260", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/Composer.jsx:260"}, "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-0bda724635d177e9", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/OverviewTab.jsx:78", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/OverviewTab.jsx:78"}, "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-b3fbe8b86b78201a", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentHomePage.jsx:56", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentHomePage.jsx:56"}, "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-f7f36c79a8c1388c", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentSubjectViewPage.jsx:211", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentSubjectViewPage.jsx:211"}, "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-66e5955ad66dd158", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentVideoPlayerPage.jsx:810", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentVideoPlayerPage.jsx:810"}, "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-7e5b8046932ed0df", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentTestReviewPage.jsx:60", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentTestReviewPage.jsx:60"}, "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-1a5d077bd4aba17d", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentProfilePage.jsx:365", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentProfilePage.jsx:365"}, "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-24a6e791b5e7c030", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentBroadcastsPage.jsx:143", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentBroadcastsPage.jsx:143"}, "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-4f5715f9e98dbf58", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentTestTakingPage.jsx:370", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentTestTakingPage.jsx:370"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-bdf0995220aaa538", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/BroadcastsPage.jsx:184", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/BroadcastsPage.jsx: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-70da55281aa912f0", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/TodayPage.jsx:53", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/TodayPage.jsx: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-e358e13e5e58aecb", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/QuestionBankPage.jsx:144", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/QuestionBankPage.jsx:144"}, "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-62cc96a767db41fa", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/WhatsAppCenterPage.jsx:177", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/WhatsAppCenterPage.jsx:177"}, "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-dd14a5900f5649da", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/StandardDetailPage.jsx:387", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/StandardDetailPage.jsx:387"}, "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-b18719f9e3058b68", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/StudentDetailPage.jsx:267", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/StudentDetailPage.jsx:267"}, "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-7e93e140587aa5ae", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/SettingsPage.jsx:378", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/SettingsPage.jsx:378"}, "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-25b50dd4daa81bab", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/SubjectDetailPage.jsx:46", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/SubjectDetailPage.jsx:46"}, "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-947b3937d66ff5dc", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/StudentsPage.jsx:175", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/StudentsPage.jsx:175"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d63da3583b14afc0", "name": "Dockerfile runs as root: Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e066691601852931", "name": "Docker base image is tag-pinned but not digest-pinned: python:3.11-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.11-slim"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-aa5acaa49eb8315b", "name": "Containers defined but no K8s/orchestration manifest found", "shortDescription": {"text": "Containers defined but no K8s/orchestration manifest found"}, "fullDescription": {"text": "Repo has Dockerfiles/compose but no Kubernetes/Nomad manifests. If the target deployment is K8s, the manifests may live in a separate ops repo."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4686f0816b35e560", "name": "Runtime dotenv file present in repo: frontend/.env.local", "shortDescription": {"text": "Runtime dotenv file present in repo: frontend/.env.local"}, "fullDescription": {"text": "`frontend/.env.local` looks like a runtime dotenv file. It contains secret-looking assignments for VITE_SUPABASE_KEY. Move real values to a secret manager and keep only `.env.example` style templates in source control."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-9e9c231a310fb881", "name": "Runtime dotenv file present in repo: backend/.env", "shortDescription": {"text": "Runtime dotenv file present in repo: backend/.env"}, "fullDescription": {"text": "`backend/.env` looks like a runtime dotenv file. It contains secret-looking assignments for SUPABASE_KEY, SUPABASE_SERVICE_KEY, ZOOM_CLIENT_SECRET, ZOOM_WEBHOOK_SECRET_TOKEN, ZOOM_SDK_KEY. Move real values to a secret manager and keep only `.env.example` style templates in source control."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-81fde056e5d6aff7", "name": "Possible secret in frontend/src/store.js", "shortDescription": {"text": "Possible secret in frontend/src/store.js"}, "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-364030da3280fd5f", "name": "Insecure pattern 'direct_innerhtml_assignment' in frontend/src/pages/student/StudentVideoPlayerPage.jsx:257", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/src/pages/student/StudentVideoPlayerPage.jsx:257"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0e83e6a03db76e23", "name": "Insecure pattern 'cors_wildcard' in backend/main.py:46", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in backend/main.py:46"}, "fullDescription": {"text": "Found a known-risky pattern (cors_wildcard). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a82c8d0a5ee8a4c2", "name": "Very large file: lms-v3_9.jsx (2951 lines)", "shortDescription": {"text": "Very large file: lms-v3_9.jsx (2951 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-f47481f4105c6b9d", "name": "Very large file: frontend/src/components/shared/StudentReportCard.jsx (1655 lines)", "shortDescription": {"text": "Very large file: frontend/src/components/shared/StudentReportCard.jsx (1655 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-bda27fc38860055e", "name": "Very large file: backend/main.py (11482 lines)", "shortDescription": {"text": "Very large file: backend/main.py (11482 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-ea3b5e389d8c9c0f", "name": "Low test-to-source ratio", "shortDescription": {"text": "Low test-to-source ratio"}, "fullDescription": {"text": "21 tests / 157 src (ratio 0.13)."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 54 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 170 placeholder/mock markers across 38 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-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. 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-17d866d91a7c451e", "name": "Agent instruction/config may expose a secret: CLAUDE.md", "shortDescription": {"text": "Agent instruction/config may expose a secret: CLAUDE.md"}, "fullDescription": {"text": "Agent-facing files are routinely pasted into LLM/tool contexts. Move literal tokens, keys, and passwords into a secret manager or document them as placeholders only."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-cbb5857940ba0dc2", "name": "Agent instruction/config may expose a secret: AGENTS.md", "shortDescription": {"text": "Agent instruction/config may expose a secret: AGENTS.md"}, "fullDescription": {"text": "Agent-facing files are routinely pasted into LLM/tool contexts. Move literal tokens, keys, and passwords into a secret manager or document them as placeholders only."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-2679282aa1c484b5", "name": "Agent authority lacks a verifier contract: AGENTS.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: AGENTS.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e725d2ab884fbd49", "name": "Multiple root agent instruction files without precedence", "shortDescription": {"text": "Multiple root agent instruction files without precedence"}, "fullDescription": {"text": "The repo has multiple top-level AI-coder instruction files. Without precedence rules, different agents may follow different policies."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2e65a6b1fb58db14", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/public/sw.js:54", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/public/sw.js:54"}, "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-f7547f4d99ab441f", "name": "Commented-code block (5 lines) in frontend/src/App.jsx:153", "shortDescription": {"text": "Commented-code block (5 lines) in frontend/src/App.jsx:153"}, "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-c45041fa2dcd5bc5", "name": "Commented-code block (6 lines) in frontend/src/components/ZoomMeetingView.jsx:104", "shortDescription": {"text": "Commented-code block (6 lines) in frontend/src/components/ZoomMeetingView.jsx:104"}, "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-81bb89db81190df5", "name": "Commented-code block (5 lines) in frontend/src/components/aurora/AuroraBackground.jsx:3", "shortDescription": {"text": "Commented-code block (5 lines) in frontend/src/components/aurora/AuroraBackground.jsx:3"}, "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-24966474c98d5b9e", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/teacher/StudentManageGrid.jsx:59", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/teacher/StudentManageGrid.jsx:59"}, "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-af0b3939c9275cce", "name": "Commented-code block (5 lines) in frontend/src/components/teacher/PendingReattemptsCard.jsx:8", "shortDescription": {"text": "Commented-code block (5 lines) in frontend/src/components/teacher/PendingReattemptsCard.jsx:8"}, "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-488fd4087c5bf3fc", "name": "Commented-code block (6 lines) in frontend/src/components/teacher/whatsapp/previewText.jsx:22", "shortDescription": {"text": "Commented-code block (6 lines) in frontend/src/components/teacher/whatsapp/previewText.jsx:22"}, "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-307c33ef40d32b29", "name": "Commented-code block (5 lines) in frontend/src/components/teacher/whatsapp/RecipientPicker.jsx:6", "shortDescription": {"text": "Commented-code block (5 lines) in frontend/src/components/teacher/whatsapp/RecipientPicker.jsx:6"}, "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-7398a387c76292cf", "name": "Commented-code block (5 lines) in frontend/src/lib/bulkImport.js:1", "shortDescription": {"text": "Commented-code block (5 lines) in frontend/src/lib/bulkImport.js:1"}, "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-9fd8f7a389fde740", "name": "Commented-code block (6 lines) in frontend/src/lib/studentBackup.js:3", "shortDescription": {"text": "Commented-code block (6 lines) in frontend/src/lib/studentBackup.js:3"}, "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-a5a4231696dc87a1", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/api.js:45", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/api.js:45"}, "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-627f56f907223ac6", "name": "Commented-code block (7 lines) in frontend/src/pages/student/StudentVideoPlayerPage.jsx:26", "shortDescription": {"text": "Commented-code block (7 lines) in frontend/src/pages/student/StudentVideoPlayerPage.jsx:26"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-711a6a9216942db5", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/pages/student/StudentProfilePage.jsx:82", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/pages/student/StudentProfilePage.jsx:82"}, "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-ebba83566d342865", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/pages/student/StudentLayout.jsx:36", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/pages/student/StudentLayout.jsx:36"}, "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-e8584ef029b81921", "name": "Network/subprocess call without timeout or try/except \u2014 backend/create_demo_accounts.py:18", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/create_demo_accounts.py:18"}, "fullDescription": {"text": "`requests.post(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-486d2eaebde64a3d", "name": "Legacy-named symbol `get_student_report_v2` in backend/main.py:3014", "shortDescription": {"text": "Legacy-named symbol `get_student_report_v2` in backend/main.py:3014"}, "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-b972847c6f47c575", "name": "Commented-code block (6 lines) in backend/main.py:2212", "shortDescription": {"text": "Commented-code block (6 lines) in backend/main.py:2212"}, "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-1adc2f9998705242", "name": "Network/subprocess call without timeout or try/except \u2014 backend/scripts/backup_db.py:33", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/scripts/backup_db.py:33"}, "fullDescription": {"text": "`subprocess.run(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d785c17821858dcb", "name": "22 env vars used in code but missing from .env.example", "shortDescription": {"text": "22 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_STREAM_API_TOKEN`, `DATABASE_URL`, `ENVIRONMENT`, `GEMINI_API_KEY`, `MODE`, `R2_ACCESS_KEY`, `R2_ACCOUNT_ID` + 14 more. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-02525d39071dd2c7", "name": "Near-duplicate function bodies in 5 places", "shortDescription": {"text": "Near-duplicate function bodies in 5 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/whatsapp.py:send_template, backend/whatsapp.py:send_template, backend/whatsapp.py:send_template, backend/whatsapp.py:send_template\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-49c98f7cedd9c977", "name": "Near-duplicate function bodies in 4 places", "shortDescription": {"text": "Near-duplicate function bodies in 4 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/whatsapp.py:get_session_state, backend/whatsapp.py:get_session_state, backend/whatsapp.py:get_session_state, backend/whatsapp.py:get_session_state\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2c04133e54348533", "name": "Near-duplicate function bodies in 2 places", "shortDescription": {"text": "Near-duplicate function bodies in 2 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/whatsapp.py:section, backend/whatsapp.py:section\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f9e11fcbaa9d43c5", "name": "Near-duplicate function bodies in 39 places", "shortDescription": {"text": "Near-duplicate function bodies in 39 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/main.py:get_dashboard_stats, backend/main.py:get_dashboard_activity, backend/main.py:create_standard, backend/main.py:update_standard\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-be46ea126aa5d8dc", "name": "Near-duplicate function bodies in 3 places", "shortDescription": {"text": "Near-duplicate function bodies in 3 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/main.py:fetch_subs, backend/main.py:fetch_subs, backend/main.py:fetch_subs\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-687925783d9879bd", "name": "Frontend route `standards` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `standards` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b8b53934f768e47a", "name": "Frontend route `standards/:standardId` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `standards/:standardId` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-de2502b0b3459135", "name": "Frontend route `standards/:standardId/subjects/:classId` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `standards/:standardId/subjects/:classId` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2269e240a511c745", "name": "Frontend route `live-classes` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `live-classes` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-864bee41afc52783", "name": "Frontend route `students/:studentId` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `students/:studentId` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-bba4402688749efc", "name": "Frontend route `more` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `more` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6a235105f730a349", "name": "Frontend route `question-bank` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `question-bank` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0650c16c2cf18347", "name": "Frontend route `profile` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `profile` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3f95a7341f0739b2", "name": "Frontend route `reports` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `reports` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0bd3de6bb01a9fd0", "name": "Frontend route `reminders` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `reminders` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f4859238d70b32ea", "name": "Frontend route `settings` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `settings` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-94ab7dbed6362111", "name": "Frontend route `attendance` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `attendance` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a10de9b759af6388", "name": "Frontend route `whatsapp` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `whatsapp` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-85f60fe95064fc86", "name": "Frontend route `calendar` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `calendar` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-db6e34d5087fa462", "name": "Frontend route `subjects/:classId` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `subjects/:classId` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4759bbc6867a984f", "name": "Frontend route `subjects/:classId/video/:videoId` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `subjects/:classId/video/:videoId` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3c9ee6d6d9e4d65c", "name": "Frontend route `tests/:testId/take` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `tests/:testId/take` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-5ede4210a4af08ac", "name": "Frontend route `tests/result` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `tests/result` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a977542d17510664", "name": "Frontend route `tests/review` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `tests/review` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3bc95044e30858e7", "name": "Frontend route `change-password` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `change-password` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-51157df775c4e8ec", "name": "Frontend route `leaderboard` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `leaderboard` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-85445084ede3b45b", "name": "Frontend route `report` has no Link/navigate to it \u2014 frontend/src/App.jsx", "shortDescription": {"text": "Frontend route `report` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-fd55aa0818a7c897", "name": "Unused endpoint: POST /api/auth/login", "shortDescription": {"text": "Unused endpoint: POST /api/auth/login"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/auth/login` 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-39b18ae8d1850128", "name": "Unused endpoint: POST /api/auth/verify-otp", "shortDescription": {"text": "Unused endpoint: POST /api/auth/verify-otp"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/auth/verify-otp` 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-17bbe95b93cfcfc6", "name": "Unused endpoint: POST /api/auth/resend-otp", "shortDescription": {"text": "Unused endpoint: POST /api/auth/resend-otp"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/auth/resend-otp` 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-49ac19bb61ef30a3", "name": "Unused endpoint: POST /api/auth/refresh", "shortDescription": {"text": "Unused endpoint: POST /api/auth/refresh"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/auth/refresh` 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-d5a39262ac205120", "name": "Unused endpoint: POST /api/auth/logout", "shortDescription": {"text": "Unused endpoint: POST /api/auth/logout"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/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-5c6eea00c792d5d2", "name": "Unused endpoint: POST /api/auth/verify-device", "shortDescription": {"text": "Unused endpoint: POST /api/auth/verify-device"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/auth/verify-device` 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-ee4aa5ddab88c9dc", "name": "Unused endpoint: GET /api/auth/me", "shortDescription": {"text": "Unused endpoint: GET /api/auth/me"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/auth/me` 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-0f6767eb74dd2470", "name": "Unused endpoint: PATCH /api/auth/profile", "shortDescription": {"text": "Unused endpoint: PATCH /api/auth/profile"}, "fullDescription": {"text": "`backend/main.py` declares `PATCH /api/auth/profile` 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-866cfadefccd0b5c", "name": "Unused endpoint: POST /api/auth/change-password", "shortDescription": {"text": "Unused endpoint: POST /api/auth/change-password"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/auth/change-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-d579aa9fcca5bf82", "name": "Unused endpoint: GET /api/dashboard/stats", "shortDescription": {"text": "Unused endpoint: GET /api/dashboard/stats"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/dashboard/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-65cf511ead5f19f7", "name": "Unused endpoint: GET /api/dashboard/activity", "shortDescription": {"text": "Unused endpoint: GET /api/dashboard/activity"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/dashboard/activity` 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-8f1af42f6d990f81", "name": "Unused endpoint: GET /api/dashboard/overview", "shortDescription": {"text": "Unused endpoint: GET /api/dashboard/overview"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/dashboard/overview` 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-57fbbf87f325d582", "name": "Unused endpoint: GET /api/dashboard/insights", "shortDescription": {"text": "Unused endpoint: GET /api/dashboard/insights"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/dashboard/insights` 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-922b01b318aaffd4", "name": "Unused endpoint: GET /api/standards", "shortDescription": {"text": "Unused endpoint: GET /api/standards"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/standards` 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-933962650579fa54", "name": "Unused endpoint: GET /api/standards/{standard_id}", "shortDescription": {"text": "Unused endpoint: GET /api/standards/{standard_id}"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/standards/{standard_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8510c5de7b9d7322", "name": "Unused endpoint: POST /api/standards", "shortDescription": {"text": "Unused endpoint: POST /api/standards"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/standards` 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-aaf8743f3baba683", "name": "Unused endpoint: PATCH /api/standards/{standard_id}", "shortDescription": {"text": "Unused endpoint: PATCH /api/standards/{standard_id}"}, "fullDescription": {"text": "`backend/main.py` declares `PATCH /api/standards/{standard_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-fa5d58f6df0a26e7", "name": "Unused endpoint: DELETE /api/standards/{standard_id}", "shortDescription": {"text": "Unused endpoint: DELETE /api/standards/{standard_id}"}, "fullDescription": {"text": "`backend/main.py` declares `DELETE /api/standards/{standard_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e49817677de31706", "name": "Unused endpoint: GET /api/subjects", "shortDescription": {"text": "Unused endpoint: GET /api/subjects"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/subjects` 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-00db63fd110adcd0", "name": "Unused endpoint: POST /api/subjects", "shortDescription": {"text": "Unused endpoint: POST /api/subjects"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/subjects` 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-e46adb2ef997c8f7", "name": "Unused endpoint: PATCH /api/subjects/{subject_id}", "shortDescription": {"text": "Unused endpoint: PATCH /api/subjects/{subject_id}"}, "fullDescription": {"text": "`backend/main.py` declares `PATCH /api/subjects/{subject_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-94299d1d891a24b5", "name": "Unused endpoint: DELETE /api/subjects/{subject_id}", "shortDescription": {"text": "Unused endpoint: DELETE /api/subjects/{subject_id}"}, "fullDescription": {"text": "`backend/main.py` declares `DELETE /api/subjects/{subject_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9d84d5f4e65de0d9", "name": "Unused endpoint: GET /api/students", "shortDescription": {"text": "Unused endpoint: GET /api/students"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/students` 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-dfc073b66dedea5c", "name": "Unused endpoint: GET /api/students/{student_id}", "shortDescription": {"text": "Unused endpoint: GET /api/students/{student_id}"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/students/{student_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d753018fd7b46c77", "name": "Unused endpoint: GET /api/reports/standard/{standard_id}/analytics", "shortDescription": {"text": "Unused endpoint: GET /api/reports/standard/{standard_id}/analytics"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/reports/standard/{standard_id}/analytics` 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-4452c86d86712636", "name": "Unused endpoint: GET /api/reports/performance", "shortDescription": {"text": "Unused endpoint: GET /api/reports/performance"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/reports/performance` 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-c6def581eed32385", "name": "Unused endpoint: GET /api/students/{student_id}/report", "shortDescription": {"text": "Unused endpoint: GET /api/students/{student_id}/report"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/students/{student_id}/report` 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-093ba530ee58839f", "name": "Unused endpoint: GET /api/students/{student_id}/report/v2", "shortDescription": {"text": "Unused endpoint: GET /api/students/{student_id}/report/v2"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/students/{student_id}/report/v2` 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-caa8bf7835658645", "name": "Unused endpoint: POST /api/admin/create-student", "shortDescription": {"text": "Unused endpoint: POST /api/admin/create-student"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/admin/create-student` 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-8e286f21f4d1789b", "name": "Unused endpoint: POST /api/admin/backfill-student-codes", "shortDescription": {"text": "Unused endpoint: POST /api/admin/backfill-student-codes"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/admin/backfill-student-codes` 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-01d0c7f9938fa119", "name": "Unused endpoint: PATCH /api/students/me", "shortDescription": {"text": "Unused endpoint: PATCH /api/students/me"}, "fullDescription": {"text": "`backend/main.py` declares `PATCH /api/students/me` 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-46fb4fa76041235e", "name": "Unused endpoint: GET /api/students/me/videos", "shortDescription": {"text": "Unused endpoint: GET /api/students/me/videos"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/students/me/videos` 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-3e63f9f2db034c85", "name": "Unused endpoint: GET /api/student/calendar-events", "shortDescription": {"text": "Unused endpoint: GET /api/student/calendar-events"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/student/calendar-events` 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-933163bbf8aa0ba5", "name": "Unused endpoint: GET /api/student/whats-new", "shortDescription": {"text": "Unused endpoint: GET /api/student/whats-new"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/student/whats-new` 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-340dd283c54a0595", "name": "Unused endpoint: POST /api/student/seen", "shortDescription": {"text": "Unused endpoint: POST /api/student/seen"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/student/seen` 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-9c5206d4180fc009", "name": "Unused endpoint: POST /api/students/me/avatar", "shortDescription": {"text": "Unused endpoint: POST /api/students/me/avatar"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/students/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-d0d3a57d3aee6ca0", "name": "Unused endpoint: GET /api/teacher/thumbnail", "shortDescription": {"text": "Unused endpoint: GET /api/teacher/thumbnail"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/teacher/thumbnail` 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-963384701b1b9b5a", "name": "Unused endpoint: POST /api/teacher/thumbnail", "shortDescription": {"text": "Unused endpoint: POST /api/teacher/thumbnail"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/teacher/thumbnail` 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-556707c3b6a769e2", "name": "Unused endpoint: POST /api/teacher/profile-photo", "shortDescription": {"text": "Unused endpoint: POST /api/teacher/profile-photo"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/teacher/profile-photo` 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-6c323c0dfb7d781a", "name": "Unused endpoint: PATCH /api/students/{student_id}/block", "shortDescription": {"text": "Unused endpoint: PATCH /api/students/{student_id}/block"}, "fullDescription": {"text": "`backend/main.py` declares `PATCH /api/students/{student_id}/block` 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-88e94d464d5ae918", "name": "Unused endpoint: POST /api/students/{student_id}/reset-password", "shortDescription": {"text": "Unused endpoint: POST /api/students/{student_id}/reset-password"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/students/{student_id}/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-fb1bec6cd4b5bab0", "name": "Unused endpoint: GET /api/students/{student_id}/password", "shortDescription": {"text": "Unused endpoint: GET /api/students/{student_id}/password"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/students/{student_id}/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-60d0a03fcafa0d84", "name": "Unused endpoint: PATCH /api/students/{student_id}", "shortDescription": {"text": "Unused endpoint: PATCH /api/students/{student_id}"}, "fullDescription": {"text": "`backend/main.py` declares `PATCH /api/students/{student_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-611e710b80d402d3", "name": "Unused endpoint: DELETE /api/students/{student_id}", "shortDescription": {"text": "Unused endpoint: DELETE /api/students/{student_id}"}, "fullDescription": {"text": "`backend/main.py` declares `DELETE /api/students/{student_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-85bd28b98f0899e1", "name": "Unused endpoint: PATCH /api/students/{student_id}/unenroll", "shortDescription": {"text": "Unused endpoint: PATCH /api/students/{student_id}/unenroll"}, "fullDescription": {"text": "`backend/main.py` declares `PATCH /api/students/{student_id}/unenroll` 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-a69d0968599dbbc9", "name": "Unused endpoint: GET /api/videos", "shortDescription": {"text": "Unused endpoint: GET /api/videos"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/videos` 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-b48afca31cb15859", "name": "Unused endpoint: GET /api/videos/{video_id}/viewers", "shortDescription": {"text": "Unused endpoint: GET /api/videos/{video_id}/viewers"}, "fullDescription": {"text": "`backend/main.py` declares `GET /api/videos/{video_id}/viewers` 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-de68d1932d6fb401", "name": "Unused endpoint: POST /api/videos/youtube", "shortDescription": {"text": "Unused endpoint: POST /api/videos/youtube"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/videos/youtube` 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-60cbbbb8e26a70e4", "name": "Unused endpoint: POST /api/videos", "shortDescription": {"text": "Unused endpoint: POST /api/videos"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/videos` 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-cb2cb5fe9d17dd73", "name": "Unused endpoint: POST /api/videos/upload", "shortDescription": {"text": "Unused endpoint: POST /api/videos/upload"}, "fullDescription": {"text": "`backend/main.py` declares `POST /api/videos/upload` 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/18479"}, "properties": {"repository": "roshannandhu/Udaya_LMS", "repoUrl": "https://github.com/roshannandhu/Udaya_LMS", "branch": "main"}, "results": [{"ruleId": "scanner-c48073a20c9da3f9", "level": "note", "message": {"text": "Possibly dead Python function: build_report_pdf"}, "properties": {"repobilityId": "fec4c70e80b110f1", "scanner": "scanner-primary", "fingerprint": "c48073a20c9da3f9", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/whatsapp.py:626"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-30b1027ef22ab25f", "level": "note", "message": {"text": "Possibly dead Python function: build_report_image"}, "properties": {"repobilityId": "9d70cd704025319d", "scanner": "scanner-primary", "fingerprint": "30b1027ef22ab25f", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/whatsapp.py:711"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2933efb86c372873", "level": "note", "message": {"text": "Possibly dead Python function: request_with_retry"}, "properties": {"repobilityId": "babaea4d4ef5c128", "scanner": "scanner-primary", "fingerprint": "2933efb86c372873", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:89"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-e1e3e996f53b9889", "level": "note", "message": {"text": "Possibly dead Python function: save_and_insert"}, "properties": {"repobilityId": "efd4b1139dbd39f5", "scanner": "scanner-primary", "fingerprint": "e1e3e996f53b9889", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:679"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-b52358acf479a1bf", "level": "note", "message": {"text": "Possibly dead Python function: zoom_get_zak"}, "properties": {"repobilityId": "92b216902ab1bd21", "scanner": "scanner-primary", "fingerprint": "b52358acf479a1bf", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:739"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-c98f35dc863edc6e", "level": "note", "message": {"text": "Possibly dead Python function: verify_token"}, "properties": {"repobilityId": "6a5c4adccfca0a15", "scanner": "scanner-primary", "fingerprint": "c98f35dc863edc6e", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:987"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-1eee186884b93539", "level": "note", "message": {"text": "Possibly dead Python function: login_rate_limit"}, "properties": {"repobilityId": "069c5e640d7da48a", "scanner": "scanner-primary", "fingerprint": "1eee186884b93539", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1215"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-fe76e00d4b7a9cff", "level": "note", "message": {"text": "Possibly dead Python function: fetch_students"}, "properties": {"repobilityId": "b06c674115bbcdfc", "scanner": "scanner-primary", "fingerprint": "fe76e00d4b7a9cff", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1559"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-78e9c3d33b7a269c", "level": "note", "message": {"text": "Possibly dead Python function: fetch_subjects"}, "properties": {"repobilityId": "2968b1bdee1ab3d3", "scanner": "scanner-primary", "fingerprint": "78e9c3d33b7a269c", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:2729"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-bc24447d84a7765d", "level": "note", "message": {"text": "Possibly dead Python function: fetch_broadcasts"}, "properties": {"repobilityId": "10b94b585226e267", "scanner": "scanner-primary", "fingerprint": "bc24447d84a7765d", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1561"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-517fe1fb4e7f306c", "level": "note", "message": {"text": "Possibly dead Python function: fetch_class_ids"}, "properties": {"repobilityId": "e29ee8a0a03cd6a3", "scanner": "scanner-primary", "fingerprint": "517fe1fb4e7f306c", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1562"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-b0718255478175c8", "level": "note", "message": {"text": "Possibly dead Python function: fetch_subs"}, "properties": {"repobilityId": "e39ab9d92d8e5201", "scanner": "scanner-primary", "fingerprint": "b0718255478175c8", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:7530"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-002b1240ce921845", "level": "note", "message": {"text": "Possibly dead Python function: fetch_studs"}, "properties": {"repobilityId": "4ad2d7302df95025", "scanner": "scanner-primary", "fingerprint": "002b1240ce921845", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1961"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-86cb5970badf9030", "level": "note", "message": {"text": "Possibly dead Python function: fetch_links"}, "properties": {"repobilityId": "8399c726228be391", "scanner": "scanner-primary", "fingerprint": "86cb5970badf9030", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1677"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-19071fa8a9f40da9", "level": "note", "message": {"text": "Possibly dead Python function: fetch_tests_cnt"}, "properties": {"repobilityId": "be12e24014d4ab4c", "scanner": "scanner-primary", "fingerprint": "19071fa8a9f40da9", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1695"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-ffab1c04c88b0dee", "level": "note", "message": {"text": "Possibly dead Python function: fetch_asg"}, "properties": {"repobilityId": "3388450c304da84a", "scanner": "scanner-primary", "fingerprint": "ffab1c04c88b0dee", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1696"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d02f5f0087a97291", "level": "note", "message": {"text": "Possibly dead Python function: fetch_lc"}, "properties": {"repobilityId": "d9708f68d2127291", "scanner": "scanner-primary", "fingerprint": "d02f5f0087a97291", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1698"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-7d6433e91ce9ac69", "level": "note", "message": {"text": "Possibly dead Python function: fetch_upc_tests"}, "properties": {"repobilityId": "115f53a901b58e4d", "scanner": "scanner-primary", "fingerprint": "7d6433e91ce9ac69", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1699"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-4fe7a6059b707ea4", "level": "note", "message": {"text": "Possibly dead Python function: fetch_tests"}, "properties": {"repobilityId": "b093b84ff0ea43ec", "scanner": "scanner-primary", "fingerprint": "4fe7a6059b707ea4", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:2776"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-253f82c49c9bc1ff", "level": "note", "message": {"text": "Possibly dead Python function: fetch_videos"}, "properties": {"repobilityId": "6ef10ec5c093c69a", "scanner": "scanner-primary", "fingerprint": "253f82c49c9bc1ff", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:2778"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-0ca2340179762112", "level": "note", "message": {"text": "Possibly dead Python function: fetch_assignments"}, "properties": {"repobilityId": "df66e3b016cac1cc", "scanner": "scanner-primary", "fingerprint": "0ca2340179762112", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:2780"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-ee75a550154d1f0f", "level": "note", "message": {"text": "Possibly dead Python function: fetch_live"}, "properties": {"repobilityId": "69c7864d3735d50f", "scanner": "scanner-primary", "fingerprint": "ee75a550154d1f0f", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1989"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-4536f177713a93d4", "level": "note", "message": {"text": "Possibly dead Python function: fetch_att_30"}, "properties": {"repobilityId": "84f18fb3b04e0789", "scanner": "scanner-primary", "fingerprint": "4536f177713a93d4", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1993"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-615d71a135d6eb6b", "level": "note", "message": {"text": "Possibly dead Python function: fetch_attempts_30"}, "properties": {"repobilityId": "a64232f355a57662", "scanner": "scanner-primary", "fingerprint": "615d71a135d6eb6b", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1996"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-7c3245c19f6fdcbc", "level": "note", "message": {"text": "Possibly dead Python function: fetch_subm_30"}, "properties": {"repobilityId": "0475a83343c62054", "scanner": "scanner-primary", "fingerprint": "7c3245c19f6fdcbc", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:1999"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-30167e1970a2b92b", "level": "note", "message": {"text": "Possibly dead Python function: fetch_questions"}, "properties": {"repobilityId": "a436dde21101d073", "scanner": "scanner-primary", "fingerprint": "30167e1970a2b92b", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:2020"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6b25944e151b7235", "level": "note", "message": {"text": "Possibly dead Python function: fetch_test_attempts"}, "properties": {"repobilityId": "eef2b1ae3b538f43", "scanner": "scanner-primary", "fingerprint": "6b25944e151b7235", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:2024"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-77af0cd041cee449", "level": "note", "message": {"text": "Possibly dead Python function: fetch_video_progress"}, "properties": {"repobilityId": "948aa2bdd7695478", "scanner": "scanner-primary", "fingerprint": "77af0cd041cee449", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:2811"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3fbaffc9bb5ec657", "level": "note", "message": {"text": "Possibly dead Python function: fetch_submissions"}, "properties": {"repobilityId": "90f648f435e9f2a8", "scanner": "scanner-primary", "fingerprint": "3fbaffc9bb5ec657", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py:2817"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-831f09651693f238", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 lms-v3_9.jsx:338"}, "properties": {"repobilityId": "4dddfce6c14b660f", "scanner": "scanner-primary", "fingerprint": "831f09651693f238", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a8595a0f049109f3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/student/StudentAssignmentSheet.jsx:165"}, "properties": {"repobilityId": "9770a0445f824675", "scanner": "scanner-primary", "fingerprint": "a8595a0f049109f3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-80b8010bb5d628ea", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/StudentReportCard.jsx:1402"}, "properties": {"repobilityId": "430e4bbedb8952b7", "scanner": "scanner-primary", "fingerprint": "80b8010bb5d628ea", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6c996b65b1d6c8d7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/SearchPalette.jsx:60"}, "properties": {"repobilityId": "327f1850c49c6a6d", "scanner": "scanner-primary", "fingerprint": "6c996b65b1d6c8d7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-fef09a079f12ee6a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/Sidebar.jsx:43"}, "properties": {"repobilityId": "46617fbd94bbea2f", "scanner": "scanner-primary", "fingerprint": "fef09a079f12ee6a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-505b1e6574b8c596", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/LeaderboardPanel.jsx:113"}, "properties": {"repobilityId": "48340a965df52f6e", "scanner": "scanner-primary", "fingerprint": "505b1e6574b8c596", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-132d32d924563576", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/TopBar.jsx:42"}, "properties": {"repobilityId": "22967fb186fa7065", "scanner": "scanner-primary", "fingerprint": "132d32d924563576", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8911715c029ab600", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/NotificationBell.jsx:113"}, "properties": {"repobilityId": "a7c0c6c02e70d77a", "scanner": "scanner-primary", "fingerprint": "8911715c029ab600", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5a7ac294db90d252", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/shared/TopNav.jsx:52"}, "properties": {"repobilityId": "59dccb3666bbbc3c", "scanner": "scanner-primary", "fingerprint": "5a7ac294db90d252", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c77c4c8479a1f86e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/ui/index.tsx:239"}, "properties": {"repobilityId": "327c2128d55641b4", "scanner": "scanner-primary", "fingerprint": "c77c4c8479a1f86e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5bc0027755f490d7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/cards/PageHeader.jsx:20"}, "properties": {"repobilityId": "86627a466dce89aa", "scanner": "scanner-primary", "fingerprint": "5bc0027755f490d7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6a11938de1ddf192", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/cards/EventCard.jsx:41"}, "properties": {"repobilityId": "0fe7d8bd29fbb71e", "scanner": "scanner-primary", "fingerprint": "6a11938de1ddf192", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-476031e2e0b00065", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/TestResultsSheet.jsx:343"}, "properties": {"repobilityId": "5486c44a6ea090ce", "scanner": "scanner-primary", "fingerprint": "476031e2e0b00065", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4c03d5b2faff0074", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/StudentManageGrid.jsx:51"}, "properties": {"repobilityId": "591045f6d69f8260", "scanner": "scanner-primary", "fingerprint": "4c03d5b2faff0074", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-42593fa68d0bf394", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/AttendanceStudentCard.jsx:98"}, "properties": {"repobilityId": "3690eca6b60d30cb", "scanner": "scanner-primary", "fingerprint": "42593fa68d0bf394", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-88fb5e65f4a46c7b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/AttendanceTab.jsx:274"}, "properties": {"repobilityId": "6c002865b70f6706", "scanner": "scanner-primary", "fingerprint": "88fb5e65f4a46c7b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-dc9f6c9ca3ec41ba", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/LiveClassAttendanceSheet.jsx:58"}, "properties": {"repobilityId": "b311853466e6cc81", "scanner": "scanner-primary", "fingerprint": "dc9f6c9ca3ec41ba", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ee3a968fb65d93ff", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/PerformancePanel.jsx:124"}, "properties": {"repobilityId": "96f7218a616ee668", "scanner": "scanner-primary", "fingerprint": "ee3a968fb65d93ff", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-df383dcc563da447", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/BulkImportModal.jsx:276"}, "properties": {"repobilityId": "3af1d9a453b63e00", "scanner": "scanner-primary", "fingerprint": "df383dcc563da447", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-22d7bc3a11f15e4c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/NewAssignmentModal.jsx:135"}, "properties": {"repobilityId": "27db8ff5e3261208", "scanner": "scanner-primary", "fingerprint": "22d7bc3a11f15e4c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9e122896bd8877b2", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/AssignmentSubmissionsSheet.jsx:136"}, "properties": {"repobilityId": "e7a0d56e15da27c2", "scanner": "scanner-primary", "fingerprint": "9e122896bd8877b2", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1d107cc4303e4bcc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/BroadcastThread.jsx:336"}, "properties": {"repobilityId": "8a2bb6e22da72ad4", "scanner": "scanner-primary", "fingerprint": "1d107cc4303e4bcc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-98586d19cb070312", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/Modals.jsx:92"}, "properties": {"repobilityId": "af5f8b74c3dd7a8e", "scanner": "scanner-primary", "fingerprint": "98586d19cb070312", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-de1fffa78abcefa1", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/PendingReattemptsCard.jsx:91"}, "properties": {"repobilityId": "7ee1d22002c524cf", "scanner": "scanner-primary", "fingerprint": "de1fffa78abcefa1", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-17386cde695c7104", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/LiveAbsenteesCard.jsx:19"}, "properties": {"repobilityId": "ca1e4dfe2da91e4e", "scanner": "scanner-primary", "fingerprint": "17386cde695c7104", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7d03bc3221c9b0dd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/AssignmentStatusCard.jsx:25"}, "properties": {"repobilityId": "384fa139c49edc7b", "scanner": "scanner-primary", "fingerprint": "7d03bc3221c9b0dd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8260642e5e4810e0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/VideoEngagementCard.jsx:42"}, "properties": {"repobilityId": "3c44e743552db166", "scanner": "scanner-primary", "fingerprint": "8260642e5e4810e0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-bbb496b26730c796", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/PerformanceSnapshotCard.jsx:82"}, "properties": {"repobilityId": "925576e379aab426", "scanner": "scanner-primary", "fingerprint": "bbb496b26730c796", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c39978fd31247e26", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/dashboard/CopySuspectsCard.jsx:26"}, "properties": {"repobilityId": "2483ef9fd054d466", "scanner": "scanner-primary", "fingerprint": "c39978fd31247e26", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-49d8221a80bf029e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/subject/NoteFormModal.jsx:61"}, "properties": {"repobilityId": "1481cc841717f6dd", "scanner": "scanner-primary", "fingerprint": "49d8221a80bf029e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f087ecb6e9b26d36", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/subject/VideoViewersModal.jsx:94"}, "properties": {"repobilityId": "37fef72df0c03475", "scanner": "scanner-primary", "fingerprint": "f087ecb6e9b26d36", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0ff31b4e30e2fc2d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/subject/NotesSection.jsx:26"}, "properties": {"repobilityId": "7f0db63fc592ff5d", "scanner": "scanner-primary", "fingerprint": "0ff31b4e30e2fc2d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c8e601c0551f3bcd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/RecentMessagesTable.jsx:58"}, "properties": {"repobilityId": "4ccda8b115a915a1", "scanner": "scanner-primary", "fingerprint": "c8e601c0551f3bcd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ca81e8a165d9c19b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/ClassPicker.jsx:90"}, "properties": {"repobilityId": "411cf8b8718d9edd", "scanner": "scanner-primary", "fingerprint": "ca81e8a165d9c19b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-babcae604a37e2e3", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/teacher/whatsapp/previewText.jsx:51"}, "properties": {"repobilityId": "ed80f3061d5853dc", "scanner": "scanner-primary", "fingerprint": "babcae604a37e2e3", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-38cb1c99f6828539", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/WhatsAppPreview.jsx:18"}, "properties": {"repobilityId": "16421fdf32fc5754", "scanner": "scanner-primary", "fingerprint": "38cb1c99f6828539", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3b74731763c8cd11", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/HistoryTab.jsx:96"}, "properties": {"repobilityId": "5da766712c4568f1", "scanner": "scanner-primary", "fingerprint": "3b74731763c8cd11", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-88c48969e16878eb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/RecipientPicker.jsx:103"}, "properties": {"repobilityId": "6b0fc770625c7f06", "scanner": "scanner-primary", "fingerprint": "88c48969e16878eb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-62e0456da585a09e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/SendWizard.jsx:301"}, "properties": {"repobilityId": "b5c532061a0e3b0b", "scanner": "scanner-primary", "fingerprint": "62e0456da585a09e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3338dff3dc1c1c45", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/TemplatesTab.jsx:111"}, "properties": {"repobilityId": "0040f14d5f2c1530", "scanner": "scanner-primary", "fingerprint": "3338dff3dc1c1c45", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-daa26bc4afeb1047", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/PendingActions.jsx:65"}, "properties": {"repobilityId": "0ce84f6018d361b7", "scanner": "scanner-primary", "fingerprint": "daa26bc4afeb1047", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0b58931d0a854e18", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/InboxTab.jsx:64"}, "properties": {"repobilityId": "42770022cdf0f465", "scanner": "scanner-primary", "fingerprint": "0b58931d0a854e18", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-774b45d119a01107", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/AutomationTab.jsx:213"}, "properties": {"repobilityId": "8c33f1f21c55c1fb", "scanner": "scanner-primary", "fingerprint": "774b45d119a01107", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-80e740c6ee96bc76", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/Composer.jsx:260"}, "properties": {"repobilityId": "bf2e80875db0bd1b", "scanner": "scanner-primary", "fingerprint": "80e740c6ee96bc76", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0bda724635d177e9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/teacher/whatsapp/OverviewTab.jsx:78"}, "properties": {"repobilityId": "53386b42c71b1ece", "scanner": "scanner-primary", "fingerprint": "0bda724635d177e9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b3fbe8b86b78201a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentHomePage.jsx:56"}, "properties": {"repobilityId": "8bcdf9cb9bbcc7d6", "scanner": "scanner-primary", "fingerprint": "b3fbe8b86b78201a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f7f36c79a8c1388c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentSubjectViewPage.jsx:211"}, "properties": {"repobilityId": "455ce1f29cd17af9", "scanner": "scanner-primary", "fingerprint": "f7f36c79a8c1388c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-66e5955ad66dd158", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentVideoPlayerPage.jsx:810"}, "properties": {"repobilityId": "3bb68d2aef317901", "scanner": "scanner-primary", "fingerprint": "66e5955ad66dd158", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7e5b8046932ed0df", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentTestReviewPage.jsx:60"}, "properties": {"repobilityId": "e544d3f06d28fa47", "scanner": "scanner-primary", "fingerprint": "7e5b8046932ed0df", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1a5d077bd4aba17d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentProfilePage.jsx:365"}, "properties": {"repobilityId": "138ce5e8b0a7a2d5", "scanner": "scanner-primary", "fingerprint": "1a5d077bd4aba17d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-24a6e791b5e7c030", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentBroadcastsPage.jsx:143"}, "properties": {"repobilityId": "a65ef5349c082f6a", "scanner": "scanner-primary", "fingerprint": "24a6e791b5e7c030", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4f5715f9e98dbf58", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/student/StudentTestTakingPage.jsx:370"}, "properties": {"repobilityId": "78022ce16aecd7b2", "scanner": "scanner-primary", "fingerprint": "4f5715f9e98dbf58", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-bdf0995220aaa538", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/BroadcastsPage.jsx:184"}, "properties": {"repobilityId": "e04c7cf01b80a615", "scanner": "scanner-primary", "fingerprint": "bdf0995220aaa538", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-70da55281aa912f0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/TodayPage.jsx:53"}, "properties": {"repobilityId": "11c309630f64a549", "scanner": "scanner-primary", "fingerprint": "70da55281aa912f0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e358e13e5e58aecb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/QuestionBankPage.jsx:144"}, "properties": {"repobilityId": "7e4f92cb9c63fe57", "scanner": "scanner-primary", "fingerprint": "e358e13e5e58aecb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-62cc96a767db41fa", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/WhatsAppCenterPage.jsx:177"}, "properties": {"repobilityId": "74126614c6e60a2f", "scanner": "scanner-primary", "fingerprint": "62cc96a767db41fa", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-dd14a5900f5649da", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/StandardDetailPage.jsx:387"}, "properties": {"repobilityId": "570b1e5debddf1df", "scanner": "scanner-primary", "fingerprint": "dd14a5900f5649da", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b18719f9e3058b68", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/StudentDetailPage.jsx:267"}, "properties": {"repobilityId": "89b48003d652c843", "scanner": "scanner-primary", "fingerprint": "b18719f9e3058b68", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7e93e140587aa5ae", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/SettingsPage.jsx:378"}, "properties": {"repobilityId": "b58930a314e3cb95", "scanner": "scanner-primary", "fingerprint": "7e93e140587aa5ae", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-25b50dd4daa81bab", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/SubjectDetailPage.jsx:46"}, "properties": {"repobilityId": "4ae5fdc4b8fae54e", "scanner": "scanner-primary", "fingerprint": "25b50dd4daa81bab", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-947b3937d66ff5dc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/teacher/StudentsPage.jsx:175"}, "properties": {"repobilityId": "f35ec21b1f847dc1", "scanner": "scanner-primary", "fingerprint": "947b3937d66ff5dc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d63da3583b14afc0", "level": "warning", "message": {"text": "Dockerfile runs as root: Dockerfile"}, "properties": {"repobilityId": "a2ed1bd120e507db", "scanner": "scanner-primary", "fingerprint": "d63da3583b14afc0", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-e066691601852931", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.11-slim"}, "properties": {"repobilityId": "f391052c9bfd7e8b", "scanner": "scanner-primary", "fingerprint": "e066691601852931", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 1}}}]}, {"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-4686f0816b35e560", "level": "error", "message": {"text": "Runtime dotenv file present in repo: frontend/.env.local"}, "properties": {"repobilityId": "a4813eec87cc3ac3", "scanner": "scanner-primary", "fingerprint": "4686f0816b35e560", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets", "config", "env-file", "runtime-env", "env_file_with_secret"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/.env.local"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-9e9c231a310fb881", "level": "error", "message": {"text": "Runtime dotenv file present in repo: backend/.env"}, "properties": {"repobilityId": "13e19f78c8806475", "scanner": "scanner-primary", "fingerprint": "9e9c231a310fb881", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets", "config", "env-file", "runtime-env", "env_file_with_secret"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/.env"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-81fde056e5d6aff7", "level": "error", "message": {"text": "Possible secret in frontend/src/store.js"}, "properties": {"repobilityId": "c7b1560ec1a184e7", "scanner": "scanner-primary", "fingerprint": "81fde056e5d6aff7", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/store.js"}, "region": {"startLine": 27}}}]}, {"ruleId": "scanner-364030da3280fd5f", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/src/pages/student/StudentVideoPlayerPage.jsx:257"}, "properties": {"repobilityId": "1490b85d0156f112", "scanner": "scanner-primary", "fingerprint": "364030da3280fd5f", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/pages/student/StudentVideoPlayerPage.jsx"}, "region": {"startLine": 257}}}]}, {"ruleId": "scanner-0e83e6a03db76e23", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in backend/main.py:46"}, "properties": {"repobilityId": "68276992e65b84f9", "scanner": "scanner-primary", "fingerprint": "0e83e6a03db76e23", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py"}, "region": {"startLine": 46}}}]}, {"ruleId": "scanner-a82c8d0a5ee8a4c2", "level": "note", "message": {"text": "Very large file: lms-v3_9.jsx (2951 lines)"}, "properties": {"repobilityId": "cc721d58d732f486", "scanner": "scanner-primary", "fingerprint": "a82c8d0a5ee8a4c2", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-f47481f4105c6b9d", "level": "note", "message": {"text": "Very large file: frontend/src/components/shared/StudentReportCard.jsx (1655 lines)"}, "properties": {"repobilityId": "ce80052463b5d6be", "scanner": "scanner-primary", "fingerprint": "f47481f4105c6b9d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-bda27fc38860055e", "level": "note", "message": {"text": "Very large file: backend/main.py (11482 lines)"}, "properties": {"repobilityId": "fb764a5c13811891", "scanner": "scanner-primary", "fingerprint": "bda27fc38860055e", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-ea3b5e389d8c9c0f", "level": "note", "message": {"text": "Low test-to-source ratio"}, "properties": {"repobilityId": "ef7b2552cc00a375", "scanner": "scanner-primary", "fingerprint": "ea3b5e389d8c9c0f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["tests"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "4d42e5d6a97ccceb", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "d8cdc9070e10ae72", "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": "3c2bfa804894a6cb", "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": "e42587a66e068e25", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "03430bd49f557e85", "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": "c5c3c186502d61ab", "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": "b581394de083539d", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-17d866d91a7c451e", "level": "error", "message": {"text": "Agent instruction/config may expose a secret: CLAUDE.md"}, "properties": {"repobilityId": "ccce5984e58a48f0", "scanner": "scanner-primary", "fingerprint": "17d866d91a7c451e", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["agent-instructions", "secrets", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "CLAUDE.md"}, "region": {"startLine": 224}}}]}, {"ruleId": "scanner-cbb5857940ba0dc2", "level": "error", "message": {"text": "Agent instruction/config may expose a secret: AGENTS.md"}, "properties": {"repobilityId": "e12c7213d5eadf3e", "scanner": "scanner-primary", "fingerprint": "cbb5857940ba0dc2", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["agent-instructions", "secrets", "agents_md"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "AGENTS.md"}, "region": {"startLine": 63}}}]}, {"ruleId": "scanner-2679282aa1c484b5", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: AGENTS.md"}, "properties": {"repobilityId": "27d579812e6be614", "scanner": "scanner-primary", "fingerprint": "2679282aa1c484b5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "agents_md"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "AGENTS.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-e725d2ab884fbd49", "level": "note", "message": {"text": "Multiple root agent instruction files without precedence"}, "properties": {"repobilityId": "1953db6c89508d22", "scanner": "scanner-primary", "fingerprint": "e725d2ab884fbd49", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["agent-instructions", "governance"]}}, {"ruleId": "scanner-2e65a6b1fb58db14", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/public/sw.js:54"}, "properties": {"repobilityId": "36aade5f3e324e0b", "scanner": "scanner-primary", "fingerprint": "2e65a6b1fb58db14", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-f7547f4d99ab441f", "level": "none", "message": {"text": "Commented-code block (5 lines) in frontend/src/App.jsx:153"}, "properties": {"repobilityId": "7b2c8491cb9ee532", "scanner": "scanner-primary", "fingerprint": "f7547f4d99ab441f", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c45041fa2dcd5bc5", "level": "none", "message": {"text": "Commented-code block (6 lines) in frontend/src/components/ZoomMeetingView.jsx:104"}, "properties": {"repobilityId": "788cee470f000279", "scanner": "scanner-primary", "fingerprint": "c45041fa2dcd5bc5", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-81bb89db81190df5", "level": "none", "message": {"text": "Commented-code block (5 lines) in frontend/src/components/aurora/AuroraBackground.jsx:3"}, "properties": {"repobilityId": "406dd5aa4a89ce43", "scanner": "scanner-primary", "fingerprint": "81bb89db81190df5", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-24966474c98d5b9e", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/teacher/StudentManageGrid.jsx:59"}, "properties": {"repobilityId": "61416b852458f27f", "scanner": "scanner-primary", "fingerprint": "24966474c98d5b9e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-af0b3939c9275cce", "level": "none", "message": {"text": "Commented-code block (5 lines) in frontend/src/components/teacher/PendingReattemptsCard.jsx:8"}, "properties": {"repobilityId": "3b57736509a296f9", "scanner": "scanner-primary", "fingerprint": "af0b3939c9275cce", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-488fd4087c5bf3fc", "level": "none", "message": {"text": "Commented-code block (6 lines) in frontend/src/components/teacher/whatsapp/previewText.jsx:22"}, "properties": {"repobilityId": "0937086d3ac2865e", "scanner": "scanner-primary", "fingerprint": "488fd4087c5bf3fc", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-307c33ef40d32b29", "level": "none", "message": {"text": "Commented-code block (5 lines) in frontend/src/components/teacher/whatsapp/RecipientPicker.jsx:6"}, "properties": {"repobilityId": "1cff47ed10e6d85a", "scanner": "scanner-primary", "fingerprint": "307c33ef40d32b29", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-7398a387c76292cf", "level": "none", "message": {"text": "Commented-code block (5 lines) in frontend/src/lib/bulkImport.js:1"}, "properties": {"repobilityId": "7aeac94fc0b3717a", "scanner": "scanner-primary", "fingerprint": "7398a387c76292cf", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-9fd8f7a389fde740", "level": "none", "message": {"text": "Commented-code block (6 lines) in frontend/src/lib/studentBackup.js:3"}, "properties": {"repobilityId": "6537f9a853a3b5cb", "scanner": "scanner-primary", "fingerprint": "9fd8f7a389fde740", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a5a4231696dc87a1", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/api.js:45"}, "properties": {"repobilityId": "622d8ae504f287dd", "scanner": "scanner-primary", "fingerprint": "a5a4231696dc87a1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-627f56f907223ac6", "level": "none", "message": {"text": "Commented-code block (7 lines) in frontend/src/pages/student/StudentVideoPlayerPage.jsx:26"}, "properties": {"repobilityId": "769b55fa3afc51c9", "scanner": "scanner-primary", "fingerprint": "627f56f907223ac6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-711a6a9216942db5", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/pages/student/StudentProfilePage.jsx:82"}, "properties": {"repobilityId": "063d266f92c9b6fc", "scanner": "scanner-primary", "fingerprint": "711a6a9216942db5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ebba83566d342865", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/pages/student/StudentLayout.jsx:36"}, "properties": {"repobilityId": "7ac932d0cd7c7c6d", "scanner": "scanner-primary", "fingerprint": "ebba83566d342865", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e8584ef029b81921", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/create_demo_accounts.py:18"}, "properties": {"repobilityId": "1bf951eecbf0a998", "scanner": "scanner-primary", "fingerprint": "e8584ef029b81921", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-486d2eaebde64a3d", "level": "note", "message": {"text": "Legacy-named symbol `get_student_report_v2` in backend/main.py:3014"}, "properties": {"repobilityId": "8e01c2c442a75672", "scanner": "scanner-primary", "fingerprint": "486d2eaebde64a3d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-b972847c6f47c575", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/main.py:2212"}, "properties": {"repobilityId": "ac450a51b7e9a3cb", "scanner": "scanner-primary", "fingerprint": "b972847c6f47c575", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1adc2f9998705242", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/scripts/backup_db.py:33"}, "properties": {"repobilityId": "ac9e1848ce239eed", "scanner": "scanner-primary", "fingerprint": "1adc2f9998705242", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d785c17821858dcb", "level": "note", "message": {"text": "22 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "f5222babac44ad42", "scanner": "scanner-primary", "fingerprint": "d785c17821858dcb", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-02525d39071dd2c7", "level": "note", "message": {"text": "Near-duplicate function bodies in 5 places"}, "properties": {"repobilityId": "757d6bb36b0cb076", "scanner": "scanner-primary", "fingerprint": "02525d39071dd2c7", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-02525d39071dd2c7", "level": "note", "message": {"text": "Near-duplicate function bodies in 5 places"}, "properties": {"repobilityId": "613af1fe97e360c6", "scanner": "scanner-primary", "fingerprint": "02525d39071dd2c7", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-02525d39071dd2c7", "level": "note", "message": {"text": "Near-duplicate function bodies in 5 places"}, "properties": {"repobilityId": "9be9b8460b730554", "scanner": "scanner-primary", "fingerprint": "02525d39071dd2c7", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-02525d39071dd2c7", "level": "note", "message": {"text": "Near-duplicate function bodies in 5 places"}, "properties": {"repobilityId": "2161e5aebae92b24", "scanner": "scanner-primary", "fingerprint": "02525d39071dd2c7", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-49c98f7cedd9c977", "level": "note", "message": {"text": "Near-duplicate function bodies in 4 places"}, "properties": {"repobilityId": "dd4de969e6cd2bc6", "scanner": "scanner-primary", "fingerprint": "49c98f7cedd9c977", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "1b5f8b9d45edd64e", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "135eefbf13753871", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "511e56bd17d4b4ee", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-f9e11fcbaa9d43c5", "level": "note", "message": {"text": "Near-duplicate function bodies in 39 places"}, "properties": {"repobilityId": "56a18aac840ad060", "scanner": "scanner-primary", "fingerprint": "f9e11fcbaa9d43c5", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "2bf1aab392b5dfb0", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "58f47a7c1d57f4b7", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "e6271dc23af21e88", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "23fcbaa67cea1104", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "eed36f6be07f272d", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "33c8ef773654803d", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "80ab0a09b97bb94f", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "4a213f49c7febd93", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "039049cabe7527c9", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "9dfec6c3402fed39", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "265783838f18536b", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-687925783d9879bd", "level": "warning", "message": {"text": "Frontend route `standards` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "2ceadd8a5ee2178c", "scanner": "scanner-primary", "fingerprint": "687925783d9879bd", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-b8b53934f768e47a", "level": "warning", "message": {"text": "Frontend route `standards/:standardId` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "c90a185db0c57e53", "scanner": "scanner-primary", "fingerprint": "b8b53934f768e47a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-de2502b0b3459135", "level": "warning", "message": {"text": "Frontend route `standards/:standardId/subjects/:classId` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "14876fdac5926506", "scanner": "scanner-primary", "fingerprint": "de2502b0b3459135", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-2269e240a511c745", "level": "warning", "message": {"text": "Frontend route `live-classes` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "31b64990a7f1436b", "scanner": "scanner-primary", "fingerprint": "2269e240a511c745", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-864bee41afc52783", "level": "warning", "message": {"text": "Frontend route `students/:studentId` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "22fbb1b558c06e33", "scanner": "scanner-primary", "fingerprint": "864bee41afc52783", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-bba4402688749efc", "level": "warning", "message": {"text": "Frontend route `more` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "9995afc467d660bd", "scanner": "scanner-primary", "fingerprint": "bba4402688749efc", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-6a235105f730a349", "level": "warning", "message": {"text": "Frontend route `question-bank` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "4d5185d0c33ea950", "scanner": "scanner-primary", "fingerprint": "6a235105f730a349", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-0650c16c2cf18347", "level": "warning", "message": {"text": "Frontend route `profile` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "40ac3e9f7d4b76a1", "scanner": "scanner-primary", "fingerprint": "0650c16c2cf18347", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-3f95a7341f0739b2", "level": "warning", "message": {"text": "Frontend route `reports` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "43877e526ba2945f", "scanner": "scanner-primary", "fingerprint": "3f95a7341f0739b2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-0bd3de6bb01a9fd0", "level": "warning", "message": {"text": "Frontend route `reminders` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "98d473a4008f5db6", "scanner": "scanner-primary", "fingerprint": "0bd3de6bb01a9fd0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-f4859238d70b32ea", "level": "warning", "message": {"text": "Frontend route `settings` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "1eef5bc4ce3b8368", "scanner": "scanner-primary", "fingerprint": "f4859238d70b32ea", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-94ab7dbed6362111", "level": "warning", "message": {"text": "Frontend route `attendance` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "811bd836949123bd", "scanner": "scanner-primary", "fingerprint": "94ab7dbed6362111", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-a10de9b759af6388", "level": "warning", "message": {"text": "Frontend route `whatsapp` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "a8da71ca218236f6", "scanner": "scanner-primary", "fingerprint": "a10de9b759af6388", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-85f60fe95064fc86", "level": "warning", "message": {"text": "Frontend route `calendar` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "795f4921b0444418", "scanner": "scanner-primary", "fingerprint": "85f60fe95064fc86", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-db6e34d5087fa462", "level": "warning", "message": {"text": "Frontend route `subjects/:classId` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "6ed9861438a62efd", "scanner": "scanner-primary", "fingerprint": "db6e34d5087fa462", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-4759bbc6867a984f", "level": "warning", "message": {"text": "Frontend route `subjects/:classId/video/:videoId` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "807a47b3d09fe9c4", "scanner": "scanner-primary", "fingerprint": "4759bbc6867a984f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-3c9ee6d6d9e4d65c", "level": "warning", "message": {"text": "Frontend route `tests/:testId/take` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "ea24f49726ab6ba7", "scanner": "scanner-primary", "fingerprint": "3c9ee6d6d9e4d65c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-5ede4210a4af08ac", "level": "warning", "message": {"text": "Frontend route `tests/result` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "0e1bb1465c064e19", "scanner": "scanner-primary", "fingerprint": "5ede4210a4af08ac", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-a977542d17510664", "level": "warning", "message": {"text": "Frontend route `tests/review` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "5ca1753d3d2820ec", "scanner": "scanner-primary", "fingerprint": "a977542d17510664", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-3bc95044e30858e7", "level": "warning", "message": {"text": "Frontend route `change-password` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "b43a8a5939a21573", "scanner": "scanner-primary", "fingerprint": "3bc95044e30858e7", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-51157df775c4e8ec", "level": "warning", "message": {"text": "Frontend route `leaderboard` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "544491e9c0ed4ea3", "scanner": "scanner-primary", "fingerprint": "51157df775c4e8ec", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-85445084ede3b45b", "level": "warning", "message": {"text": "Frontend route `report` has no Link/navigate to it \u2014 frontend/src/App.jsx"}, "properties": {"repobilityId": "7823932f25bb0029", "scanner": "scanner-primary", "fingerprint": "85445084ede3b45b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-fd55aa0818a7c897", "level": "note", "message": {"text": "Unused endpoint: POST /api/auth/login"}, "properties": {"repobilityId": "4dbabc54ffc416a1", "scanner": "scanner-primary", "fingerprint": "fd55aa0818a7c897", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-39b18ae8d1850128", "level": "note", "message": {"text": "Unused endpoint: POST /api/auth/verify-otp"}, "properties": {"repobilityId": "6eb8dcccf08f0012", "scanner": "scanner-primary", "fingerprint": "39b18ae8d1850128", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-17bbe95b93cfcfc6", "level": "note", "message": {"text": "Unused endpoint: POST /api/auth/resend-otp"}, "properties": {"repobilityId": "cf6cc7a0da6137c2", "scanner": "scanner-primary", "fingerprint": "17bbe95b93cfcfc6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-49ac19bb61ef30a3", "level": "note", "message": {"text": "Unused endpoint: POST /api/auth/refresh"}, "properties": {"repobilityId": "597caddbb0fd8031", "scanner": "scanner-primary", "fingerprint": "49ac19bb61ef30a3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d5a39262ac205120", "level": "note", "message": {"text": "Unused endpoint: POST /api/auth/logout"}, "properties": {"repobilityId": "ca1d6921d240f8d3", "scanner": "scanner-primary", "fingerprint": "d5a39262ac205120", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5c6eea00c792d5d2", "level": "note", "message": {"text": "Unused endpoint: POST /api/auth/verify-device"}, "properties": {"repobilityId": "ef20dbf6eabf7a83", "scanner": "scanner-primary", "fingerprint": "5c6eea00c792d5d2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ee4aa5ddab88c9dc", "level": "note", "message": {"text": "Unused endpoint: GET /api/auth/me"}, "properties": {"repobilityId": "d2e51a586b4f5ee3", "scanner": "scanner-primary", "fingerprint": "ee4aa5ddab88c9dc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0f6767eb74dd2470", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/auth/profile"}, "properties": {"repobilityId": "62e2a365851fdb0f", "scanner": "scanner-primary", "fingerprint": "0f6767eb74dd2470", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-866cfadefccd0b5c", "level": "note", "message": {"text": "Unused endpoint: POST /api/auth/change-password"}, "properties": {"repobilityId": "acb468ff11138750", "scanner": "scanner-primary", "fingerprint": "866cfadefccd0b5c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d579aa9fcca5bf82", "level": "note", "message": {"text": "Unused endpoint: GET /api/dashboard/stats"}, "properties": {"repobilityId": "45400f595cd18a2c", "scanner": "scanner-primary", "fingerprint": "d579aa9fcca5bf82", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-65cf511ead5f19f7", "level": "note", "message": {"text": "Unused endpoint: GET /api/dashboard/activity"}, "properties": {"repobilityId": "1f90150a5d5d56ca", "scanner": "scanner-primary", "fingerprint": "65cf511ead5f19f7", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8f1af42f6d990f81", "level": "note", "message": {"text": "Unused endpoint: GET /api/dashboard/overview"}, "properties": {"repobilityId": "089418fe8e52089a", "scanner": "scanner-primary", "fingerprint": "8f1af42f6d990f81", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-57fbbf87f325d582", "level": "note", "message": {"text": "Unused endpoint: GET /api/dashboard/insights"}, "properties": {"repobilityId": "89c180bd9a3f52a0", "scanner": "scanner-primary", "fingerprint": "57fbbf87f325d582", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-922b01b318aaffd4", "level": "note", "message": {"text": "Unused endpoint: GET /api/standards"}, "properties": {"repobilityId": "3c98ae6e1c2812f8", "scanner": "scanner-primary", "fingerprint": "922b01b318aaffd4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-933962650579fa54", "level": "note", "message": {"text": "Unused endpoint: GET /api/standards/{standard_id}"}, "properties": {"repobilityId": "b8df20a43666960c", "scanner": "scanner-primary", "fingerprint": "933962650579fa54", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8510c5de7b9d7322", "level": "note", "message": {"text": "Unused endpoint: POST /api/standards"}, "properties": {"repobilityId": "bf75915648d2074b", "scanner": "scanner-primary", "fingerprint": "8510c5de7b9d7322", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-aaf8743f3baba683", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/standards/{standard_id}"}, "properties": {"repobilityId": "42f27e53b6e20534", "scanner": "scanner-primary", "fingerprint": "aaf8743f3baba683", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fa5d58f6df0a26e7", "level": "note", "message": {"text": "Unused endpoint: DELETE /api/standards/{standard_id}"}, "properties": {"repobilityId": "285bc4f1793d5c8b", "scanner": "scanner-primary", "fingerprint": "fa5d58f6df0a26e7", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e49817677de31706", "level": "note", "message": {"text": "Unused endpoint: GET /api/subjects"}, "properties": {"repobilityId": "334de07db2165c8c", "scanner": "scanner-primary", "fingerprint": "e49817677de31706", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-00db63fd110adcd0", "level": "note", "message": {"text": "Unused endpoint: POST /api/subjects"}, "properties": {"repobilityId": "211b020da1222b91", "scanner": "scanner-primary", "fingerprint": "00db63fd110adcd0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e46adb2ef997c8f7", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/subjects/{subject_id}"}, "properties": {"repobilityId": "3b8d4aecbc681203", "scanner": "scanner-primary", "fingerprint": "e46adb2ef997c8f7", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-94299d1d891a24b5", "level": "note", "message": {"text": "Unused endpoint: DELETE /api/subjects/{subject_id}"}, "properties": {"repobilityId": "5963bbf0d8ebc367", "scanner": "scanner-primary", "fingerprint": "94299d1d891a24b5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9d84d5f4e65de0d9", "level": "note", "message": {"text": "Unused endpoint: GET /api/students"}, "properties": {"repobilityId": "b739e2a39ff75440", "scanner": "scanner-primary", "fingerprint": "9d84d5f4e65de0d9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-dfc073b66dedea5c", "level": "note", "message": {"text": "Unused endpoint: GET /api/students/{student_id}"}, "properties": {"repobilityId": "de90b5e77e1f064f", "scanner": "scanner-primary", "fingerprint": "dfc073b66dedea5c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d753018fd7b46c77", "level": "note", "message": {"text": "Unused endpoint: GET /api/reports/standard/{standard_id}/analytics"}, "properties": {"repobilityId": "5be4ecbca40478f9", "scanner": "scanner-primary", "fingerprint": "d753018fd7b46c77", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4452c86d86712636", "level": "note", "message": {"text": "Unused endpoint: GET /api/reports/performance"}, "properties": {"repobilityId": "107622003f533683", "scanner": "scanner-primary", "fingerprint": "4452c86d86712636", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c6def581eed32385", "level": "note", "message": {"text": "Unused endpoint: GET /api/students/{student_id}/report"}, "properties": {"repobilityId": "b32d97897431d29a", "scanner": "scanner-primary", "fingerprint": "c6def581eed32385", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-093ba530ee58839f", "level": "note", "message": {"text": "Unused endpoint: GET /api/students/{student_id}/report/v2"}, "properties": {"repobilityId": "dbbcd2cf18790568", "scanner": "scanner-primary", "fingerprint": "093ba530ee58839f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-caa8bf7835658645", "level": "note", "message": {"text": "Unused endpoint: POST /api/admin/create-student"}, "properties": {"repobilityId": "ec24fc1c0c71553e", "scanner": "scanner-primary", "fingerprint": "caa8bf7835658645", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8e286f21f4d1789b", "level": "note", "message": {"text": "Unused endpoint: POST /api/admin/backfill-student-codes"}, "properties": {"repobilityId": "818cfd3ff66b2792", "scanner": "scanner-primary", "fingerprint": "8e286f21f4d1789b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-01d0c7f9938fa119", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/students/me"}, "properties": {"repobilityId": "cd5b61b80d800b53", "scanner": "scanner-primary", "fingerprint": "01d0c7f9938fa119", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-46fb4fa76041235e", "level": "note", "message": {"text": "Unused endpoint: GET /api/students/me/videos"}, "properties": {"repobilityId": "35815287cbeaa164", "scanner": "scanner-primary", "fingerprint": "46fb4fa76041235e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3e63f9f2db034c85", "level": "note", "message": {"text": "Unused endpoint: GET /api/student/calendar-events"}, "properties": {"repobilityId": "39479bf871ec687b", "scanner": "scanner-primary", "fingerprint": "3e63f9f2db034c85", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-933163bbf8aa0ba5", "level": "note", "message": {"text": "Unused endpoint: GET /api/student/whats-new"}, "properties": {"repobilityId": "f956793a7971030d", "scanner": "scanner-primary", "fingerprint": "933163bbf8aa0ba5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-340dd283c54a0595", "level": "note", "message": {"text": "Unused endpoint: POST /api/student/seen"}, "properties": {"repobilityId": "9259ec2e95c1d4e0", "scanner": "scanner-primary", "fingerprint": "340dd283c54a0595", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9c5206d4180fc009", "level": "note", "message": {"text": "Unused endpoint: POST /api/students/me/avatar"}, "properties": {"repobilityId": "c53617922e03d389", "scanner": "scanner-primary", "fingerprint": "9c5206d4180fc009", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d0d3a57d3aee6ca0", "level": "note", "message": {"text": "Unused endpoint: GET /api/teacher/thumbnail"}, "properties": {"repobilityId": "b3f78692b0f15bfd", "scanner": "scanner-primary", "fingerprint": "d0d3a57d3aee6ca0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-963384701b1b9b5a", "level": "note", "message": {"text": "Unused endpoint: POST /api/teacher/thumbnail"}, "properties": {"repobilityId": "f1f356d8d7e7d53b", "scanner": "scanner-primary", "fingerprint": "963384701b1b9b5a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-556707c3b6a769e2", "level": "note", "message": {"text": "Unused endpoint: POST /api/teacher/profile-photo"}, "properties": {"repobilityId": "578c7904a4c06291", "scanner": "scanner-primary", "fingerprint": "556707c3b6a769e2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6c323c0dfb7d781a", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/students/{student_id}/block"}, "properties": {"repobilityId": "540fe79000527754", "scanner": "scanner-primary", "fingerprint": "6c323c0dfb7d781a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-88e94d464d5ae918", "level": "note", "message": {"text": "Unused endpoint: POST /api/students/{student_id}/reset-password"}, "properties": {"repobilityId": "41b8a4f40d7a12d0", "scanner": "scanner-primary", "fingerprint": "88e94d464d5ae918", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fb1bec6cd4b5bab0", "level": "note", "message": {"text": "Unused endpoint: GET /api/students/{student_id}/password"}, "properties": {"repobilityId": "6e37c5ac5a26d70a", "scanner": "scanner-primary", "fingerprint": "fb1bec6cd4b5bab0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-60d0a03fcafa0d84", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/students/{student_id}"}, "properties": {"repobilityId": "0cd5593392c67c36", "scanner": "scanner-primary", "fingerprint": "60d0a03fcafa0d84", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-611e710b80d402d3", "level": "note", "message": {"text": "Unused endpoint: DELETE /api/students/{student_id}"}, "properties": {"repobilityId": "9c6f9d2afab92e72", "scanner": "scanner-primary", "fingerprint": "611e710b80d402d3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-85bd28b98f0899e1", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/students/{student_id}/unenroll"}, "properties": {"repobilityId": "c0ceabb0c65212ae", "scanner": "scanner-primary", "fingerprint": "85bd28b98f0899e1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a69d0968599dbbc9", "level": "note", "message": {"text": "Unused endpoint: GET /api/videos"}, "properties": {"repobilityId": "650a7dfc3796fe8e", "scanner": "scanner-primary", "fingerprint": "a69d0968599dbbc9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b48afca31cb15859", "level": "note", "message": {"text": "Unused endpoint: GET /api/videos/{video_id}/viewers"}, "properties": {"repobilityId": "09e8ef83313be119", "scanner": "scanner-primary", "fingerprint": "b48afca31cb15859", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-de68d1932d6fb401", "level": "note", "message": {"text": "Unused endpoint: POST /api/videos/youtube"}, "properties": {"repobilityId": "5f6dc4c073bcc739", "scanner": "scanner-primary", "fingerprint": "de68d1932d6fb401", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-60cbbbb8e26a70e4", "level": "note", "message": {"text": "Unused endpoint: POST /api/videos"}, "properties": {"repobilityId": "56c4a9e0d407cda7", "scanner": "scanner-primary", "fingerprint": "60cbbbb8e26a70e4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cb2cb5fe9d17dd73", "level": "note", "message": {"text": "Unused endpoint: POST /api/videos/upload"}, "properties": {"repobilityId": "f5d7d56fef6eaafa", "scanner": "scanner-primary", "fingerprint": "cb2cb5fe9d17dd73", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}