{"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-fc9cff9fe2879178", "name": "Stray `console.log` in TS/JS \u2014 scripts/importExcel.js:86", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/importExcel.js:86"}, "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-528d518beb26e490", "name": "Stray `console.log` in TS/JS \u2014 worker/index.js:155", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 worker/index.js:155"}, "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-3518ee9b8fe27844", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/VoteContacts.jsx:136", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/VoteContacts.jsx:136"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-0b4d3062b82566f5", "name": "Icon-only button without accessible name \u2014 src/components/BallotResults.jsx:530", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/BallotResults.jsx:530"}, "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-172623f6f1e52ccb", "name": "Icon-only button without accessible name \u2014 src/components/email/CampaignSendModal.jsx:422", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/email/CampaignSendModal.jsx:422"}, "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-3dd458493f3e8a13", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/email/CampaignSendModal.jsx:451", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/email/CampaignSendModal.jsx:451"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-80b0ef5d8d97b165", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/email/MetricsTab.jsx:220", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/email/MetricsTab.jsx:220"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-92704d2f75643e7f", "name": "Icon-only button without accessible name \u2014 src/components/email/ContactUploadModal.jsx:161", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/email/ContactUploadModal.jsx:161"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e5d4519f91f19dc9", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/email/CampaignsTab.jsx:321", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/email/CampaignsTab.jsx:321"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-63f39123041dfac1", "name": "Icon-only button without accessible name \u2014 src/components/email/ContactDetailModal.jsx:147", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/email/ContactDetailModal.jsx:147"}, "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-c3beebd67dd0ba42", "name": "Icon-only button without accessible name \u2014 src/components/email/CreateCampaignModal.jsx:64", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/email/CreateCampaignModal.jsx:64"}, "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-a12405feb3a39eff", "name": "Icon-only button without accessible name \u2014 src/components/ekloges/Eklogik\u00e1Kentra.jsx:855", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/ekloges/Eklogik\u00e1Kentra.jsx:855"}, "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-e14fd0b61f9634d3", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/bookkeeping/Bookkeeping.jsx:290", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/bookkeeping/Bookkeeping.jsx:290"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4ace9f59163b979a", "name": "Icon-only button without accessible name \u2014 src/components/bookkeeping/ExpenseModal.jsx:347", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/bookkeeping/ExpenseModal.jsx:347"}, "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-dc67255fc0577089", "name": "Icon-only button without accessible name \u2014 src/components/medical/VisitModal.jsx:47", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/medical/VisitModal.jsx:47"}, "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-17233772b65769dc", "name": "Icon-only button without accessible name \u2014 src/components/medical/ConsentFormModal.jsx:116", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/medical/ConsentFormModal.jsx:116"}, "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-18df781fbe781a24", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/claude/ClaudeRemote.jsx:228", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/claude/ClaudeRemote.jsx:228"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-fe333babc161e21c", "name": "Insecure pattern 'node_child_process' in scripts/watchAndEnrich.mjs:13", "shortDescription": {"text": "Insecure pattern 'node_child_process' in scripts/watchAndEnrich.mjs:13"}, "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-951c9cb3f7401015", "name": "Insecure pattern 'private_key_in_repo' in worker/index.js:1539", "shortDescription": {"text": "Insecure pattern 'private_key_in_repo' in worker/index.js:1539"}, "fullDescription": {"text": "Found a known-risky pattern (private_key_in_repo). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-c5c6a36556bf6231", "name": "Possible secret in src/components/AdminPanel.jsx", "shortDescription": {"text": "Possible secret in src/components/AdminPanel.jsx"}, "fullDescription": {"text": "Detected pattern matching password_literal. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-9818a6fa4e472202", "name": "Insecure pattern 'document_write' in src/components/bookkeeping/ExportPrint.jsx:281", "shortDescription": {"text": "Insecure pattern 'document_write' in src/components/bookkeeping/ExportPrint.jsx:281"}, "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-28c4a04bd807da0c", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "peaceiris/actions-gh-pages@v3 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-ad6701f0a8405e22", "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-85af1562372ae6ef", "name": "Very large file: worker/index.js (1571 lines)", "shortDescription": {"text": "Very large file: worker/index.js (1571 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-1cb42964422d91f4", "name": "Very large file: src/components/ekloges/Eklogik\u00e1Kentra.jsx (1062 lines)", "shortDescription": {"text": "Very large file: src/components/ekloges/Eklogik\u00e1Kentra.jsx (1062 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 77 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 196 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 85 placeholder/mock markers across 27 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-11825279136b53a3", "name": "CI is configured but no tests are detected", "shortDescription": {"text": "CI is configured but no tests are detected"}, "fullDescription": {"text": "A CI pipeline exists, but the scan found no test files to gate. Opus labeled this generated-code pattern as config theater: release machinery exists, but it has little behavioral signal."}, "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, 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": "low", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license, 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-eab9e90b9e4d5262", "name": "Commented-code block (9 lines) in make-email-images.py:39", "shortDescription": {"text": "Commented-code block (9 lines) in make-email-images.py:39"}, "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-bb7ab252a1c2c385", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/cleanupFakeEmails.mjs:68", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/cleanupFakeEmails.mjs:68"}, "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-115485baf30ed92a", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/importInvoices.mjs:226", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/importInvoices.mjs:226"}, "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-62921d0d49dd8a8d", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/mark-bounced.mjs:63", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/mark-bounced.mjs:63"}, "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-215293823289f940", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/fixCampaignUnsubscribe.mjs:31", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/fixCampaignUnsubscribe.mjs:31"}, "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-effd343e4e8cdd7d", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/addTreatmentCategories.mjs:31", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/addTreatmentCategories.mjs:31"}, "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-7e8bcb7542f01f0e", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/importOmniLux0606.mjs:39", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/importOmniLux0606.mjs:39"}, "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-6e68795a3d96ca55", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/auditEmails.mjs:25", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/auditEmails.mjs:25"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1af163bf610878a1", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/cleanupEmails.mjs:24", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/cleanupEmails.mjs:24"}, "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-72db916be8504d05", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/flag_campaign.mjs:15", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/flag_campaign.mjs:15"}, "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-35a60ac93e8fee88", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/removeInvalidEmails.mjs:33", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/removeInvalidEmails.mjs:33"}, "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-a3d2ee6b589de185", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/enrichContacts.mjs:59", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/enrichContacts.mjs:59"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e6ab8a4470dc1d0a", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/uploadInvoiceImages.mjs:28", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/uploadInvoiceImages.mjs:28"}, "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-fe76c827c9c567c7", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/checkDuplicates.mjs:35", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/checkDuplicates.mjs:35"}, "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-3d30edda47729f0f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/deleteNumberHeavy.mjs:26", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/deleteNumberHeavy.mjs:26"}, "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-0307ca5f4ca53fcb", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/merge_duplicates.mjs:20", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/merge_duplicates.mjs:20"}, "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-e53fcc07f7f7ef41", "name": "`fetch()` without try/.catch or AbortSignal \u2014 worker/index.js:114", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 worker/index.js:114"}, "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-955a63d3e07f867c", "name": "Commented-code block (5 lines) in src/utils/contactsCache.js:1", "shortDescription": {"text": "Commented-code block (5 lines) in src/utils/contactsCache.js:1"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a30c439196a56ad4", "name": "Commented-code block (6 lines) in src/components/OfficialPartyResults.jsx:41", "shortDescription": {"text": "Commented-code block (6 lines) in src/components/OfficialPartyResults.jsx:41"}, "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-3482f7e5dd70cd1a", "name": "6 env vars used in code but missing from .env.example", "shortDescription": {"text": "6 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `ANTHROPIC_API_KEY`, `BASE_URL`, `BOT_TOKEN`, `FIREBASE_SERVICE_ACCOUNT`, `PORT`, `VITE_WORKER_URL`. 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-cb5e57e2bb14dde1", "name": "Frontend route `/votes` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/votes` has no Link/navigate to it \u2014 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-8d146f2d75ac4d31", "name": "Frontend route `/ballot-results` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/ballot-results` has no Link/navigate to it \u2014 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-f16c12f70bcdc423", "name": "Frontend route `/medical/:id` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/medical/:id` has no Link/navigate to it \u2014 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-7b34104e3c6e8ee2", "name": "Frontend route `/import-expensify` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/import-expensify` has no Link/navigate to it \u2014 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-9f049faf99f26c2d", "name": "Frontend route `/unsubscribe` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/unsubscribe` has no Link/navigate to it \u2014 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-fbecea4b423bfe38", "name": "Flask mutation route `webhook` without `@login_required` \u2014 vote-bot/bot.py:355", "shortDescription": {"text": "Flask mutation route `webhook` without `@login_required` \u2014 vote-bot/bot.py:355"}, "fullDescription": {"text": "Flask route declares POST/PUT/DELETE/PATCH methods without an auth decorator. Add `@login_required` (Flask-Login) or equivalent."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-f67fa4e553ede278", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/cleanupFakeEmails.mjs:68)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/cleanupFakeEmails.mjs:68)"}, "fullDescription": {"text": "`scripts/cleanupFakeEmails.mjs:68` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-20198079fff4379f", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/mark-bounced.mjs:63)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/mark-bounced.mjs:63)"}, "fullDescription": {"text": "`scripts/mark-bounced.mjs:63` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-7e1535fae50bcc69", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/fixCampaignUnsubscribe.mjs:31)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/fixCampaignUnsubscribe.mjs:31)"}, "fullDescription": {"text": "`scripts/fixCampaignUnsubscribe.mjs:31` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-0541d8aa8125e0a8", "name": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/${name}?updateMask.fieldPaths=htmlBody (scripts/fixCampaignUns", "shortDescription": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/${name}?updateMask.fieldPaths=htmlBody (scripts/fixCampaignUnsubscribe.mjs:87)"}, "fullDescription": {"text": "`scripts/fixCampaignUnsubscribe.mjs:87` calls `PATCH https://firestore.googleapis.com/v1/${name}?updateMask.fieldPaths=htmlBody` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/<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-6a73f263f7257751", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/addTreatmentCategories.mjs:31)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/addTreatmentCategories.mjs:31)"}, "fullDescription": {"text": "`scripts/addTreatmentCategories.mjs:31` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-1ea5105539be2dce", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/importOmniLux0606.mjs:39)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/importOmniLux0606.mjs:39)"}, "fullDescription": {"text": "`scripts/importOmniLux0606.mjs:39` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-50a2ad7e7559c41b", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/auditEmails.mjs:25)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/auditEmails.mjs:25)"}, "fullDescription": {"text": "`scripts/auditEmails.mjs:25` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-bc79004d71c59ea4", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/cleanupEmails.mjs:24)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/cleanupEmails.mjs:24)"}, "fullDescription": {"text": "`scripts/cleanupEmails.mjs:24` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-678a5c2c2a57c448", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/flag_campaign.mjs:15)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/flag_campaign.mjs:15)"}, "fullDescription": {"text": "`scripts/flag_campaign.mjs:15` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-1b5166a006646d86", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/removeInvalidEmails.mjs:33)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/removeInvalidEmails.mjs:33)"}, "fullDescription": {"text": "`scripts/removeInvalidEmails.mjs:33` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-ed40faeaa47deb2f", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/enrichContacts.mjs:59)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/enrichContacts.mjs:59)"}, "fullDescription": {"text": "`scripts/enrichContacts.mjs:59` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-0a0c24631f68098e", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/checkDuplicates.mjs:35)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/checkDuplicates.mjs:35)"}, "fullDescription": {"text": "`scripts/checkDuplicates.mjs:35` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-740d202bc2711315", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/deleteNumberHeavy.mjs:26)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/deleteNumberHeavy.mjs:26)"}, "fullDescription": {"text": "`scripts/deleteNumberHeavy.mjs:26` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-49c36f8230efeb81", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/merge_duplicates.mjs:20)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/merge_duplicates.mjs:20)"}, "fullDescription": {"text": "`scripts/merge_duplicates.mjs:20` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-a18d69165064542c", "name": "Dangling fetch: POST https://api.resend.com/emails/batch (worker/index.js:260)", "shortDescription": {"text": "Dangling fetch: POST https://api.resend.com/emails/batch (worker/index.js:260)"}, "fullDescription": {"text": "`worker/index.js:260` calls `POST https://api.resend.com/emails/batch` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/api.resend.com/emails/batch`\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-60a4006ce6da356e", "name": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_contac", "shortDescription": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_contacts/${contactId}?${mask} (worker/index.js:318)"}, "fullDescription": {"text": "`worker/index.js:318` calls `PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_contacts/${contactId}?${mask}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/email_contacts/<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-90d6124032e3b114", "name": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:commit (worke", "shortDescription": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:commit (worker/index.js:336)"}, "fullDescription": {"text": "`worker/index.js:336` calls `POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:commit` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/<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-7330db2b48fbc28e", "name": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (w", "shortDescription": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (worker/index.js:584)"}, "fullDescription": {"text": "`worker/index.js:584` calls `POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/<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-f62d00165c50d3f2", "name": "Dangling fetch: GET https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_campaign", "shortDescription": {"text": "Dangling fetch: GET https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_campaigns/${forceCampaignId} (worker/index.js:620)"}, "fullDescription": {"text": "`worker/index.js:620` calls `GET https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_campaigns/${forceCampaignId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/email_campaigns/<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-da9b6bf3d25a691f", "name": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchGet (wor", "shortDescription": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchGet (worker/index.js:719)"}, "fullDescription": {"text": "`worker/index.js:719` calls `POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchGet` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/<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-b517ffc094604064", "name": "Dangling fetch: POST https://api.resend.com/emails/batch (worker/index.js:807)", "shortDescription": {"text": "Dangling fetch: POST https://api.resend.com/emails/batch (worker/index.js:807)"}, "fullDescription": {"text": "`worker/index.js:807` calls `POST https://api.resend.com/emails/batch` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/api.resend.com/emails/batch`\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-830674bf309f8a67", "name": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (w", "shortDescription": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (worker/index.js:861)"}, "fullDescription": {"text": "`worker/index.js:861` calls `POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/<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-802a59a159fd956e", "name": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (w", "shortDescription": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (worker/index.js:877)"}, "fullDescription": {"text": "`worker/index.js:877` calls `POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/<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-56a3c3123982754a", "name": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_contac", "shortDescription": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_contacts/${contactId}?${mask} (worker/index.js:957)"}, "fullDescription": {"text": "`worker/index.js:957` calls `PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_contacts/${contactId}?${mask}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/email_contacts/<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-a055b96b97f8a13b", "name": "Dangling fetch: POST https://api.anthropic.com/v1/messages (worker/index.js:1003)", "shortDescription": {"text": "Dangling fetch: POST https://api.anthropic.com/v1/messages (worker/index.js:1003)"}, "fullDescription": {"text": "`worker/index.js:1003` calls `POST https://api.anthropic.com/v1/messages` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/api.anthropic.com/v1/messages`\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-28fe3ae69228fdcc", "name": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/${docName}?${mask} (worker/index.js:1144)", "shortDescription": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/${docName}?${mask} (worker/index.js:1144)"}, "fullDescription": {"text": "`worker/index.js:1144` calls `PATCH https://firestore.googleapis.com/v1/${docName}?${mask}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/<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-4e6058ce8d648f17", "name": "Dangling fetch: GET https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/users/${uid} (", "shortDescription": {"text": "Dangling fetch: GET https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/users/${uid} (worker/index.js:1217)"}, "fullDescription": {"text": "`worker/index.js:1217` calls `GET https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/users/${uid}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/users/<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-f3f844a255b01121", "name": "Dangling fetch: POST https://identitytoolkit.googleapis.com/v1/projects/${project}/accounts:lookup (worker/index.js:1230", "shortDescription": {"text": "Dangling fetch: POST https://identitytoolkit.googleapis.com/v1/projects/${project}/accounts:lookup (worker/index.js:1230)"}, "fullDescription": {"text": "`worker/index.js:1230` calls `POST https://identitytoolkit.googleapis.com/v1/projects/${project}/accounts:lookup` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/identitytoolkit.googleapis.com/v1/projects/<p>/accounts/<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-fb281baeb80e7b10", "name": "Dangling fetch: POST https://identitytoolkit.googleapis.com/v1/projects/${caller.project}/accounts:update (worker/index.", "shortDescription": {"text": "Dangling fetch: POST https://identitytoolkit.googleapis.com/v1/projects/${caller.project}/accounts:update (worker/index.js:1250)"}, "fullDescription": {"text": "`worker/index.js:1250` calls `POST https://identitytoolkit.googleapis.com/v1/projects/${caller.project}/accounts:update` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/identitytoolkit.googleapis.com/v1/projects/<p>/accounts/<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-f82a51f5cc4103ff", "name": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${caller.project}/databases/(default)/documents/users", "shortDescription": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${caller.project}/databases/(default)/documents/users/${target.localId}?updateMask.fieldPaths=password (worker/index.js:1258)"}, "fullDescription": {"text": "`worker/index.js:1258` calls `PATCH https://firestore.googleapis.com/v1/projects/${caller.project}/databases/(default)/documents/users/${target.localId}?updateMask.fieldPaths=password` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/users/<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-5482cab902da3906", "name": "Dangling fetch: POST https://identitytoolkit.googleapis.com/v1/projects/${caller.project}/accounts:delete (worker/index.", "shortDescription": {"text": "Dangling fetch: POST https://identitytoolkit.googleapis.com/v1/projects/${caller.project}/accounts:delete (worker/index.js:1280)"}, "fullDescription": {"text": "`worker/index.js:1280` calls `POST https://identitytoolkit.googleapis.com/v1/projects/${caller.project}/accounts:delete` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/identitytoolkit.googleapis.com/v1/projects/<p>/accounts/<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-936e33c9a1e86538", "name": "Dangling fetch: DELETE https://firestore.googleapis.com/v1/projects/${caller.project}/databases/(default)/documents/user", "shortDescription": {"text": "Dangling fetch: DELETE https://firestore.googleapis.com/v1/projects/${caller.project}/databases/(default)/documents/users/${target.localId} (worker/index.js:1288)"}, "fullDescription": {"text": "`worker/index.js:1288` calls `DELETE https://firestore.googleapis.com/v1/projects/${caller.project}/databases/(default)/documents/users/${target.localId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/users/<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-7d91a809555ca0bc", "name": "Dangling fetch: GET https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com (worker/in", "shortDescription": {"text": "Dangling fetch: GET https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com (worker/index.js:1312)"}, "fullDescription": {"text": "`worker/index.js:1312` calls `GET https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com`\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-c7e812ad6d637a57", "name": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:runQuery (wor", "shortDescription": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:runQuery (worker/index.js:1333)"}, "fullDescription": {"text": "`worker/index.js:1333` calls `POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:runQuery` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/<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-335a0d9af8e1f833", "name": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/${collection", "shortDescription": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/${collection}/${id}?${mask} (worker/index.js:1353)"}, "fullDescription": {"text": "`worker/index.js:1353` calls `PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/${collection}/${id}?${mask}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/<p>/<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-a0f28b8f8236e82e", "name": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (w", "shortDescription": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (worker/index.js:1410)"}, "fullDescription": {"text": "`worker/index.js:1410` calls `POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/firestore.googleapis.com/v1/projects/<p>/databases/(default)/documents/<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-08400c4f2b5c98f8", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (worker/index.js:1563)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (worker/index.js:1563)"}, "fullDescription": {"text": "`worker/index.js:1563` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\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-68c9d5e17d04d050", "name": "Unused endpoint: ANY /webhook", "shortDescription": {"text": "Unused endpoint: ANY /webhook"}, "fullDescription": {"text": "`vote-bot/bot.py` declares `ANY /webhook` 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-01fce3d34f85db5a", "name": "Unused endpoint: ANY /set_webhook", "shortDescription": {"text": "Unused endpoint: ANY /set_webhook"}, "fullDescription": {"text": "`vote-bot/bot.py` declares `ANY /set_webhook` 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/21144"}, "properties": {"repository": "therapon1997-DERMLUX/dermlux-waitlist", "repoUrl": "https://github.com/therapon1997-DERMLUX/dermlux-waitlist", "branch": "main"}, "results": [{"ruleId": "scanner-fc9cff9fe2879178", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/importExcel.js:86"}, "properties": {"repobilityId": "c2385a8a31510889", "scanner": "scanner-primary", "fingerprint": "fc9cff9fe2879178", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-528d518beb26e490", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 worker/index.js:155"}, "properties": {"repobilityId": "9834735383e15fdc", "scanner": "scanner-primary", "fingerprint": "528d518beb26e490", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-3518ee9b8fe27844", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/VoteContacts.jsx:136"}, "properties": {"repobilityId": "3ebf27e460766e2d", "scanner": "scanner-primary", "fingerprint": "3518ee9b8fe27844", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0b4d3062b82566f5", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/BallotResults.jsx:530"}, "properties": {"repobilityId": "1263708f0e6382ba", "scanner": "scanner-primary", "fingerprint": "0b4d3062b82566f5", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-172623f6f1e52ccb", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/email/CampaignSendModal.jsx:422"}, "properties": {"repobilityId": "c3b41f53447e2bcc", "scanner": "scanner-primary", "fingerprint": "172623f6f1e52ccb", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-3dd458493f3e8a13", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/email/CampaignSendModal.jsx:451"}, "properties": {"repobilityId": "decb5c25e5dfc331", "scanner": "scanner-primary", "fingerprint": "3dd458493f3e8a13", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-80b0ef5d8d97b165", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/email/MetricsTab.jsx:220"}, "properties": {"repobilityId": "022f4bc5fab09490", "scanner": "scanner-primary", "fingerprint": "80b0ef5d8d97b165", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-92704d2f75643e7f", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/email/ContactUploadModal.jsx:161"}, "properties": {"repobilityId": "5959d5e9097699e0", "scanner": "scanner-primary", "fingerprint": "92704d2f75643e7f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-e5d4519f91f19dc9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/email/CampaignsTab.jsx:321"}, "properties": {"repobilityId": "bc82e5180c060d69", "scanner": "scanner-primary", "fingerprint": "e5d4519f91f19dc9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-63f39123041dfac1", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/email/ContactDetailModal.jsx:147"}, "properties": {"repobilityId": "f38b14f09caf091c", "scanner": "scanner-primary", "fingerprint": "63f39123041dfac1", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-c3beebd67dd0ba42", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/email/CreateCampaignModal.jsx:64"}, "properties": {"repobilityId": "940fb4c6cd5f1ec9", "scanner": "scanner-primary", "fingerprint": "c3beebd67dd0ba42", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-a12405feb3a39eff", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/ekloges/Eklogik\u00e1Kentra.jsx:855"}, "properties": {"repobilityId": "0bbdb1513b3ea9c1", "scanner": "scanner-primary", "fingerprint": "a12405feb3a39eff", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-e14fd0b61f9634d3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/bookkeeping/Bookkeeping.jsx:290"}, "properties": {"repobilityId": "b38a04497d0f22b1", "scanner": "scanner-primary", "fingerprint": "e14fd0b61f9634d3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4ace9f59163b979a", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/bookkeeping/ExpenseModal.jsx:347"}, "properties": {"repobilityId": "75b34c88debf19a7", "scanner": "scanner-primary", "fingerprint": "4ace9f59163b979a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-dc67255fc0577089", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/medical/VisitModal.jsx:47"}, "properties": {"repobilityId": "eea42500d1af872b", "scanner": "scanner-primary", "fingerprint": "dc67255fc0577089", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-17233772b65769dc", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/medical/ConsentFormModal.jsx:116"}, "properties": {"repobilityId": "aa017d4212d310a7", "scanner": "scanner-primary", "fingerprint": "17233772b65769dc", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-18df781fbe781a24", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/claude/ClaudeRemote.jsx:228"}, "properties": {"repobilityId": "a3441190feb63116", "scanner": "scanner-primary", "fingerprint": "18df781fbe781a24", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-fe333babc161e21c", "level": "warning", "message": {"text": "Insecure pattern 'node_child_process' in scripts/watchAndEnrich.mjs:13"}, "properties": {"repobilityId": "c0c1964b23daa6d6", "scanner": "scanner-primary", "fingerprint": "fe333babc161e21c", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "node_child_process"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "scripts/watchAndEnrich.mjs"}, "region": {"startLine": 13}}}]}, {"ruleId": "scanner-951c9cb3f7401015", "level": "error", "message": {"text": "Insecure pattern 'private_key_in_repo' in worker/index.js:1539"}, "properties": {"repobilityId": "c3d6fd8eb8da49c6", "scanner": "scanner-primary", "fingerprint": "951c9cb3f7401015", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["owasp", "private_key_in_repo"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "worker/index.js"}, "region": {"startLine": 1539}}}]}, {"ruleId": "scanner-c5c6a36556bf6231", "level": "error", "message": {"text": "Possible secret in src/components/AdminPanel.jsx"}, "properties": {"repobilityId": "2ed0252e07090322", "scanner": "scanner-primary", "fingerprint": "c5c6a36556bf6231", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/AdminPanel.jsx"}, "region": {"startLine": 370}}}]}, {"ruleId": "scanner-9818a6fa4e472202", "level": "note", "message": {"text": "Insecure pattern 'document_write' in src/components/bookkeeping/ExportPrint.jsx:281"}, "properties": {"repobilityId": "729fb0f0633b45c4", "scanner": "scanner-primary", "fingerprint": "9818a6fa4e472202", "layer": "security", "severity": "low", "confidence": 1.0, "tags": ["owasp", "document_write"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/bookkeeping/ExportPrint.jsx"}, "region": {"startLine": 281}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "ab7ccd611a3fc28e", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 36}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "09a60410de7f2c23", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 47}}}]}, {"ruleId": "scanner-ad6701f0a8405e22", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "8384c23520d55657", "scanner": "scanner-primary", "fingerprint": "ad6701f0a8405e22", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-85af1562372ae6ef", "level": "note", "message": {"text": "Very large file: worker/index.js (1571 lines)"}, "properties": {"repobilityId": "90d4b0a2b78c2467", "scanner": "scanner-primary", "fingerprint": "85af1562372ae6ef", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-1cb42964422d91f4", "level": "note", "message": {"text": "Very large file: src/components/ekloges/Eklogik\u00e1Kentra.jsx (1062 lines)"}, "properties": {"repobilityId": "f5307be9a6609dec", "scanner": "scanner-primary", "fingerprint": "1cb42964422d91f4", "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": "e23a40bbe06b821a", "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": "ebcfa7a5feea1edd", "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": "ab7831d660b933b0", "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": "f19f9e1884398a59", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-11825279136b53a3", "level": "warning", "message": {"text": "CI is configured but no tests are detected"}, "properties": {"repobilityId": "6e901d63e18fa917", "scanner": "scanner-primary", "fingerprint": "11825279136b53a3", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "ci", "config-theater", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "note", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "f51829a25ad30ec3", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "86f0d97b6eddfb6e", "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": "975a504f9f7a9267", "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": "ea7687cf6cf1f76a", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-eab9e90b9e4d5262", "level": "none", "message": {"text": "Commented-code block (9 lines) in make-email-images.py:39"}, "properties": {"repobilityId": "4279d4509e60c49f", "scanner": "scanner-primary", "fingerprint": "eab9e90b9e4d5262", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-bb7ab252a1c2c385", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/cleanupFakeEmails.mjs:68"}, "properties": {"repobilityId": "87476e1b79ed170f", "scanner": "scanner-primary", "fingerprint": "bb7ab252a1c2c385", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-115485baf30ed92a", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/importInvoices.mjs:226"}, "properties": {"repobilityId": "1559687fc7790e4e", "scanner": "scanner-primary", "fingerprint": "115485baf30ed92a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-62921d0d49dd8a8d", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/mark-bounced.mjs:63"}, "properties": {"repobilityId": "4c240a5c2b3234b3", "scanner": "scanner-primary", "fingerprint": "62921d0d49dd8a8d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-215293823289f940", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/fixCampaignUnsubscribe.mjs:31"}, "properties": {"repobilityId": "6d61bef7f3b558cf", "scanner": "scanner-primary", "fingerprint": "215293823289f940", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-effd343e4e8cdd7d", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/addTreatmentCategories.mjs:31"}, "properties": {"repobilityId": "3bd86372d8296c38", "scanner": "scanner-primary", "fingerprint": "effd343e4e8cdd7d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-7e8bcb7542f01f0e", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/importOmniLux0606.mjs:39"}, "properties": {"repobilityId": "85a774261ed3e735", "scanner": "scanner-primary", "fingerprint": "7e8bcb7542f01f0e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-6e68795a3d96ca55", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/auditEmails.mjs:25"}, "properties": {"repobilityId": "c600570b94b4f1d5", "scanner": "scanner-primary", "fingerprint": "6e68795a3d96ca55", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-1af163bf610878a1", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/cleanupEmails.mjs:24"}, "properties": {"repobilityId": "301e50f1c6fa84d0", "scanner": "scanner-primary", "fingerprint": "1af163bf610878a1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-72db916be8504d05", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/flag_campaign.mjs:15"}, "properties": {"repobilityId": "b7c9682e895cbb29", "scanner": "scanner-primary", "fingerprint": "72db916be8504d05", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-35a60ac93e8fee88", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/removeInvalidEmails.mjs:33"}, "properties": {"repobilityId": "1c00a6495f2ce91c", "scanner": "scanner-primary", "fingerprint": "35a60ac93e8fee88", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-a3d2ee6b589de185", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/enrichContacts.mjs:59"}, "properties": {"repobilityId": "ee6763c6038942c7", "scanner": "scanner-primary", "fingerprint": "a3d2ee6b589de185", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e6ab8a4470dc1d0a", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/uploadInvoiceImages.mjs:28"}, "properties": {"repobilityId": "66b89ccbab00950e", "scanner": "scanner-primary", "fingerprint": "e6ab8a4470dc1d0a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-fe76c827c9c567c7", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/checkDuplicates.mjs:35"}, "properties": {"repobilityId": "838b71aa17242cb7", "scanner": "scanner-primary", "fingerprint": "fe76c827c9c567c7", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3d30edda47729f0f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/deleteNumberHeavy.mjs:26"}, "properties": {"repobilityId": "e4aea3e6ed014890", "scanner": "scanner-primary", "fingerprint": "3d30edda47729f0f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-0307ca5f4ca53fcb", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/merge_duplicates.mjs:20"}, "properties": {"repobilityId": "4b6324c3d56e8587", "scanner": "scanner-primary", "fingerprint": "0307ca5f4ca53fcb", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e53fcc07f7f7ef41", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 worker/index.js:114"}, "properties": {"repobilityId": "81ef9350b131563d", "scanner": "scanner-primary", "fingerprint": "e53fcc07f7f7ef41", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-955a63d3e07f867c", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/utils/contactsCache.js:1"}, "properties": {"repobilityId": "3611f31f48a9b045", "scanner": "scanner-primary", "fingerprint": "955a63d3e07f867c", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a30c439196a56ad4", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/components/OfficialPartyResults.jsx:41"}, "properties": {"repobilityId": "e349cb2de847b00e", "scanner": "scanner-primary", "fingerprint": "a30c439196a56ad4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3482f7e5dd70cd1a", "level": "note", "message": {"text": "6 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "1da70f25aa46f6e9", "scanner": "scanner-primary", "fingerprint": "3482f7e5dd70cd1a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-cb5e57e2bb14dde1", "level": "warning", "message": {"text": "Frontend route `/votes` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "7792fb276de49bd8", "scanner": "scanner-primary", "fingerprint": "cb5e57e2bb14dde1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-8d146f2d75ac4d31", "level": "warning", "message": {"text": "Frontend route `/ballot-results` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "d9137efad6e4be5d", "scanner": "scanner-primary", "fingerprint": "8d146f2d75ac4d31", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-f16c12f70bcdc423", "level": "warning", "message": {"text": "Frontend route `/medical/:id` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "7db30a6c7e02ec05", "scanner": "scanner-primary", "fingerprint": "f16c12f70bcdc423", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-7b34104e3c6e8ee2", "level": "warning", "message": {"text": "Frontend route `/import-expensify` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "03e3290e6fc89133", "scanner": "scanner-primary", "fingerprint": "7b34104e3c6e8ee2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-9f049faf99f26c2d", "level": "warning", "message": {"text": "Frontend route `/unsubscribe` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "3538ff847eea53d9", "scanner": "scanner-primary", "fingerprint": "9f049faf99f26c2d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-fbecea4b423bfe38", "level": "error", "message": {"text": "Flask mutation route `webhook` without `@login_required` \u2014 vote-bot/bot.py:355"}, "properties": {"repobilityId": "5d6dbc3daac36eeb", "scanner": "scanner-primary", "fingerprint": "fbecea4b423bfe38", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.flask.unauth_route"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "vote-bot/bot.py"}, "region": {"startLine": 355}}}]}, {"ruleId": "scanner-f67fa4e553ede278", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/cleanupFakeEmails.mjs:68)"}, "properties": {"repobilityId": "ca39a5795414e407", "scanner": "scanner-primary", "fingerprint": "f67fa4e553ede278", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-20198079fff4379f", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/mark-bounced.mjs:63)"}, "properties": {"repobilityId": "1c9e4941f050a287", "scanner": "scanner-primary", "fingerprint": "20198079fff4379f", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-7e1535fae50bcc69", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/fixCampaignUnsubscribe.mjs:31)"}, "properties": {"repobilityId": "840940b990380602", "scanner": "scanner-primary", "fingerprint": "7e1535fae50bcc69", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-0541d8aa8125e0a8", "level": "error", "message": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/${name}?updateMask.fieldPaths=htmlBody (scripts/fixCampaignUnsubscribe.mjs:87)"}, "properties": {"repobilityId": "b9ad3e3a86b1c2c4", "scanner": "scanner-primary", "fingerprint": "0541d8aa8125e0a8", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-6a73f263f7257751", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/addTreatmentCategories.mjs:31)"}, "properties": {"repobilityId": "e2713a0252bfd6e0", "scanner": "scanner-primary", "fingerprint": "6a73f263f7257751", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-1ea5105539be2dce", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/importOmniLux0606.mjs:39)"}, "properties": {"repobilityId": "64153812facd69e4", "scanner": "scanner-primary", "fingerprint": "1ea5105539be2dce", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-50a2ad7e7559c41b", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/auditEmails.mjs:25)"}, "properties": {"repobilityId": "e883a7501af35afb", "scanner": "scanner-primary", "fingerprint": "50a2ad7e7559c41b", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-bc79004d71c59ea4", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/cleanupEmails.mjs:24)"}, "properties": {"repobilityId": "3eed36ef9d694493", "scanner": "scanner-primary", "fingerprint": "bc79004d71c59ea4", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-678a5c2c2a57c448", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/flag_campaign.mjs:15)"}, "properties": {"repobilityId": "0df478fca68118e4", "scanner": "scanner-primary", "fingerprint": "678a5c2c2a57c448", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-1b5166a006646d86", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/removeInvalidEmails.mjs:33)"}, "properties": {"repobilityId": "29a5fa19892ef5f9", "scanner": "scanner-primary", "fingerprint": "1b5166a006646d86", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-ed40faeaa47deb2f", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/enrichContacts.mjs:59)"}, "properties": {"repobilityId": "b82cc7c8532d06ef", "scanner": "scanner-primary", "fingerprint": "ed40faeaa47deb2f", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-0a0c24631f68098e", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/checkDuplicates.mjs:35)"}, "properties": {"repobilityId": "5b348fa523ba5ab0", "scanner": "scanner-primary", "fingerprint": "0a0c24631f68098e", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-740d202bc2711315", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/deleteNumberHeavy.mjs:26)"}, "properties": {"repobilityId": "58fc88bb9084d8c1", "scanner": "scanner-primary", "fingerprint": "740d202bc2711315", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-49c36f8230efeb81", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (scripts/merge_duplicates.mjs:20)"}, "properties": {"repobilityId": "ff74735f1c27f807", "scanner": "scanner-primary", "fingerprint": "49c36f8230efeb81", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-a18d69165064542c", "level": "error", "message": {"text": "Dangling fetch: POST https://api.resend.com/emails/batch (worker/index.js:260)"}, "properties": {"repobilityId": "562e614042c75a0c", "scanner": "scanner-primary", "fingerprint": "a18d69165064542c", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-60a4006ce6da356e", "level": "error", "message": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_contacts/${contactId}?${mask} (worker/index.js:318)"}, "properties": {"repobilityId": "bbaebcf29ed2e68c", "scanner": "scanner-primary", "fingerprint": "60a4006ce6da356e", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-90d6124032e3b114", "level": "error", "message": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:commit (worker/index.js:336)"}, "properties": {"repobilityId": "86322c4b7831228f", "scanner": "scanner-primary", "fingerprint": "90d6124032e3b114", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-7330db2b48fbc28e", "level": "error", "message": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (worker/index.js:584)"}, "properties": {"repobilityId": "29266757e63edff7", "scanner": "scanner-primary", "fingerprint": "7330db2b48fbc28e", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-f62d00165c50d3f2", "level": "error", "message": {"text": "Dangling fetch: GET https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_campaigns/${forceCampaignId} (worker/index.js:620)"}, "properties": {"repobilityId": "13a252a673eab684", "scanner": "scanner-primary", "fingerprint": "f62d00165c50d3f2", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-da9b6bf3d25a691f", "level": "error", "message": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchGet (worker/index.js:719)"}, "properties": {"repobilityId": "fd41637b5c510fd5", "scanner": "scanner-primary", "fingerprint": "da9b6bf3d25a691f", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-b517ffc094604064", "level": "error", "message": {"text": "Dangling fetch: POST https://api.resend.com/emails/batch (worker/index.js:807)"}, "properties": {"repobilityId": "54700ea37035b5d3", "scanner": "scanner-primary", "fingerprint": "b517ffc094604064", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-830674bf309f8a67", "level": "error", "message": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (worker/index.js:861)"}, "properties": {"repobilityId": "b97650bb953cc711", "scanner": "scanner-primary", "fingerprint": "830674bf309f8a67", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-802a59a159fd956e", "level": "error", "message": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (worker/index.js:877)"}, "properties": {"repobilityId": "e126f1268c090e38", "scanner": "scanner-primary", "fingerprint": "802a59a159fd956e", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-56a3c3123982754a", "level": "error", "message": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/email_contacts/${contactId}?${mask} (worker/index.js:957)"}, "properties": {"repobilityId": "a7abdaad6f4e0343", "scanner": "scanner-primary", "fingerprint": "56a3c3123982754a", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-a055b96b97f8a13b", "level": "error", "message": {"text": "Dangling fetch: POST https://api.anthropic.com/v1/messages (worker/index.js:1003)"}, "properties": {"repobilityId": "c14351fe833e4050", "scanner": "scanner-primary", "fingerprint": "a055b96b97f8a13b", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-28fe3ae69228fdcc", "level": "error", "message": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/${docName}?${mask} (worker/index.js:1144)"}, "properties": {"repobilityId": "bc4b0fef39d70604", "scanner": "scanner-primary", "fingerprint": "28fe3ae69228fdcc", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-4e6058ce8d648f17", "level": "error", "message": {"text": "Dangling fetch: GET https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/users/${uid} (worker/index.js:1217)"}, "properties": {"repobilityId": "3876ea020e11821b", "scanner": "scanner-primary", "fingerprint": "4e6058ce8d648f17", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-f3f844a255b01121", "level": "error", "message": {"text": "Dangling fetch: POST https://identitytoolkit.googleapis.com/v1/projects/${project}/accounts:lookup (worker/index.js:1230)"}, "properties": {"repobilityId": "abd37c87c4cd4120", "scanner": "scanner-primary", "fingerprint": "f3f844a255b01121", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-fb281baeb80e7b10", "level": "error", "message": {"text": "Dangling fetch: POST https://identitytoolkit.googleapis.com/v1/projects/${caller.project}/accounts:update (worker/index.js:1250)"}, "properties": {"repobilityId": "7fbba7beb3047472", "scanner": "scanner-primary", "fingerprint": "fb281baeb80e7b10", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-f82a51f5cc4103ff", "level": "error", "message": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${caller.project}/databases/(default)/documents/users/${target.localId}?updateMask.fieldPaths=password (worker/index.js:1258)"}, "properties": {"repobilityId": "ebfaf37d46f1a957", "scanner": "scanner-primary", "fingerprint": "f82a51f5cc4103ff", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-5482cab902da3906", "level": "error", "message": {"text": "Dangling fetch: POST https://identitytoolkit.googleapis.com/v1/projects/${caller.project}/accounts:delete (worker/index.js:1280)"}, "properties": {"repobilityId": "17efebc8ac0005b3", "scanner": "scanner-primary", "fingerprint": "5482cab902da3906", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-936e33c9a1e86538", "level": "error", "message": {"text": "Dangling fetch: DELETE https://firestore.googleapis.com/v1/projects/${caller.project}/databases/(default)/documents/users/${target.localId} (worker/index.js:1288)"}, "properties": {"repobilityId": "89ab83a74412cbac", "scanner": "scanner-primary", "fingerprint": "936e33c9a1e86538", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-7d91a809555ca0bc", "level": "error", "message": {"text": "Dangling fetch: GET https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com (worker/index.js:1312)"}, "properties": {"repobilityId": "cb5e4e1da3e4729e", "scanner": "scanner-primary", "fingerprint": "7d91a809555ca0bc", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-c7e812ad6d637a57", "level": "error", "message": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:runQuery (worker/index.js:1333)"}, "properties": {"repobilityId": "abf479d12477f958", "scanner": "scanner-primary", "fingerprint": "c7e812ad6d637a57", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-335a0d9af8e1f833", "level": "error", "message": {"text": "Dangling fetch: PATCH https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents/${collection}/${id}?${mask} (worker/index.js:1353)"}, "properties": {"repobilityId": "099dc82fa4aa4225", "scanner": "scanner-primary", "fingerprint": "335a0d9af8e1f833", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-a0f28b8f8236e82e", "level": "error", "message": {"text": "Dangling fetch: POST https://firestore.googleapis.com/v1/projects/${project}/databases/(default)/documents:batchWrite (worker/index.js:1410)"}, "properties": {"repobilityId": "cb0b2abf16e5e625", "scanner": "scanner-primary", "fingerprint": "a0f28b8f8236e82e", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-08400c4f2b5c98f8", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (worker/index.js:1563)"}, "properties": {"repobilityId": "8b0688ffd9807329", "scanner": "scanner-primary", "fingerprint": "08400c4f2b5c98f8", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-68c9d5e17d04d050", "level": "note", "message": {"text": "Unused endpoint: ANY /webhook"}, "properties": {"repobilityId": "d52e6e61d15a8e30", "scanner": "scanner-primary", "fingerprint": "68c9d5e17d04d050", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-01fce3d34f85db5a", "level": "note", "message": {"text": "Unused endpoint: ANY /set_webhook"}, "properties": {"repobilityId": "4fba2285c01ee635", "scanner": "scanner-primary", "fingerprint": "01fce3d34f85db5a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}