{"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-e8aa43534e49b7dd", "name": "Stray `console.log` in TS/JS \u2014 client/scripts/copy-tinymce.js:24", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 client/scripts/copy-tinymce.js:24"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-06d210bb7bb6a9f3", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/MathBlock.jsx:3", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/MathBlock.jsx:3"}, "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-a9dbba3eb6dfc5bb", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/editor/ElementToolbar.jsx:216", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/editor/ElementToolbar.jsx:216"}, "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-210f2b1604cca430", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/editor/slideRender.jsx:83", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/editor/slideRender.jsx:83"}, "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-c6ec6bd1f896af2e", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/editor/StatementModal.jsx:17", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/editor/StatementModal.jsx:17"}, "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-f52fee69fe924d46", "name": "Icon-only button without accessible name \u2014 client/src/components/codeEditor/CodeEditor.jsx:335", "shortDescription": {"text": "Icon-only button without accessible name \u2014 client/src/components/codeEditor/CodeEditor.jsx:335"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-48f49604e41640c0", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/pages/LessonPage.jsx:503", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/pages/LessonPage.jsx:503"}, "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-0f8f5af18fcbb6d2", "name": "Icon-only button without accessible name \u2014 client/src/pages/BankPage.jsx:820", "shortDescription": {"text": "Icon-only button without accessible name \u2014 client/src/pages/BankPage.jsx:820"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c0173ea8a718a963", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/pages/VariantSolvePage.jsx:166", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/pages/VariantSolvePage.jsx:166"}, "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-b1b700c537af0d09", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/pages/NotesPage.jsx:47", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/pages/NotesPage.jsx:47"}, "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-0f8f38580446bfe9", "name": "Stray `console.log` in TS/JS \u2014 server/room.js:127", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 server/room.js:127"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b0450c40a3e6d1d6", "name": "Stray `console.log` in TS/JS \u2014 server/kompegeAuth.js:5", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 server/kompegeAuth.js:5"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b68feb33368fac4c", "name": "Stray `console.log` in TS/JS \u2014 server/bot.js:124", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 server/bot.js:124"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-50e6c1f494fe4547", "name": "Stray `console.log` in TS/JS \u2014 server/index.js:149", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 server/index.js:149"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c8ba031346cc5299", "name": "Stray `console.log` in TS/JS \u2014 server/scripts/clean-task-content.js:50", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 server/scripts/clean-task-content.js:50"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-21df0b827cb169e0", "name": "Stray `console.log` in TS/JS \u2014 server/scripts/test-zip-extract.js:35", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 server/scripts/test-zip-extract.js:35"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7b66ac5db6850129", "name": "Stray `console.log` in TS/JS \u2014 server/scripts/generate-task9-txt.js:44", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 server/scripts/generate-task9-txt.js:44"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-49eb64dac4386b1f", "name": "Privileged port 465 in use", "shortDescription": {"text": "Privileged port 465 in use"}, "fullDescription": {"text": "Port 465 is privileged (<1024). Make sure the service runs with the right caps or front it with a non-privileged port via a load balancer."}, "properties": {"scanner": "scanner-primary", "layer": "network", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-77d34e1ad2a57928", "name": "Insecure pattern 'local_storage_auth_token' in client/src/components/AuthForm.jsx:44", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in client/src/components/AuthForm.jsx:44"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-cf89940c7f983dad", "name": "Insecure pattern 'dangerous_innerhtml' in client/src/components/editor/ElementToolbar.jsx:216", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/components/editor/ElementToolbar.jsx:216"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea443e215508649a", "name": "Insecure pattern 'domparser_html_parse' in client/src/components/editor/richText.js:100", "shortDescription": {"text": "Insecure pattern 'domparser_html_parse' in client/src/components/editor/richText.js:100"}, "fullDescription": {"text": "Found a known-risky pattern (domparser_html_parse). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ce5386858e8d1345", "name": "Insecure pattern 'dangerous_innerhtml' in client/src/components/editor/slideRender.jsx:83", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/components/editor/slideRender.jsx:83"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b31b1555286d6a88", "name": "Insecure pattern 'direct_innerhtml_assignment' in client/src/components/editor/RichTextField.jsx:21", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in client/src/components/editor/RichTextField.jsx:21"}, "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-9984b1656c886574", "name": "Insecure pattern 'dangerous_innerhtml' in client/src/components/editor/StatementModal.jsx:17", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/components/editor/StatementModal.jsx:17"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-63fe078cd68b0ba8", "name": "Insecure pattern 'dangerous_innerhtml' in client/src/pages/LessonPage.jsx:503", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/pages/LessonPage.jsx:503"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a1d69cd9252a5fa8", "name": "Insecure pattern 'direct_innerhtml_assignment' in client/src/pages/BankPage.jsx:66", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in client/src/pages/BankPage.jsx:66"}, "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-deca583dc155dd20", "name": "Insecure pattern 'dangerous_innerhtml' in client/src/pages/VariantSolvePage.jsx:166", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/pages/VariantSolvePage.jsx:166"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-43f64d6eba405f82", "name": "Insecure pattern 'dangerous_innerhtml' in client/src/pages/NotesPage.jsx:47", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/pages/NotesPage.jsx:47"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4601e3ad3bb28677", "name": "No CI/CD pipelines detected", "shortDescription": {"text": "No CI/CD pipelines detected"}, "fullDescription": {"text": "No GitHub Actions, GitLab CI, or CircleCI configs found. Without CI you can't gate deploys on tests/lints."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0c9795dc5f1dd1fe", "name": "Very large file: client/src/pages/LessonPage.jsx (926 lines)", "shortDescription": {"text": "Very large file: client/src/pages/LessonPage.jsx (926 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-1c826d2680531fbb", "name": "Very large file: client/src/pages/BankPage.jsx (1517 lines)", "shortDescription": {"text": "Very large file: client/src/pages/BankPage.jsx (1517 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-4e9f90d93f74d50c", "name": "Very large file: client/src/pages/VariantSolvePage.jsx (1804 lines)", "shortDescription": {"text": "Very large file: client/src/pages/VariantSolvePage.jsx (1804 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-05109551909bcecb", "name": "Very large file: server/index.js (3656 lines)", "shortDescription": {"text": "Very large file: server/index.js (3656 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "1 test file(s) for 89 source file(s) (ratio 0.01). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 33 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 78 placeholder/mock markers across 24 source files. This often means the repo looks complete while core flows still use generated scaffolding or fake data."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, ci, tests. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license, ci, tests. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-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-bea357a6497a2d5d", "name": "Agent authority lacks a verifier contract: CLAUDE.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: CLAUDE.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-122f91b7f2906dc4", "name": "Agent authority lacks a verifier contract: .claude/settings.json", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/settings.json"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d7cdeec872383362", "name": "Commented-code block (5 lines) in client/vite.config.js:4", "shortDescription": {"text": "Commented-code block (5 lines) in client/vite.config.js:4"}, "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-4dd894d6babb4f75", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/App.jsx:53", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/App.jsx:53"}, "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-5a64d3886d166191", "name": "Commented-code block (5 lines) in client/src/api.js:3", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/api.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-a01226c0e7f07a80", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/api.js:46", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/api.js:46"}, "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-7e1838fe4aff2eb2", "name": "Commented-code block (6 lines) in client/src/utils/useGoBack.js:4", "shortDescription": {"text": "Commented-code block (6 lines) in client/src/utils/useGoBack.js:4"}, "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-b749e8516a43ff1d", "name": "Legacy-named symbol `brand__copy` in client/src/components/AuthForm.jsx:104", "shortDescription": {"text": "Legacy-named symbol `brand__copy` in client/src/components/AuthForm.jsx:104"}, "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-7fe418e0a09cd647", "name": "Commented-code block (5 lines) in client/src/components/studio/palette.js:14", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/components/studio/palette.js:14"}, "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-d5a4d4dcb333a1a8", "name": "Commented-code block (6 lines) in client/src/components/studio/PreviewTool.jsx:75", "shortDescription": {"text": "Commented-code block (6 lines) in client/src/components/studio/PreviewTool.jsx:75"}, "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-34870b81fbc31588", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/components/studio/PreviewTool.jsx:124", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/components/studio/PreviewTool.jsx:124"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d2d4c04ddc45a02b", "name": "Commented-code block (5 lines) in client/src/components/editor/slideTemplates.js:5", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/components/editor/slideTemplates.js:5"}, "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-740b0c754e27e7fe", "name": "Commented-code block (6 lines) in client/src/components/editor/statementParser.js:3", "shortDescription": {"text": "Commented-code block (6 lines) in client/src/components/editor/statementParser.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-9e319afc8ce359a8", "name": "Commented-code block (5 lines) in client/src/components/editor/richText.js:3", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/components/editor/richText.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-ce159581828121b9", "name": "Commented-code block (5 lines) in client/src/components/editor/slideRender.jsx:1", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/components/editor/slideRender.jsx: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-8cccc07236871336", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/components/editor/upload.js:11", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/components/editor/upload.js:11"}, "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-804d1b96628f31d5", "name": "Commented-code block (5 lines) in client/src/components/editor/StatementModal.jsx:1", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/components/editor/StatementModal.jsx: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-aafff702bc1ea24e", "name": "Commented-code block (5 lines) in client/src/components/codeEditor/pyodide.worker.js:4", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/components/codeEditor/pyodide.worker.js:4"}, "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-c022c2ea6b657d25", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/components/codeEditor/usePyodideRunner.js:120", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/components/codeEditor/usePyodideRunner.js:120"}, "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-360dffb47c19e169", "name": "Commented-code block (5 lines) in client/src/components/board/CodeCard.jsx:8", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/components/board/CodeCard.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-267561ba9fc2c1b2", "name": "Commented-code block (5 lines) in client/src/components/board/FileShowOverlay.jsx:1", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/components/board/FileShowOverlay.jsx: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-4339788ea09a31bb", "name": "Commented-code block (6 lines) in client/src/components/board/LiveCodePanel.jsx:3", "shortDescription": {"text": "Commented-code block (6 lines) in client/src/components/board/LiveCodePanel.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-27db71a574067079", "name": "Commented-code block (5 lines) in client/src/components/board/BoardCanvas.jsx:143", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/components/board/BoardCanvas.jsx:143"}, "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-76e8ff73486210e2", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/LessonPage.jsx:289", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/LessonPage.jsx:289"}, "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-5ae94a91686f46b3", "name": "Commented-code block (5 lines) in client/src/pages/BankPage.jsx:433", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/pages/BankPage.jsx:433"}, "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-0d3d8674f5fef4d2", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/BankPage.jsx:249", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/BankPage.jsx:249"}, "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-d10fbbc2bad08bc8", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/WeeklyCalendarPage.jsx:106", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/WeeklyCalendarPage.jsx:106"}, "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-6826cd46baafcbed", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/ProfilePage.jsx:140", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/ProfilePage.jsx:140"}, "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-d18e2e84a19741de", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/CoursePage.jsx:110", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/CoursePage.jsx:110"}, "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-270965cba62fe2ec", "name": "Commented-code block (8 lines) in client/src/pages/VariantSolvePage.jsx:12", "shortDescription": {"text": "Commented-code block (8 lines) in client/src/pages/VariantSolvePage.jsx:12"}, "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-49ee29aee685d5c5", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/VariantSolvePage.jsx:303", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/VariantSolvePage.jsx:303"}, "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-3a36175576f30564", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/SectionPage.jsx:88", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/SectionPage.jsx:88"}, "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-9337b0ecd08d7f1a", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/CategoryPage.jsx:86", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/CategoryPage.jsx:86"}, "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-52353910837e82b5", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/StudentDetailPage.jsx:69", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/StudentDetailPage.jsx:69"}, "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-d426a78d0bca2267", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/MaterialsFeedPage.jsx:148", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/MaterialsFeedPage.jsx:148"}, "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-80ade93dc0b41614", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/BulkAccessPage.jsx:62", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/BulkAccessPage.jsx:62"}, "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-8cf4d3f282e03b5a", "name": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/StudentsPage.jsx:50", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/StudentsPage.jsx:50"}, "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-ac9f98e1e6de7135", "name": "Commented-code block (5 lines) in client/src/hooks/useRoom.js:343", "shortDescription": {"text": "Commented-code block (5 lines) in client/src/hooks/useRoom.js:343"}, "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-4433726d9e6c4784", "name": "`fetch()` without try/.catch or AbortSignal \u2014 finance-pwa/sw.js:19", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 finance-pwa/sw.js:19"}, "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-eae0601f693c80a1", "name": "Commented-code block (6 lines) in server/bot.js:587", "shortDescription": {"text": "Commented-code block (6 lines) in server/bot.js:587"}, "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-0e183fc945269250", "name": "Commented-code block (7 lines) in server/index.js:18", "shortDescription": {"text": "Commented-code block (7 lines) in server/index.js:18"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-636bcd77374fb2bc", "name": "Commented-code block (5 lines) in server/routes/presentations.js:205", "shortDescription": {"text": "Commented-code block (5 lines) in server/routes/presentations.js:205"}, "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-250f57e8a1dbd3c5", "name": "4 env vars used in code but missing from .env.example", "shortDescription": {"text": "4 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `NODE_ENV`, `TG_BOT_TOKEN`, `TG_BOT_USERNAME`, `TG_PROXY`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-39a3c19fbd12dd0d", "name": "Frontend route `/reset-password/:token` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/reset-password/:token` has no Link/navigate to it \u2014 client/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-97ad4ee378fc9ad0", "name": "Frontend route `/room/:roomId` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/room/:roomId` has no Link/navigate to it \u2014 client/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-ee37919cac84f0b2", "name": "Frontend route `/notes/:id` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/notes/:id` has no Link/navigate to it \u2014 client/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-5c51f36680f77e26", "name": "Frontend route `/board/:topicId` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/board/:topicId` has no Link/navigate to it \u2014 client/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-5b301bc9d59e2185", "name": "Frontend route `/course/category/:id` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/course/category/:id` has no Link/navigate to it \u2014 client/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-4094e5e62d39066d", "name": "Frontend route `/course/:id` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/course/:id` has no Link/navigate to it \u2014 client/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-cc86a5e5f51f7c9b", "name": "Frontend route `/lesson/:id` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/lesson/:id` has no Link/navigate to it \u2014 client/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-07fd56092651974e", "name": "Frontend route `/variant/:id` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/variant/:id` has no Link/navigate to it \u2014 client/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-c5529554491256ba", "name": "Frontend route `/topic/:id/stats` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/topic/:id/stats` has no Link/navigate to it \u2014 client/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-f2937793c8db39bf", "name": "Frontend route `/students/:id` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/students/:id` has no Link/navigate to it \u2014 client/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-007052e6120503ba", "name": "Frontend route `/review/:variantId/:studentId` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/review/:variantId/:studentId` has no Link/navigate to it \u2014 client/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-f44ec30c36019f4c", "name": "Frontend route `/studio/presentations` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/studio/presentations` has no Link/navigate to it \u2014 client/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-e9ec84b083f25cee", "name": "Frontend route `/studio/presentations/:id` has no Link/navigate to it \u2014 client/src/App.jsx", "shortDescription": {"text": "Frontend route `/studio/presentations/:id` has no Link/navigate to it \u2014 client/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-d549f19d3ac19fc9", "name": "Dangling fetch: GET https://kompege.ru/api/v1/course/${courseId} (server/index.js:2157)", "shortDescription": {"text": "Dangling fetch: GET https://kompege.ru/api/v1/course/${courseId} (server/index.js:2157)"}, "fullDescription": {"text": "`server/index.js:2157` calls `GET https://kompege.ru/api/v1/course/${courseId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/kompege.ru/api/v1/course/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-6a0034bfd54116f0", "name": "Dangling fetch: GET https://kompege.ru/api/v1/task/${id} (server/index.js:2308)", "shortDescription": {"text": "Dangling fetch: GET https://kompege.ru/api/v1/task/${id} (server/index.js:2308)"}, "fullDescription": {"text": "`server/index.js:2308` calls `GET https://kompege.ru/api/v1/task/${id}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/kompege.ru/api/v1/task/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-848679f1f341557f", "name": "Unused endpoint: POST /api/rooms", "shortDescription": {"text": "Unused endpoint: POST /api/rooms"}, "fullDescription": {"text": "`server/room.js` declares `POST /api/rooms` 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-d5e5affb161a3212", "name": "Unused endpoint: GET /api/rooms/:roomId", "shortDescription": {"text": "Unused endpoint: GET /api/rooms/:roomId"}, "fullDescription": {"text": "`server/room.js` declares `GET /api/rooms/:roomId` 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-d3ff16b6f060673e", "name": "Unused endpoint: POST /api/rooms/:roomId/save", "shortDescription": {"text": "Unused endpoint: POST /api/rooms/:roomId/save"}, "fullDescription": {"text": "`server/room.js` declares `POST /api/rooms/:roomId/save` 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-4e0144e669bf1d7a", "name": "Unused endpoint: GET /api/board/:topicId", "shortDescription": {"text": "Unused endpoint: GET /api/board/:topicId"}, "fullDescription": {"text": "`server/room.js` declares `GET /api/board/:topicId` 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-683385533454e925", "name": "Unused endpoint: PUT /api/board/:topicId", "shortDescription": {"text": "Unused endpoint: PUT /api/board/:topicId"}, "fullDescription": {"text": "`server/room.js` declares `PUT /api/board/:topicId` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4756b4c4da7d2088", "name": "Unused endpoint: GET /api/health", "shortDescription": {"text": "Unused endpoint: GET /api/health"}, "fullDescription": {"text": "`server/index.js` declares `GET /api/health` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1bc898b3b7565990", "name": "Unused endpoint: USE /uploads", "shortDescription": {"text": "Unused endpoint: USE /uploads"}, "fullDescription": {"text": "`server/index.js` declares `USE /uploads` 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-df092b9a20d61863", "name": "Unused endpoint: GET /api/table-preview", "shortDescription": {"text": "Unused endpoint: GET /api/table-preview"}, "fullDescription": {"text": "`server/index.js` declares `GET /api/table-preview` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-25702767f50d6c7d", "name": "Unused endpoint: POST /api/register", "shortDescription": {"text": "Unused endpoint: POST /api/register"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/register` 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-790da11c30a99c35", "name": "Unused endpoint: POST /api/verify-email", "shortDescription": {"text": "Unused endpoint: POST /api/verify-email"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/verify-email` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-200ab2e98a288506", "name": "Unused endpoint: POST /api/login", "shortDescription": {"text": "Unused endpoint: POST /api/login"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/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-9bcbb99cfee422c2", "name": "Unused endpoint: POST /api/google-login", "shortDescription": {"text": "Unused endpoint: POST /api/google-login"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/google-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-a310d5b81aef3f4d", "name": "Unused endpoint: POST /api/forgot-password", "shortDescription": {"text": "Unused endpoint: POST /api/forgot-password"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/forgot-password` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-96aa6a37afa1dbf3", "name": "Unused endpoint: POST /api/reset-password", "shortDescription": {"text": "Unused endpoint: POST /api/reset-password"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/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-5c1545494ab6166c", "name": "Unused endpoint: GET /api/me", "shortDescription": {"text": "Unused endpoint: GET /api/me"}, "fullDescription": {"text": "`server/index.js` declares `GET /api/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-74ad413b851b3249", "name": "Unused endpoint: PATCH /api/profile", "shortDescription": {"text": "Unused endpoint: PATCH /api/profile"}, "fullDescription": {"text": "`server/index.js` declares `PATCH /api/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-804c70b53f6dfa2a", "name": "Unused endpoint: POST /api/change-password", "shortDescription": {"text": "Unused endpoint: POST /api/change-password"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/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-9d84d5f4e65de0d9", "name": "Unused endpoint: GET /api/students", "shortDescription": {"text": "Unused endpoint: GET /api/students"}, "fullDescription": {"text": "`server/index.js` 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-38d135d3d4d617c9", "name": "Unused endpoint: PATCH /api/students/:id", "shortDescription": {"text": "Unused endpoint: PATCH /api/students/:id"}, "fullDescription": {"text": "`server/index.js` declares `PATCH /api/students/: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-536fc60d1287e634", "name": "Unused endpoint: POST /api/upload", "shortDescription": {"text": "Unused endpoint: POST /api/upload"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/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}}, {"id": "scanner-1ffefb07914311a6", "name": "Unused endpoint: GET /api/lessons", "shortDescription": {"text": "Unused endpoint: GET /api/lessons"}, "fullDescription": {"text": "`server/index.js` declares `GET /api/lessons` 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-c9657d2ab1b52730", "name": "Unused endpoint: POST /api/lessons", "shortDescription": {"text": "Unused endpoint: POST /api/lessons"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/lessons` 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-220d57dbae0383c7", "name": "Unused endpoint: PATCH /api/lessons/:id", "shortDescription": {"text": "Unused endpoint: PATCH /api/lessons/:id"}, "fullDescription": {"text": "`server/index.js` declares `PATCH /api/lessons/: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-7923d0660f168105", "name": "Unused endpoint: DELETE /api/lessons/:id", "shortDescription": {"text": "Unused endpoint: DELETE /api/lessons/:id"}, "fullDescription": {"text": "`server/index.js` declares `DELETE /api/lessons/: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-ef9b199d79321db2", "name": "Unused endpoint: GET /api/course", "shortDescription": {"text": "Unused endpoint: GET /api/course"}, "fullDescription": {"text": "`server/index.js` declares `GET /api/course` 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-3c6f4bdfd596e901", "name": "Unused endpoint: GET /api/course/categories", "shortDescription": {"text": "Unused endpoint: GET /api/course/categories"}, "fullDescription": {"text": "`server/index.js` declares `GET /api/course/categories` 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-5e29cf5b36415331", "name": "Unused endpoint: POST /api/course/category", "shortDescription": {"text": "Unused endpoint: POST /api/course/category"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/course/category` 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-4067d0d112d19a4e", "name": "Unused endpoint: PATCH /api/course/category/reorder", "shortDescription": {"text": "Unused endpoint: PATCH /api/course/category/reorder"}, "fullDescription": {"text": "`server/index.js` declares `PATCH /api/course/category/reorder` 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-499122b8fb1523d5", "name": "Unused endpoint: PATCH /api/course/category/:id", "shortDescription": {"text": "Unused endpoint: PATCH /api/course/category/:id"}, "fullDescription": {"text": "`server/index.js` declares `PATCH /api/course/category/: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-4462f65ad190111d", "name": "Unused endpoint: DELETE /api/course/category/:id", "shortDescription": {"text": "Unused endpoint: DELETE /api/course/category/:id"}, "fullDescription": {"text": "`server/index.js` declares `DELETE /api/course/category/: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-677d167f09b70daf", "name": "Unused endpoint: GET /api/course/category/:id/sections", "shortDescription": {"text": "Unused endpoint: GET /api/course/category/:id/sections"}, "fullDescription": {"text": "`server/index.js` declares `GET /api/course/category/:id/sections` 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-5f688d7e83864011", "name": "Unused endpoint: POST /api/course/category/:id/topic", "shortDescription": {"text": "Unused endpoint: POST /api/course/category/:id/topic"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/course/category/:id/topic` 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-4409701e31d1067c", "name": "Unused endpoint: POST /api/course/topic", "shortDescription": {"text": "Unused endpoint: POST /api/course/topic"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/course/topic` 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-7ed931d27b64e471", "name": "Unused endpoint: DELETE /api/course/section/:id", "shortDescription": {"text": "Unused endpoint: DELETE /api/course/section/:id"}, "fullDescription": {"text": "`server/index.js` declares `DELETE /api/course/section/: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-b9f0f97a9398cedc", "name": "Unused endpoint: POST /api/course/section", "shortDescription": {"text": "Unused endpoint: POST /api/course/section"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/course/section` 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-f7c1311142ac7c42", "name": "Unused endpoint: PATCH /api/course/section/reorder", "shortDescription": {"text": "Unused endpoint: PATCH /api/course/section/reorder"}, "fullDescription": {"text": "`server/index.js` declares `PATCH /api/course/section/reorder` 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-88f969d69170a01f", "name": "Unused endpoint: PATCH /api/course/section/:id", "shortDescription": {"text": "Unused endpoint: PATCH /api/course/section/:id"}, "fullDescription": {"text": "`server/index.js` declares `PATCH /api/course/section/: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-e1a38ea3375f5475", "name": "Unused endpoint: GET /api/course/section/:id", "shortDescription": {"text": "Unused endpoint: GET /api/course/section/:id"}, "fullDescription": {"text": "`server/index.js` declares `GET /api/course/section/: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-9e7335780e4ce271", "name": "Unused endpoint: POST /api/course/section/:id/topic", "shortDescription": {"text": "Unused endpoint: POST /api/course/section/:id/topic"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/course/section/:id/topic` 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-20944f4e887445e2", "name": "Unused endpoint: POST /api/course/section/:id/unpack", "shortDescription": {"text": "Unused endpoint: POST /api/course/section/:id/unpack"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/course/section/:id/unpack` 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-57e8caf5320055c9", "name": "Unused endpoint: PATCH /api/course/topic/reorder", "shortDescription": {"text": "Unused endpoint: PATCH /api/course/topic/reorder"}, "fullDescription": {"text": "`server/index.js` declares `PATCH /api/course/topic/reorder` 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-58812a9f02f41327", "name": "Unused endpoint: GET /api/course/topic/:id", "shortDescription": {"text": "Unused endpoint: GET /api/course/topic/:id"}, "fullDescription": {"text": "`server/index.js` declares `GET /api/course/topic/: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-353010e9008939ba", "name": "Unused endpoint: POST /api/calendar/token", "shortDescription": {"text": "Unused endpoint: POST /api/calendar/token"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/calendar/token` 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-c15284ea1d1e4ada", "name": "Unused endpoint: PUT /api/course/topic/:id", "shortDescription": {"text": "Unused endpoint: PUT /api/course/topic/:id"}, "fullDescription": {"text": "`server/index.js` declares `PUT /api/course/topic/: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-51daeca915f28074", "name": "Unused endpoint: POST /api/course/topic/:id/material", "shortDescription": {"text": "Unused endpoint: POST /api/course/topic/:id/material"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/course/topic/:id/material` 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-45d50b30cce14830", "name": "Unused endpoint: POST /api/bulk-access", "shortDescription": {"text": "Unused endpoint: POST /api/bulk-access"}, "fullDescription": {"text": "`server/index.js` declares `POST /api/bulk-access` 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-aebd9c09c0116575", "name": "Unused endpoint: DELETE /api/course/topic/:topicId/material/:studentId", "shortDescription": {"text": "Unused endpoint: DELETE /api/course/topic/:topicId/material/:studentId"}, "fullDescription": {"text": "`server/index.js` declares `DELETE /api/course/topic/:topicId/material/:studentId` 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-612ef722df60f60e", "name": "Unused endpoint: DELETE /api/course/topic/:id", "shortDescription": {"text": "Unused endpoint: DELETE /api/course/topic/:id"}, "fullDescription": {"text": "`server/index.js` declares `DELETE /api/course/topic/: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-cf16ae0930dc161a", "name": "Unused endpoint: GET /api/tasks", "shortDescription": {"text": "Unused endpoint: GET /api/tasks"}, "fullDescription": {"text": "`server/index.js` declares `GET /api/tasks` 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-1d5b18f8708facc4", "name": "Unused endpoint: PATCH /api/tasks/:id", "shortDescription": {"text": "Unused endpoint: PATCH /api/tasks/:id"}, "fullDescription": {"text": "`server/index.js` declares `PATCH /api/tasks/: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}}]}}, "automationDetails": {"id": "repobility/22495"}, "properties": {"repository": "wakl3/infege", "repoUrl": "https://github.com/wakl3/infege", "branch": "main"}, "results": [{"ruleId": "scanner-e8aa43534e49b7dd", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 client/scripts/copy-tinymce.js:24"}, "properties": {"repobilityId": "565deed703b14927", "scanner": "scanner-primary", "fingerprint": "e8aa43534e49b7dd", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-06d210bb7bb6a9f3", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/MathBlock.jsx:3"}, "properties": {"repobilityId": "3b1116293e7b9af8", "scanner": "scanner-primary", "fingerprint": "06d210bb7bb6a9f3", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-a9dbba3eb6dfc5bb", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/editor/ElementToolbar.jsx:216"}, "properties": {"repobilityId": "814a1fbd7ecb3085", "scanner": "scanner-primary", "fingerprint": "a9dbba3eb6dfc5bb", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-210f2b1604cca430", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/editor/slideRender.jsx:83"}, "properties": {"repobilityId": "31df50a43e26c556", "scanner": "scanner-primary", "fingerprint": "210f2b1604cca430", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-c6ec6bd1f896af2e", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/components/editor/StatementModal.jsx:17"}, "properties": {"repobilityId": "497b3828f2f479da", "scanner": "scanner-primary", "fingerprint": "c6ec6bd1f896af2e", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-f52fee69fe924d46", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 client/src/components/codeEditor/CodeEditor.jsx:335"}, "properties": {"repobilityId": "14fcf9b75d0021de", "scanner": "scanner-primary", "fingerprint": "f52fee69fe924d46", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-48f49604e41640c0", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/pages/LessonPage.jsx:503"}, "properties": {"repobilityId": "461ef2e48979f529", "scanner": "scanner-primary", "fingerprint": "48f49604e41640c0", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-0f8f5af18fcbb6d2", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 client/src/pages/BankPage.jsx:820"}, "properties": {"repobilityId": "a4f48d7a8b149ef3", "scanner": "scanner-primary", "fingerprint": "0f8f5af18fcbb6d2", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-c0173ea8a718a963", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/pages/VariantSolvePage.jsx:166"}, "properties": {"repobilityId": "f9ee1d0d3e38d3da", "scanner": "scanner-primary", "fingerprint": "c0173ea8a718a963", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-b1b700c537af0d09", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 client/src/pages/NotesPage.jsx:47"}, "properties": {"repobilityId": "85983664a303d06f", "scanner": "scanner-primary", "fingerprint": "b1b700c537af0d09", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-0f8f38580446bfe9", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 server/room.js:127"}, "properties": {"repobilityId": "0203bc5c63d19889", "scanner": "scanner-primary", "fingerprint": "0f8f38580446bfe9", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-b0450c40a3e6d1d6", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 server/kompegeAuth.js:5"}, "properties": {"repobilityId": "37f4db67a8012f9f", "scanner": "scanner-primary", "fingerprint": "b0450c40a3e6d1d6", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-b68feb33368fac4c", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 server/bot.js:124"}, "properties": {"repobilityId": "ca397cf66de19bcc", "scanner": "scanner-primary", "fingerprint": "b68feb33368fac4c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-50e6c1f494fe4547", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 server/index.js:149"}, "properties": {"repobilityId": "21e6b3de2b3dd856", "scanner": "scanner-primary", "fingerprint": "50e6c1f494fe4547", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-c8ba031346cc5299", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 server/scripts/clean-task-content.js:50"}, "properties": {"repobilityId": "d4a8695ca18f3012", "scanner": "scanner-primary", "fingerprint": "c8ba031346cc5299", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-21df0b827cb169e0", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 server/scripts/test-zip-extract.js:35"}, "properties": {"repobilityId": "4886cea0441a0d1d", "scanner": "scanner-primary", "fingerprint": "21df0b827cb169e0", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-7b66ac5db6850129", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 server/scripts/generate-task9-txt.js:44"}, "properties": {"repobilityId": "8edfc0508dd5dfba", "scanner": "scanner-primary", "fingerprint": "7b66ac5db6850129", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-49eb64dac4386b1f", "level": "warning", "message": {"text": "Privileged port 465 in use"}, "properties": {"repobilityId": "bcd1f06b60a2b6bc", "scanner": "scanner-primary", "fingerprint": "49eb64dac4386b1f", "layer": "network", "severity": "medium", "confidence": 1.0, "tags": ["security", "ports"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "server/index.js"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-77d34e1ad2a57928", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in client/src/components/AuthForm.jsx:44"}, "properties": {"repobilityId": "ccfa9d9c64c1306f", "scanner": "scanner-primary", "fingerprint": "77d34e1ad2a57928", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "client/src/components/AuthForm.jsx"}, "region": {"startLine": 44}}}]}, {"ruleId": "scanner-cf89940c7f983dad", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/components/editor/ElementToolbar.jsx:216"}, "properties": {"repobilityId": "d1f4e84b74248738", "scanner": "scanner-primary", "fingerprint": "cf89940c7f983dad", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "client/src/components/editor/ElementToolbar.jsx"}, "region": {"startLine": 216}}}]}, {"ruleId": "scanner-ea443e215508649a", "level": "warning", "message": {"text": "Insecure pattern 'domparser_html_parse' in client/src/components/editor/richText.js:100"}, "properties": {"repobilityId": "4ca7acf2526f1ab7", "scanner": "scanner-primary", "fingerprint": "ea443e215508649a", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "domparser_html_parse"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "client/src/components/editor/richText.js"}, "region": {"startLine": 100}}}]}, {"ruleId": "scanner-ce5386858e8d1345", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/components/editor/slideRender.jsx:83"}, "properties": {"repobilityId": "bee633772d466862", "scanner": "scanner-primary", "fingerprint": "ce5386858e8d1345", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "client/src/components/editor/slideRender.jsx"}, "region": {"startLine": 83}}}]}, {"ruleId": "scanner-b31b1555286d6a88", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in client/src/components/editor/RichTextField.jsx:21"}, "properties": {"repobilityId": "f551df6d69c35836", "scanner": "scanner-primary", "fingerprint": "b31b1555286d6a88", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "client/src/components/editor/RichTextField.jsx"}, "region": {"startLine": 21}}}]}, {"ruleId": "scanner-9984b1656c886574", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/components/editor/StatementModal.jsx:17"}, "properties": {"repobilityId": "d72c39faf0486361", "scanner": "scanner-primary", "fingerprint": "9984b1656c886574", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "client/src/components/editor/StatementModal.jsx"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-63fe078cd68b0ba8", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/pages/LessonPage.jsx:503"}, "properties": {"repobilityId": "bcbeda9d192fc089", "scanner": "scanner-primary", "fingerprint": "63fe078cd68b0ba8", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "client/src/pages/LessonPage.jsx"}, "region": {"startLine": 503}}}]}, {"ruleId": "scanner-a1d69cd9252a5fa8", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in client/src/pages/BankPage.jsx:66"}, "properties": {"repobilityId": "d8e596d2bf89f0bc", "scanner": "scanner-primary", "fingerprint": "a1d69cd9252a5fa8", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "client/src/pages/BankPage.jsx"}, "region": {"startLine": 66}}}]}, {"ruleId": "scanner-deca583dc155dd20", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/pages/VariantSolvePage.jsx:166"}, "properties": {"repobilityId": "ea59603f086b1b9e", "scanner": "scanner-primary", "fingerprint": "deca583dc155dd20", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "client/src/pages/VariantSolvePage.jsx"}, "region": {"startLine": 166}}}]}, {"ruleId": "scanner-43f64d6eba405f82", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in client/src/pages/NotesPage.jsx:47"}, "properties": {"repobilityId": "c40ab26ec6446e66", "scanner": "scanner-primary", "fingerprint": "43f64d6eba405f82", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "client/src/pages/NotesPage.jsx"}, "region": {"startLine": 47}}}]}, {"ruleId": "scanner-4601e3ad3bb28677", "level": "warning", "message": {"text": "No CI/CD pipelines detected"}, "properties": {"repobilityId": "c3ee439bce2bc51e", "scanner": "scanner-primary", "fingerprint": "4601e3ad3bb28677", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-0c9795dc5f1dd1fe", "level": "note", "message": {"text": "Very large file: client/src/pages/LessonPage.jsx (926 lines)"}, "properties": {"repobilityId": "84a27c0102894ee7", "scanner": "scanner-primary", "fingerprint": "0c9795dc5f1dd1fe", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-1c826d2680531fbb", "level": "note", "message": {"text": "Very large file: client/src/pages/BankPage.jsx (1517 lines)"}, "properties": {"repobilityId": "a8da9b57f1b3b7a1", "scanner": "scanner-primary", "fingerprint": "1c826d2680531fbb", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-4e9f90d93f74d50c", "level": "note", "message": {"text": "Very large file: client/src/pages/VariantSolvePage.jsx (1804 lines)"}, "properties": {"repobilityId": "0d335206dceed4d7", "scanner": "scanner-primary", "fingerprint": "4e9f90d93f74d50c", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-05109551909bcecb", "level": "note", "message": {"text": "Very large file: server/index.js (3656 lines)"}, "properties": {"repobilityId": "4d84f5062adc96c0", "scanner": "scanner-primary", "fingerprint": "05109551909bcecb", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-6893a6c8b0861585", "level": "warning", "message": {"text": "Very low test-to-source ratio"}, "properties": {"repobilityId": "54a7de3f06314bf0", "scanner": "scanner-primary", "fingerprint": "6893a6c8b0861585", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "coverage"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "a7151a249bb74a3f", "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": "159106e5fcf338db", "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": "c5f9a5096036acbd", "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": "dde70cc1522994c7", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "warning", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "c3d86c2f8c43b20d", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "a50fbe3196c4f03b", "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": "74575167467cf645", "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": "9ee3e0248fbe174b", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-bea357a6497a2d5d", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: CLAUDE.md"}, "properties": {"repobilityId": "aae72df3934829ac", "scanner": "scanner-primary", "fingerprint": "bea357a6497a2d5d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "CLAUDE.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-122f91b7f2906dc4", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/settings.json"}, "properties": {"repobilityId": "a2967269048b6a9d", "scanner": "scanner-primary", "fingerprint": "122f91b7f2906dc4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/settings.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d7cdeec872383362", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/vite.config.js:4"}, "properties": {"repobilityId": "2cad40298e76d7e5", "scanner": "scanner-primary", "fingerprint": "d7cdeec872383362", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4dd894d6babb4f75", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/App.jsx:53"}, "properties": {"repobilityId": "6750f82b363baf32", "scanner": "scanner-primary", "fingerprint": "4dd894d6babb4f75", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-5a64d3886d166191", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/api.js:3"}, "properties": {"repobilityId": "087b74fd4f925b5e", "scanner": "scanner-primary", "fingerprint": "5a64d3886d166191", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a01226c0e7f07a80", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/api.js:46"}, "properties": {"repobilityId": "2a6adbd0e3e63a0a", "scanner": "scanner-primary", "fingerprint": "a01226c0e7f07a80", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-7e1838fe4aff2eb2", "level": "none", "message": {"text": "Commented-code block (6 lines) in client/src/utils/useGoBack.js:4"}, "properties": {"repobilityId": "57676dcafd36b622", "scanner": "scanner-primary", "fingerprint": "7e1838fe4aff2eb2", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b749e8516a43ff1d", "level": "note", "message": {"text": "Legacy-named symbol `brand__copy` in client/src/components/AuthForm.jsx:104"}, "properties": {"repobilityId": "6468e45a47ccb86d", "scanner": "scanner-primary", "fingerprint": "b749e8516a43ff1d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-7fe418e0a09cd647", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/components/studio/palette.js:14"}, "properties": {"repobilityId": "b2ef1d81dfacdc59", "scanner": "scanner-primary", "fingerprint": "7fe418e0a09cd647", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-d5a4d4dcb333a1a8", "level": "none", "message": {"text": "Commented-code block (6 lines) in client/src/components/studio/PreviewTool.jsx:75"}, "properties": {"repobilityId": "a6084c8fbd763ac3", "scanner": "scanner-primary", "fingerprint": "d5a4d4dcb333a1a8", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-34870b81fbc31588", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/components/studio/PreviewTool.jsx:124"}, "properties": {"repobilityId": "71f0e447003ddb3b", "scanner": "scanner-primary", "fingerprint": "34870b81fbc31588", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d2d4c04ddc45a02b", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/components/editor/slideTemplates.js:5"}, "properties": {"repobilityId": "de031bdf6cfc1ca3", "scanner": "scanner-primary", "fingerprint": "d2d4c04ddc45a02b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-740b0c754e27e7fe", "level": "none", "message": {"text": "Commented-code block (6 lines) in client/src/components/editor/statementParser.js:3"}, "properties": {"repobilityId": "77ad071782db6c7f", "scanner": "scanner-primary", "fingerprint": "740b0c754e27e7fe", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-9e319afc8ce359a8", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/components/editor/richText.js:3"}, "properties": {"repobilityId": "a2a3f70a2cd3a856", "scanner": "scanner-primary", "fingerprint": "9e319afc8ce359a8", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-ce159581828121b9", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/components/editor/slideRender.jsx:1"}, "properties": {"repobilityId": "cbc79dc9c8803412", "scanner": "scanner-primary", "fingerprint": "ce159581828121b9", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8cccc07236871336", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/components/editor/upload.js:11"}, "properties": {"repobilityId": "e43a8301f927eb24", "scanner": "scanner-primary", "fingerprint": "8cccc07236871336", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-804d1b96628f31d5", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/components/editor/StatementModal.jsx:1"}, "properties": {"repobilityId": "0cb262377cd11d82", "scanner": "scanner-primary", "fingerprint": "804d1b96628f31d5", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-aafff702bc1ea24e", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/components/codeEditor/pyodide.worker.js:4"}, "properties": {"repobilityId": "645796a849178113", "scanner": "scanner-primary", "fingerprint": "aafff702bc1ea24e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c022c2ea6b657d25", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/components/codeEditor/usePyodideRunner.js:120"}, "properties": {"repobilityId": "abd6eb070c2a44f8", "scanner": "scanner-primary", "fingerprint": "c022c2ea6b657d25", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-360dffb47c19e169", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/components/board/CodeCard.jsx:8"}, "properties": {"repobilityId": "1694c4b726702278", "scanner": "scanner-primary", "fingerprint": "360dffb47c19e169", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-267561ba9fc2c1b2", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/components/board/FileShowOverlay.jsx:1"}, "properties": {"repobilityId": "425bad9f4a6ddbd3", "scanner": "scanner-primary", "fingerprint": "267561ba9fc2c1b2", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4339788ea09a31bb", "level": "none", "message": {"text": "Commented-code block (6 lines) in client/src/components/board/LiveCodePanel.jsx:3"}, "properties": {"repobilityId": "f51bc3e52fe1cec3", "scanner": "scanner-primary", "fingerprint": "4339788ea09a31bb", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-27db71a574067079", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/components/board/BoardCanvas.jsx:143"}, "properties": {"repobilityId": "5af9f9a90f2c9f94", "scanner": "scanner-primary", "fingerprint": "27db71a574067079", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-76e8ff73486210e2", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/LessonPage.jsx:289"}, "properties": {"repobilityId": "486023ee720cc4b3", "scanner": "scanner-primary", "fingerprint": "76e8ff73486210e2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-5ae94a91686f46b3", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/pages/BankPage.jsx:433"}, "properties": {"repobilityId": "aacbf0b5692e0cac", "scanner": "scanner-primary", "fingerprint": "5ae94a91686f46b3", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-0d3d8674f5fef4d2", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/BankPage.jsx:249"}, "properties": {"repobilityId": "c905a110859c9142", "scanner": "scanner-primary", "fingerprint": "0d3d8674f5fef4d2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d10fbbc2bad08bc8", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/WeeklyCalendarPage.jsx:106"}, "properties": {"repobilityId": "f8d4bcdd7566b22f", "scanner": "scanner-primary", "fingerprint": "d10fbbc2bad08bc8", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-6826cd46baafcbed", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/ProfilePage.jsx:140"}, "properties": {"repobilityId": "0d9532af7ed555e5", "scanner": "scanner-primary", "fingerprint": "6826cd46baafcbed", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d18e2e84a19741de", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/CoursePage.jsx:110"}, "properties": {"repobilityId": "8d2fcc952a289eac", "scanner": "scanner-primary", "fingerprint": "d18e2e84a19741de", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-270965cba62fe2ec", "level": "none", "message": {"text": "Commented-code block (8 lines) in client/src/pages/VariantSolvePage.jsx:12"}, "properties": {"repobilityId": "73431a7c7c316b05", "scanner": "scanner-primary", "fingerprint": "270965cba62fe2ec", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-49ee29aee685d5c5", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/VariantSolvePage.jsx:303"}, "properties": {"repobilityId": "7d284920ed8f2aca", "scanner": "scanner-primary", "fingerprint": "49ee29aee685d5c5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3a36175576f30564", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/SectionPage.jsx:88"}, "properties": {"repobilityId": "223f49812db61493", "scanner": "scanner-primary", "fingerprint": "3a36175576f30564", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-9337b0ecd08d7f1a", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/CategoryPage.jsx:86"}, "properties": {"repobilityId": "99cfb5d90af416fb", "scanner": "scanner-primary", "fingerprint": "9337b0ecd08d7f1a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-52353910837e82b5", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/StudentDetailPage.jsx:69"}, "properties": {"repobilityId": "a14139d594c7a404", "scanner": "scanner-primary", "fingerprint": "52353910837e82b5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d426a78d0bca2267", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/MaterialsFeedPage.jsx:148"}, "properties": {"repobilityId": "ab181d59a8a150f8", "scanner": "scanner-primary", "fingerprint": "d426a78d0bca2267", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-80ade93dc0b41614", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/BulkAccessPage.jsx:62"}, "properties": {"repobilityId": "953cb037ea8417d6", "scanner": "scanner-primary", "fingerprint": "80ade93dc0b41614", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8cf4d3f282e03b5a", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 client/src/pages/StudentsPage.jsx:50"}, "properties": {"repobilityId": "ded1fb5e8ebca93e", "scanner": "scanner-primary", "fingerprint": "8cf4d3f282e03b5a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ac9f98e1e6de7135", "level": "none", "message": {"text": "Commented-code block (5 lines) in client/src/hooks/useRoom.js:343"}, "properties": {"repobilityId": "65cae29b92490aa4", "scanner": "scanner-primary", "fingerprint": "ac9f98e1e6de7135", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4433726d9e6c4784", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 finance-pwa/sw.js:19"}, "properties": {"repobilityId": "eb7100de5efde455", "scanner": "scanner-primary", "fingerprint": "4433726d9e6c4784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-eae0601f693c80a1", "level": "none", "message": {"text": "Commented-code block (6 lines) in server/bot.js:587"}, "properties": {"repobilityId": "7cbba1e7c1e8b325", "scanner": "scanner-primary", "fingerprint": "eae0601f693c80a1", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-0e183fc945269250", "level": "none", "message": {"text": "Commented-code block (7 lines) in server/index.js:18"}, "properties": {"repobilityId": "8bb911eb1b1a415c", "scanner": "scanner-primary", "fingerprint": "0e183fc945269250", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-636bcd77374fb2bc", "level": "none", "message": {"text": "Commented-code block (5 lines) in server/routes/presentations.js:205"}, "properties": {"repobilityId": "79ab58af9e8b9583", "scanner": "scanner-primary", "fingerprint": "636bcd77374fb2bc", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-250f57e8a1dbd3c5", "level": "none", "message": {"text": "4 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "57584f22b735b5ee", "scanner": "scanner-primary", "fingerprint": "250f57e8a1dbd3c5", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-39a3c19fbd12dd0d", "level": "warning", "message": {"text": "Frontend route `/reset-password/:token` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "84ec7871bfe08825", "scanner": "scanner-primary", "fingerprint": "39a3c19fbd12dd0d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-97ad4ee378fc9ad0", "level": "warning", "message": {"text": "Frontend route `/room/:roomId` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "d3d7aa64668788b3", "scanner": "scanner-primary", "fingerprint": "97ad4ee378fc9ad0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-ee37919cac84f0b2", "level": "warning", "message": {"text": "Frontend route `/notes/:id` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "0a717627217a95be", "scanner": "scanner-primary", "fingerprint": "ee37919cac84f0b2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-5c51f36680f77e26", "level": "warning", "message": {"text": "Frontend route `/board/:topicId` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "b859868dbacc0b00", "scanner": "scanner-primary", "fingerprint": "5c51f36680f77e26", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-5b301bc9d59e2185", "level": "warning", "message": {"text": "Frontend route `/course/category/:id` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "0d5fe8d7279a01e0", "scanner": "scanner-primary", "fingerprint": "5b301bc9d59e2185", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-4094e5e62d39066d", "level": "warning", "message": {"text": "Frontend route `/course/:id` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "2fd6bc53e1dbecf8", "scanner": "scanner-primary", "fingerprint": "4094e5e62d39066d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-cc86a5e5f51f7c9b", "level": "warning", "message": {"text": "Frontend route `/lesson/:id` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "35fdcf283eac7ba6", "scanner": "scanner-primary", "fingerprint": "cc86a5e5f51f7c9b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-07fd56092651974e", "level": "warning", "message": {"text": "Frontend route `/variant/:id` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "ae4e5b9846ad8e5e", "scanner": "scanner-primary", "fingerprint": "07fd56092651974e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-c5529554491256ba", "level": "warning", "message": {"text": "Frontend route `/topic/:id/stats` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "b76b4671fe00d577", "scanner": "scanner-primary", "fingerprint": "c5529554491256ba", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-f2937793c8db39bf", "level": "warning", "message": {"text": "Frontend route `/students/:id` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "e669956e93d76efe", "scanner": "scanner-primary", "fingerprint": "f2937793c8db39bf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-007052e6120503ba", "level": "warning", "message": {"text": "Frontend route `/review/:variantId/:studentId` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "8d2eb8cecff9e396", "scanner": "scanner-primary", "fingerprint": "007052e6120503ba", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-f44ec30c36019f4c", "level": "warning", "message": {"text": "Frontend route `/studio/presentations` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "c507a17598cc3332", "scanner": "scanner-primary", "fingerprint": "f44ec30c36019f4c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-e9ec84b083f25cee", "level": "warning", "message": {"text": "Frontend route `/studio/presentations/:id` has no Link/navigate to it \u2014 client/src/App.jsx"}, "properties": {"repobilityId": "951e31fae3d90d29", "scanner": "scanner-primary", "fingerprint": "e9ec84b083f25cee", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-d549f19d3ac19fc9", "level": "error", "message": {"text": "Dangling fetch: GET https://kompege.ru/api/v1/course/${courseId} (server/index.js:2157)"}, "properties": {"repobilityId": "a448e1f088f9bcad", "scanner": "scanner-primary", "fingerprint": "d549f19d3ac19fc9", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-6a0034bfd54116f0", "level": "error", "message": {"text": "Dangling fetch: GET https://kompege.ru/api/v1/task/${id} (server/index.js:2308)"}, "properties": {"repobilityId": "daafe03289969801", "scanner": "scanner-primary", "fingerprint": "6a0034bfd54116f0", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-848679f1f341557f", "level": "note", "message": {"text": "Unused endpoint: POST /api/rooms"}, "properties": {"repobilityId": "9cacbce3211fe718", "scanner": "scanner-primary", "fingerprint": "848679f1f341557f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d5e5affb161a3212", "level": "note", "message": {"text": "Unused endpoint: GET /api/rooms/:roomId"}, "properties": {"repobilityId": "94bfe058ed8ced85", "scanner": "scanner-primary", "fingerprint": "d5e5affb161a3212", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d3ff16b6f060673e", "level": "note", "message": {"text": "Unused endpoint: POST /api/rooms/:roomId/save"}, "properties": {"repobilityId": "853db7c1aa5a276a", "scanner": "scanner-primary", "fingerprint": "d3ff16b6f060673e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4e0144e669bf1d7a", "level": "note", "message": {"text": "Unused endpoint: GET /api/board/:topicId"}, "properties": {"repobilityId": "307d60b51b16754a", "scanner": "scanner-primary", "fingerprint": "4e0144e669bf1d7a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-683385533454e925", "level": "note", "message": {"text": "Unused endpoint: PUT /api/board/:topicId"}, "properties": {"repobilityId": "d21fc67d28cfe8dd", "scanner": "scanner-primary", "fingerprint": "683385533454e925", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4756b4c4da7d2088", "level": "note", "message": {"text": "Unused endpoint: GET /api/health"}, "properties": {"repobilityId": "0d2a6e55cb055de8", "scanner": "scanner-primary", "fingerprint": "4756b4c4da7d2088", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1bc898b3b7565990", "level": "note", "message": {"text": "Unused endpoint: USE /uploads"}, "properties": {"repobilityId": "cd93f5e718a74b3e", "scanner": "scanner-primary", "fingerprint": "1bc898b3b7565990", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-df092b9a20d61863", "level": "note", "message": {"text": "Unused endpoint: GET /api/table-preview"}, "properties": {"repobilityId": "435c0c9179576502", "scanner": "scanner-primary", "fingerprint": "df092b9a20d61863", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-25702767f50d6c7d", "level": "note", "message": {"text": "Unused endpoint: POST /api/register"}, "properties": {"repobilityId": "b18cdd899275f0b7", "scanner": "scanner-primary", "fingerprint": "25702767f50d6c7d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-790da11c30a99c35", "level": "note", "message": {"text": "Unused endpoint: POST /api/verify-email"}, "properties": {"repobilityId": "8ba8fb34c83a06ec", "scanner": "scanner-primary", "fingerprint": "790da11c30a99c35", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-200ab2e98a288506", "level": "note", "message": {"text": "Unused endpoint: POST /api/login"}, "properties": {"repobilityId": "630a2d77bf27edcb", "scanner": "scanner-primary", "fingerprint": "200ab2e98a288506", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9bcbb99cfee422c2", "level": "note", "message": {"text": "Unused endpoint: POST /api/google-login"}, "properties": {"repobilityId": "cc791109c1a9387f", "scanner": "scanner-primary", "fingerprint": "9bcbb99cfee422c2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a310d5b81aef3f4d", "level": "note", "message": {"text": "Unused endpoint: POST /api/forgot-password"}, "properties": {"repobilityId": "f041a0640ad6ac49", "scanner": "scanner-primary", "fingerprint": "a310d5b81aef3f4d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-96aa6a37afa1dbf3", "level": "note", "message": {"text": "Unused endpoint: POST /api/reset-password"}, "properties": {"repobilityId": "3e85025fc7640238", "scanner": "scanner-primary", "fingerprint": "96aa6a37afa1dbf3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5c1545494ab6166c", "level": "note", "message": {"text": "Unused endpoint: GET /api/me"}, "properties": {"repobilityId": "481fae4065af422a", "scanner": "scanner-primary", "fingerprint": "5c1545494ab6166c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-74ad413b851b3249", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/profile"}, "properties": {"repobilityId": "53fd1d3dd37fe7eb", "scanner": "scanner-primary", "fingerprint": "74ad413b851b3249", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-804c70b53f6dfa2a", "level": "note", "message": {"text": "Unused endpoint: POST /api/change-password"}, "properties": {"repobilityId": "36fe2af9dc1818c4", "scanner": "scanner-primary", "fingerprint": "804c70b53f6dfa2a", "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": "7b66cbc2a72db9bb", "scanner": "scanner-primary", "fingerprint": "9d84d5f4e65de0d9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-38d135d3d4d617c9", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/students/:id"}, "properties": {"repobilityId": "81817738406b5767", "scanner": "scanner-primary", "fingerprint": "38d135d3d4d617c9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-536fc60d1287e634", "level": "note", "message": {"text": "Unused endpoint: POST /api/upload"}, "properties": {"repobilityId": "21d1faf8c8a14857", "scanner": "scanner-primary", "fingerprint": "536fc60d1287e634", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1ffefb07914311a6", "level": "note", "message": {"text": "Unused endpoint: GET /api/lessons"}, "properties": {"repobilityId": "4b793251cebaa36b", "scanner": "scanner-primary", "fingerprint": "1ffefb07914311a6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c9657d2ab1b52730", "level": "note", "message": {"text": "Unused endpoint: POST /api/lessons"}, "properties": {"repobilityId": "9b47515471fd1f35", "scanner": "scanner-primary", "fingerprint": "c9657d2ab1b52730", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-220d57dbae0383c7", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/lessons/:id"}, "properties": {"repobilityId": "344ba4c109936a3a", "scanner": "scanner-primary", "fingerprint": "220d57dbae0383c7", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7923d0660f168105", "level": "note", "message": {"text": "Unused endpoint: DELETE /api/lessons/:id"}, "properties": {"repobilityId": "43d66bd7a05b564f", "scanner": "scanner-primary", "fingerprint": "7923d0660f168105", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ef9b199d79321db2", "level": "note", "message": {"text": "Unused endpoint: GET /api/course"}, "properties": {"repobilityId": "ac7ae620804215ef", "scanner": "scanner-primary", "fingerprint": "ef9b199d79321db2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3c6f4bdfd596e901", "level": "note", "message": {"text": "Unused endpoint: GET /api/course/categories"}, "properties": {"repobilityId": "3e1e855da000a690", "scanner": "scanner-primary", "fingerprint": "3c6f4bdfd596e901", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5e29cf5b36415331", "level": "note", "message": {"text": "Unused endpoint: POST /api/course/category"}, "properties": {"repobilityId": "9404e6cdd2f33821", "scanner": "scanner-primary", "fingerprint": "5e29cf5b36415331", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4067d0d112d19a4e", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/course/category/reorder"}, "properties": {"repobilityId": "b4c0780c5ad37ea1", "scanner": "scanner-primary", "fingerprint": "4067d0d112d19a4e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-499122b8fb1523d5", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/course/category/:id"}, "properties": {"repobilityId": "3f97c5e9fdcf1686", "scanner": "scanner-primary", "fingerprint": "499122b8fb1523d5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4462f65ad190111d", "level": "note", "message": {"text": "Unused endpoint: DELETE /api/course/category/:id"}, "properties": {"repobilityId": "b8e59d5a8477b821", "scanner": "scanner-primary", "fingerprint": "4462f65ad190111d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-677d167f09b70daf", "level": "note", "message": {"text": "Unused endpoint: GET /api/course/category/:id/sections"}, "properties": {"repobilityId": "7628f60dae0c3286", "scanner": "scanner-primary", "fingerprint": "677d167f09b70daf", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5f688d7e83864011", "level": "note", "message": {"text": "Unused endpoint: POST /api/course/category/:id/topic"}, "properties": {"repobilityId": "318c88905f0f7275", "scanner": "scanner-primary", "fingerprint": "5f688d7e83864011", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4409701e31d1067c", "level": "note", "message": {"text": "Unused endpoint: POST /api/course/topic"}, "properties": {"repobilityId": "20464ae9a2fe6d90", "scanner": "scanner-primary", "fingerprint": "4409701e31d1067c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7ed931d27b64e471", "level": "note", "message": {"text": "Unused endpoint: DELETE /api/course/section/:id"}, "properties": {"repobilityId": "19cb78e8e03919e5", "scanner": "scanner-primary", "fingerprint": "7ed931d27b64e471", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b9f0f97a9398cedc", "level": "note", "message": {"text": "Unused endpoint: POST /api/course/section"}, "properties": {"repobilityId": "74346973d18ff089", "scanner": "scanner-primary", "fingerprint": "b9f0f97a9398cedc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f7c1311142ac7c42", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/course/section/reorder"}, "properties": {"repobilityId": "87a6afe84cb271b9", "scanner": "scanner-primary", "fingerprint": "f7c1311142ac7c42", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-88f969d69170a01f", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/course/section/:id"}, "properties": {"repobilityId": "35c91505be68c7cf", "scanner": "scanner-primary", "fingerprint": "88f969d69170a01f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e1a38ea3375f5475", "level": "note", "message": {"text": "Unused endpoint: GET /api/course/section/:id"}, "properties": {"repobilityId": "48947626ba88becd", "scanner": "scanner-primary", "fingerprint": "e1a38ea3375f5475", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9e7335780e4ce271", "level": "note", "message": {"text": "Unused endpoint: POST /api/course/section/:id/topic"}, "properties": {"repobilityId": "8056b5dd777df444", "scanner": "scanner-primary", "fingerprint": "9e7335780e4ce271", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-20944f4e887445e2", "level": "note", "message": {"text": "Unused endpoint: POST /api/course/section/:id/unpack"}, "properties": {"repobilityId": "260078087daf97e3", "scanner": "scanner-primary", "fingerprint": "20944f4e887445e2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-57e8caf5320055c9", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/course/topic/reorder"}, "properties": {"repobilityId": "559e3a4ca56369ba", "scanner": "scanner-primary", "fingerprint": "57e8caf5320055c9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-58812a9f02f41327", "level": "note", "message": {"text": "Unused endpoint: GET /api/course/topic/:id"}, "properties": {"repobilityId": "ec6b7fb04486a9e9", "scanner": "scanner-primary", "fingerprint": "58812a9f02f41327", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-353010e9008939ba", "level": "note", "message": {"text": "Unused endpoint: POST /api/calendar/token"}, "properties": {"repobilityId": "d0b60119170df542", "scanner": "scanner-primary", "fingerprint": "353010e9008939ba", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c15284ea1d1e4ada", "level": "note", "message": {"text": "Unused endpoint: PUT /api/course/topic/:id"}, "properties": {"repobilityId": "17026964963eeb41", "scanner": "scanner-primary", "fingerprint": "c15284ea1d1e4ada", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-51daeca915f28074", "level": "note", "message": {"text": "Unused endpoint: POST /api/course/topic/:id/material"}, "properties": {"repobilityId": "15980da976fe4c4c", "scanner": "scanner-primary", "fingerprint": "51daeca915f28074", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-45d50b30cce14830", "level": "note", "message": {"text": "Unused endpoint: POST /api/bulk-access"}, "properties": {"repobilityId": "01601317fdfd18cd", "scanner": "scanner-primary", "fingerprint": "45d50b30cce14830", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-aebd9c09c0116575", "level": "note", "message": {"text": "Unused endpoint: DELETE /api/course/topic/:topicId/material/:studentId"}, "properties": {"repobilityId": "847e3ea96049a576", "scanner": "scanner-primary", "fingerprint": "aebd9c09c0116575", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-612ef722df60f60e", "level": "note", "message": {"text": "Unused endpoint: DELETE /api/course/topic/:id"}, "properties": {"repobilityId": "85ae583a7a648272", "scanner": "scanner-primary", "fingerprint": "612ef722df60f60e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cf16ae0930dc161a", "level": "note", "message": {"text": "Unused endpoint: GET /api/tasks"}, "properties": {"repobilityId": "166eb3c0e62dedaf", "scanner": "scanner-primary", "fingerprint": "cf16ae0930dc161a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1d5b18f8708facc4", "level": "note", "message": {"text": "Unused endpoint: PATCH /api/tasks/:id"}, "properties": {"repobilityId": "6f477a970ea0ad98", "scanner": "scanner-primary", "fingerprint": "1d5b18f8708facc4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}