{"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-3c0f43772efebd30", "name": "Stray `console.log` in TS/JS \u2014 scripts/migrate-to-sqlite.ts:36", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/migrate-to-sqlite.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-7cf14c5f749ab8be", "name": "Stray `console.log` in TS/JS \u2014 scripts/cron-runner.ts:40", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/cron-runner.ts:40"}, "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-933ccaa37bfdce64", "name": "Stray `console.log` in TS/JS \u2014 scripts/import-spreadsheet.ts:35", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/import-spreadsheet.ts:35"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ac5000555c8ed87b", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/Marketing/MarketingPlanPage.tsx:22", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/Marketing/MarketingPlanPage.tsx:22"}, "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-1d1815e215f804c7", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/Dashboard/ActivityLog.tsx:121", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Dashboard/ActivityLog.tsx:121"}, "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-3de1c55fde74526c", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/Dashboard/NotificationsPanel.tsx:303", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Dashboard/NotificationsPanel.tsx:303"}, "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-091bfd4f69030445", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/Dashboard/ProposalCard.tsx:263", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Dashboard/ProposalCard.tsx:263"}, "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-014d26f837293edc", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/MarketingStep.tsx:523", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/MarketingStep.tsx:523"}, "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-ede95298457197d2", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/ReviewGenerateStep.tsx:340", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/ReviewGenerateStep.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-370cceddfd9c137b", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/ForSalePropertiesStep.tsx:1167", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/ForSalePropertiesStep.tsx:1167"}, "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-b149969c083a0cdf", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/SoldPropertiesStep.tsx:1874", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/SoldPropertiesStep.tsx:1874"}, "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-70e61db3338ae85b", "name": "Stray `console.log` in TS/JS \u2014 src/components/Wizard/steps/SoldPropertiesStep.tsx:766", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/components/Wizard/steps/SoldPropertiesStep.tsx:766"}, "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-fb17e59a3f496885", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/ComparablesStep.tsx:1409", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/ComparablesStep.tsx:1409"}, "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-9cd837371df44794", "name": "Stray `console.log` in TS/JS \u2014 src/app/page.tsx:557", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/app/page.tsx:557"}, "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-b4e9ec16e743b7ea", "name": "Stray `console.log` in TS/JS \u2014 src/app/api/proposals/route.ts:149", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/app/api/proposals/route.ts:149"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1875f7765ed3ae4d", "name": "Stray `console.log` in TS/JS \u2014 src/app/api/comparables/route.ts:33", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/app/api/comparables/route.ts:33"}, "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-eb258e39cb7fa34f", "name": "Stray `console.log` in TS/JS \u2014 src/app/api/cache/route.ts:23", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/app/api/cache/route.ts:23"}, "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-caff7318de7ce75c", "name": "Stray `console.log` in TS/JS \u2014 src/app/api/scrape-sold/route.ts:29", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/app/api/scrape-sold/route.ts:29"}, "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-8afe3fad067e4727", "name": "Stray `console.log` in TS/JS \u2014 src/app/api/approve/route.ts:38", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/app/api/approve/route.ts:38"}, "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-63914ccf8dfbaade", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/edit/[id]/page.tsx:851", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/edit/[id]/page.tsx:851"}, "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-a8d3b2d8e9daeffe", "name": "Stray `console.log` in TS/JS \u2014 src/lib/email-intake.ts:213", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/email-intake.ts:213"}, "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-68c703e2d20f64d5", "name": "Stray `console.log` in TS/JS \u2014 src/lib/firecrawl-scraper.ts:444", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/firecrawl-scraper.ts:444"}, "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-8cbd40d1ed3dbbd2", "name": "Stray `console.log` in TS/JS \u2014 src/lib/apify-scraper.ts:85", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/apify-scraper.ts:85"}, "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-83708c9f2854990f", "name": "Stray `console.log` in TS/JS \u2014 src/lib/email.ts:112", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/email.ts:112"}, "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-3fdc40744902c0be", "name": "Stray `console.log` in TS/JS \u2014 src/lib/rental-scraper.ts:157", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/rental-scraper.ts:157"}, "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-7a022f62d9b1d60e", "name": "Stray `console.log` in TS/JS \u2014 src/lib/agent-scraper.ts:133", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/agent-scraper.ts:133"}, "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-9d9d4b119dbe1216", "name": "Stray `console.log` in TS/JS \u2014 src/lib/cache-refresh.ts:49", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/cache-refresh.ts:49"}, "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-e3b13471d16dc75d", "name": "Stray `console.log` in TS/JS \u2014 src/lib/geocoding.ts:159", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/geocoding.ts:159"}, "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-e7ec8f553a3dccd0", "name": "Stray `console.log` in TS/JS \u2014 src/lib/onmarket-scraper.ts:113", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/onmarket-scraper.ts:113"}, "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-aed4519d126c5ecb", "name": "Stray `console.log` in TS/JS \u2014 src/lib/nurture.ts:490", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/nurture.ts:490"}, "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-5cac6fc24964d491", "name": "Stray `console.log` in TS/JS \u2014 src/lib/comparables-lookup.ts:24", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/comparables-lookup.ts:24"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-55070d9d72b33b1c", "name": "Stray `console.log` in TS/JS \u2014 src/lib/cron.ts:101", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/cron.ts:101"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d63da3583b14afc0", "name": "Dockerfile runs as root: Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a35c6a00f751880f", "name": "Docker base image is tag-pinned but not digest-pinned: node:20-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: node:20-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-aa5acaa49eb8315b", "name": "Containers defined but no K8s/orchestration manifest found", "shortDescription": {"text": "Containers defined but no K8s/orchestration manifest found"}, "fullDescription": {"text": "Repo has Dockerfiles/compose but no Kubernetes/Nomad manifests. If the target deployment is K8s, the manifests may live in a separate ops repo."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-221aa469664df522", "name": "Insecure pattern 'dangerous_innerhtml' in src/components/Marketing/MarketingPlanPage.tsx:22", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/components/Marketing/MarketingPlanPage.tsx:22"}, "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-6372cebde0220094", "name": "No auth library detected", "shortDescription": {"text": "No auth library detected"}, "fullDescription": {"text": "The scanner did not find any standard auth library (JWT, OAuth, NextAuth, Auth0, etc.). The repo has auth/admin/session surface indicators, so auth may live in custom code, in a separate service, or be missing."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-09aaf7b2ac92e2f5", "name": "Very large file: src/components/Wizard/steps/ForSalePropertiesStep.tsx (1213 lines)", "shortDescription": {"text": "Very large file: src/components/Wizard/steps/ForSalePropertiesStep.tsx (1213 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-ad10ff965f48fdfe", "name": "Very large file: src/components/Wizard/steps/SoldPropertiesStep.tsx (1909 lines)", "shortDescription": {"text": "Very large file: src/components/Wizard/steps/SoldPropertiesStep.tsx (1909 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-3fb76139f991ae79", "name": "Very large file: src/components/Wizard/steps/ComparablesStep.tsx (1970 lines)", "shortDescription": {"text": "Very large file: src/components/Wizard/steps/ComparablesStep.tsx (1970 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-d2ba9d5e1a3137ca", "name": "Very large file: src/app/edit/[id]/page.tsx (1147 lines)", "shortDescription": {"text": "Very large file: src/app/edit/[id]/page.tsx (1147 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "2 test file(s) for 121 source file(s) (ratio 0.02). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 224 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 122 placeholder/mock markers across 15 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-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-17d866d91a7c451e", "name": "Agent instruction/config may expose a secret: CLAUDE.md", "shortDescription": {"text": "Agent instruction/config may expose a secret: CLAUDE.md"}, "fullDescription": {"text": "Agent-facing files are routinely pasted into LLM/tool contexts. Move literal tokens, keys, and passwords into a secret manager or document them as placeholders only."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-eefb933082bf4b5c", "name": "Legacy-named symbol `nLegacy` in scripts/export-missing-from-ep.mjs:89", "shortDescription": {"text": "Legacy-named symbol `nLegacy` in scripts/export-missing-from-ep.mjs:89"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f8d4afa057696b35", "name": "Commented-code block (6 lines) in scripts/export-missing-from-ep.mjs:5", "shortDescription": {"text": "Commented-code block (6 lines) in scripts/export-missing-from-ep.mjs:5"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-bb5471ae7674d92c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/export-missing-from-ep.mjs:82", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/export-missing-from-ep.mjs:82"}, "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-c1dafb5e434f10ad", "name": "Commented-code block (6 lines) in src/components/Marketing/MarketingPlanSheet.tsx:1", "shortDescription": {"text": "Commented-code block (6 lines) in src/components/Marketing/MarketingPlanSheet.tsx:1"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4d622f63377ec3cc", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/Wizard/steps/SoldPropertiesStep.tsx:388", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/Wizard/steps/SoldPropertiesStep.tsx:388"}, "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-31717b532bb8f4a5", "name": "Commented-code block (8 lines) in src/app/page.tsx:85", "shortDescription": {"text": "Commented-code block (8 lines) in src/app/page.tsx:85"}, "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-9854c0ff124c1c6f", "name": "Commented-code block (5 lines) in src/app/api/comparables/route.ts:148", "shortDescription": {"text": "Commented-code block (5 lines) in src/app/api/comparables/route.ts:148"}, "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-0cae2b5270cdced3", "name": "Commented-code block (6 lines) in src/app/api/cache/route.ts:94", "shortDescription": {"text": "Commented-code block (6 lines) in src/app/api/cache/route.ts:94"}, "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-8c9f632e2946fd4c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/edit/[id]/page.tsx:242", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/edit/[id]/page.tsx:242"}, "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-50fd371e6f166abd", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/email-intake.ts:35", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/email-intake.ts:35"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e421cad116c29c15", "name": "Commented-code block (6 lines) in src/lib/auth.ts:4", "shortDescription": {"text": "Commented-code block (6 lines) in src/lib/auth.ts:4"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-80cb8a28ec9b3f3b", "name": "Commented-code block (7 lines) in src/lib/firecrawl-scraper.ts:329", "shortDescription": {"text": "Commented-code block (7 lines) in src/lib/firecrawl-scraper.ts:329"}, "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-ec36345b76f86648", "name": "Commented-code block (6 lines) in src/lib/geocode-backfill.ts:4", "shortDescription": {"text": "Commented-code block (6 lines) in src/lib/geocode-backfill.ts:4"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-ff03b664208106fe", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/comparables-lookup.ts:311", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/comparables-lookup.ts:311"}, "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-3ae623850bf15061", "name": "Commented-code block (6 lines) in src/lib/marketing-plan.ts:4", "shortDescription": {"text": "Commented-code block (6 lines) in src/lib/marketing-plan.ts:4"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b0b5e7cb1208a7cd", "name": "13 env vars used in code but missing from .env.example", "shortDescription": {"text": "13 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `ANTHROPIC_API_KEY`, `AUTH_ALLOWED_EMAILS`, `AUTH_PASSWORD`, `AUTH_SECRET`, `CRON_SECRET`, `DATABASE_PATH`, `DATA_DIR`, `EMAIL_FROM` + 5 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/23721"}, "properties": {"repository": "zumu-g/GEA_proposals", "repoUrl": "https://github.com/zumu-g/GEA_proposals", "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-3c0f43772efebd30", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/migrate-to-sqlite.ts:36"}, "properties": {"repobilityId": "5fe497dfacd16b8a", "scanner": "scanner-primary", "fingerprint": "3c0f43772efebd30", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-7cf14c5f749ab8be", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/cron-runner.ts:40"}, "properties": {"repobilityId": "59c3e5f166314a1f", "scanner": "scanner-primary", "fingerprint": "7cf14c5f749ab8be", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-933ccaa37bfdce64", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/import-spreadsheet.ts:35"}, "properties": {"repobilityId": "db06d711990358da", "scanner": "scanner-primary", "fingerprint": "933ccaa37bfdce64", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-ac5000555c8ed87b", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/Marketing/MarketingPlanPage.tsx:22"}, "properties": {"repobilityId": "8120c7f1bc1bb702", "scanner": "scanner-primary", "fingerprint": "ac5000555c8ed87b", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-1d1815e215f804c7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Dashboard/ActivityLog.tsx:121"}, "properties": {"repobilityId": "dece205dd0607341", "scanner": "scanner-primary", "fingerprint": "1d1815e215f804c7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3de1c55fde74526c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Dashboard/NotificationsPanel.tsx:303"}, "properties": {"repobilityId": "e5047f0acbb58681", "scanner": "scanner-primary", "fingerprint": "3de1c55fde74526c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-091bfd4f69030445", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Dashboard/ProposalCard.tsx:263"}, "properties": {"repobilityId": "babe826cd7cf8969", "scanner": "scanner-primary", "fingerprint": "091bfd4f69030445", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-014d26f837293edc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/MarketingStep.tsx:523"}, "properties": {"repobilityId": "abd8ea5b08bc16e6", "scanner": "scanner-primary", "fingerprint": "014d26f837293edc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ede95298457197d2", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/ReviewGenerateStep.tsx:340"}, "properties": {"repobilityId": "7b0b93f536df09b4", "scanner": "scanner-primary", "fingerprint": "ede95298457197d2", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-370cceddfd9c137b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/ForSalePropertiesStep.tsx:1167"}, "properties": {"repobilityId": "71fe206755f342de", "scanner": "scanner-primary", "fingerprint": "370cceddfd9c137b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b149969c083a0cdf", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/SoldPropertiesStep.tsx:1874"}, "properties": {"repobilityId": "b8981b797c6597de", "scanner": "scanner-primary", "fingerprint": "b149969c083a0cdf", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-70e61db3338ae85b", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/components/Wizard/steps/SoldPropertiesStep.tsx:766"}, "properties": {"repobilityId": "26730474d003ac1c", "scanner": "scanner-primary", "fingerprint": "70e61db3338ae85b", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-fb17e59a3f496885", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/Wizard/steps/ComparablesStep.tsx:1409"}, "properties": {"repobilityId": "383822d97ccb9e16", "scanner": "scanner-primary", "fingerprint": "fb17e59a3f496885", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9cd837371df44794", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/app/page.tsx:557"}, "properties": {"repobilityId": "f6d2d4533cf9c615", "scanner": "scanner-primary", "fingerprint": "9cd837371df44794", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-b4e9ec16e743b7ea", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/app/api/proposals/route.ts:149"}, "properties": {"repobilityId": "5a127fab7ba67ead", "scanner": "scanner-primary", "fingerprint": "b4e9ec16e743b7ea", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-1875f7765ed3ae4d", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/app/api/comparables/route.ts:33"}, "properties": {"repobilityId": "faad431e67e6487c", "scanner": "scanner-primary", "fingerprint": "1875f7765ed3ae4d", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-eb258e39cb7fa34f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/app/api/cache/route.ts:23"}, "properties": {"repobilityId": "fd3d49fec5d35126", "scanner": "scanner-primary", "fingerprint": "eb258e39cb7fa34f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-caff7318de7ce75c", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/app/api/scrape-sold/route.ts:29"}, "properties": {"repobilityId": "a958633f65b0f9ec", "scanner": "scanner-primary", "fingerprint": "caff7318de7ce75c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-8afe3fad067e4727", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/app/api/approve/route.ts:38"}, "properties": {"repobilityId": "9e203ea69a529d62", "scanner": "scanner-primary", "fingerprint": "8afe3fad067e4727", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-63914ccf8dfbaade", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/edit/[id]/page.tsx:851"}, "properties": {"repobilityId": "2ea85d7e2cffb568", "scanner": "scanner-primary", "fingerprint": "63914ccf8dfbaade", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a8d3b2d8e9daeffe", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/email-intake.ts:213"}, "properties": {"repobilityId": "1370729b12646f9b", "scanner": "scanner-primary", "fingerprint": "a8d3b2d8e9daeffe", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-68c703e2d20f64d5", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/firecrawl-scraper.ts:444"}, "properties": {"repobilityId": "73c65266324b8e0f", "scanner": "scanner-primary", "fingerprint": "68c703e2d20f64d5", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-8cbd40d1ed3dbbd2", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/apify-scraper.ts:85"}, "properties": {"repobilityId": "c484cc2c085e9814", "scanner": "scanner-primary", "fingerprint": "8cbd40d1ed3dbbd2", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-83708c9f2854990f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/email.ts:112"}, "properties": {"repobilityId": "bdf73540c4990d36", "scanner": "scanner-primary", "fingerprint": "83708c9f2854990f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-3fdc40744902c0be", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/rental-scraper.ts:157"}, "properties": {"repobilityId": "0e365f320954c8fb", "scanner": "scanner-primary", "fingerprint": "3fdc40744902c0be", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-7a022f62d9b1d60e", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/agent-scraper.ts:133"}, "properties": {"repobilityId": "7c1600afbc9171be", "scanner": "scanner-primary", "fingerprint": "7a022f62d9b1d60e", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-9d9d4b119dbe1216", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/cache-refresh.ts:49"}, "properties": {"repobilityId": "3885cc59023569a1", "scanner": "scanner-primary", "fingerprint": "9d9d4b119dbe1216", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-e3b13471d16dc75d", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/geocoding.ts:159"}, "properties": {"repobilityId": "225a3eaaf2b87f3c", "scanner": "scanner-primary", "fingerprint": "e3b13471d16dc75d", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-e7ec8f553a3dccd0", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/onmarket-scraper.ts:113"}, "properties": {"repobilityId": "55992b23d76445a4", "scanner": "scanner-primary", "fingerprint": "e7ec8f553a3dccd0", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-aed4519d126c5ecb", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/nurture.ts:490"}, "properties": {"repobilityId": "a77c40120a3f0081", "scanner": "scanner-primary", "fingerprint": "aed4519d126c5ecb", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-5cac6fc24964d491", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/comparables-lookup.ts:24"}, "properties": {"repobilityId": "4a5896064bf1e077", "scanner": "scanner-primary", "fingerprint": "5cac6fc24964d491", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-55070d9d72b33b1c", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/cron.ts:101"}, "properties": {"repobilityId": "93daed9c829a86be", "scanner": "scanner-primary", "fingerprint": "55070d9d72b33b1c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-d63da3583b14afc0", "level": "warning", "message": {"text": "Dockerfile runs as root: Dockerfile"}, "properties": {"repobilityId": "a2ed1bd120e507db", "scanner": "scanner-primary", "fingerprint": "d63da3583b14afc0", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-a35c6a00f751880f", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:20-slim"}, "properties": {"repobilityId": "be924fbee382ebe0", "scanner": "scanner-primary", "fingerprint": "a35c6a00f751880f", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-aa5acaa49eb8315b", "level": "note", "message": {"text": "Containers defined but no K8s/orchestration manifest found"}, "properties": {"repobilityId": "b230ea9b68736081", "scanner": "scanner-primary", "fingerprint": "aa5acaa49eb8315b", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["coverage", "deployment"]}}, {"ruleId": "scanner-221aa469664df522", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/components/Marketing/MarketingPlanPage.tsx:22"}, "properties": {"repobilityId": "6a42ba435cbecdf0", "scanner": "scanner-primary", "fingerprint": "221aa469664df522", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/Marketing/MarketingPlanPage.tsx"}, "region": {"startLine": 22}}}]}, {"ruleId": "scanner-6372cebde0220094", "level": "warning", "message": {"text": "No auth library detected"}, "properties": {"repobilityId": "a5b6035a5bbf8054", "scanner": "scanner-primary", "fingerprint": "6372cebde0220094", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["coverage", "auth"]}}, {"ruleId": "scanner-09aaf7b2ac92e2f5", "level": "note", "message": {"text": "Very large file: src/components/Wizard/steps/ForSalePropertiesStep.tsx (1213 lines)"}, "properties": {"repobilityId": "781f6a1f66f3a252", "scanner": "scanner-primary", "fingerprint": "09aaf7b2ac92e2f5", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-ad10ff965f48fdfe", "level": "note", "message": {"text": "Very large file: src/components/Wizard/steps/SoldPropertiesStep.tsx (1909 lines)"}, "properties": {"repobilityId": "7cb873b3217e8b79", "scanner": "scanner-primary", "fingerprint": "ad10ff965f48fdfe", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-3fb76139f991ae79", "level": "note", "message": {"text": "Very large file: src/components/Wizard/steps/ComparablesStep.tsx (1970 lines)"}, "properties": {"repobilityId": "34dfee04a5d714ca", "scanner": "scanner-primary", "fingerprint": "3fb76139f991ae79", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-d2ba9d5e1a3137ca", "level": "note", "message": {"text": "Very large file: src/app/edit/[id]/page.tsx (1147 lines)"}, "properties": {"repobilityId": "a2fade51ccc7c95a", "scanner": "scanner-primary", "fingerprint": "d2ba9d5e1a3137ca", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-6893a6c8b0861585", "level": "warning", "message": {"text": "Very low test-to-source ratio"}, "properties": {"repobilityId": "54a7de3f06314bf0", "scanner": "scanner-primary", "fingerprint": "6893a6c8b0861585", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "coverage"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "494da9ca2de36440", "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": "95b26e74cb47de18", "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": "220f752a49a5e79e", "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": "9c2f9742909af362", "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": "a0971d4e11f52d92", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "a405dbd73931d041", "scanner": "scanner-primary", "fingerprint": "ea8f3013f588db25", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-8424db9c75e04ba4", "level": "none", "message": {"text": "Very short observed git history"}, "properties": {"repobilityId": "016ec7a0fccb6de3", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-17d866d91a7c451e", "level": "error", "message": {"text": "Agent instruction/config may expose a secret: CLAUDE.md"}, "properties": {"repobilityId": "ccce5984e58a48f0", "scanner": "scanner-primary", "fingerprint": "17d866d91a7c451e", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["agent-instructions", "secrets", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "CLAUDE.md"}, "region": {"startLine": 68}}}]}, {"ruleId": "scanner-eefb933082bf4b5c", "level": "note", "message": {"text": "Legacy-named symbol `nLegacy` in scripts/export-missing-from-ep.mjs:89"}, "properties": {"repobilityId": "5dfb6e453dd7c7c3", "scanner": "scanner-primary", "fingerprint": "eefb933082bf4b5c", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-f8d4afa057696b35", "level": "none", "message": {"text": "Commented-code block (6 lines) in scripts/export-missing-from-ep.mjs:5"}, "properties": {"repobilityId": "a9da5e4c424fde49", "scanner": "scanner-primary", "fingerprint": "f8d4afa057696b35", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-bb5471ae7674d92c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/export-missing-from-ep.mjs:82"}, "properties": {"repobilityId": "416957bfdba49021", "scanner": "scanner-primary", "fingerprint": "bb5471ae7674d92c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c1dafb5e434f10ad", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/components/Marketing/MarketingPlanSheet.tsx:1"}, "properties": {"repobilityId": "7dcedb8184b8a690", "scanner": "scanner-primary", "fingerprint": "c1dafb5e434f10ad", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4d622f63377ec3cc", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/components/Wizard/steps/SoldPropertiesStep.tsx:388"}, "properties": {"repobilityId": "789c658a7d47e95f", "scanner": "scanner-primary", "fingerprint": "4d622f63377ec3cc", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-31717b532bb8f4a5", "level": "none", "message": {"text": "Commented-code block (8 lines) in src/app/page.tsx:85"}, "properties": {"repobilityId": "42a313c7ce52f37a", "scanner": "scanner-primary", "fingerprint": "31717b532bb8f4a5", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-9854c0ff124c1c6f", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/app/api/comparables/route.ts:148"}, "properties": {"repobilityId": "8db0fdfae1f4ba9f", "scanner": "scanner-primary", "fingerprint": "9854c0ff124c1c6f", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-0cae2b5270cdced3", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/app/api/cache/route.ts:94"}, "properties": {"repobilityId": "b32ca282d2a30212", "scanner": "scanner-primary", "fingerprint": "0cae2b5270cdced3", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8c9f632e2946fd4c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/edit/[id]/page.tsx:242"}, "properties": {"repobilityId": "1cbeec972b86df54", "scanner": "scanner-primary", "fingerprint": "8c9f632e2946fd4c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-50fd371e6f166abd", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/email-intake.ts:35"}, "properties": {"repobilityId": "f94aeca2ded8a310", "scanner": "scanner-primary", "fingerprint": "50fd371e6f166abd", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e421cad116c29c15", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/lib/auth.ts:4"}, "properties": {"repobilityId": "295e394221f35adf", "scanner": "scanner-primary", "fingerprint": "e421cad116c29c15", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-80cb8a28ec9b3f3b", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/lib/firecrawl-scraper.ts:329"}, "properties": {"repobilityId": "a9edd8a4f2d4ddcf", "scanner": "scanner-primary", "fingerprint": "80cb8a28ec9b3f3b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-ec36345b76f86648", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/lib/geocode-backfill.ts:4"}, "properties": {"repobilityId": "010e158e3e3f25fd", "scanner": "scanner-primary", "fingerprint": "ec36345b76f86648", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-ff03b664208106fe", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/comparables-lookup.ts:311"}, "properties": {"repobilityId": "c334a9bb20455519", "scanner": "scanner-primary", "fingerprint": "ff03b664208106fe", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3ae623850bf15061", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/lib/marketing-plan.ts:4"}, "properties": {"repobilityId": "931c78d0b6af03a9", "scanner": "scanner-primary", "fingerprint": "3ae623850bf15061", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b0b5e7cb1208a7cd", "level": "note", "message": {"text": "13 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "2737b8666c1f7eeb", "scanner": "scanner-primary", "fingerprint": "b0b5e7cb1208a7cd", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}]}]}