{"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-88a502142c17dd9c", "name": "Stray `console.log` in TS/JS \u2014 scripts/test-bot.ts:4", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/test-bot.ts:4"}, "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-ca44b51fbc67fed2", "name": "Stray `console.log` in TS/JS \u2014 scripts/seed_staging.js:7", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed_staging.js:7"}, "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-e9cfd2dda4de9dad", "name": "Stray `console.log` in TS/JS \u2014 scripts/backfill-translations.ts:31", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/backfill-translations.ts:31"}, "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-ffeab2ac07607ae7", "name": "Stray `console.log` in TS/JS \u2014 scripts/test-telegram.ts:4", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/test-telegram.ts:4"}, "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-5b676768ad299d8a", "name": "Stray `console.log` in TS/JS \u2014 scripts/backfill-embeddings.ts:36", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/backfill-embeddings.ts:36"}, "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-c20ddaa41679790d", "name": "Stray `console.log` in TS/JS \u2014 scripts/grant-initial-cu.ts:32", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/grant-initial-cu.ts:32"}, "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-d1f3976410b67654", "name": "Stray `console.log` in TS/JS \u2014 scripts/test-resolution.ts:100", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/test-resolution.ts:100"}, "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-58e5c58a750204c9", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/page.tsx:72", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/page.tsx:72"}, "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-2adb2171292c617e", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/forecasts/page.tsx:70", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/forecasts/page.tsx:70"}, "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-c8620394b22d5bbf", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/[id]/ForecastDetailClient.tsx:707", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/[id]/ForecastDetailClient.tsx:707"}, "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-72edc43151912b50", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/forecasts/[id]/page.tsx:322", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/forecasts/[id]/page.tsx:322"}, "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-862a583b694e6484", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/[id]/_forecast/ForecastInfoPanel.tsx:22", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/[id]/_forecast/ForecastInfoPanel.tsx:22"}, "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-04470091a4b2484d", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/[id]/_forecast/CommitmentsHistory.tsx:63", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/[id]/_forecast/CommitmentsHistory.tsx:63"}, "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-644515594a2d960e", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/express/ExpressForecastClient.tsx:480", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/express/ExpressForecastClient.tsx:480"}, "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-78d87692fc9537d7", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/admin/BotsTable.tsx:205", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/admin/BotsTable.tsx:205"}, "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-9243b13188536ef0", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/admin/CommentsTable.tsx:111", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/admin/CommentsTable.tsx:111"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b5e57ba6bf0ed0c5", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/admin/AdminClient.tsx:248", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/admin/AdminClient.tsx:248"}, "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-9a3d4e5098827899", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/profile/[id]/page.tsx:146", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/profile/[id]/page.tsx:146"}, "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-3875c26d7549f33f", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/[locale]/forecasts/[id]/page.tsx:251", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/[locale]/forecasts/[id]/page.tsx:251"}, "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-192f3f5d82aa1d4b", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/leaderboard/layout.tsx:50", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/leaderboard/layout.tsx:50"}, "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-7140bcbfe0c9db5e", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/leaderboard/page.tsx:282", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/leaderboard/page.tsx:282"}, "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-db4fa342564f6c0f", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/Sidebar.tsx:321", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Sidebar.tsx:321"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a102690ddaff9ed4", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/forecasts/ForecastWizard.tsx:340", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/forecasts/ForecastWizard.tsx:340"}, "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-6708ed019446db3a", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/forecasts/ForecastCard.tsx:482", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/forecasts/ForecastCard.tsx:482"}, "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-437a9c387a9dbb5e", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/forecasts/SimilarForecastsWarning.tsx:69", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/forecasts/SimilarForecastsWarning.tsx:69"}, "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-f291767c8dd4180f", "name": "Stray `console.log` in TS/JS \u2014 src/test/integration-helper.ts:9", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/test/integration-helper.ts:9"}, "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-fcd9b82ce1a221c3", "name": "Stray `console.log` in TS/JS \u2014 prisma/seed-tags.ts:44", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 prisma/seed-tags.ts:44"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-386fa730f2df156e", "name": "Stray `console.log` in TS/JS \u2014 prisma/seed.ts:12", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 prisma/seed.ts:12"}, "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-bde18e68d93b3da9", "name": "Stray `console.log` in TS/JS \u2014 public/sw.js:15", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 public/sw.js:15"}, "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-36f0ee3ad84c6ab6", "name": "Privileged port 4 in use", "shortDescription": {"text": "Privileged port 4 in use"}, "fullDescription": {"text": "Port 4 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-e1468352d5adfc1e", "name": "Privileged port 16 in use", "shortDescription": {"text": "Privileged port 16 in use"}, "fullDescription": {"text": "Port 16 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-20f1d133ab646703", "name": "Docker base image is tag-pinned but not digest-pinned: node:24-bookworm-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: node:24-bookworm-slim"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a4e62fef1066ee93", "name": "Insecure pattern 'dangerous_innerhtml' in src/app/page.tsx:72", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/page.tsx:72"}, "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-f28c3c5a07da53a5", "name": "Insecure pattern 'dangerous_innerhtml' in src/app/forecasts/page.tsx:70", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/forecasts/page.tsx:70"}, "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-f2822fa66d1ebffe", "name": "Insecure pattern 'dangerous_innerhtml' in src/app/forecasts/[id]/page.tsx:322", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/forecasts/[id]/page.tsx:322"}, "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-f963aac94b5ade9d", "name": "Insecure pattern 'dangerous_innerhtml' in src/app/profile/[id]/page.tsx:146", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/profile/[id]/page.tsx:146"}, "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-0b88f48c881981ae", "name": "Insecure pattern 'dangerous_innerhtml' in src/app/[locale]/forecasts/[id]/page.tsx:251", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/[locale]/forecasts/[id]/page.tsx:251"}, "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-2e700d9c68623ebf", "name": "Insecure pattern 'dangerous_innerhtml' in src/app/leaderboard/layout.tsx:50", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/leaderboard/layout.tsx:50"}, "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-ce4133b7a5edcf3d", "name": "Insecure pattern 'node_child_process' in screenshot-checker/scripts/get_latest_screenshots.cjs:3", "shortDescription": {"text": "Insecure pattern 'node_child_process' in screenshot-checker/scripts/get_latest_screenshots.cjs:3"}, "fullDescription": {"text": "Found a known-risky pattern (node_child_process). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-5e9d4a7e1b0eabc1", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "aws-actions/configure-aws-credentials@v4 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea73f7bd8a7bbda2", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-deb3f428d35f3c4b", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/cache/restore@v4 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f5a68be8c740544c", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2436c819d540d575", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/checkout@v4 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1e355a8e6b2c4da8", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-28c4a04bd807da0c", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/checkout@v4 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ad6701f0a8405e22", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9e3fa0632c7bfb57", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/checkout@v4 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-801c3c8c9049a452", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-cb639d9a10a47b23", "name": "package.json defines install-time lifecycle scripts", "shortDescription": {"text": "package.json defines install-time lifecycle scripts"}, "fullDescription": {"text": "preinstall/install/postinstall/prepare scripts execute during dependency installation. Review them carefully for network calls, obfuscation, shell execution, or credential access."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-51a1614e37a6a300", "name": "Very large file: __tests__/services/bot-runner.test.ts (1709 lines)", "shortDescription": {"text": "Very large file: __tests__/services/bot-runner.test.ts (1709 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-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 76 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 131 placeholder/mock markers across 39 source files. This often means the repo looks complete while core flows still use generated scaffolding or fake data."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f27c7be9f2111c87", "name": "Agent authority lacks a verifier contract: agents/qa/AGENTS.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: agents/qa/AGENTS.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ade5f4db7b916ec6", "name": "Agent authority lacks a verifier contract: agents/devops/AGENTS.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: agents/devops/AGENTS.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-115debc270d44c0e", "name": "Agent authority lacks a verifier contract: .cursor/rules/daatan.mdc", "shortDescription": {"text": "Agent authority lacks a verifier contract: .cursor/rules/daatan.mdc"}, "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-c9572b4bcc98408f", "name": "Agent authority lacks a verifier contract: screenshot-checker/SKILL.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: screenshot-checker/SKILL.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-122f91b7f2906dc4", "name": "Agent authority lacks a verifier contract: .claude/settings.json", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/settings.json"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-719cbc90b8bb701f", "name": "Network/subprocess call without timeout or try/except \u2014 scripts/render-esperanto-slides-pdf.py:43", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 scripts/render-esperanto-slides-pdf.py:43"}, "fullDescription": {"text": "`subprocess.run(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-15a19c724d03f8ad", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/page.tsx:37", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/page.tsx:37"}, "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-799926fd0531a239", "name": "Commented-code block (5 lines) in src/app/api/forecasts/[id]/context/route.ts:88", "shortDescription": {"text": "Commented-code block (5 lines) in src/app/api/forecasts/[id]/context/route.ts:88"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b0276ded66d409d8", "name": "Commented-code block (5 lines) in src/app/api/news-indexer/context/route.ts:26", "shortDescription": {"text": "Commented-code block (5 lines) in src/app/api/news-indexer/context/route.ts:26"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1872ef81f7647ae5", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/telegram/rollback/route.ts:37", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/telegram/rollback/route.ts:37"}, "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-fdfe72f53bb02ae0", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/forecasts/[id]/ForecastDetailClient.tsx:173", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/forecasts/[id]/ForecastDetailClient.tsx:173"}, "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-bb632a7473773e83", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/forecasts/express/ExpressForecastClient.tsx:266", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/forecasts/express/ExpressForecastClient.tsx:266"}, "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-c92a6912e3d27b41", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/BotsTable.tsx:121", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/BotsTable.tsx:121"}, "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-48b42bdce01e5d6e", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/BackfillTagsButton.tsx:20", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/BackfillTagsButton.tsx:20"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-35e73b51eae3bf9f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/AdminClient.tsx:163", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/AdminClient.tsx:163"}, "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-a1b6b59568dadcaf", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/OracleTab.tsx:257", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/OracleTab.tsx:257"}, "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-524ce144ad81b9af", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/ContextTimeline.tsx:170", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/ContextTimeline.tsx:170"}, "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-fe3e54b85e657fd2", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/ForecastWizard.tsx:205", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/ForecastWizard.tsx:205"}, "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-f35b2566f3183a0e", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/CommitmentForm.tsx:147", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/CommitmentForm.tsx:147"}, "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-de41a2b78c875a59", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/steps/StepNewsAnchor.tsx:142", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/steps/StepNewsAnchor.tsx:142"}, "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-91924bf20ba51945", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/profile/ProfileEditForm.tsx:98", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/profile/ProfileEditForm.tsx:98"}, "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-d10d19f9a5e520b1", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/ibi/IbiTool.tsx:117", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/ibi/IbiTool.tsx:117"}, "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-40ee123010c81a08", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/comments/CommentItem.tsx:92", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/comments/CommentItem.tsx:92"}, "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-1675ba8eec34a042", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/llm/providers/openrouter.ts:39", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/llm/providers/openrouter.ts:39"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-5f1e5ec8f39827d8", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/utils/scraper.ts:115", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/utils/scraper.ts:115"}, "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-f6b905530beef343", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/hooks/usePushSubscription.ts:64", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/hooks/usePushSubscription.ts:64"}, "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-422a01fdc049b9f6", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/services/oracleClient.ts:108", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/services/oracleClient.ts:108"}, "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-57a05336c57bbe92", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/services/indexnow.ts:11", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/services/indexnow.ts:11"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-55b00bcaf370f715", "name": "Commented-code block (7 lines) in src/lib/services/bots/voting.ts:14", "shortDescription": {"text": "Commented-code block (7 lines) in src/lib/services/bots/voting.ts:14"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-671b6b11038a98b6", "name": "Commented-code block (6 lines) in src/lib/services/__tests__/oracle.test.ts:21", "shortDescription": {"text": "Commented-code block (6 lines) in src/lib/services/__tests__/oracle.test.ts:21"}, "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-f9f97ea946ca8c8a", "name": "Commented-code block (6 lines) in infra/mail-forwarder/index.mjs:12", "shortDescription": {"text": "Commented-code block (6 lines) in infra/mail-forwarder/index.mjs:12"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-35632ad8f04f73a2", "name": "`fetch()` without try/.catch or AbortSignal \u2014 __tests__/lib/express-prediction-url.test.ts:144", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 __tests__/lib/express-prediction-url.test.ts:144"}, "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-99c0f46afb2ebacc", "name": "Commented-code block (6 lines) in __tests__/services/bot-runner.test.ts:1596", "shortDescription": {"text": "Commented-code block (6 lines) in __tests__/services/bot-runner.test.ts:1596"}, "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-e64ca466000bdd1d", "name": "Commented-code block (6 lines) in __tests__/config/middleware-routing.test.ts:125", "shortDescription": {"text": "Commented-code block (6 lines) in __tests__/config/middleware-routing.test.ts:125"}, "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-1662ae7a5bb4e048", "name": "33 env vars used in code but missing from .env.example", "shortDescription": {"text": "33 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `ALL_USERS`, `APP_ENV`, `AWS_ACCOUNT_ID`, `AWS_REGION`, `BOT_RUNNER_SECRET`, `CATCH_ALL_DESTINATIONS`, `CI`, `DRY_RUN` + 25 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}}]}}, "automationDetails": {"id": "repobility/25180"}, "properties": {"repository": "Daatan/daatan", "repoUrl": "https://github.com/Daatan/daatan", "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-88a502142c17dd9c", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/test-bot.ts:4"}, "properties": {"repobilityId": "28ebcf89e48dcc06", "scanner": "scanner-primary", "fingerprint": "88a502142c17dd9c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-ca44b51fbc67fed2", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed_staging.js:7"}, "properties": {"repobilityId": "822b150396619949", "scanner": "scanner-primary", "fingerprint": "ca44b51fbc67fed2", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-e9cfd2dda4de9dad", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/backfill-translations.ts:31"}, "properties": {"repobilityId": "04ca5766b6341e0a", "scanner": "scanner-primary", "fingerprint": "e9cfd2dda4de9dad", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-ffeab2ac07607ae7", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/test-telegram.ts:4"}, "properties": {"repobilityId": "90784f330f718043", "scanner": "scanner-primary", "fingerprint": "ffeab2ac07607ae7", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-5b676768ad299d8a", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/backfill-embeddings.ts:36"}, "properties": {"repobilityId": "bf4662e64bf6c75a", "scanner": "scanner-primary", "fingerprint": "5b676768ad299d8a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-c20ddaa41679790d", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/grant-initial-cu.ts:32"}, "properties": {"repobilityId": "7d605dfe8a07b82d", "scanner": "scanner-primary", "fingerprint": "c20ddaa41679790d", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-d1f3976410b67654", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/test-resolution.ts:100"}, "properties": {"repobilityId": "a23b9621a2a5af62", "scanner": "scanner-primary", "fingerprint": "d1f3976410b67654", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-58e5c58a750204c9", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/page.tsx:72"}, "properties": {"repobilityId": "4d4ab3e03315f684", "scanner": "scanner-primary", "fingerprint": "58e5c58a750204c9", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-2adb2171292c617e", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/forecasts/page.tsx:70"}, "properties": {"repobilityId": "7e4186227bf9b1f9", "scanner": "scanner-primary", "fingerprint": "2adb2171292c617e", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-c8620394b22d5bbf", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/[id]/ForecastDetailClient.tsx:707"}, "properties": {"repobilityId": "3b46b6b0b79d6459", "scanner": "scanner-primary", "fingerprint": "c8620394b22d5bbf", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-72edc43151912b50", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/forecasts/[id]/page.tsx:322"}, "properties": {"repobilityId": "be1b9edce02c5eba", "scanner": "scanner-primary", "fingerprint": "72edc43151912b50", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-862a583b694e6484", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/[id]/_forecast/ForecastInfoPanel.tsx:22"}, "properties": {"repobilityId": "f8e52927da9c45d1", "scanner": "scanner-primary", "fingerprint": "862a583b694e6484", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-04470091a4b2484d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/[id]/_forecast/CommitmentsHistory.tsx:63"}, "properties": {"repobilityId": "4d8cdd729c62dbd3", "scanner": "scanner-primary", "fingerprint": "04470091a4b2484d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-644515594a2d960e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/forecasts/express/ExpressForecastClient.tsx:480"}, "properties": {"repobilityId": "000e84c0c05ae649", "scanner": "scanner-primary", "fingerprint": "644515594a2d960e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-78d87692fc9537d7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/admin/BotsTable.tsx:205"}, "properties": {"repobilityId": "86da3ee853915a3e", "scanner": "scanner-primary", "fingerprint": "78d87692fc9537d7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9243b13188536ef0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/admin/CommentsTable.tsx:111"}, "properties": {"repobilityId": "82af9168387b13a7", "scanner": "scanner-primary", "fingerprint": "9243b13188536ef0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b5e57ba6bf0ed0c5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/admin/AdminClient.tsx:248"}, "properties": {"repobilityId": "425c7e170c68334c", "scanner": "scanner-primary", "fingerprint": "b5e57ba6bf0ed0c5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9a3d4e5098827899", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/profile/[id]/page.tsx:146"}, "properties": {"repobilityId": "383d04a1a909bd3c", "scanner": "scanner-primary", "fingerprint": "9a3d4e5098827899", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-3875c26d7549f33f", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/[locale]/forecasts/[id]/page.tsx:251"}, "properties": {"repobilityId": "4d2e1df3929ae4ed", "scanner": "scanner-primary", "fingerprint": "3875c26d7549f33f", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-192f3f5d82aa1d4b", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/app/leaderboard/layout.tsx:50"}, "properties": {"repobilityId": "d69679669819bcd7", "scanner": "scanner-primary", "fingerprint": "192f3f5d82aa1d4b", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-7140bcbfe0c9db5e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/leaderboard/page.tsx:282"}, "properties": {"repobilityId": "cc38b7123001dc00", "scanner": "scanner-primary", "fingerprint": "7140bcbfe0c9db5e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-db4fa342564f6c0f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Sidebar.tsx:321"}, "properties": {"repobilityId": "450176a4d82f7dad", "scanner": "scanner-primary", "fingerprint": "db4fa342564f6c0f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a102690ddaff9ed4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/forecasts/ForecastWizard.tsx:340"}, "properties": {"repobilityId": "be0a1101a52ec5c9", "scanner": "scanner-primary", "fingerprint": "a102690ddaff9ed4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6708ed019446db3a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/forecasts/ForecastCard.tsx:482"}, "properties": {"repobilityId": "5cd28c6c8b2f0c81", "scanner": "scanner-primary", "fingerprint": "6708ed019446db3a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-437a9c387a9dbb5e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/forecasts/SimilarForecastsWarning.tsx:69"}, "properties": {"repobilityId": "9745152762d5b3e0", "scanner": "scanner-primary", "fingerprint": "437a9c387a9dbb5e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f291767c8dd4180f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/test/integration-helper.ts:9"}, "properties": {"repobilityId": "d5049bae8fb7e34a", "scanner": "scanner-primary", "fingerprint": "f291767c8dd4180f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-fcd9b82ce1a221c3", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 prisma/seed-tags.ts:44"}, "properties": {"repobilityId": "ccbf12b77ee226e9", "scanner": "scanner-primary", "fingerprint": "fcd9b82ce1a221c3", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-386fa730f2df156e", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 prisma/seed.ts:12"}, "properties": {"repobilityId": "f77d7e0fb34b08e2", "scanner": "scanner-primary", "fingerprint": "386fa730f2df156e", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-bde18e68d93b3da9", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 public/sw.js:15"}, "properties": {"repobilityId": "19ecb22d48da856c", "scanner": "scanner-primary", "fingerprint": "bde18e68d93b3da9", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-36f0ee3ad84c6ab6", "level": "warning", "message": {"text": "Privileged port 4 in use"}, "properties": {"repobilityId": "1594bfeff919296e", "scanner": "scanner-primary", "fingerprint": "36f0ee3ad84c6ab6", "layer": "network", "severity": "medium", "confidence": 1.0, "tags": ["security", "ports"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/backup.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-e1468352d5adfc1e", "level": "warning", "message": {"text": "Privileged port 16 in use"}, "properties": {"repobilityId": "d31009168c502ace", "scanner": "scanner-primary", "fingerprint": "e1468352d5adfc1e", "layer": "network", "severity": "medium", "confidence": 1.0, "tags": ["security", "ports"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/backup.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-20f1d133ab646703", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:24-bookworm-slim"}, "properties": {"repobilityId": "447aca0c40b5a62b", "scanner": "scanner-primary", "fingerprint": "20f1d133ab646703", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 2}}}]}, {"ruleId": "scanner-20f1d133ab646703", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:24-bookworm-slim"}, "properties": {"repobilityId": "078b4bace2cdcb77", "scanner": "scanner-primary", "fingerprint": "20f1d133ab646703", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 62}}}]}, {"ruleId": "scanner-a4e62fef1066ee93", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/page.tsx:72"}, "properties": {"repobilityId": "88fd235b712bda65", "scanner": "scanner-primary", "fingerprint": "a4e62fef1066ee93", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/app/page.tsx"}, "region": {"startLine": 72}}}]}, {"ruleId": "scanner-f28c3c5a07da53a5", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/forecasts/page.tsx:70"}, "properties": {"repobilityId": "b9ddaf17cbd00d01", "scanner": "scanner-primary", "fingerprint": "f28c3c5a07da53a5", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/app/forecasts/page.tsx"}, "region": {"startLine": 70}}}]}, {"ruleId": "scanner-f2822fa66d1ebffe", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/forecasts/[id]/page.tsx:322"}, "properties": {"repobilityId": "77586247fcde07ea", "scanner": "scanner-primary", "fingerprint": "f2822fa66d1ebffe", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/app/forecasts/[id]/page.tsx"}, "region": {"startLine": 322}}}]}, {"ruleId": "scanner-f963aac94b5ade9d", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/profile/[id]/page.tsx:146"}, "properties": {"repobilityId": "5aa5cc340b1cfcea", "scanner": "scanner-primary", "fingerprint": "f963aac94b5ade9d", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/app/profile/[id]/page.tsx"}, "region": {"startLine": 146}}}]}, {"ruleId": "scanner-0b88f48c881981ae", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/[locale]/forecasts/[id]/page.tsx:251"}, "properties": {"repobilityId": "e959f8281f27f3ee", "scanner": "scanner-primary", "fingerprint": "0b88f48c881981ae", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/app/[locale]/forecasts/[id]/page.tsx"}, "region": {"startLine": 251}}}]}, {"ruleId": "scanner-2e700d9c68623ebf", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/app/leaderboard/layout.tsx:50"}, "properties": {"repobilityId": "6e5cecb5453be606", "scanner": "scanner-primary", "fingerprint": "2e700d9c68623ebf", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/app/leaderboard/layout.tsx"}, "region": {"startLine": 50}}}]}, {"ruleId": "scanner-ce4133b7a5edcf3d", "level": "warning", "message": {"text": "Insecure pattern 'node_child_process' in screenshot-checker/scripts/get_latest_screenshots.cjs:3"}, "properties": {"repobilityId": "1d9f422308e63b78", "scanner": "scanner-primary", "fingerprint": "ce4133b7a5edcf3d", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "node_child_process"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "screenshot-checker/scripts/get_latest_screenshots.cjs"}, "region": {"startLine": 3}}}]}, {"ruleId": "scanner-5e9d4a7e1b0eabc1", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "d0e4f3e37d39f7b0", "scanner": "scanner-primary", "fingerprint": "5e9d4a7e1b0eabc1", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/backup.yml"}, "region": {"startLine": 19}}}]}, {"ruleId": "scanner-5e9d4a7e1b0eabc1", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "274de9fb1c890e5e", "scanner": "scanner-primary", "fingerprint": "5e9d4a7e1b0eabc1", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/backup.yml"}, "region": {"startLine": 25}}}]}, {"ruleId": "scanner-ea73f7bd8a7bbda2", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "a9d7fe1b5b83ec78", "scanner": "scanner-primary", "fingerprint": "ea73f7bd8a7bbda2", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/backup.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-deb3f428d35f3c4b", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "afd3639997056dea", "scanner": "scanner-primary", "fingerprint": "deb3f428d35f3c4b", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/watchdog.yml"}, "region": {"startLine": 160}}}]}, {"ruleId": "scanner-deb3f428d35f3c4b", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "8ad9ed59c41b581b", "scanner": "scanner-primary", "fingerprint": "deb3f428d35f3c4b", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/watchdog.yml"}, "region": {"startLine": 223}}}]}, {"ruleId": "scanner-deb3f428d35f3c4b", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "53ef9ccb6b6f2a5c", "scanner": "scanner-primary", "fingerprint": "deb3f428d35f3c4b", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/watchdog.yml"}, "region": {"startLine": 244}}}]}, {"ruleId": "scanner-deb3f428d35f3c4b", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "15844f326c627945", "scanner": "scanner-primary", "fingerprint": "deb3f428d35f3c4b", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/watchdog.yml"}, "region": {"startLine": 247}}}]}, {"ruleId": "scanner-deb3f428d35f3c4b", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "15844f326c627945", "scanner": "scanner-primary", "fingerprint": "deb3f428d35f3c4b", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/watchdog.yml"}, "region": {"startLine": 329}}}]}, {"ruleId": "scanner-f5a68be8c740544c", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "0ca8a61a331fe9de", "scanner": "scanner-primary", "fingerprint": "f5a68be8c740544c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/watchdog.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2436c819d540d575", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "850a78df1d063654", "scanner": "scanner-primary", "fingerprint": "2436c819d540d575", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/rollback.yml"}, "region": {"startLine": 37}}}]}, {"ruleId": "scanner-2436c819d540d575", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "f118647b9b5352ed", "scanner": "scanner-primary", "fingerprint": "2436c819d540d575", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/rollback.yml"}, "region": {"startLine": 40}}}]}, {"ruleId": "scanner-1e355a8e6b2c4da8", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "0039735a38b2f3cd", "scanner": "scanner-primary", "fingerprint": "1e355a8e6b2c4da8", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/rollback.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "2aee2e2d969c7c6b", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 45}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "bee6b8956e03198c", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 48}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "735be02f00f3d798", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 70}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "4319262162feb627", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 95}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "cdd488c07b90bf4b", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 102}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "8c49f82bc1fad1c1", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 107}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "161a25eab2e68ed3", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 124}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "b5ff68ae3a5989fc", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 137}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "b5ff68ae3a5989fc", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 155}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "2aee2e2d969c7c6b", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 190}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "4319262162feb627", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 193}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "2aee2e2d969c7c6b", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 350}}}]}, {"ruleId": "scanner-28c4a04bd807da0c", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "4319262162feb627", "scanner": "scanner-primary", "fingerprint": "28c4a04bd807da0c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 353}}}]}, {"ruleId": "scanner-ad6701f0a8405e22", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "8384c23520d55657", "scanner": "scanner-primary", "fingerprint": "ad6701f0a8405e22", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-9e3fa0632c7bfb57", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "404203dc3f89da44", "scanner": "scanner-primary", "fingerprint": "9e3fa0632c7bfb57", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy-next.yml"}, "region": {"startLine": 22}}}]}, {"ruleId": "scanner-9e3fa0632c7bfb57", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "76e06217b515ec2c", "scanner": "scanner-primary", "fingerprint": "9e3fa0632c7bfb57", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy-next.yml"}, "region": {"startLine": 27}}}]}, {"ruleId": "scanner-9e3fa0632c7bfb57", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "7f29f10c5a450d61", "scanner": "scanner-primary", "fingerprint": "9e3fa0632c7bfb57", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy-next.yml"}, "region": {"startLine": 36}}}]}, {"ruleId": "scanner-9e3fa0632c7bfb57", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "d3f8762cd55ace0c", "scanner": "scanner-primary", "fingerprint": "9e3fa0632c7bfb57", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy-next.yml"}, "region": {"startLine": 43}}}]}, {"ruleId": "scanner-801c3c8c9049a452", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "34bcee5f4147f783", "scanner": "scanner-primary", "fingerprint": "801c3c8c9049a452", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/deploy-next.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-cb639d9a10a47b23", "level": "note", "message": {"text": "package.json defines install-time lifecycle scripts"}, "properties": {"repobilityId": "714673743ff59cef", "scanner": "scanner-primary", "fingerprint": "cb639d9a10a47b23", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "npm", "install-scripts"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-51a1614e37a6a300", "level": "note", "message": {"text": "Very large file: __tests__/services/bot-runner.test.ts (1709 lines)"}, "properties": {"repobilityId": "e68d2463fb9c0702", "scanner": "scanner-primary", "fingerprint": "51a1614e37a6a300", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "920bc59f17277439", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "724d1d4208acf404", "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": "76793d0d7a8b3ad4", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "109a292618827317", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "2fb27b9b55d9780b", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-f27c7be9f2111c87", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: agents/qa/AGENTS.md"}, "properties": {"repobilityId": "5dce59e5be00eb8d", "scanner": "scanner-primary", "fingerprint": "f27c7be9f2111c87", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "agents_md"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "agents/qa/AGENTS.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-ade5f4db7b916ec6", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: agents/devops/AGENTS.md"}, "properties": {"repobilityId": "f81b5384c5184509", "scanner": "scanner-primary", "fingerprint": "ade5f4db7b916ec6", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "agents_md"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "agents/devops/AGENTS.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-115debc270d44c0e", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .cursor/rules/daatan.mdc"}, "properties": {"repobilityId": "419a78cb18efd3de", "scanner": "scanner-primary", "fingerprint": "115debc270d44c0e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "cursor_rule"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".cursor/rules/daatan.mdc"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-c9572b4bcc98408f", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: screenshot-checker/SKILL.md"}, "properties": {"repobilityId": "77a359c1b039f652", "scanner": "scanner-primary", "fingerprint": "c9572b4bcc98408f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "skill_file"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "screenshot-checker/SKILL.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-122f91b7f2906dc4", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/settings.json"}, "properties": {"repobilityId": "a2967269048b6a9d", "scanner": "scanner-primary", "fingerprint": "122f91b7f2906dc4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/settings.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-719cbc90b8bb701f", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 scripts/render-esperanto-slides-pdf.py:43"}, "properties": {"repobilityId": "6745b29baffd8b00", "scanner": "scanner-primary", "fingerprint": "719cbc90b8bb701f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-15a19c724d03f8ad", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/page.tsx:37"}, "properties": {"repobilityId": "3aa895e8c58b23da", "scanner": "scanner-primary", "fingerprint": "15a19c724d03f8ad", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-799926fd0531a239", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/app/api/forecasts/[id]/context/route.ts:88"}, "properties": {"repobilityId": "35f0d2aeaa8c25bf", "scanner": "scanner-primary", "fingerprint": "799926fd0531a239", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b0276ded66d409d8", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/app/api/news-indexer/context/route.ts:26"}, "properties": {"repobilityId": "1f24bcea45058541", "scanner": "scanner-primary", "fingerprint": "b0276ded66d409d8", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1872ef81f7647ae5", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/telegram/rollback/route.ts:37"}, "properties": {"repobilityId": "cdb1d1b569a20c22", "scanner": "scanner-primary", "fingerprint": "1872ef81f7647ae5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-fdfe72f53bb02ae0", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/forecasts/[id]/ForecastDetailClient.tsx:173"}, "properties": {"repobilityId": "f17bcc1d887eefd4", "scanner": "scanner-primary", "fingerprint": "fdfe72f53bb02ae0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-bb632a7473773e83", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/forecasts/express/ExpressForecastClient.tsx:266"}, "properties": {"repobilityId": "0fbd3356a58d77dc", "scanner": "scanner-primary", "fingerprint": "bb632a7473773e83", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c92a6912e3d27b41", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/BotsTable.tsx:121"}, "properties": {"repobilityId": "128e24dfb3e34310", "scanner": "scanner-primary", "fingerprint": "c92a6912e3d27b41", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-48b42bdce01e5d6e", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/BackfillTagsButton.tsx:20"}, "properties": {"repobilityId": "68134c43c0e34384", "scanner": "scanner-primary", "fingerprint": "48b42bdce01e5d6e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-35e73b51eae3bf9f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/AdminClient.tsx:163"}, "properties": {"repobilityId": "9e54d8a22d556aaa", "scanner": "scanner-primary", "fingerprint": "35e73b51eae3bf9f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-a1b6b59568dadcaf", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/admin/OracleTab.tsx:257"}, "properties": {"repobilityId": "12e4a5c39f848b45", "scanner": "scanner-primary", "fingerprint": "a1b6b59568dadcaf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-524ce144ad81b9af", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/ContextTimeline.tsx:170"}, "properties": {"repobilityId": "8b86520cc7c4ab68", "scanner": "scanner-primary", "fingerprint": "524ce144ad81b9af", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-fe3e54b85e657fd2", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/ForecastWizard.tsx:205"}, "properties": {"repobilityId": "f8f8a4f1bf3ae29e", "scanner": "scanner-primary", "fingerprint": "fe3e54b85e657fd2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-f35b2566f3183a0e", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/CommitmentForm.tsx:147"}, "properties": {"repobilityId": "a9d5f1d84ab46def", "scanner": "scanner-primary", "fingerprint": "f35b2566f3183a0e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-de41a2b78c875a59", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/forecasts/steps/StepNewsAnchor.tsx:142"}, "properties": {"repobilityId": "eb9afcc278602d2e", "scanner": "scanner-primary", "fingerprint": "de41a2b78c875a59", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-91924bf20ba51945", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/profile/ProfileEditForm.tsx:98"}, "properties": {"repobilityId": "36d4e37f66efc558", "scanner": "scanner-primary", "fingerprint": "91924bf20ba51945", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d10d19f9a5e520b1", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/ibi/IbiTool.tsx:117"}, "properties": {"repobilityId": "352f04b76aead32c", "scanner": "scanner-primary", "fingerprint": "d10d19f9a5e520b1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-40ee123010c81a08", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/comments/CommentItem.tsx:92"}, "properties": {"repobilityId": "261a02c34e4ac302", "scanner": "scanner-primary", "fingerprint": "40ee123010c81a08", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-1675ba8eec34a042", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/llm/providers/openrouter.ts:39"}, "properties": {"repobilityId": "c5c2303353203e42", "scanner": "scanner-primary", "fingerprint": "1675ba8eec34a042", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-5f1e5ec8f39827d8", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/utils/scraper.ts:115"}, "properties": {"repobilityId": "db39256df1cb65f8", "scanner": "scanner-primary", "fingerprint": "5f1e5ec8f39827d8", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-f6b905530beef343", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/hooks/usePushSubscription.ts:64"}, "properties": {"repobilityId": "26b9e8defb0c6e02", "scanner": "scanner-primary", "fingerprint": "f6b905530beef343", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-422a01fdc049b9f6", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/services/oracleClient.ts:108"}, "properties": {"repobilityId": "d6788bf790c7e8f4", "scanner": "scanner-primary", "fingerprint": "422a01fdc049b9f6", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-57a05336c57bbe92", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/services/indexnow.ts:11"}, "properties": {"repobilityId": "4151375f73a805a1", "scanner": "scanner-primary", "fingerprint": "57a05336c57bbe92", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-55b00bcaf370f715", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/lib/services/bots/voting.ts:14"}, "properties": {"repobilityId": "61deb19e97a90fc1", "scanner": "scanner-primary", "fingerprint": "55b00bcaf370f715", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-671b6b11038a98b6", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/lib/services/__tests__/oracle.test.ts:21"}, "properties": {"repobilityId": "cf3a62ac869d9980", "scanner": "scanner-primary", "fingerprint": "671b6b11038a98b6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-f9f97ea946ca8c8a", "level": "none", "message": {"text": "Commented-code block (6 lines) in infra/mail-forwarder/index.mjs:12"}, "properties": {"repobilityId": "367876182adf9858", "scanner": "scanner-primary", "fingerprint": "f9f97ea946ca8c8a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-35632ad8f04f73a2", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 __tests__/lib/express-prediction-url.test.ts:144"}, "properties": {"repobilityId": "9516de750146d7f4", "scanner": "scanner-primary", "fingerprint": "35632ad8f04f73a2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-99c0f46afb2ebacc", "level": "none", "message": {"text": "Commented-code block (6 lines) in __tests__/services/bot-runner.test.ts:1596"}, "properties": {"repobilityId": "8e9e5fe09c8c4a66", "scanner": "scanner-primary", "fingerprint": "99c0f46afb2ebacc", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e64ca466000bdd1d", "level": "none", "message": {"text": "Commented-code block (6 lines) in __tests__/config/middleware-routing.test.ts:125"}, "properties": {"repobilityId": "be6eb0800d560ea9", "scanner": "scanner-primary", "fingerprint": "e64ca466000bdd1d", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1662ae7a5bb4e048", "level": "note", "message": {"text": "33 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "90293c220e284644", "scanner": "scanner-primary", "fingerprint": "1662ae7a5bb4e048", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}]}]}