{"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-bead75b0f9233e05", "name": "No API endpoints detected", "shortDescription": {"text": "No API endpoints detected"}, "fullDescription": {"text": "The scanner did not find FastAPI/Flask/Express/NestJS/GraphQL/gRPC routes. If this repo exposes APIs, the framework may be unsupported."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "info", "confidence": 1.0}}, {"id": "scanner-bf8d33116377fb38", "name": "Stray `console.log` in TS/JS \u2014 fish-id-migration/seed_fish_species.js:101", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 fish-id-migration/seed_fish_species.js:101"}, "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-2a91665f65939838", "name": "Stray `console.log` in TS/JS \u2014 netlify/functions/send-results-email.js:61", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/send-results-email.js:61"}, "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-b7206a1f46cc3f53", "name": "Stray `console.log` in TS/JS \u2014 netlify/functions/refund-payment.js:164", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/refund-payment.js:164"}, "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-f8bf3c0f3d8f70c7", "name": "Stray `console.log` in TS/JS \u2014 netlify/functions/invite-member.js:179", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/invite-member.js:179"}, "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-19847ca178919c54", "name": "Stray `console.log` in TS/JS \u2014 netlify/functions/daily-backup.js:16", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/daily-backup.js:16"}, "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-cccbb7172e986f38", "name": "Stray `console.log` in TS/JS \u2014 netlify/functions/stripe-webhook.js:70", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/stripe-webhook.js:70"}, "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-23ffa6dcccc2646d", "name": "Stray `console.log` in TS/JS \u2014 netlify/functions/verify-checkout-session.js:71", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/verify-checkout-session.js:71"}, "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-486c0bfe32d4d0aa", "name": "Stray `console.log` in TS/JS \u2014 netlify/functions/lib/backup.js:128", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/lib/backup.js:128"}, "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-5d11ea84adbd2af9", "name": "Icon-only button without accessible name \u2014 src/App.jsx:176", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/App.jsx:176"}, "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-0724be944140cd22", "name": "`truncate` class without `title=` for hover reveal \u2014 src/App.jsx:496", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/App.jsx:496"}, "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-e57e58ae2b381e9b", "name": "Icon-only button without accessible name \u2014 src/components/PWAInstallPrompt.jsx:61", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/components/PWAInstallPrompt.jsx:61"}, "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-6273012fee3fb547", "name": "Icon-only button without accessible name \u2014 src/wfsc/WFSCApp.jsx:154", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/wfsc/WFSCApp.jsx:154"}, "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-7c1d2fd752c45397", "name": "Stray `console.log` in TS/JS \u2014 src/wfsc/WFSCApp.jsx:1838", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/wfsc/WFSCApp.jsx:1838"}, "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-a5d955e108f741a5", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/PublicLeaderboard.jsx:249", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/PublicLeaderboard.jsx:249"}, "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-eb776b93c490c3f9", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/NationalsPage.jsx:279", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/NationalsPage.jsx:279"}, "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-f328f5e70783b5ed", "name": "Icon-only button without accessible name \u2014 src/pages/CompCopilot.jsx:105", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/pages/CompCopilot.jsx:105"}, "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-3ea94675a57f3b4f", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/pages/CompCopilot.jsx:194", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/pages/CompCopilot.jsx:194"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6341c88bed006c0a", "name": "Icon-only button without accessible name \u2014 src/pages/NationalsAdmin.jsx:177", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/pages/NationalsAdmin.jsx:177"}, "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-67b8e9c165ee7af4", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/NationalsAdmin.jsx:648", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/NationalsAdmin.jsx:648"}, "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-6b5422b0fda8c6e2", "name": "Icon-only button without accessible name \u2014 src/pages/CompSuperAdmin.jsx:257", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/pages/CompSuperAdmin.jsx:257"}, "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-3e6fac584986422a", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/NationalsRegister.jsx:568", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/NationalsRegister.jsx:568"}, "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-74f42d680d1c200d", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CompetitionDetail.jsx:327", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CompetitionDetail.jsx:327"}, "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-3dcfd7da6e302217", "name": "Icon-only button without accessible name \u2014 src/pages/BigFishPage.jsx:760", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/pages/BigFishPage.jsx:760"}, "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-16161d705cf692cb", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/BigFishPage.jsx:289", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/BigFishPage.jsx:289"}, "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-46c01d95f7ac8c17", "name": "Icon-only button without accessible name \u2014 src/pages/CompAdmin.jsx:398", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/pages/CompAdmin.jsx:398"}, "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-72222f8d9c546787", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CompAdmin.jsx:571", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CompAdmin.jsx:571"}, "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-77bd8e0c63b13f68", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/pages/FishIDPage.jsx:373", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/pages/FishIDPage.jsx:373"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-625a8d422d54f026", "name": "Icon-only button without accessible name \u2014 src/pages/AGMAdmin.jsx:671", "shortDescription": {"text": "Icon-only button without accessible name \u2014 src/pages/AGMAdmin.jsx:671"}, "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-f1a0afcf6016f0b4", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CatfishCullPage.jsx:116", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CatfishCullPage.jsx:116"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-242a82f21c80272f", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/AnalyticsDashboard.jsx:40", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/AnalyticsDashboard.jsx:40"}, "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-219b96df1d761e2d", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CheckInDisplay.jsx:104", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CheckInDisplay.jsx:104"}, "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-741cc7bd5bbdbfa1", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/MembershipAdmin.jsx:260", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/MembershipAdmin.jsx:260"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a4c4b6a88350edf7", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/pages/bingo/BingoPlayPage.jsx:190", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/pages/bingo/BingoPlayPage.jsx:190"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-331cb06bffa39ba7", "name": "Privileged port 465 in use", "shortDescription": {"text": "Privileged port 465 in use"}, "fullDescription": {"text": "Port 465 is privileged (<1024). Make sure the service runs with the right caps or front it with a non-privileged port via a load balancer."}, "properties": {"scanner": "scanner-primary", "layer": "network", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6e2bd0763dd1b190", "name": "Insecure pattern 'cors_wildcard' in netlify/functions/bingo-claim.mjs:11", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in netlify/functions/bingo-claim.mjs:11"}, "fullDescription": {"text": "Found a known-risky pattern (cors_wildcard). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e66dae9933c8de2c", "name": "Insecure pattern 'document_write' in src/wfsc/WFSCApp.jsx:1087", "shortDescription": {"text": "Insecure pattern 'document_write' in src/wfsc/WFSCApp.jsx:1087"}, "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-5cc645b4480dffac", "name": "Insecure pattern 'local_storage_auth_token' in src/wfsc/WFSCApp.jsx:23", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in src/wfsc/WFSCApp.jsx:23"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6bc678ff1f9b8c58", "name": "Insecure pattern 'local_storage_auth_token' in src/lib/useAnalytics.js:40", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in src/lib/useAnalytics.js:40"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-8ea97fb525b762cb", "name": "Insecure pattern 'dangerous_innerhtml' in src/pages/CompCopilot.jsx:194", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/pages/CompCopilot.jsx:194"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f78d46136a2cc9f9", "name": "Insecure pattern 'local_storage_auth_token' in src/pages/CompCopilot.jsx:28", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in src/pages/CompCopilot.jsx:28"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7f3c36d9666b12a0", "name": "Insecure pattern 'dangerous_innerhtml' in src/pages/FishIDPage.jsx:373", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/pages/FishIDPage.jsx:373"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-42b8be59194c1c63", "name": "Insecure pattern 'dangerous_innerhtml' in src/pages/bingo/BingoPlayPage.jsx:190", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/pages/bingo/BingoPlayPage.jsx:190"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4601e3ad3bb28677", "name": "No CI/CD pipelines detected", "shortDescription": {"text": "No CI/CD pipelines detected"}, "fullDescription": {"text": "No GitHub Actions, GitLab CI, or CircleCI configs found. Without CI you can't gate deploys on tests/lints."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-dcb43b2f03b8b436", "name": "Very large file: src/App.jsx (1132 lines)", "shortDescription": {"text": "Very large file: src/App.jsx (1132 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-2741336b47a908a7", "name": "Very large file: src/wfsc/WFSCApp.jsx (2762 lines)", "shortDescription": {"text": "Very large file: src/wfsc/WFSCApp.jsx (2762 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-eb8039ad826a0d65", "name": "Very large file: src/pages/NationalsAdmin.jsx (1838 lines)", "shortDescription": {"text": "Very large file: src/pages/NationalsAdmin.jsx (1838 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-de5b8c631f22904c", "name": "Very large file: src/pages/NationalsRegister.jsx (948 lines)", "shortDescription": {"text": "Very large file: src/pages/NationalsRegister.jsx (948 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-bae6af044ce0224f", "name": "Very large file: src/pages/CompAdmin.jsx (2761 lines)", "shortDescription": {"text": "Very large file: src/pages/CompAdmin.jsx (2761 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-e1c5b3e7dee986ce", "name": "Very large file: src/pages/TeamManagement.jsx (1338 lines)", "shortDescription": {"text": "Very large file: src/pages/TeamManagement.jsx (1338 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-946a0c677263c49f", "name": "Very large file: src/pages/MembershipPage.jsx (2062 lines)", "shortDescription": {"text": "Very large file: src/pages/MembershipPage.jsx (2062 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-26e333f6434862e2", "name": "Very large file: src/pages/CompRegister.jsx (926 lines)", "shortDescription": {"text": "Very large file: src/pages/CompRegister.jsx (926 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "1 test file(s) for 86 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-b3ed68815bca2f8c", "name": "Node manifest has dependencies but no lockfile: package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-70f60e423cba52c6", "name": "Node manifest has dependencies but no lockfile: fish-id-migration/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: fish-id-migration/package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a7253a4cdd01b3c3", "name": "Node manifest has dependencies but no lockfile: netlify/functions/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: netlify/functions/package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 34 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 211 placeholder/mock markers across 35 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-9d79c4077342a7d0", "name": "Runtime service client appears to use placeholder configuration", "shortDescription": {"text": "Runtime service client appears to use placeholder configuration"}, "fullDescription": {"text": "A runtime source file appears to wire Supabase/Firebase/AI/payment-style clients to placeholder URLs, keys, or fallback values. In the Fable corpus this often means the UI/API shape is present while the backend service is not actually configured."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, ci, tests, lockfile. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license, ci, tests, lockfile. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-ecb0d2c55ed6875d", "name": "Agent authority lacks a verifier contract: .claude/settings.local.json", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/settings.local.json"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1753cca8ad8f616e", "name": "Commented-code block (6 lines) in fish-id-migration/seed_fish_species.js:4", "shortDescription": {"text": "Commented-code block (6 lines) in fish-id-migration/seed_fish_species.js:4"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1cd312fc3d183e28", "name": "Commented-code block (5 lines) in netlify/functions/comp-copilot.js:237", "shortDescription": {"text": "Commented-code block (5 lines) in netlify/functions/comp-copilot.js:237"}, "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-1609ccfec0a6adce", "name": "`fetch()` without try/.catch or AbortSignal \u2014 netlify/functions/comp-copilot.js:402", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 netlify/functions/comp-copilot.js:402"}, "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-907192cc83300ebc", "name": "`fetch()` without try/.catch or AbortSignal \u2014 netlify/functions/send-results-email.js:74", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 netlify/functions/send-results-email.js:74"}, "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-f44705e8292b7d1f", "name": "Commented-code block (5 lines) in netlify/functions/refund-payment.js:7", "shortDescription": {"text": "Commented-code block (5 lines) in netlify/functions/refund-payment.js:7"}, "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-31cf57084dfd0b02", "name": "Commented-code block (5 lines) in netlify/functions/daily-backup.js:4", "shortDescription": {"text": "Commented-code block (5 lines) in netlify/functions/daily-backup.js:4"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-6aa19e852d948ad0", "name": "Commented-code block (5 lines) in netlify/functions/verify-checkout-session.js:4", "shortDescription": {"text": "Commented-code block (5 lines) in netlify/functions/verify-checkout-session.js:4"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-5c5679f1aa5229e2", "name": "`fetch()` without try/.catch or AbortSignal \u2014 netlify/functions/identify-fish.js:76", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 netlify/functions/identify-fish.js:76"}, "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-69d7748a654ee3a1", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/wfsc/lib/hooks.js:19", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/wfsc/lib/hooks.js:19"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b372ab44cbef92df", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsConfirm.jsx:308", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsConfirm.jsx:308"}, "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-76c7ce38942de109", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsRegisterIndividual.jsx:180", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsRegisterIndividual.jsx:180"}, "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-797848920573cfc1", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsAdmin.jsx:502", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsAdmin.jsx:502"}, "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-a78e425fbf39c32d", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsRegister.jsx:368", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsRegister.jsx:368"}, "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-b576895fd0ff682c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/CompAdmin.jsx:1508", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/CompAdmin.jsx:1508"}, "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-105335c65f33faa4", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/MembershipPage.jsx:777", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/MembershipPage.jsx:777"}, "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-d81a1400423775ec", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/WeighmasterInterface.jsx:183", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/WeighmasterInterface.jsx:183"}, "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-c973bbd101436658", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/MembershipAdmin.jsx:129", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/MembershipAdmin.jsx:129"}, "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-87acb4066071a15a", "name": "19 env vars used in code but missing from .env.example", "shortDescription": {"text": "19 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `ANTHROPIC_API_KEY`, `FB_SERVICE_KEY`, `FB_SUPABASE_URL`, `SMTP_HOST`, `SMTP_PASSWORD`, `SMTP_PORT`, `SMTP_USER`, `SNZ_SERVICE_KEY` + 11 more. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-49b4b28f1619263b", "name": "Frontend route `/records/admin/archive/:id` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/records/admin/archive/: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-25dc62e81ddc3d50", "name": "Frontend route `/news` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/news` 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-4c21c888f14f4982", "name": "Frontend route `/leaderboard` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/leaderboard` 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-1c194854b69c3d05", "name": "Frontend route `/membership/*` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/membership/*` 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-482e999d1e2c16f6", "name": "Frontend route `/membership/invited` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/membership/invited` 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-78b9f78ee83b6d1d", "name": "Frontend route `/nationals/confirm` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/nationals/confirm` 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-3b8e6ec11a8643a0", "name": "Frontend route `/competitions/:id` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/competitions/: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-b7138f7350f65f92", "name": "Frontend route `/competitions/:id/register` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/competitions/:id/register` 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-eec070d397203d63", "name": "Frontend route `/competitions/:id/admin` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/competitions/:id/admin` 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-16554a713767ee58", "name": "Frontend route `/c/:id` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/c/: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-7d87ec9d95eeca8a", "name": "Frontend route `/big-fish/sponsor` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/big-fish/sponsor` 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-71ae912c001da630", "name": "Frontend route `/bingo/diver` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/bingo/diver` 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-e89dad246ef1cb79", "name": "Frontend route `/agm/:id` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/agm/: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-44041f9badd77471", "name": "Frontend route `/wfsc/*` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/wfsc/*` 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}}]}}, "automationDetails": {"id": "repobility/18015"}, "properties": {"repository": "remoterob/SNZ", "repoUrl": "https://github.com/remoterob/SNZ", "branch": "main"}, "results": [{"ruleId": "scanner-bead75b0f9233e05", "level": "none", "message": {"text": "No API endpoints detected"}, "properties": {"repobilityId": "0f8bb852027c38f8", "scanner": "scanner-primary", "fingerprint": "bead75b0f9233e05", "layer": "api", "severity": "info", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-bf8d33116377fb38", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 fish-id-migration/seed_fish_species.js:101"}, "properties": {"repobilityId": "64cba15fd5fcb1f9", "scanner": "scanner-primary", "fingerprint": "bf8d33116377fb38", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-2a91665f65939838", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/send-results-email.js:61"}, "properties": {"repobilityId": "a968c631406fe4ae", "scanner": "scanner-primary", "fingerprint": "2a91665f65939838", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-b7206a1f46cc3f53", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/refund-payment.js:164"}, "properties": {"repobilityId": "532770e8e34220f4", "scanner": "scanner-primary", "fingerprint": "b7206a1f46cc3f53", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-f8bf3c0f3d8f70c7", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/invite-member.js:179"}, "properties": {"repobilityId": "7ab7e52f682159df", "scanner": "scanner-primary", "fingerprint": "f8bf3c0f3d8f70c7", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-19847ca178919c54", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/daily-backup.js:16"}, "properties": {"repobilityId": "7bc95fccc666f4aa", "scanner": "scanner-primary", "fingerprint": "19847ca178919c54", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-cccbb7172e986f38", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/stripe-webhook.js:70"}, "properties": {"repobilityId": "4a01d28e8d06241e", "scanner": "scanner-primary", "fingerprint": "cccbb7172e986f38", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-23ffa6dcccc2646d", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/verify-checkout-session.js:71"}, "properties": {"repobilityId": "b7add1900d829bb2", "scanner": "scanner-primary", "fingerprint": "23ffa6dcccc2646d", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-486c0bfe32d4d0aa", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 netlify/functions/lib/backup.js:128"}, "properties": {"repobilityId": "9f6f9bb4cd0e8180", "scanner": "scanner-primary", "fingerprint": "486c0bfe32d4d0aa", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-5d11ea84adbd2af9", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/App.jsx:176"}, "properties": {"repobilityId": "9476f60e89fe241e", "scanner": "scanner-primary", "fingerprint": "5d11ea84adbd2af9", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-0724be944140cd22", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/App.jsx:496"}, "properties": {"repobilityId": "eb5008e648a1f49c", "scanner": "scanner-primary", "fingerprint": "0724be944140cd22", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e57e58ae2b381e9b", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/components/PWAInstallPrompt.jsx:61"}, "properties": {"repobilityId": "32d5a35ed930d6da", "scanner": "scanner-primary", "fingerprint": "e57e58ae2b381e9b", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-6273012fee3fb547", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/wfsc/WFSCApp.jsx:154"}, "properties": {"repobilityId": "6d39cce3fedb63bf", "scanner": "scanner-primary", "fingerprint": "6273012fee3fb547", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-7c1d2fd752c45397", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/wfsc/WFSCApp.jsx:1838"}, "properties": {"repobilityId": "8e6bb590688978ba", "scanner": "scanner-primary", "fingerprint": "7c1d2fd752c45397", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-a5d955e108f741a5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/PublicLeaderboard.jsx:249"}, "properties": {"repobilityId": "2870216fe2b9f593", "scanner": "scanner-primary", "fingerprint": "a5d955e108f741a5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-eb776b93c490c3f9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/NationalsPage.jsx:279"}, "properties": {"repobilityId": "dba5f7093b1ed7df", "scanner": "scanner-primary", "fingerprint": "eb776b93c490c3f9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f328f5e70783b5ed", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/pages/CompCopilot.jsx:105"}, "properties": {"repobilityId": "616a064b9bdc5b35", "scanner": "scanner-primary", "fingerprint": "f328f5e70783b5ed", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-3ea94675a57f3b4f", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/pages/CompCopilot.jsx:194"}, "properties": {"repobilityId": "2888d53310dad71c", "scanner": "scanner-primary", "fingerprint": "3ea94675a57f3b4f", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-6341c88bed006c0a", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/pages/NationalsAdmin.jsx:177"}, "properties": {"repobilityId": "2a01127b67d77acb", "scanner": "scanner-primary", "fingerprint": "6341c88bed006c0a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-67b8e9c165ee7af4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/NationalsAdmin.jsx:648"}, "properties": {"repobilityId": "4f041cfe15050d4e", "scanner": "scanner-primary", "fingerprint": "67b8e9c165ee7af4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6b5422b0fda8c6e2", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/pages/CompSuperAdmin.jsx:257"}, "properties": {"repobilityId": "25a36d77ae5ef77e", "scanner": "scanner-primary", "fingerprint": "6b5422b0fda8c6e2", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-3e6fac584986422a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/NationalsRegister.jsx:568"}, "properties": {"repobilityId": "d4d1ba3d2ab7a0af", "scanner": "scanner-primary", "fingerprint": "3e6fac584986422a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-74f42d680d1c200d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CompetitionDetail.jsx:327"}, "properties": {"repobilityId": "d09d3e068473b327", "scanner": "scanner-primary", "fingerprint": "74f42d680d1c200d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3dcfd7da6e302217", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/pages/BigFishPage.jsx:760"}, "properties": {"repobilityId": "86011efc75483759", "scanner": "scanner-primary", "fingerprint": "3dcfd7da6e302217", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-16161d705cf692cb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/BigFishPage.jsx:289"}, "properties": {"repobilityId": "85f8079da35beea0", "scanner": "scanner-primary", "fingerprint": "16161d705cf692cb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-46c01d95f7ac8c17", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/pages/CompAdmin.jsx:398"}, "properties": {"repobilityId": "28b447313f4e9452", "scanner": "scanner-primary", "fingerprint": "46c01d95f7ac8c17", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-72222f8d9c546787", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CompAdmin.jsx:571"}, "properties": {"repobilityId": "0295187a058cee16", "scanner": "scanner-primary", "fingerprint": "72222f8d9c546787", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-77bd8e0c63b13f68", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/pages/FishIDPage.jsx:373"}, "properties": {"repobilityId": "4892d041a4d61361", "scanner": "scanner-primary", "fingerprint": "77bd8e0c63b13f68", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-625a8d422d54f026", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 src/pages/AGMAdmin.jsx:671"}, "properties": {"repobilityId": "e6fae7234cf4bc06", "scanner": "scanner-primary", "fingerprint": "625a8d422d54f026", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-f1a0afcf6016f0b4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CatfishCullPage.jsx:116"}, "properties": {"repobilityId": "72a3f5b22bb9d537", "scanner": "scanner-primary", "fingerprint": "f1a0afcf6016f0b4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-242a82f21c80272f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/AnalyticsDashboard.jsx:40"}, "properties": {"repobilityId": "0f1ec9d1446b4565", "scanner": "scanner-primary", "fingerprint": "242a82f21c80272f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-219b96df1d761e2d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/CheckInDisplay.jsx:104"}, "properties": {"repobilityId": "f6e2626dd0415c08", "scanner": "scanner-primary", "fingerprint": "219b96df1d761e2d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-741cc7bd5bbdbfa1", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/MembershipAdmin.jsx:260"}, "properties": {"repobilityId": "7df889c277b2890f", "scanner": "scanner-primary", "fingerprint": "741cc7bd5bbdbfa1", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a4c4b6a88350edf7", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/pages/bingo/BingoPlayPage.jsx:190"}, "properties": {"repobilityId": "4419b641ec80a86e", "scanner": "scanner-primary", "fingerprint": "a4c4b6a88350edf7", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-331cb06bffa39ba7", "level": "warning", "message": {"text": "Privileged port 465 in use"}, "properties": {"repobilityId": "bcd1f06b60a2b6bc", "scanner": "scanner-primary", "fingerprint": "331cb06bffa39ba7", "layer": "network", "severity": "medium", "confidence": 1.0, "tags": ["security", "ports"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "netlify/functions/lib/backup.js"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6e2bd0763dd1b190", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in netlify/functions/bingo-claim.mjs:11"}, "properties": {"repobilityId": "d565af0d49a497a1", "scanner": "scanner-primary", "fingerprint": "6e2bd0763dd1b190", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "netlify/functions/bingo-claim.mjs"}, "region": {"startLine": 11}}}]}, {"ruleId": "scanner-e66dae9933c8de2c", "level": "note", "message": {"text": "Insecure pattern 'document_write' in src/wfsc/WFSCApp.jsx:1087"}, "properties": {"repobilityId": "88f51a23fcfbf140", "scanner": "scanner-primary", "fingerprint": "e66dae9933c8de2c", "layer": "security", "severity": "low", "confidence": 1.0, "tags": ["owasp", "document_write"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/wfsc/WFSCApp.jsx"}, "region": {"startLine": 1087}}}]}, {"ruleId": "scanner-5cc645b4480dffac", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in src/wfsc/WFSCApp.jsx:23"}, "properties": {"repobilityId": "aa32c19df47f696d", "scanner": "scanner-primary", "fingerprint": "5cc645b4480dffac", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/wfsc/WFSCApp.jsx"}, "region": {"startLine": 23}}}]}, {"ruleId": "scanner-6bc678ff1f9b8c58", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in src/lib/useAnalytics.js:40"}, "properties": {"repobilityId": "48d8cd5cc670d62d", "scanner": "scanner-primary", "fingerprint": "6bc678ff1f9b8c58", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/lib/useAnalytics.js"}, "region": {"startLine": 40}}}]}, {"ruleId": "scanner-8ea97fb525b762cb", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/pages/CompCopilot.jsx:194"}, "properties": {"repobilityId": "9412c28a0007e201", "scanner": "scanner-primary", "fingerprint": "8ea97fb525b762cb", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/pages/CompCopilot.jsx"}, "region": {"startLine": 194}}}]}, {"ruleId": "scanner-f78d46136a2cc9f9", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in src/pages/CompCopilot.jsx:28"}, "properties": {"repobilityId": "fa80a2c52114683a", "scanner": "scanner-primary", "fingerprint": "f78d46136a2cc9f9", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/pages/CompCopilot.jsx"}, "region": {"startLine": 28}}}]}, {"ruleId": "scanner-7f3c36d9666b12a0", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/pages/FishIDPage.jsx:373"}, "properties": {"repobilityId": "fe6c0c4e9a4fb112", "scanner": "scanner-primary", "fingerprint": "7f3c36d9666b12a0", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/pages/FishIDPage.jsx"}, "region": {"startLine": 373}}}]}, {"ruleId": "scanner-42b8be59194c1c63", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/pages/bingo/BingoPlayPage.jsx:190"}, "properties": {"repobilityId": "b667e961d4e29762", "scanner": "scanner-primary", "fingerprint": "42b8be59194c1c63", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/pages/bingo/BingoPlayPage.jsx"}, "region": {"startLine": 190}}}]}, {"ruleId": "scanner-4601e3ad3bb28677", "level": "warning", "message": {"text": "No CI/CD pipelines detected"}, "properties": {"repobilityId": "c3ee439bce2bc51e", "scanner": "scanner-primary", "fingerprint": "4601e3ad3bb28677", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-dcb43b2f03b8b436", "level": "note", "message": {"text": "Very large file: src/App.jsx (1132 lines)"}, "properties": {"repobilityId": "a59a84e7052cf35b", "scanner": "scanner-primary", "fingerprint": "dcb43b2f03b8b436", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-2741336b47a908a7", "level": "note", "message": {"text": "Very large file: src/wfsc/WFSCApp.jsx (2762 lines)"}, "properties": {"repobilityId": "09f91848a77600a6", "scanner": "scanner-primary", "fingerprint": "2741336b47a908a7", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-eb8039ad826a0d65", "level": "note", "message": {"text": "Very large file: src/pages/NationalsAdmin.jsx (1838 lines)"}, "properties": {"repobilityId": "7fa2873636b22ce2", "scanner": "scanner-primary", "fingerprint": "eb8039ad826a0d65", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-de5b8c631f22904c", "level": "note", "message": {"text": "Very large file: src/pages/NationalsRegister.jsx (948 lines)"}, "properties": {"repobilityId": "4c423610d65a9447", "scanner": "scanner-primary", "fingerprint": "de5b8c631f22904c", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-bae6af044ce0224f", "level": "note", "message": {"text": "Very large file: src/pages/CompAdmin.jsx (2761 lines)"}, "properties": {"repobilityId": "354004b55beb0150", "scanner": "scanner-primary", "fingerprint": "bae6af044ce0224f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-e1c5b3e7dee986ce", "level": "note", "message": {"text": "Very large file: src/pages/TeamManagement.jsx (1338 lines)"}, "properties": {"repobilityId": "2bb8eadb7e53c8c5", "scanner": "scanner-primary", "fingerprint": "e1c5b3e7dee986ce", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-946a0c677263c49f", "level": "note", "message": {"text": "Very large file: src/pages/MembershipPage.jsx (2062 lines)"}, "properties": {"repobilityId": "4aebeeeca31cbbdf", "scanner": "scanner-primary", "fingerprint": "946a0c677263c49f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-26e333f6434862e2", "level": "note", "message": {"text": "Very large file: src/pages/CompRegister.jsx (926 lines)"}, "properties": {"repobilityId": "d0b67628dfd53d26", "scanner": "scanner-primary", "fingerprint": "26e333f6434862e2", "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": "793aeb8f73529a80", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-b3ed68815bca2f8c", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: package.json"}, "properties": {"repobilityId": "7edae0550c126386", "scanner": "scanner-primary", "fingerprint": "b3ed68815bca2f8c", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-70f60e423cba52c6", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: fish-id-migration/package.json"}, "properties": {"repobilityId": "364820bcdfffbd5d", "scanner": "scanner-primary", "fingerprint": "70f60e423cba52c6", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "fish-id-migration/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-a7253a4cdd01b3c3", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: netlify/functions/package.json"}, "properties": {"repobilityId": "508f12f5f4740b5c", "scanner": "scanner-primary", "fingerprint": "a7253a4cdd01b3c3", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "netlify/functions/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "20e072e7dabfb0a9", "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": "0c7c19b73c92422d", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-9d79c4077342a7d0", "level": "warning", "message": {"text": "Runtime service client appears to use placeholder configuration"}, "properties": {"repobilityId": "5d39009d73bde2d1", "scanner": "scanner-primary", "fingerprint": "9d79c4077342a7d0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "runtime-config", "service-client", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "a2767d1203bad67b", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "warning", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "704d69d80279957a", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "584daf811bb6570f", "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": "f88a21bcc974696e", "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": "a64bfa49845cf0bf", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-ecb0d2c55ed6875d", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/settings.local.json"}, "properties": {"repobilityId": "d8bae33a6d517bf0", "scanner": "scanner-primary", "fingerprint": "ecb0d2c55ed6875d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/settings.local.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-1753cca8ad8f616e", "level": "none", "message": {"text": "Commented-code block (6 lines) in fish-id-migration/seed_fish_species.js:4"}, "properties": {"repobilityId": "e2db90e1bdc722c0", "scanner": "scanner-primary", "fingerprint": "1753cca8ad8f616e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1cd312fc3d183e28", "level": "none", "message": {"text": "Commented-code block (5 lines) in netlify/functions/comp-copilot.js:237"}, "properties": {"repobilityId": "9ebe2e9b0d674890", "scanner": "scanner-primary", "fingerprint": "1cd312fc3d183e28", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1609ccfec0a6adce", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 netlify/functions/comp-copilot.js:402"}, "properties": {"repobilityId": "5e2f1ab581029022", "scanner": "scanner-primary", "fingerprint": "1609ccfec0a6adce", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-907192cc83300ebc", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 netlify/functions/send-results-email.js:74"}, "properties": {"repobilityId": "a6a22312ef2396ce", "scanner": "scanner-primary", "fingerprint": "907192cc83300ebc", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-f44705e8292b7d1f", "level": "none", "message": {"text": "Commented-code block (5 lines) in netlify/functions/refund-payment.js:7"}, "properties": {"repobilityId": "e1f8bffece2f0bf6", "scanner": "scanner-primary", "fingerprint": "f44705e8292b7d1f", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-31cf57084dfd0b02", "level": "none", "message": {"text": "Commented-code block (5 lines) in netlify/functions/daily-backup.js:4"}, "properties": {"repobilityId": "5c97b8f7a0b42335", "scanner": "scanner-primary", "fingerprint": "31cf57084dfd0b02", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-6aa19e852d948ad0", "level": "none", "message": {"text": "Commented-code block (5 lines) in netlify/functions/verify-checkout-session.js:4"}, "properties": {"repobilityId": "22b36ba8480ecf86", "scanner": "scanner-primary", "fingerprint": "6aa19e852d948ad0", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-5c5679f1aa5229e2", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 netlify/functions/identify-fish.js:76"}, "properties": {"repobilityId": "ea8933d03daf7b67", "scanner": "scanner-primary", "fingerprint": "5c5679f1aa5229e2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-69d7748a654ee3a1", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/wfsc/lib/hooks.js:19"}, "properties": {"repobilityId": "e15108b35f1d831e", "scanner": "scanner-primary", "fingerprint": "69d7748a654ee3a1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-b372ab44cbef92df", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsConfirm.jsx:308"}, "properties": {"repobilityId": "50cf1eaa1004372b", "scanner": "scanner-primary", "fingerprint": "b372ab44cbef92df", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-76c7ce38942de109", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsRegisterIndividual.jsx:180"}, "properties": {"repobilityId": "4e5b117019deb721", "scanner": "scanner-primary", "fingerprint": "76c7ce38942de109", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-797848920573cfc1", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsAdmin.jsx:502"}, "properties": {"repobilityId": "41cf252b109c836a", "scanner": "scanner-primary", "fingerprint": "797848920573cfc1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-a78e425fbf39c32d", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/NationalsRegister.jsx:368"}, "properties": {"repobilityId": "b820c1f3e5b373b2", "scanner": "scanner-primary", "fingerprint": "a78e425fbf39c32d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-b576895fd0ff682c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/CompAdmin.jsx:1508"}, "properties": {"repobilityId": "000d1d026e6cf14a", "scanner": "scanner-primary", "fingerprint": "b576895fd0ff682c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-105335c65f33faa4", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/MembershipPage.jsx:777"}, "properties": {"repobilityId": "fd6c44204b7fa698", "scanner": "scanner-primary", "fingerprint": "105335c65f33faa4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d81a1400423775ec", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/WeighmasterInterface.jsx:183"}, "properties": {"repobilityId": "20bc144bb6fba709", "scanner": "scanner-primary", "fingerprint": "d81a1400423775ec", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c973bbd101436658", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/pages/MembershipAdmin.jsx:129"}, "properties": {"repobilityId": "f9fa1e93c74c04fe", "scanner": "scanner-primary", "fingerprint": "c973bbd101436658", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-87acb4066071a15a", "level": "note", "message": {"text": "19 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "b1f30c58de7ffb20", "scanner": "scanner-primary", "fingerprint": "87acb4066071a15a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-49b4b28f1619263b", "level": "warning", "message": {"text": "Frontend route `/records/admin/archive/:id` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "d410dd6914688bbb", "scanner": "scanner-primary", "fingerprint": "49b4b28f1619263b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-25dc62e81ddc3d50", "level": "warning", "message": {"text": "Frontend route `/news` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "61a90ec6049b0829", "scanner": "scanner-primary", "fingerprint": "25dc62e81ddc3d50", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-4c21c888f14f4982", "level": "warning", "message": {"text": "Frontend route `/leaderboard` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "fa5d82dcb9fca9d8", "scanner": "scanner-primary", "fingerprint": "4c21c888f14f4982", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-1c194854b69c3d05", "level": "warning", "message": {"text": "Frontend route `/membership/*` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "b354b810b4e43e60", "scanner": "scanner-primary", "fingerprint": "1c194854b69c3d05", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-482e999d1e2c16f6", "level": "warning", "message": {"text": "Frontend route `/membership/invited` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "eb5400d56c11f8c7", "scanner": "scanner-primary", "fingerprint": "482e999d1e2c16f6", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-78b9f78ee83b6d1d", "level": "warning", "message": {"text": "Frontend route `/nationals/confirm` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "186e9e46660b159b", "scanner": "scanner-primary", "fingerprint": "78b9f78ee83b6d1d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-3b8e6ec11a8643a0", "level": "warning", "message": {"text": "Frontend route `/competitions/:id` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "3429d28d2ec6ace7", "scanner": "scanner-primary", "fingerprint": "3b8e6ec11a8643a0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-b7138f7350f65f92", "level": "warning", "message": {"text": "Frontend route `/competitions/:id/register` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "6f9df3cd2c463fd9", "scanner": "scanner-primary", "fingerprint": "b7138f7350f65f92", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-eec070d397203d63", "level": "warning", "message": {"text": "Frontend route `/competitions/:id/admin` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "8f92ba7504b6aa0c", "scanner": "scanner-primary", "fingerprint": "eec070d397203d63", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-16554a713767ee58", "level": "warning", "message": {"text": "Frontend route `/c/:id` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "e7b892a1fca324aa", "scanner": "scanner-primary", "fingerprint": "16554a713767ee58", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-7d87ec9d95eeca8a", "level": "warning", "message": {"text": "Frontend route `/big-fish/sponsor` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "b33e71cf1cb969a3", "scanner": "scanner-primary", "fingerprint": "7d87ec9d95eeca8a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-71ae912c001da630", "level": "warning", "message": {"text": "Frontend route `/bingo/diver` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "78c0b089d03d9bab", "scanner": "scanner-primary", "fingerprint": "71ae912c001da630", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-e89dad246ef1cb79", "level": "warning", "message": {"text": "Frontend route `/agm/:id` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "4fa72cb6de600b6e", "scanner": "scanner-primary", "fingerprint": "e89dad246ef1cb79", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-44041f9badd77471", "level": "warning", "message": {"text": "Frontend route `/wfsc/*` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "f27dd2c2587a96b9", "scanner": "scanner-primary", "fingerprint": "44041f9badd77471", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}]}]}