{"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-8b155af5ee4d678e", "name": "Icon-only button without accessible name \u2014 src/components/portal/messages/MessageComposer.vue:70", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/portal/messages/MessageComposer.vue:70"}, "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-d63da3583b14afc0", "name": "Dockerfile runs as root: Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-25de52372c63f233", "name": "Docker base image is tag-pinned but not digest-pinned: node:24-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: node:24-slim"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2f3178ddda7c2897", "name": "Docker base image is tag-pinned but not digest-pinned: nginx:alpine", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: nginx:alpine"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-aa5acaa49eb8315b", "name": "Containers defined but no K8s/orchestration manifest found", "shortDescription": {"text": "Containers defined but no K8s/orchestration manifest found"}, "fullDescription": {"text": "Repo has Dockerfiles/compose but no Kubernetes/Nomad manifests. If the target deployment is K8s, the manifests may live in a separate ops repo."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8c33387cf6242e8a", "name": "Insecure pattern 'node_child_process' in scripts/check-api-drift.mjs:7", "shortDescription": {"text": "Insecure pattern 'node_child_process' in scripts/check-api-drift.mjs:7"}, "fullDescription": {"text": "Found a known-risky pattern (node_child_process). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b1443c37baa7abaf", "name": "Insecure pattern 'node_child_process' in scripts/lint-tokens.mjs:9", "shortDescription": {"text": "Insecure pattern 'node_child_process' in scripts/lint-tokens.mjs:9"}, "fullDescription": {"text": "Found a known-risky pattern (node_child_process). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-aa22ea0902c8611c", "name": "Insecure pattern 'vue_v_html' in src/parent/components/assistant/FaqAnswer.vue:43", "shortDescription": {"text": "Insecure pattern 'vue_v_html' in src/parent/components/assistant/FaqAnswer.vue:43"}, "fullDescription": {"text": "Found a known-risky pattern (vue_v_html). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-228279a7a65c039a", "name": "Insecure pattern 'document_write' in src/utils/printPdfWindow.ts:24", "shortDescription": {"text": "Insecure pattern 'document_write' in src/utils/printPdfWindow.ts:24"}, "fullDescription": {"text": "Found a known-risky pattern (document_write). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9974b735fc2ff1fb", "name": "Insecure pattern 'direct_innerhtml_assignment' in src/utils/printPdfWindow.ts:56", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in src/utils/printPdfWindow.ts:56"}, "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-b1302bae2a5aa486", "name": "Insecure pattern 'vue_v_html' in src/components/GlobalSearch.vue:33", "shortDescription": {"text": "Insecure pattern 'vue_v_html' in src/components/GlobalSearch.vue:33"}, "fullDescription": {"text": "Found a known-risky pattern (vue_v_html). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d8de2a0f62ff652", "name": "Insecure pattern 'direct_innerhtml_assignment' in src/components/recruitment/RecruitmentAddressHeatmap.vue:1049", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in src/components/recruitment/RecruitmentAddressHeatmap.vue:1049"}, "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-8eb547798188c020", "name": "Insecure pattern 'vue_v_html' in src/views/public/ActivityPublicQueryView.vue:11", "shortDescription": {"text": "Insecure pattern 'vue_v_html' in src/views/public/ActivityPublicQueryView.vue:11"}, "fullDescription": {"text": "Found a known-risky pattern (vue_v_html). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-afa4f55459d02d2f", "name": "Insecure pattern 'vue_v_html' in src/views/public/components/ToastStack.vue:37", "shortDescription": {"text": "Insecure pattern 'vue_v_html' in src/views/public/components/ToastStack.vue:37"}, "fullDescription": {"text": "Found a known-risky pattern (vue_v_html). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-740b88ab8dd23d2f", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "dependabot/fetch-metadata@v2 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-768e8f28c1850d98", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-27924aa79fa4a517", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/setup-node@v4 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 7 console/debugger/print-style debug statements in non-test source. This is a common fast-generation residue before production cleanup."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e725d2ab884fbd49", "name": "Multiple root agent instruction files without precedence", "shortDescription": {"text": "Multiple root agent instruction files without precedence"}, "fullDescription": {"text": "The repo has multiple top-level AI-coder instruction files. Without precedence rules, different agents may follow different policies."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-92e616f8f6553228", "name": "Commented-code block (5 lines) in vite.config.js:68", "shortDescription": {"text": "Commented-code block (5 lines) in vite.config.js:68"}, "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-53a14108e9e3784c", "name": "Legacy-named symbol `parent_faq_v1` in tests/unit/parent/composables/useFaq.test.js:28", "shortDescription": {"text": "Legacy-named symbol `parent_faq_v1` in tests/unit/parent/composables/useFaq.test.js:28"}, "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-6fdfb8d63a96954f", "name": "Legacy-named symbol `parent_selected_student_id_v2` in tests/unit/parent/composables/useChildSelection.test.js:20", "shortDescription": {"text": "Legacy-named symbol `parent_selected_student_id_v2` in tests/unit/parent/composables/useChildSelection.test.js:20"}, "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-38272204f61314d4", "name": "Legacy-named symbol `resolveOld` in tests/unit/parent/composables/useChildTimeline.test.js:118", "shortDescription": {"text": "Legacy-named symbol `resolveOld` in tests/unit/parent/composables/useChildTimeline.test.js:118"}, "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-ae68338dcf86ebdb", "name": "Commented-code block (7 lines) in tests/unit/utils/scope-aware-parity.test.ts:8", "shortDescription": {"text": "Commented-code block (7 lines) in tests/unit/utils/scope-aware-parity.test.ts: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-4efbc9761d559c17", "name": "Commented-code block (6 lines) in tests/unit/components/RecruitmentAddressHeatmap.test.js:335", "shortDescription": {"text": "Commented-code block (6 lines) in tests/unit/components/RecruitmentAddressHeatmap.test.js:335"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-09b1e9830c164f44", "name": "Commented-code block (6 lines) in tests/unit/components/gov-reports/ClassroomSummaryTable.spec.js:6", "shortDescription": {"text": "Commented-code block (6 lines) in tests/unit/components/gov-reports/ClassroomSummaryTable.spec.js:6"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4070f37226323d25", "name": "Commented-code block (7 lines) in tests/components/EmployeeFormBasic.test.ts:88", "shortDescription": {"text": "Commented-code block (7 lines) in tests/components/EmployeeFormBasic.test.ts:88"}, "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-0e5f9a2c8bc70cf9", "name": "Legacy-named symbol `parent_user_v1` in src/parent/stores/parentAuth.ts:11", "shortDescription": {"text": "Legacy-named symbol `parent_user_v1` in src/parent/stores/parentAuth.ts:11"}, "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-afa352d4b19a552e", "name": "Commented-code block (5 lines) in src/parent/api/index.ts:196", "shortDescription": {"text": "Commented-code block (5 lines) in src/parent/api/index.ts:196"}, "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-ce41ef5671df947a", "name": "Legacy-named symbol `parent_faq_v1` in src/parent/composables/useFaq.ts:4", "shortDescription": {"text": "Legacy-named symbol `parent_faq_v1` in src/parent/composables/useFaq.ts:4"}, "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-dee21b0cf94e2f8f", "name": "Legacy-named symbol `parent_selected_student_id_v2` in src/parent/composables/useChildSelection.ts:10", "shortDescription": {"text": "Legacy-named symbol `parent_selected_student_id_v2` in src/parent/composables/useChildSelection.ts:10"}, "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-2a99124331672b74", "name": "Commented-code block (6 lines) in src/api/leaves.ts:9", "shortDescription": {"text": "Commented-code block (6 lines) in src/api/leaves.ts:9"}, "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-adf5e2dd1ec2e30d", "name": "Commented-code block (6 lines) in src/api/index.ts:153", "shortDescription": {"text": "Commented-code block (6 lines) in src/api/index.ts:153"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-8130ed5d3f7ad275", "name": "Commented-code block (7 lines) in src/api/activity.ts:87", "shortDescription": {"text": "Commented-code block (7 lines) in src/api/activity.ts:87"}, "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-a686649e36e8d8d1", "name": "Commented-code block (5 lines) in src/constants/permissions.ts:164", "shortDescription": {"text": "Commented-code block (5 lines) in src/constants/permissions.ts:164"}, "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-c6f551234c972317", "name": "Commented-code block (5 lines) in src/composables/useActivityAttendanceDrawer.ts:54", "shortDescription": {"text": "Commented-code block (5 lines) in src/composables/useActivityAttendanceDrawer.ts:54"}, "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-51dfe247aa7e45dd", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/composables/useTableFilters.ts:85", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/composables/useTableFilters.ts:85"}, "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-92f05c389ca5abdc", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/utils/geocoding.ts:45", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/utils/geocoding.ts:45"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f808a4ef3e1071fb", "name": "14 env vars used in code but missing from .env.example", "shortDescription": {"text": "14 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `DEV`, `IVY_BACKEND_DIR`, `IVY_FRONTEND_DIR`, `MODE`, `SENTRY_AUTH_TOKEN`, `SENTRY_ORG`, `SENTRY_PROJECT`, `SENTRY_RELEASE` + 6 more. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7722370f2c938c09", "name": "Unused endpoint: POST /parent/auth/liff-login", "shortDescription": {"text": "Unused endpoint: POST /parent/auth/liff-login"}, "fullDescription": {"text": "`src/parent/api/auth.ts` declares `POST /parent/auth/liff-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-684f2181902ec666", "name": "Unused endpoint: POST /parent/auth/bind", "shortDescription": {"text": "Unused endpoint: POST /parent/auth/bind"}, "fullDescription": {"text": "`src/parent/api/auth.ts` declares `POST /parent/auth/bind` 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-0bbf074bd3e2820b", "name": "Unused endpoint: POST /parent/auth/bind-additional", "shortDescription": {"text": "Unused endpoint: POST /parent/auth/bind-additional"}, "fullDescription": {"text": "`src/parent/api/auth.ts` declares `POST /parent/auth/bind-additional` 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-e4a6cee72c409e4b", "name": "Unused endpoint: POST /parent/auth/logout", "shortDescription": {"text": "Unused endpoint: POST /parent/auth/logout"}, "fullDescription": {"text": "`src/parent/api/auth.ts` declares `POST /parent/auth/logout` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d2de70efa072cb0e", "name": "Unused endpoint: GET /parent/growth-reports", "shortDescription": {"text": "Unused endpoint: GET /parent/growth-reports"}, "fullDescription": {"text": "`src/parent/api/childReports.ts` declares `GET /parent/growth-reports` 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-9b4341c5a77e6526", "name": "Unused endpoint: GET /parent/photos", "shortDescription": {"text": "Unused endpoint: GET /parent/photos"}, "fullDescription": {"text": "`src/parent/api/childPhotos.ts` declares `GET /parent/photos` 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-c0f56e8e478141d0", "name": "Unused endpoint: GET /parent/fees/summary", "shortDescription": {"text": "Unused endpoint: GET /parent/fees/summary"}, "fullDescription": {"text": "`src/parent/api/fees.ts` declares `GET /parent/fees/summary` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d68693eaa1344308", "name": "Unused endpoint: GET /parent/fees/records", "shortDescription": {"text": "Unused endpoint: GET /parent/fees/records"}, "fullDescription": {"text": "`src/parent/api/fees.ts` declares `GET /parent/fees/records` 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-b306d809fc4ebdc3", "name": "Unused endpoint: POST /parent/student-leaves", "shortDescription": {"text": "Unused endpoint: POST /parent/student-leaves"}, "fullDescription": {"text": "`src/parent/api/leaves.ts` declares `POST /parent/student-leaves` 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-3e123a6baaaac45a", "name": "Unused endpoint: GET /parent/student-leaves", "shortDescription": {"text": "Unused endpoint: GET /parent/student-leaves"}, "fullDescription": {"text": "`src/parent/api/leaves.ts` declares `GET /parent/student-leaves` 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-131161d74f9b1786", "name": "Unused endpoint: GET /parent/messages/threads", "shortDescription": {"text": "Unused endpoint: GET /parent/messages/threads"}, "fullDescription": {"text": "`src/parent/api/messages.ts` declares `GET /parent/messages/threads` 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-3f09b5e3b5b61d53", "name": "Unused endpoint: GET /parent/messages/unread-count", "shortDescription": {"text": "Unused endpoint: GET /parent/messages/unread-count"}, "fullDescription": {"text": "`src/parent/api/messages.ts` declares `GET /parent/messages/unread-count` 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-e88a1360c8b00d36", "name": "Unused endpoint: GET /parent/assistant/faq", "shortDescription": {"text": "Unused endpoint: GET /parent/assistant/faq"}, "fullDescription": {"text": "`src/parent/api/assistant.ts` declares `GET /parent/assistant/faq` 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-b0b5304cb10e0ec3", "name": "Unused endpoint: GET /parent/notifications/preferences", "shortDescription": {"text": "Unused endpoint: GET /parent/notifications/preferences"}, "fullDescription": {"text": "`src/parent/api/notifications.ts` declares `GET /parent/notifications/preferences` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7ad6b8e38e2f0bba", "name": "Unused endpoint: PUT /parent/notifications/preferences", "shortDescription": {"text": "Unused endpoint: PUT /parent/notifications/preferences"}, "fullDescription": {"text": "`src/parent/api/notifications.ts` declares `PUT /parent/notifications/preferences` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-979d8cb0a57f0b8c", "name": "Unused endpoint: GET /parent/milestones", "shortDescription": {"text": "Unused endpoint: GET /parent/milestones"}, "fullDescription": {"text": "`src/parent/api/childMilestones.ts` declares `GET /parent/milestones` 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-8815280ba5b2b441", "name": "Unused endpoint: GET /parent/me", "shortDescription": {"text": "Unused endpoint: GET /parent/me"}, "fullDescription": {"text": "`src/parent/api/profile.ts` declares `GET /parent/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-ed76c6e61bbd0612", "name": "Unused endpoint: GET /parent/my-children", "shortDescription": {"text": "Unused endpoint: GET /parent/my-children"}, "fullDescription": {"text": "`src/parent/api/profile.ts` declares `GET /parent/my-children` 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-03ec6d1635ab2b4e", "name": "Unused endpoint: GET /parent/home/summary", "shortDescription": {"text": "Unused endpoint: GET /parent/home/summary"}, "fullDescription": {"text": "`src/parent/api/profile.ts` declares `GET /parent/home/summary` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-581cbf9384e525fd", "name": "Unused endpoint: GET /parent/home/today-status", "shortDescription": {"text": "Unused endpoint: GET /parent/home/today-status"}, "fullDescription": {"text": "`src/parent/api/profile.ts` declares `GET /parent/home/today-status` 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-7a233a93bb88b7d6", "name": "Unused endpoint: GET /parent/attendance/daily", "shortDescription": {"text": "Unused endpoint: GET /parent/attendance/daily"}, "fullDescription": {"text": "`src/parent/api/attendance.ts` declares `GET /parent/attendance/daily` 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-248cd53ee9dd35b8", "name": "Unused endpoint: GET /parent/attendance/monthly", "shortDescription": {"text": "Unused endpoint: GET /parent/attendance/monthly"}, "fullDescription": {"text": "`src/parent/api/attendance.ts` declares `GET /parent/attendance/monthly` 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-7dda1ba860c39611", "name": "Unused endpoint: GET /parent/calendar/week", "shortDescription": {"text": "Unused endpoint: GET /parent/calendar/week"}, "fullDescription": {"text": "`src/parent/api/calendar.ts` declares `GET /parent/calendar/week` 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-435f6529e0e976dd", "name": "Unused endpoint: GET /parent/activity/courses", "shortDescription": {"text": "Unused endpoint: GET /parent/activity/courses"}, "fullDescription": {"text": "`src/parent/api/activity.ts` declares `GET /parent/activity/courses` 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-9bf994040e1f9beb", "name": "Unused endpoint: GET /parent/activity/my-registrations", "shortDescription": {"text": "Unused endpoint: GET /parent/activity/my-registrations"}, "fullDescription": {"text": "`src/parent/api/activity.ts` declares `GET /parent/activity/my-registrations` 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-c848487fa5040f0d", "name": "Unused endpoint: POST /parent/activity/register", "shortDescription": {"text": "Unused endpoint: POST /parent/activity/register"}, "fullDescription": {"text": "`src/parent/api/activity.ts` declares `POST /parent/activity/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-b52abae016ac2e83", "name": "Unused endpoint: GET /parent/measurements", "shortDescription": {"text": "Unused endpoint: GET /parent/measurements"}, "fullDescription": {"text": "`src/parent/api/childMeasurements.ts` declares `GET /parent/measurements` 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-468c746e61bd8a7d", "name": "Unused endpoint: GET /parent/measurements/chart-data", "shortDescription": {"text": "Unused endpoint: GET /parent/measurements/chart-data"}, "fullDescription": {"text": "`src/parent/api/childMeasurements.ts` declares `GET /parent/measurements/chart-data` 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-039c1eba35b0f684", "name": "Unused endpoint: GET /parent/timeline", "shortDescription": {"text": "Unused endpoint: GET /parent/timeline"}, "fullDescription": {"text": "`src/parent/api/childTimeline.ts` declares `GET /parent/timeline` 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-ff8318e0703e9ac5", "name": "Unused endpoint: GET /parent/family/timeline", "shortDescription": {"text": "Unused endpoint: GET /parent/family/timeline"}, "fullDescription": {"text": "`src/parent/api/family.ts` declares `GET /parent/family/timeline` 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-b662234cc868ee9b", "name": "Unused endpoint: GET /parent/contact-book/today", "shortDescription": {"text": "Unused endpoint: GET /parent/contact-book/today"}, "fullDescription": {"text": "`src/parent/api/contactBook.ts` declares `GET /parent/contact-book/today` 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-c3015977fc49af64", "name": "Unused endpoint: GET /parent/contact-book", "shortDescription": {"text": "Unused endpoint: GET /parent/contact-book"}, "fullDescription": {"text": "`src/parent/api/contactBook.ts` declares `GET /parent/contact-book` 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-314ad3f8b48ce28b", "name": "Unused endpoint: GET /parent/events", "shortDescription": {"text": "Unused endpoint: GET /parent/events"}, "fullDescription": {"text": "`src/parent/api/events.ts` declares `GET /parent/events` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a3fdec6929cc0359", "name": "Unused endpoint: GET /parent/announcements", "shortDescription": {"text": "Unused endpoint: GET /parent/announcements"}, "fullDescription": {"text": "`src/parent/api/announcements.ts` declares `GET /parent/announcements` 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-d2bff920e9a109ec", "name": "Unused endpoint: GET /parent/announcements/unread-count", "shortDescription": {"text": "Unused endpoint: GET /parent/announcements/unread-count"}, "fullDescription": {"text": "`src/parent/api/announcements.ts` declares `GET /parent/announcements/unread-count` 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-dd5bf5ce83a34a9b", "name": "Unused endpoint: GET /parent/medication-orders", "shortDescription": {"text": "Unused endpoint: GET /parent/medication-orders"}, "fullDescription": {"text": "`src/parent/api/medications.ts` declares `GET /parent/medication-orders` 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-b2d73ce83003fad6", "name": "Unused endpoint: POST /parent/medication-orders", "shortDescription": {"text": "Unused endpoint: POST /parent/medication-orders"}, "fullDescription": {"text": "`src/parent/api/medications.ts` declares `POST /parent/medication-orders` 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-debbbaf41593f22a", "name": "Unused endpoint: GET /parent/me/data-export", "shortDescription": {"text": "Unused endpoint: GET /parent/me/data-export"}, "fullDescription": {"text": "`src/parent/composables/useDataExport.ts` declares `GET /parent/me/data-export` 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-6c506e7afeca2307", "name": "Unused endpoint: GET /config/titles", "shortDescription": {"text": "Unused endpoint: GET /config/titles"}, "fullDescription": {"text": "`src/api/config.ts` declares `GET /config/titles` 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-06948c288d396ce5", "name": "Unused endpoint: POST /config/titles", "shortDescription": {"text": "Unused endpoint: POST /config/titles"}, "fullDescription": {"text": "`src/api/config.ts` declares `POST /config/titles` 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-de802ebe0ab50a42", "name": "Unused endpoint: GET /config/attendance-policy", "shortDescription": {"text": "Unused endpoint: GET /config/attendance-policy"}, "fullDescription": {"text": "`src/api/config.ts` declares `GET /config/attendance-policy` 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-953a157b251861bf", "name": "Unused endpoint: PUT /config/attendance-policy", "shortDescription": {"text": "Unused endpoint: PUT /config/attendance-policy"}, "fullDescription": {"text": "`src/api/config.ts` declares `PUT /config/attendance-policy` 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-773e1b003c2ecc2a", "name": "Unused endpoint: GET /config/insurance-rates", "shortDescription": {"text": "Unused endpoint: GET /config/insurance-rates"}, "fullDescription": {"text": "`src/api/config.ts` declares `GET /config/insurance-rates` 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-431247de0af41bfd", "name": "Unused endpoint: PUT /config/insurance-rates", "shortDescription": {"text": "Unused endpoint: PUT /config/insurance-rates"}, "fullDescription": {"text": "`src/api/config.ts` declares `PUT /config/insurance-rates` 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-0c7596bdedac5cba", "name": "Unused endpoint: GET /config/bonus", "shortDescription": {"text": "Unused endpoint: GET /config/bonus"}, "fullDescription": {"text": "`src/api/config.ts` declares `GET /config/bonus` 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-dee1d9d953900afc", "name": "Unused endpoint: PUT /config/bonus", "shortDescription": {"text": "Unused endpoint: PUT /config/bonus"}, "fullDescription": {"text": "`src/api/config.ts` declares `PUT /config/bonus` 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-ca3f8861f8afddc2", "name": "Unused endpoint: GET /config/grade-targets", "shortDescription": {"text": "Unused endpoint: GET /config/grade-targets"}, "fullDescription": {"text": "`src/api/config.ts` declares `GET /config/grade-targets` 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-f71991114fff76da", "name": "Unused endpoint: PUT /config/grade-targets", "shortDescription": {"text": "Unused endpoint: PUT /config/grade-targets"}, "fullDescription": {"text": "`src/api/config.ts` declares `PUT /config/grade-targets` 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-e70b6619f47a3b8e", "name": "Unused endpoint: GET /config/position-salary", "shortDescription": {"text": "Unused endpoint: GET /config/position-salary"}, "fullDescription": {"text": "`src/api/config.ts` declares `GET /config/position-salary` 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-afd79aa45ad75042", "name": "Unused endpoint: PUT /config/position-salary", "shortDescription": {"text": "Unused endpoint: PUT /config/position-salary"}, "fullDescription": {"text": "`src/api/config.ts` declares `PUT /config/position-salary` 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/22904"}, "properties": {"repository": "wu0010802-stack/ivyManageSystem-frontend", "repoUrl": "https://github.com/wu0010802-stack/ivyManageSystem-frontend", "branch": "main"}, "results": [{"ruleId": "scanner-8b155af5ee4d678e", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/portal/messages/MessageComposer.vue:70"}, "properties": {"repobilityId": "fd50a3408806eecb", "scanner": "scanner-primary", "fingerprint": "8b155af5ee4d678e", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-d63da3583b14afc0", "level": "warning", "message": {"text": "Dockerfile runs as root: Dockerfile"}, "properties": {"repobilityId": "a2ed1bd120e507db", "scanner": "scanner-primary", "fingerprint": "d63da3583b14afc0", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-25de52372c63f233", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:24-slim"}, "properties": {"repobilityId": "be5253d142d74612", "scanner": "scanner-primary", "fingerprint": "25de52372c63f233", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 4}}}]}, {"ruleId": "scanner-2f3178ddda7c2897", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: nginx:alpine"}, "properties": {"repobilityId": "9fac64cd95c6dbcd", "scanner": "scanner-primary", "fingerprint": "2f3178ddda7c2897", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 26}}}]}, {"ruleId": "scanner-aa5acaa49eb8315b", "level": "note", "message": {"text": "Containers defined but no K8s/orchestration manifest found"}, "properties": {"repobilityId": "b230ea9b68736081", "scanner": "scanner-primary", "fingerprint": "aa5acaa49eb8315b", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["coverage", "deployment"]}}, {"ruleId": "scanner-8c33387cf6242e8a", "level": "warning", "message": {"text": "Insecure pattern 'node_child_process' in scripts/check-api-drift.mjs:7"}, "properties": {"repobilityId": "5cc809cf2dcddf17", "scanner": "scanner-primary", "fingerprint": "8c33387cf6242e8a", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "node_child_process"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "scripts/check-api-drift.mjs"}, "region": {"startLine": 7}}}]}, {"ruleId": "scanner-b1443c37baa7abaf", "level": "warning", "message": {"text": "Insecure pattern 'node_child_process' in scripts/lint-tokens.mjs:9"}, "properties": {"repobilityId": "37c6956500dab921", "scanner": "scanner-primary", "fingerprint": "b1443c37baa7abaf", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "node_child_process"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "scripts/lint-tokens.mjs"}, "region": {"startLine": 9}}}]}, {"ruleId": "scanner-aa22ea0902c8611c", "level": "warning", "message": {"text": "Insecure pattern 'vue_v_html' in src/parent/components/assistant/FaqAnswer.vue:43"}, "properties": {"repobilityId": "b64c3f577cf4567c", "scanner": "scanner-primary", "fingerprint": "aa22ea0902c8611c", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "vue_v_html"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/parent/components/assistant/FaqAnswer.vue"}, "region": {"startLine": 43}}}]}, {"ruleId": "scanner-228279a7a65c039a", "level": "note", "message": {"text": "Insecure pattern 'document_write' in src/utils/printPdfWindow.ts:24"}, "properties": {"repobilityId": "d181ba523e316004", "scanner": "scanner-primary", "fingerprint": "228279a7a65c039a", "layer": "security", "severity": "low", "confidence": 1.0, "tags": ["owasp", "document_write"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/utils/printPdfWindow.ts"}, "region": {"startLine": 24}}}]}, {"ruleId": "scanner-9974b735fc2ff1fb", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in src/utils/printPdfWindow.ts:56"}, "properties": {"repobilityId": "7925c2c61dae7768", "scanner": "scanner-primary", "fingerprint": "9974b735fc2ff1fb", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/utils/printPdfWindow.ts"}, "region": {"startLine": 56}}}]}, {"ruleId": "scanner-b1302bae2a5aa486", "level": "warning", "message": {"text": "Insecure pattern 'vue_v_html' in src/components/GlobalSearch.vue:33"}, "properties": {"repobilityId": "80256afa02b35d01", "scanner": "scanner-primary", "fingerprint": "b1302bae2a5aa486", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "vue_v_html"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/GlobalSearch.vue"}, "region": {"startLine": 33}}}]}, {"ruleId": "scanner-2d8de2a0f62ff652", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in src/components/recruitment/RecruitmentAddressHeatmap.vue:1049"}, "properties": {"repobilityId": "3ddc7ec188514ab2", "scanner": "scanner-primary", "fingerprint": "2d8de2a0f62ff652", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/recruitment/RecruitmentAddressHeatmap.vue"}, "region": {"startLine": 1049}}}]}, {"ruleId": "scanner-8eb547798188c020", "level": "warning", "message": {"text": "Insecure pattern 'vue_v_html' in src/views/public/ActivityPublicQueryView.vue:11"}, "properties": {"repobilityId": "ae0d68d710ed901b", "scanner": "scanner-primary", "fingerprint": "8eb547798188c020", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "vue_v_html"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/views/public/ActivityPublicQueryView.vue"}, "region": {"startLine": 11}}}]}, {"ruleId": "scanner-afa4f55459d02d2f", "level": "warning", "message": {"text": "Insecure pattern 'vue_v_html' in src/views/public/components/ToastStack.vue:37"}, "properties": {"repobilityId": "92284b27e8c0fd46", "scanner": "scanner-primary", "fingerprint": "afa4f55459d02d2f", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "vue_v_html"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/views/public/components/ToastStack.vue"}, "region": {"startLine": 37}}}]}, {"ruleId": "scanner-740b88ab8dd23d2f", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "6c22316cfcffbcef", "scanner": "scanner-primary", "fingerprint": "740b88ab8dd23d2f", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/dependabot-auto-merge.yml"}, "region": {"startLine": 18}}}]}, {"ruleId": "scanner-768e8f28c1850d98", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "f3c306ca3743dfa1", "scanner": "scanner-primary", "fingerprint": "768e8f28c1850d98", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/dependabot-auto-merge.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "989a74409a402368", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 36}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "989a74409a402368", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 53}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "ae16880318b99912", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 91}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "ae16880318b99912", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 96}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "04f57d208548fcef", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 102}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "989a74409a402368", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 121}}}]}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "e13602ac427a064f", "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": "ebbf58ab45146ca3", "scanner": "scanner-primary", "fingerprint": "3ab5d313dda8e5f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["debug", "cleanup", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "c4b0096e07d00264", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "ea83ee5feceea6bd", "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": "6f661bde66d6e1da", "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": "84d62673074d3659", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-e725d2ab884fbd49", "level": "note", "message": {"text": "Multiple root agent instruction files without precedence"}, "properties": {"repobilityId": "1953db6c89508d22", "scanner": "scanner-primary", "fingerprint": "e725d2ab884fbd49", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["agent-instructions", "governance"]}}, {"ruleId": "scanner-92e616f8f6553228", "level": "none", "message": {"text": "Commented-code block (5 lines) in vite.config.js:68"}, "properties": {"repobilityId": "847de161babe7afd", "scanner": "scanner-primary", "fingerprint": "92e616f8f6553228", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-53a14108e9e3784c", "level": "note", "message": {"text": "Legacy-named symbol `parent_faq_v1` in tests/unit/parent/composables/useFaq.test.js:28"}, "properties": {"repobilityId": "30bfa9fe4a237f37", "scanner": "scanner-primary", "fingerprint": "53a14108e9e3784c", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-6fdfb8d63a96954f", "level": "note", "message": {"text": "Legacy-named symbol `parent_selected_student_id_v2` in tests/unit/parent/composables/useChildSelection.test.js:20"}, "properties": {"repobilityId": "787199dd93bf4f95", "scanner": "scanner-primary", "fingerprint": "6fdfb8d63a96954f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-38272204f61314d4", "level": "note", "message": {"text": "Legacy-named symbol `resolveOld` in tests/unit/parent/composables/useChildTimeline.test.js:118"}, "properties": {"repobilityId": "01b9ad6a73f13cda", "scanner": "scanner-primary", "fingerprint": "38272204f61314d4", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-ae68338dcf86ebdb", "level": "none", "message": {"text": "Commented-code block (7 lines) in tests/unit/utils/scope-aware-parity.test.ts:8"}, "properties": {"repobilityId": "5b8fc48572e060e7", "scanner": "scanner-primary", "fingerprint": "ae68338dcf86ebdb", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4efbc9761d559c17", "level": "none", "message": {"text": "Commented-code block (6 lines) in tests/unit/components/RecruitmentAddressHeatmap.test.js:335"}, "properties": {"repobilityId": "9798668801507b6c", "scanner": "scanner-primary", "fingerprint": "4efbc9761d559c17", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-09b1e9830c164f44", "level": "none", "message": {"text": "Commented-code block (6 lines) in tests/unit/components/gov-reports/ClassroomSummaryTable.spec.js:6"}, "properties": {"repobilityId": "1bcdbbe621f22214", "scanner": "scanner-primary", "fingerprint": "09b1e9830c164f44", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4070f37226323d25", "level": "none", "message": {"text": "Commented-code block (7 lines) in tests/components/EmployeeFormBasic.test.ts:88"}, "properties": {"repobilityId": "c87841e12c5b65d3", "scanner": "scanner-primary", "fingerprint": "4070f37226323d25", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-0e5f9a2c8bc70cf9", "level": "note", "message": {"text": "Legacy-named symbol `parent_user_v1` in src/parent/stores/parentAuth.ts:11"}, "properties": {"repobilityId": "5c4481e3c0b3149d", "scanner": "scanner-primary", "fingerprint": "0e5f9a2c8bc70cf9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-afa352d4b19a552e", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/parent/api/index.ts:196"}, "properties": {"repobilityId": "3dc4a90684e7e649", "scanner": "scanner-primary", "fingerprint": "afa352d4b19a552e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-ce41ef5671df947a", "level": "note", "message": {"text": "Legacy-named symbol `parent_faq_v1` in src/parent/composables/useFaq.ts:4"}, "properties": {"repobilityId": "bd150b5695aea3b9", "scanner": "scanner-primary", "fingerprint": "ce41ef5671df947a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-dee21b0cf94e2f8f", "level": "note", "message": {"text": "Legacy-named symbol `parent_selected_student_id_v2` in src/parent/composables/useChildSelection.ts:10"}, "properties": {"repobilityId": "67b32545d3960b39", "scanner": "scanner-primary", "fingerprint": "dee21b0cf94e2f8f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-2a99124331672b74", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/api/leaves.ts:9"}, "properties": {"repobilityId": "9228e30fb99967ee", "scanner": "scanner-primary", "fingerprint": "2a99124331672b74", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-adf5e2dd1ec2e30d", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/api/index.ts:153"}, "properties": {"repobilityId": "4e6fcf28eea2e18a", "scanner": "scanner-primary", "fingerprint": "adf5e2dd1ec2e30d", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8130ed5d3f7ad275", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/api/activity.ts:87"}, "properties": {"repobilityId": "f2f49701688fc4d7", "scanner": "scanner-primary", "fingerprint": "8130ed5d3f7ad275", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a686649e36e8d8d1", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/constants/permissions.ts:164"}, "properties": {"repobilityId": "2de897a415ccf8d1", "scanner": "scanner-primary", "fingerprint": "a686649e36e8d8d1", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c6f551234c972317", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/composables/useActivityAttendanceDrawer.ts:54"}, "properties": {"repobilityId": "24ef62a69939d856", "scanner": "scanner-primary", "fingerprint": "c6f551234c972317", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-51dfe247aa7e45dd", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/composables/useTableFilters.ts:85"}, "properties": {"repobilityId": "94f43330e8f94c86", "scanner": "scanner-primary", "fingerprint": "51dfe247aa7e45dd", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-92f05c389ca5abdc", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/utils/geocoding.ts:45"}, "properties": {"repobilityId": "4575364033d50831", "scanner": "scanner-primary", "fingerprint": "92f05c389ca5abdc", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-f808a4ef3e1071fb", "level": "note", "message": {"text": "14 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "ce6b2ec4be4ec75a", "scanner": "scanner-primary", "fingerprint": "f808a4ef3e1071fb", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-7722370f2c938c09", "level": "note", "message": {"text": "Unused endpoint: POST /parent/auth/liff-login"}, "properties": {"repobilityId": "5913388682124e36", "scanner": "scanner-primary", "fingerprint": "7722370f2c938c09", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-684f2181902ec666", "level": "note", "message": {"text": "Unused endpoint: POST /parent/auth/bind"}, "properties": {"repobilityId": "5ca8aaf437e9c457", "scanner": "scanner-primary", "fingerprint": "684f2181902ec666", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0bbf074bd3e2820b", "level": "note", "message": {"text": "Unused endpoint: POST /parent/auth/bind-additional"}, "properties": {"repobilityId": "a33c182702380dc6", "scanner": "scanner-primary", "fingerprint": "0bbf074bd3e2820b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e4a6cee72c409e4b", "level": "note", "message": {"text": "Unused endpoint: POST /parent/auth/logout"}, "properties": {"repobilityId": "f1d34ed96585650b", "scanner": "scanner-primary", "fingerprint": "e4a6cee72c409e4b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d2de70efa072cb0e", "level": "note", "message": {"text": "Unused endpoint: GET /parent/growth-reports"}, "properties": {"repobilityId": "66fb8605ee694651", "scanner": "scanner-primary", "fingerprint": "d2de70efa072cb0e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9b4341c5a77e6526", "level": "note", "message": {"text": "Unused endpoint: GET /parent/photos"}, "properties": {"repobilityId": "2dd9694694f6bf99", "scanner": "scanner-primary", "fingerprint": "9b4341c5a77e6526", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c0f56e8e478141d0", "level": "note", "message": {"text": "Unused endpoint: GET /parent/fees/summary"}, "properties": {"repobilityId": "cc4b3e3ca8a5490b", "scanner": "scanner-primary", "fingerprint": "c0f56e8e478141d0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d68693eaa1344308", "level": "note", "message": {"text": "Unused endpoint: GET /parent/fees/records"}, "properties": {"repobilityId": "d39deb2a3a15d4be", "scanner": "scanner-primary", "fingerprint": "d68693eaa1344308", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b306d809fc4ebdc3", "level": "note", "message": {"text": "Unused endpoint: POST /parent/student-leaves"}, "properties": {"repobilityId": "02f57b36b0f50168", "scanner": "scanner-primary", "fingerprint": "b306d809fc4ebdc3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3e123a6baaaac45a", "level": "note", "message": {"text": "Unused endpoint: GET /parent/student-leaves"}, "properties": {"repobilityId": "9d2088fb29642634", "scanner": "scanner-primary", "fingerprint": "3e123a6baaaac45a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-131161d74f9b1786", "level": "note", "message": {"text": "Unused endpoint: GET /parent/messages/threads"}, "properties": {"repobilityId": "bf1928e40c4485fe", "scanner": "scanner-primary", "fingerprint": "131161d74f9b1786", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3f09b5e3b5b61d53", "level": "note", "message": {"text": "Unused endpoint: GET /parent/messages/unread-count"}, "properties": {"repobilityId": "f8e91149745f5691", "scanner": "scanner-primary", "fingerprint": "3f09b5e3b5b61d53", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e88a1360c8b00d36", "level": "note", "message": {"text": "Unused endpoint: GET /parent/assistant/faq"}, "properties": {"repobilityId": "357695f8d7fbcf01", "scanner": "scanner-primary", "fingerprint": "e88a1360c8b00d36", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b0b5304cb10e0ec3", "level": "note", "message": {"text": "Unused endpoint: GET /parent/notifications/preferences"}, "properties": {"repobilityId": "81635f49fbaa45b0", "scanner": "scanner-primary", "fingerprint": "b0b5304cb10e0ec3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7ad6b8e38e2f0bba", "level": "note", "message": {"text": "Unused endpoint: PUT /parent/notifications/preferences"}, "properties": {"repobilityId": "e89e072d3016d6c1", "scanner": "scanner-primary", "fingerprint": "7ad6b8e38e2f0bba", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-979d8cb0a57f0b8c", "level": "note", "message": {"text": "Unused endpoint: GET /parent/milestones"}, "properties": {"repobilityId": "b02c097a7185bff8", "scanner": "scanner-primary", "fingerprint": "979d8cb0a57f0b8c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8815280ba5b2b441", "level": "note", "message": {"text": "Unused endpoint: GET /parent/me"}, "properties": {"repobilityId": "0a1ac76c5f7a3611", "scanner": "scanner-primary", "fingerprint": "8815280ba5b2b441", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ed76c6e61bbd0612", "level": "note", "message": {"text": "Unused endpoint: GET /parent/my-children"}, "properties": {"repobilityId": "0cd07ffea930dc08", "scanner": "scanner-primary", "fingerprint": "ed76c6e61bbd0612", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-03ec6d1635ab2b4e", "level": "note", "message": {"text": "Unused endpoint: GET /parent/home/summary"}, "properties": {"repobilityId": "1f1161cc928b6deb", "scanner": "scanner-primary", "fingerprint": "03ec6d1635ab2b4e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-581cbf9384e525fd", "level": "note", "message": {"text": "Unused endpoint: GET /parent/home/today-status"}, "properties": {"repobilityId": "05ee9c5d75adc9d5", "scanner": "scanner-primary", "fingerprint": "581cbf9384e525fd", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7a233a93bb88b7d6", "level": "note", "message": {"text": "Unused endpoint: GET /parent/attendance/daily"}, "properties": {"repobilityId": "7b40ac4323001b26", "scanner": "scanner-primary", "fingerprint": "7a233a93bb88b7d6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-248cd53ee9dd35b8", "level": "note", "message": {"text": "Unused endpoint: GET /parent/attendance/monthly"}, "properties": {"repobilityId": "41afaf4da0fe2bcf", "scanner": "scanner-primary", "fingerprint": "248cd53ee9dd35b8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7dda1ba860c39611", "level": "note", "message": {"text": "Unused endpoint: GET /parent/calendar/week"}, "properties": {"repobilityId": "a4225af522c3594d", "scanner": "scanner-primary", "fingerprint": "7dda1ba860c39611", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-435f6529e0e976dd", "level": "note", "message": {"text": "Unused endpoint: GET /parent/activity/courses"}, "properties": {"repobilityId": "683206c28ed478a9", "scanner": "scanner-primary", "fingerprint": "435f6529e0e976dd", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9bf994040e1f9beb", "level": "note", "message": {"text": "Unused endpoint: GET /parent/activity/my-registrations"}, "properties": {"repobilityId": "c0dd49936bf1d9ed", "scanner": "scanner-primary", "fingerprint": "9bf994040e1f9beb", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c848487fa5040f0d", "level": "note", "message": {"text": "Unused endpoint: POST /parent/activity/register"}, "properties": {"repobilityId": "cbb1e8f32ca24681", "scanner": "scanner-primary", "fingerprint": "c848487fa5040f0d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b52abae016ac2e83", "level": "note", "message": {"text": "Unused endpoint: GET /parent/measurements"}, "properties": {"repobilityId": "422184fe12235de7", "scanner": "scanner-primary", "fingerprint": "b52abae016ac2e83", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-468c746e61bd8a7d", "level": "note", "message": {"text": "Unused endpoint: GET /parent/measurements/chart-data"}, "properties": {"repobilityId": "950d65752200931d", "scanner": "scanner-primary", "fingerprint": "468c746e61bd8a7d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-039c1eba35b0f684", "level": "note", "message": {"text": "Unused endpoint: GET /parent/timeline"}, "properties": {"repobilityId": "0bcdb8e6c6ec5172", "scanner": "scanner-primary", "fingerprint": "039c1eba35b0f684", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ff8318e0703e9ac5", "level": "note", "message": {"text": "Unused endpoint: GET /parent/family/timeline"}, "properties": {"repobilityId": "1006fe886851672b", "scanner": "scanner-primary", "fingerprint": "ff8318e0703e9ac5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b662234cc868ee9b", "level": "note", "message": {"text": "Unused endpoint: GET /parent/contact-book/today"}, "properties": {"repobilityId": "8c955c365c18fef8", "scanner": "scanner-primary", "fingerprint": "b662234cc868ee9b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c3015977fc49af64", "level": "note", "message": {"text": "Unused endpoint: GET /parent/contact-book"}, "properties": {"repobilityId": "50753cf8aaae6f23", "scanner": "scanner-primary", "fingerprint": "c3015977fc49af64", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-314ad3f8b48ce28b", "level": "note", "message": {"text": "Unused endpoint: GET /parent/events"}, "properties": {"repobilityId": "f6556a798fd0fb00", "scanner": "scanner-primary", "fingerprint": "314ad3f8b48ce28b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a3fdec6929cc0359", "level": "note", "message": {"text": "Unused endpoint: GET /parent/announcements"}, "properties": {"repobilityId": "dd7c2fb66c2718c0", "scanner": "scanner-primary", "fingerprint": "a3fdec6929cc0359", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d2bff920e9a109ec", "level": "note", "message": {"text": "Unused endpoint: GET /parent/announcements/unread-count"}, "properties": {"repobilityId": "85fe06073c952d74", "scanner": "scanner-primary", "fingerprint": "d2bff920e9a109ec", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-dd5bf5ce83a34a9b", "level": "note", "message": {"text": "Unused endpoint: GET /parent/medication-orders"}, "properties": {"repobilityId": "999ade5c97ba51fe", "scanner": "scanner-primary", "fingerprint": "dd5bf5ce83a34a9b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b2d73ce83003fad6", "level": "note", "message": {"text": "Unused endpoint: POST /parent/medication-orders"}, "properties": {"repobilityId": "1cf0db8c6b1eb145", "scanner": "scanner-primary", "fingerprint": "b2d73ce83003fad6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-debbbaf41593f22a", "level": "note", "message": {"text": "Unused endpoint: GET /parent/me/data-export"}, "properties": {"repobilityId": "d63a1878d816e302", "scanner": "scanner-primary", "fingerprint": "debbbaf41593f22a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6c506e7afeca2307", "level": "note", "message": {"text": "Unused endpoint: GET /config/titles"}, "properties": {"repobilityId": "9c1d9c9a546420b1", "scanner": "scanner-primary", "fingerprint": "6c506e7afeca2307", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-06948c288d396ce5", "level": "note", "message": {"text": "Unused endpoint: POST /config/titles"}, "properties": {"repobilityId": "8694d91de7f050bb", "scanner": "scanner-primary", "fingerprint": "06948c288d396ce5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-de802ebe0ab50a42", "level": "note", "message": {"text": "Unused endpoint: GET /config/attendance-policy"}, "properties": {"repobilityId": "6fbcbd350301c580", "scanner": "scanner-primary", "fingerprint": "de802ebe0ab50a42", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-953a157b251861bf", "level": "note", "message": {"text": "Unused endpoint: PUT /config/attendance-policy"}, "properties": {"repobilityId": "3f40f73b2f88e6a3", "scanner": "scanner-primary", "fingerprint": "953a157b251861bf", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-773e1b003c2ecc2a", "level": "note", "message": {"text": "Unused endpoint: GET /config/insurance-rates"}, "properties": {"repobilityId": "e1acf04e9bfc741c", "scanner": "scanner-primary", "fingerprint": "773e1b003c2ecc2a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-431247de0af41bfd", "level": "note", "message": {"text": "Unused endpoint: PUT /config/insurance-rates"}, "properties": {"repobilityId": "197df94924a23d00", "scanner": "scanner-primary", "fingerprint": "431247de0af41bfd", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0c7596bdedac5cba", "level": "note", "message": {"text": "Unused endpoint: GET /config/bonus"}, "properties": {"repobilityId": "7ff6eb5f6dae1e2a", "scanner": "scanner-primary", "fingerprint": "0c7596bdedac5cba", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-dee1d9d953900afc", "level": "note", "message": {"text": "Unused endpoint: PUT /config/bonus"}, "properties": {"repobilityId": "9f8603a08e031f6d", "scanner": "scanner-primary", "fingerprint": "dee1d9d953900afc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ca3f8861f8afddc2", "level": "note", "message": {"text": "Unused endpoint: GET /config/grade-targets"}, "properties": {"repobilityId": "d5c37dc01ffe29ad", "scanner": "scanner-primary", "fingerprint": "ca3f8861f8afddc2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f71991114fff76da", "level": "note", "message": {"text": "Unused endpoint: PUT /config/grade-targets"}, "properties": {"repobilityId": "85acd8e1d25f798b", "scanner": "scanner-primary", "fingerprint": "f71991114fff76da", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e70b6619f47a3b8e", "level": "note", "message": {"text": "Unused endpoint: GET /config/position-salary"}, "properties": {"repobilityId": "81efc93b3dc67fe6", "scanner": "scanner-primary", "fingerprint": "e70b6619f47a3b8e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-afd79aa45ad75042", "level": "note", "message": {"text": "Unused endpoint: PUT /config/position-salary"}, "properties": {"repobilityId": "6622158ba0d7c7ef", "scanner": "scanner-primary", "fingerprint": "afd79aa45ad75042", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}