{"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-1e04fa5a4b844904", "name": "Possibly dead Python function: init_supabase", "shortDescription": {"text": "Possibly dead Python function: init_supabase"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e57e3f705a685159", "name": "Possibly dead Python function: setup_error_handlers", "shortDescription": {"text": "Possibly dead Python function: setup_error_handlers"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8e9f6a30ffd397a7", "name": "Possibly dead Python function: create_default_compatibility_mappings", "shortDescription": {"text": "Possibly dead Python function: create_default_compatibility_mappings"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b986a110fb8d0455", "name": "Possibly dead Python function: check_suspicious", "shortDescription": {"text": "Possibly dead Python function: check_suspicious"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-10a4ddfb0a43c51a", "name": "Possibly dead Python function: mark_suspicious", "shortDescription": {"text": "Possibly dead Python function: mark_suspicious"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6e811f4663fe6df1", "name": "Possibly dead Python function: rate_limit", "shortDescription": {"text": "Possibly dead Python function: rate_limit"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-eceb460d72e47f1e", "name": "Possibly dead Python function: decorator", "shortDescription": {"text": "Possibly dead Python function: decorator"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ebd0a68bfdd77ffa", "name": "Possibly dead Python function: check_budget", "shortDescription": {"text": "Possibly dead Python function: check_budget"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d6e69265f43bf1c6", "name": "Possibly dead Python function: project_hero_image", "shortDescription": {"text": "Possibly dead Python function: project_hero_image"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b05a1a49e6ca7549", "name": "Possibly dead Python function: project_grid_3col", "shortDescription": {"text": "Possibly dead Python function: project_grid_3col"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-89788762ab7131b1", "name": "Possibly dead Python function: project_plan_section", "shortDescription": {"text": "Possibly dead Python function: project_plan_section"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d671470a772ad2f1", "name": "Possibly dead Python function: project_asymmetric", "shortDescription": {"text": "Possibly dead Python function: project_asymmetric"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0f46d65689c0c4d6", "name": "Possibly dead Python function: project_masonry", "shortDescription": {"text": "Possibly dead Python function: project_masonry"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2e7e22b902f9f5e2", "name": "Possibly dead Python function: project_fullbleed", "shortDescription": {"text": "Possibly dead Python function: project_fullbleed"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b22f88d51bbc10db", "name": "Possibly dead Python function: project_two_col_text", "shortDescription": {"text": "Possibly dead Python function: project_two_col_text"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-23ae23518e4a18d9", "name": "Possibly dead Python function: project_gallery_wall", "shortDescription": {"text": "Possibly dead Python function: project_gallery_wall"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-bdb5cb116a3ae1ab", "name": "Possibly dead Python function: project_blueprint", "shortDescription": {"text": "Possibly dead Python function: project_blueprint"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-db0e2b6aaabf99f7", "name": "Possibly dead Python function: project_story_timeline", "shortDescription": {"text": "Possibly dead Python function: project_story_timeline"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6270c5f7701d9d63", "name": "Possibly dead Python function: create_upload_session", "shortDescription": {"text": "Possibly dead Python function: create_upload_session"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1707d30b4869522e", "name": "Possibly dead Python function: upload_chunk", "shortDescription": {"text": "Possibly dead Python function: upload_chunk"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-53e220b4ac0f7554", "name": "Possibly dead Python function: complete_resumable_upload", "shortDescription": {"text": "Possibly dead Python function: complete_resumable_upload"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-558de36b3dd1f76b", "name": "Possibly dead Python function: cleanup_expired_sessions", "shortDescription": {"text": "Possibly dead Python function: cleanup_expired_sessions"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-28a6e9e83d8018ef", "name": "Possibly dead Python function: verify_checksum", "shortDescription": {"text": "Possibly dead Python function: verify_checksum"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ff23ac8700319db1", "name": "Stray `console.log` in TS/JS \u2014 scripts/import-templates.js:25", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/import-templates.js:25"}, "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-41c5bed21896aab2", "name": "Stray `console.log` in TS/JS \u2014 scripts/setup-tables.js:17", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/setup-tables.js:17"}, "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-4c84e2fb57e9c7e0", "name": "Stray `console.log` in TS/JS \u2014 scripts/import-direct.js:14", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/import-direct.js:14"}, "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-dd7751afa9019edb", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/project/[id]/sheet-set/page.tsx:133", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/project/[id]/sheet-set/page.tsx:133"}, "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-23b9a83c933729f2", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/project/[id]/portfolio/[portfolioId]/pag", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/project/[id]/portfolio/[portfolioId]/page.tsx:477"}, "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-8c6364e97fb210ba", "name": "Stray `console.log` in TS/JS \u2014 frontend/src/app/dashboard/project/[id]/portfolio/[portfolioId]/page.tsx:549", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 frontend/src/app/dashboard/project/[id]/portfolio/[portfolioId]/page.tsx:549"}, "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-6e4a134e4d46f7c2", "name": "Icon-only button without accessible name \u2014 frontend/src/app/dashboard/tools/cv/page.tsx:310", "shortDescription": {"text": "Icon-only button without accessible name \u2014 frontend/src/app/dashboard/tools/cv/page.tsx:310"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8332388a512d4b80", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/cv/page.tsx:375", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/cv/page.tsx:375"}, "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-01f8a6302b373584", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/concept-diagram/page.tsx:679", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/concept-diagram/page.tsx:679"}, "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-2e1b49c7c1a35856", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/site-analysis/page.tsx:325", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/site-analysis/page.tsx:325"}, "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-c60a9f20f55f51ef", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/tools/scale-north/page.tsx:165", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/tools/scale-north/page.tsx:165"}, "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-a68c4b0cdc766cd9", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/scale-north/page.tsx:141", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/scale-north/page.tsx:141"}, "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-7e31c2beff81c0b3", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/tools/entourage/page.tsx:287", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/tools/entourage/page.tsx:287"}, "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-919582c73648e9a0", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/entourage/page.tsx:286", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/entourage/page.tsx:286"}, "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-5f630131befc2042", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/templates/[id]/editor/page.tsx:872", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/templates/[id]/editor/page.tsx:872"}, "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-2444ac24d0b54cc8", "name": "Stray `console.log` in TS/JS \u2014 frontend/src/app/dashboard/templates/[id]/editor/page.tsx:930", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 frontend/src/app/dashboard/templates/[id]/editor/page.tsx:930"}, "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-f6e9202530baf0e4", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/library/page.tsx:151", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/library/page.tsx:151"}, "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-77e9761fa79c62a5", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/my-portfolios/page.tsx:205", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/my-portfolios/page.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-4737cb413d0156da", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/p/[slug]/page.tsx:127", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/p/[slug]/page.tsx:127"}, "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-d698a073da137c21", "name": "Icon-only button without accessible name \u2014 frontend/src/components/Modal.tsx:60", "shortDescription": {"text": "Icon-only button without accessible name \u2014 frontend/src/components/Modal.tsx:60"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-af07a89616ca19ec", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/design-system/StylePackGallery.tsx:242", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/design-system/StylePackGallery.tsx:242"}, "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-661514ccfb754e61", "name": "Icon-only button without accessible name \u2014 frontend/src/components/AssetManager/AssetManager.tsx:367", "shortDescription": {"text": "Icon-only button without accessible name \u2014 frontend/src/components/AssetManager/AssetManager.tsx:367"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-620367e7032d5875", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/AssetManager/AssetGridView.tsx:82", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/AssetManager/AssetGridView.tsx:82"}, "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-7c1da6109936f161", "name": "Icon-only button without accessible name \u2014 frontend/src/components/AssetManager/AssetVersionHistory.tsx:93", "shortDescription": {"text": "Icon-only button without accessible name \u2014 frontend/src/components/AssetManager/AssetVersionHistory.tsx:93"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0d5a4c94c75e47b3", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/drawingProcessor/DrawingProcessor.tsx:463", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/drawingProcessor/DrawingProcessor.tsx:463"}, "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-4ccb06b3b7df10f3", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/templates/TemplateMockup.tsx:49", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/templates/TemplateMockup.tsx:49"}, "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-597785c80d0c0553", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/library/LibraryUpload.tsx:164", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/library/LibraryUpload.tsx:164"}, "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-0662341d51b37264", "name": "Icon-only button without accessible name \u2014 frontend/src/components/ThemeManager/ThemeManager.tsx:376", "shortDescription": {"text": "Icon-only button without accessible name \u2014 frontend/src/components/ThemeManager/ThemeManager.tsx:376"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e5bc3723f06466db", "name": "Icon-only button without accessible name \u2014 frontend/src/components/siteAnalysis/MapAnnotator.tsx:192", "shortDescription": {"text": "Icon-only button without accessible name \u2014 frontend/src/components/siteAnalysis/MapAnnotator.tsx:192"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-11d404c0925001aa", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/siteAnalysis/MapAnnotator.tsx:349", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/siteAnalysis/MapAnnotator.tsx:349"}, "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-63e4a527b17f8a83", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetCanvas.tsx:188", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetCanvas.tsx:188"}, "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-7ffdb47e0eb192cc", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetEditor.tsx:214", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetEditor.tsx:214"}, "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-3ee9082f242a4b2b", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetEntouragePanel.tsx:127", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetEntouragePanel.tsx:127"}, "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-82ad53808b07272b", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/sheetSet/SheetSetEntouragePanel.tsx:126", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/sheetSet/SheetSetEntouragePanel.tsx:126"}, "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-61f98353942fc773", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetProperties.tsx:64", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetProperties.tsx:64"}, "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-7bb44abbc867d567", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetNavigator.tsx:94", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetNavigator.tsx:94"}, "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-f854e1383f84d1a0", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/portfolio-wizard/PortfolioWizard.tsx:493", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/portfolio-wizard/PortfolioWizard.tsx:493"}, "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-3ed3cdd8cf509cd4", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/SheetEditor/SheetEditor.tsx:720", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/SheetEditor/SheetEditor.tsx:720"}, "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-6fca92c2f6c7ec09", "name": "Stray `console.log` in TS/JS \u2014 frontend/src/lib/firebase.ts:165", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 frontend/src/lib/firebase.ts:165"}, "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-e066691601852931", "name": "Docker base image is tag-pinned but not digest-pinned: python:3.11-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.11-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-1f66ad88286ca30a", "name": "Dockerfile runs as root: backend/Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: backend/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-8cd20d539467d2c5", "name": "Docker base image is tag-pinned but not digest-pinned: python:3.11-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.11-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-2f717fe6d96535f7", "name": "Runtime dotenv file present in repo: backend/.env.production", "shortDescription": {"text": "Runtime dotenv file present in repo: backend/.env.production"}, "fullDescription": {"text": "`backend/.env.production` looks like a runtime dotenv file. It contains secret-looking assignments for SECRET_KEY, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, REPLICATE_API_TOKEN. Move real values to a secret manager and keep only `.env.example` style templates in source control."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-2b76d6e41839a257", "name": "Possible secret in netlify.toml", "shortDescription": {"text": "Possible secret in netlify.toml"}, "fullDescription": {"text": "Detected pattern matching generic_api_key. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-9827255a94b0b676", "name": "Insecure pattern 'cors_wildcard' in backend/main.py:32", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in backend/main.py:32"}, "fullDescription": {"text": "Found a known-risky pattern (cors_wildcard). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-5ea795ffa541ea47", "name": "Insecure pattern 'cors_wildcard' in backend/middleware/cache_headers.py:153", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in backend/middleware/cache_headers.py:153"}, "fullDescription": {"text": "Found a known-risky pattern (cors_wildcard). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0416036ae120bf78", "name": "Insecure pattern 'document_write' in frontend/src/app/dashboard/project/[id]/sheet/page.tsx:343", "shortDescription": {"text": "Insecure pattern 'document_write' in frontend/src/app/dashboard/project/[id]/sheet/page.tsx:343"}, "fullDescription": {"text": "Found a known-risky pattern (document_write). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2b7146e6f5f804fe", "name": "Insecure pattern 'document_write' in frontend/src/app/dashboard/project/[id]/sheet/editor/page.tsx:42", "shortDescription": {"text": "Insecure pattern 'document_write' in frontend/src/app/dashboard/project/[id]/sheet/editor/page.tsx:42"}, "fullDescription": {"text": "Found a known-risky pattern (document_write). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f5dca1d923f61624", "name": "Insecure pattern 'document_write' in frontend/src/app/dashboard/tools/cv/page.tsx:220", "shortDescription": {"text": "Insecure pattern 'document_write' in frontend/src/app/dashboard/tools/cv/page.tsx:220"}, "fullDescription": {"text": "Found a known-risky pattern (document_write). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "low", "confidence": 1.0}}, {"id": "scanner-535a5713b49f3587", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/cv/page.tsx:375", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/cv/page.tsx:375"}, "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-bbfa707bbeb59dea", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/concept-diagram/page.tsx:679", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/concept-diagram/page.tsx:679"}, "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-05879112a67ad6b5", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/site-analysis/page.tsx:325", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/site-analysis/page.tsx:325"}, "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-fcafbd7e0f7c8245", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/scale-north/page.tsx:141", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/scale-north/page.tsx:141"}, "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-eaff8e95eced732c", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/entourage/page.tsx:286", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/entourage/page.tsx:286"}, "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-0566da75dec38a0d", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/siteAnalysis/MapAnnotator.tsx:349", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/siteAnalysis/MapAnnotator.tsx:349"}, "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-a8a017861c57bb80", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/sheetSet/SheetSetEntouragePanel.tsx:126", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/sheetSet/SheetSetEntouragePanel.tsx:126"}, "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-01097688535ac3bd", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/SheetEditor/SheetEditor.tsx:720", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/SheetEditor/SheetEditor.tsx:720"}, "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-5b93e9dda7c31402", "name": "Insecure pattern 'local_storage_auth_token' in frontend/src/store/auth.ts:37", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/src/store/auth.ts:37"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e0f646c6a4f17ab1", "name": "Insecure pattern 'local_storage_auth_token' in frontend/src/lib/api.ts:34", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/src/lib/api.ts:34"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-c47b2aed1a1c2af7", "name": "Very large file: backend/services/portfolio_renderer.py (933 lines)", "shortDescription": {"text": "Very large file: backend/services/portfolio_renderer.py (933 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-15e5f3e3893debd2", "name": "Very large file: frontend/src/app/dashboard/templates/[id]/editor/page.tsx (1215 lines)", "shortDescription": {"text": "Very large file: frontend/src/app/dashboard/templates/[id]/editor/page.tsx (1215 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": "7 test file(s) for 229 source file(s) (ratio 0.03). 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 245 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 175 placeholder/mock markers across 51 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-2c5f98b152cddb6d", "name": "Agent authority lacks a verifier contract: .claude/launch.json", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/launch.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-505bc666a82f9849", "name": "Agent instruction/config may expose a secret: .claude/settings.local.json", "shortDescription": {"text": "Agent instruction/config may expose a secret: .claude/settings.local.json"}, "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-d990fd6d84724353", "name": "Commented-code block (7 lines) in backend/tests/test_auth.py:16", "shortDescription": {"text": "Commented-code block (7 lines) in backend/tests/test_auth.py:16"}, "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-6cd57c91ad4fc845", "name": "Legacy-named symbol `list_objects_v2` in backend/services/storage.py:467", "shortDescription": {"text": "Legacy-named symbol `list_objects_v2` in backend/services/storage.py:467"}, "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-8728eb3412e0cf4c", "name": "Blocking `requests.post(...)` inside `async def register` \u2014 backend/routes/auth.py:125", "shortDescription": {"text": "Blocking `requests.post(...)` inside `async def register` \u2014 backend/routes/auth.py:125"}, "fullDescription": {"text": "Sync I/O inside an async function blocks the event loop. While `requests.post(...)` is running, *all* other coroutines on this loop are paused \u2014 silent throughput collapse under concurrency. Use the async equivalent (`httpx.AsyncClient`, `asyncio.sleep`, `aiofiles`) or wrap with `await asyncio.to_thread(...)`."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "high", "confidence": 1.0}}, {"id": "scanner-904f9c4505127869", "name": "Blocking `requests.post(...)` inside `async def signin` \u2014 backend/routes/auth.py:209", "shortDescription": {"text": "Blocking `requests.post(...)` inside `async def signin` \u2014 backend/routes/auth.py:209"}, "fullDescription": {"text": "Sync I/O inside an async function blocks the event loop. While `requests.post(...)` is running, *all* other coroutines on this loop are paused \u2014 silent throughput collapse under concurrency. Use the async equivalent (`httpx.AsyncClient`, `asyncio.sleep`, `aiofiles`) or wrap with `await asyncio.to_thread(...)`."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "high", "confidence": 1.0}}, {"id": "scanner-06520f59734ac6c3", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/project/[id]/generate/page.tsx:97", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/project/[id]/generate/page.tsx:97"}, "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-f49e23f336672c07", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/project/[id]/portfolio/[portfolioId]/page.tsx:1", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/project/[id]/portfolio/[portfolioId]/page.tsx:134"}, "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-c64d51c7afb396ab", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/templates/page.tsx:793", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/templates/page.tsx:793"}, "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-16cf65689e818b04", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/templates/[id]/editor/page.tsx:202", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/templates/[id]/editor/page.tsx:202"}, "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-f751d851ee4c214c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/portfolio-book/[id]/page.tsx:53", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/portfolio-book/[id]/page.tsx:53"}, "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-4b96339e87f85986", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/portfolio-wizard/PortfolioWizard.tsx:94", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/portfolio-wizard/PortfolioWizard.tsx:94"}, "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-3d9ebb726694fa34", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/PortfolioPreview/PortfolioPreview.tsx:126", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/PortfolioPreview/PortfolioPreview.tsx:126"}, "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-3caeeca7d6fe267b", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/presentationExport.ts:242", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/presentationExport.ts: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-be761bc8a3756bf4", "name": "Commented-code block (5 lines) in frontend/src/lib/assetTaxonomy.ts:139", "shortDescription": {"text": "Commented-code block (5 lines) in frontend/src/lib/assetTaxonomy.ts:139"}, "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-734233e12427b0f6", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/firebase.ts:44", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/firebase.ts:44"}, "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-022e6399d1ef2beb", "name": "12 env vars used in code but missing from .env.example", "shortDescription": {"text": "12 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `DEFAULT_ENTITLEMENTS_GRANT_ALL`, `ENABLE_VISION_TAGGING`, `FIREBASE_SERVICE_ACCOUNT_KEY`, `NEXT_PUBLIC_FIREBASE_API_KEY`, `NEXT_PUBLIC_FIREBASE_APP_ID`, `NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN`, `NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID`, `NEXT_PUBLIC_FIREBASE_PROJECT_ID` + 4 more. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-33a6b62e30ce7ab4", "name": "Near-duplicate function bodies in 6 places", "shortDescription": {"text": "Near-duplicate function bodies in 6 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/error_handlers.py:validation_exception_handler, backend/error_handlers.py:auth_exception_handler, backend/error_handlers.py:authz_exception_handler, backend/error_handlers.py:notfound_exception_handler\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2c04133e54348533", "name": "Near-duplicate function bodies in 2 places", "shortDescription": {"text": "Near-duplicate function bodies in 2 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/middleware/security.py:dispatch, backend/middleware/security.py:dispatch\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-be46ea126aa5d8dc", "name": "Near-duplicate function bodies in 3 places", "shortDescription": {"text": "Near-duplicate function bodies in 3 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/routes/design_system.py:analyze_design_system, backend/routes/design_system.py:export_as_css, backend/routes/design_system.py:export_as_json\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-49c98f7cedd9c977", "name": "Near-duplicate function bodies in 4 places", "shortDescription": {"text": "Near-duplicate function bodies in 4 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/routes/sheets.py:generate_title, backend/routes/sheets.py:generate_description, backend/routes/sheets.py:generate_narrative, backend/routes/sheets.py:generate_jury_script\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-eb95fa72de198534", "name": "FastAPI PUT `save_document` without auth dependency \u2014 backend/routes/documents.py:32", "shortDescription": {"text": "FastAPI PUT `save_document` without auth dependency \u2014 backend/routes/documents.py:32"}, "fullDescription": {"text": "`@router.put` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-c0a3aaa78c16da68", "name": "FastAPI POST `check_storage_health` without auth dependency \u2014 backend/routes/documents.py:64", "shortDescription": {"text": "FastAPI POST `check_storage_health` without auth dependency \u2014 backend/routes/documents.py:64"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-2a3d52498ae8e873", "name": "FastAPI POST `export_document_as_pdf` without auth dependency \u2014 backend/routes/documents.py:85", "shortDescription": {"text": "FastAPI POST `export_document_as_pdf` without auth dependency \u2014 backend/routes/documents.py:85"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-dd1fb7c01f2a0661", "name": "FastAPI POST `create_project` without auth dependency \u2014 backend/routes/projects.py:23", "shortDescription": {"text": "FastAPI POST `create_project` without auth dependency \u2014 backend/routes/projects.py:23"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-c99e306eadd8b4b1", "name": "FastAPI PUT `update_project` without auth dependency \u2014 backend/routes/projects.py:55", "shortDescription": {"text": "FastAPI PUT `update_project` without auth dependency \u2014 backend/routes/projects.py:55"}, "fullDescription": {"text": "`@router.put` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-5c45e862ed6b181d", "name": "FastAPI DELETE `delete_project` without auth dependency \u2014 backend/routes/projects.py:68", "shortDescription": {"text": "FastAPI DELETE `delete_project` without auth dependency \u2014 backend/routes/projects.py:68"}, "fullDescription": {"text": "`@router.delete` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-a8c71168b107f9ce", "name": "FastAPI POST `analyze_project_assets` without auth dependency \u2014 backend/routes/projects.py:78", "shortDescription": {"text": "FastAPI POST `analyze_project_assets` without auth dependency \u2014 backend/routes/projects.py:78"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-720b6e3da5b485da", "name": "FastAPI POST `publish_project` without auth dependency \u2014 backend/routes/projects.py:108", "shortDescription": {"text": "FastAPI POST `publish_project` without auth dependency \u2014 backend/routes/projects.py:108"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-9a714be8c6d1ade4", "name": "FastAPI POST `unpublish_project` without auth dependency \u2014 backend/routes/projects.py:142", "shortDescription": {"text": "FastAPI POST `unpublish_project` without auth dependency \u2014 backend/routes/projects.py:142"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-14854a3b80a41a70", "name": "FastAPI POST `add_feedback` without auth dependency \u2014 backend/routes/sheets.py:445", "shortDescription": {"text": "FastAPI POST `add_feedback` without auth dependency \u2014 backend/routes/sheets.py:445"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-df599d1a838a5a0c", "name": "FastAPI POST `signin` without auth dependency \u2014 backend/routes/auth.py:189", "shortDescription": {"text": "FastAPI POST `signin` without auth dependency \u2014 backend/routes/auth.py:189"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-e5ef15bff416a811", "name": "FastAPI POST `verify_token` without auth dependency \u2014 backend/routes/auth.py:278", "shortDescription": {"text": "FastAPI POST `verify_token` without auth dependency \u2014 backend/routes/auth.py:278"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-836e5ee441781b14", "name": "FastAPI POST `log_view` without auth dependency \u2014 backend/routes/portfolios.py:703", "shortDescription": {"text": "FastAPI POST `log_view` without auth dependency \u2014 backend/routes/portfolios.py:703"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-033ee701deb8d84c", "name": "FastAPI POST `log_share` without auth dependency \u2014 backend/routes/portfolios.py:720", "shortDescription": {"text": "FastAPI POST `log_share` without auth dependency \u2014 backend/routes/portfolios.py:720"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-74c39dfca1b5dc59", "name": "FastAPI POST `log_download` without auth dependency \u2014 backend/routes/portfolios.py:737", "shortDescription": {"text": "FastAPI POST `log_download` without auth dependency \u2014 backend/routes/portfolios.py:737"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-726c7323cb9275f3", "name": "FastAPI POST `create_portfolio` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:32", "shortDescription": {"text": "FastAPI POST `create_portfolio` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:32"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-c4c9335ccdc6bcb3", "name": "FastAPI PATCH `update_portfolio` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:45", "shortDescription": {"text": "FastAPI PATCH `update_portfolio` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:45"}, "fullDescription": {"text": "`@router.patch` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-1c60c84ca18d7780", "name": "FastAPI DELETE `delete_portfolio` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:52", "shortDescription": {"text": "FastAPI DELETE `delete_portfolio` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:52"}, "fullDescription": {"text": "`@router.delete` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-9acb80ba10f25a0a", "name": "FastAPI POST `create_page` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:60", "shortDescription": {"text": "FastAPI POST `create_page` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:60"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-15fef30edc7af49f", "name": "FastAPI POST `batch_create_pages` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:74", "shortDescription": {"text": "FastAPI POST `batch_create_pages` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:74"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-8a48622297ae6f65", "name": "Dangling fetch: POST /api/portfolios/${portfolioId}/download (frontend/src/components/ShareModal/ShareModal.tsx:141)", "shortDescription": {"text": "Dangling fetch: POST /api/portfolios/${portfolioId}/download (frontend/src/components/ShareModal/ShareModal.tsx:141)"}, "fullDescription": {"text": "`frontend/src/components/ShareModal/ShareModal.tsx:141` calls `POST /api/portfolios/${portfolioId}/download` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/portfolios/<p>/download`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-5baa8971ebe192a1", "name": "Unused endpoint: GET /", "shortDescription": {"text": "Unused endpoint: GET /"}, "fullDescription": {"text": "`backend/main.py` declares `GET /` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-eb0428442a390121", "name": "Unused endpoint: GET /docs", "shortDescription": {"text": "Unused endpoint: GET /docs"}, "fullDescription": {"text": "`backend/main.py` declares `GET /docs` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ccd81e719e804d1f", "name": "Unused endpoint: PUT /api/projects/{project_id}/document", "shortDescription": {"text": "Unused endpoint: PUT /api/projects/{project_id}/document"}, "fullDescription": {"text": "`backend/routes/documents.py` declares `PUT /api/projects/{project_id}/document` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8fbd611e44e40747", "name": "Unused endpoint: GET /api/projects/{project_id}/document", "shortDescription": {"text": "Unused endpoint: GET /api/projects/{project_id}/document"}, "fullDescription": {"text": "`backend/routes/documents.py` declares `GET /api/projects/{project_id}/document` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d8c37f1cb1273669", "name": "Unused endpoint: POST /api/projects/{project_id}/document/health", "shortDescription": {"text": "Unused endpoint: POST /api/projects/{project_id}/document/health"}, "fullDescription": {"text": "`backend/routes/documents.py` declares `POST /api/projects/{project_id}/document/health` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-21f1ccd4e67e692c", "name": "Unused endpoint: POST /api/projects/{project_id}/document/export-pdf", "shortDescription": {"text": "Unused endpoint: POST /api/projects/{project_id}/document/export-pdf"}, "fullDescription": {"text": "`backend/routes/documents.py` declares `POST /api/projects/{project_id}/document/export-pdf` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e73f8bc01f6cae3b", "name": "Unused endpoint: GET /portfolios", "shortDescription": {"text": "Unused endpoint: GET /portfolios"}, "fullDescription": {"text": "`backend/routes/templates.py` declares `GET /portfolios` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-66421035e66ef306", "name": "Unused endpoint: GET /portfolios/{template_id}", "shortDescription": {"text": "Unused endpoint: GET /portfolios/{template_id}"}, "fullDescription": {"text": "`backend/routes/templates.py` declares `GET /portfolios/{template_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3e01def489117c63", "name": "Unused endpoint: GET /portfolios/categories", "shortDescription": {"text": "Unused endpoint: GET /portfolios/categories"}, "fullDescription": {"text": "`backend/routes/templates.py` declares `GET /portfolios/categories` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-24a8ae7e32d82da6", "name": "Unused endpoint: GET /sheets", "shortDescription": {"text": "Unused endpoint: GET /sheets"}, "fullDescription": {"text": "`backend/routes/templates.py` declares `GET /sheets` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-770ff7c05343426b", "name": "Unused endpoint: GET /sheets/{template_id}", "shortDescription": {"text": "Unused endpoint: GET /sheets/{template_id}"}, "fullDescription": {"text": "`backend/routes/templates.py` declares `GET /sheets/{template_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8439f9aecf4fc9c3", "name": "Unused endpoint: GET /sheets/types", "shortDescription": {"text": "Unused endpoint: GET /sheets/types"}, "fullDescription": {"text": "`backend/routes/templates.py` declares `GET /sheets/types` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9b50ad1859bcb150", "name": "Unused endpoint: GET /sheets/formats", "shortDescription": {"text": "Unused endpoint: GET /sheets/formats"}, "fullDescription": {"text": "`backend/routes/templates.py` declares `GET /sheets/formats` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-92e07935c226add3", "name": "Unused endpoint: GET /compatibility/{portfolio_id}", "shortDescription": {"text": "Unused endpoint: GET /compatibility/{portfolio_id}"}, "fullDescription": {"text": "`backend/routes/templates.py` declares `GET /compatibility/{portfolio_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5e88c2bc105d7c89", "name": "Unused endpoint: POST /portfolios/{template_id}/apply/{portfolio_id}", "shortDescription": {"text": "Unused endpoint: POST /portfolios/{template_id}/apply/{portfolio_id}"}, "fullDescription": {"text": "`backend/routes/templates.py` declares `POST /portfolios/{template_id}/apply/{portfolio_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cd8dc4599ec52a08", "name": "Unused endpoint: GET /stats", "shortDescription": {"text": "Unused endpoint: GET /stats"}, "fullDescription": {"text": "`backend/routes/templates.py` declares `GET /stats` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7f2fa92b3bfcd9ec", "name": "Unused endpoint: GET /{portfolio_id}/assets/{asset_id}/versions", "shortDescription": {"text": "Unused endpoint: GET /{portfolio_id}/assets/{asset_id}/versions"}, "fullDescription": {"text": "`backend/routes/versioning.py` declares `GET /{portfolio_id}/assets/{asset_id}/versions` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-609a5ede22faa740", "name": "Unused endpoint: GET /{portfolio_id}/assets/{asset_id}/versions/{version_num}", "shortDescription": {"text": "Unused endpoint: GET /{portfolio_id}/assets/{asset_id}/versions/{version_num}"}, "fullDescription": {"text": "`backend/routes/versioning.py` declares `GET /{portfolio_id}/assets/{asset_id}/versions/{version_num}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d117e6e68749a9cb", "name": "Unused endpoint: POST /{portfolio_id}/assets/{asset_id}/versions/{version_num}/restore", "shortDescription": {"text": "Unused endpoint: POST /{portfolio_id}/assets/{asset_id}/versions/{version_num}/restore"}, "fullDescription": {"text": "`backend/routes/versioning.py` declares `POST /{portfolio_id}/assets/{asset_id}/versions/{version_num}/restore` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7a8ec053ac4550d6", "name": "Unused endpoint: GET /{portfolio_id}/assets/{asset_id}/versions/{version_a}/compare/{version_b}", "shortDescription": {"text": "Unused endpoint: GET /{portfolio_id}/assets/{asset_id}/versions/{version_a}/compare/{version_b}"}, "fullDescription": {"text": "`backend/routes/versioning.py` declares `GET /{portfolio_id}/assets/{asset_id}/versions/{version_a}/compare/{version_b}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-55b2e4b9fcc605e0", "name": "Unused endpoint: POST /{portfolio_id}/assets/{asset_id}/versions/cleanup", "shortDescription": {"text": "Unused endpoint: POST /{portfolio_id}/assets/{asset_id}/versions/cleanup"}, "fullDescription": {"text": "`backend/routes/versioning.py` declares `POST /{portfolio_id}/assets/{asset_id}/versions/cleanup` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a9823a07cbabf4a7", "name": "Unused endpoint: GET /{portfolio_id}/versions/statistics", "shortDescription": {"text": "Unused endpoint: GET /{portfolio_id}/versions/statistics"}, "fullDescription": {"text": "`backend/routes/versioning.py` declares `GET /{portfolio_id}/versions/statistics` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b3eab01e2a828176", "name": "Unused endpoint: POST /{portfolio_id}/projects/{project_id}/generate-description", "shortDescription": {"text": "Unused endpoint: POST /{portfolio_id}/projects/{project_id}/generate-description"}, "fullDescription": {"text": "`backend/routes/ai_generation.py` declares `POST /{portfolio_id}/projects/{project_id}/generate-description` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ba12b33f9802b84c", "name": "Unused endpoint: POST /{portfolio_id}/projects/{project_id}/generate-concept", "shortDescription": {"text": "Unused endpoint: POST /{portfolio_id}/projects/{project_id}/generate-concept"}, "fullDescription": {"text": "`backend/routes/ai_generation.py` declares `POST /{portfolio_id}/projects/{project_id}/generate-concept` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ebdc6e9cbd1c0578", "name": "Unused endpoint: POST /{portfolio_id}/assets/{asset_id}/generate-caption", "shortDescription": {"text": "Unused endpoint: POST /{portfolio_id}/assets/{asset_id}/generate-caption"}, "fullDescription": {"text": "`backend/routes/ai_generation.py` declares `POST /{portfolio_id}/assets/{asset_id}/generate-caption` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1f30ae38192d3bdc", "name": "Unused endpoint: POST /{portfolio_id}/generate-bio", "shortDescription": {"text": "Unused endpoint: POST /{portfolio_id}/generate-bio"}, "fullDescription": {"text": "`backend/routes/ai_generation.py` declares `POST /{portfolio_id}/generate-bio` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7cd6ec7861145955", "name": "Unused endpoint: POST /{portfolio_id}/projects/{project_id}/suggest-titles", "shortDescription": {"text": "Unused endpoint: POST /{portfolio_id}/projects/{project_id}/suggest-titles"}, "fullDescription": {"text": "`backend/routes/ai_generation.py` declares `POST /{portfolio_id}/projects/{project_id}/suggest-titles` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-af58a8cf98426b02", "name": "Unused endpoint: POST /{portfolio_id}/generate-taglines", "shortDescription": {"text": "Unused endpoint: POST /{portfolio_id}/generate-taglines"}, "fullDescription": {"text": "`backend/routes/ai_generation.py` declares `POST /{portfolio_id}/generate-taglines` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-688593cffed22a5e", "name": "Unused endpoint: GET /ai-tones", "shortDescription": {"text": "Unused endpoint: GET /ai-tones"}, "fullDescription": {"text": "`backend/routes/ai_generation.py` declares `GET /ai-tones` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4533c42ca419ca8f", "name": "Unused endpoint: POST /{portfolio_id}/analyze-content", "shortDescription": {"text": "Unused endpoint: POST /{portfolio_id}/analyze-content"}, "fullDescription": {"text": "`backend/routes/ai_generation.py` declares `POST /{portfolio_id}/analyze-content` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a6341bb1599f3948", "name": "Unused endpoint: POST /{portfolio_id}/improve-text", "shortDescription": {"text": "Unused endpoint: POST /{portfolio_id}/improve-text"}, "fullDescription": {"text": "`backend/routes/ai_generation.py` declares `POST /{portfolio_id}/improve-text` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7a009b1a56794f45", "name": "Unused endpoint: POST /", "shortDescription": {"text": "Unused endpoint: POST /"}, "fullDescription": {"text": "`backend/routes/portfolios_v2.py` declares `POST /` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b6272106dd21a6cd", "name": "Unused endpoint: GET /{portfolio_id}", "shortDescription": {"text": "Unused endpoint: GET /{portfolio_id}"}, "fullDescription": {"text": "`backend/routes/portfolios_v2.py` declares `GET /{portfolio_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-64ee4fe3c00804e3", "name": "Unused endpoint: PUT /{portfolio_id}", "shortDescription": {"text": "Unused endpoint: PUT /{portfolio_id}"}, "fullDescription": {"text": "`backend/routes/portfolios_v2.py` declares `PUT /{portfolio_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e8ab9a663becacde", "name": "Unused endpoint: DELETE /{portfolio_id}", "shortDescription": {"text": "Unused endpoint: DELETE /{portfolio_id}"}, "fullDescription": {"text": "`backend/routes/portfolios_v2.py` declares `DELETE /{portfolio_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2e7955eca4f1ccef", "name": "Unused endpoint: GET /{portfolio_id}/settings", "shortDescription": {"text": "Unused endpoint: GET /{portfolio_id}/settings"}, "fullDescription": {"text": "`backend/routes/portfolios_v2.py` declares `GET /{portfolio_id}/settings` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4c64d9b7bb815257", "name": "Unused endpoint: PUT /{portfolio_id}/settings", "shortDescription": {"text": "Unused endpoint: PUT /{portfolio_id}/settings"}, "fullDescription": {"text": "`backend/routes/portfolios_v2.py` declares `PUT /{portfolio_id}/settings` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1f6c1a5f4dc7f897", "name": "Unused endpoint: GET /{portfolio_id}/public", "shortDescription": {"text": "Unused endpoint: GET /{portfolio_id}/public"}, "fullDescription": {"text": "`backend/routes/portfolios_v2.py` declares `GET /{portfolio_id}/public` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-fef31f6e07aa8c88", "name": "Unused endpoint: GET /api/sheet-sets", "shortDescription": {"text": "Unused endpoint: GET /api/sheet-sets"}, "fullDescription": {"text": "`backend/routes/sheet_sets.py` declares `GET /api/sheet-sets` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7322029a79126681", "name": "Unused endpoint: GET /api/projects/{project_id}/sheet-sets", "shortDescription": {"text": "Unused endpoint: GET /api/projects/{project_id}/sheet-sets"}, "fullDescription": {"text": "`backend/routes/sheet_sets.py` declares `GET /api/projects/{project_id}/sheet-sets` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-dbe7ecbe67a2bfce", "name": "Unused endpoint: GET /api/projects/{project_id}/sheet-sets/{set_id}", "shortDescription": {"text": "Unused endpoint: GET /api/projects/{project_id}/sheet-sets/{set_id}"}, "fullDescription": {"text": "`backend/routes/sheet_sets.py` declares `GET /api/projects/{project_id}/sheet-sets/{set_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-dc7eacfc509383e1", "name": "Unused endpoint: POST /api/projects/{project_id}/sheet-sets", "shortDescription": {"text": "Unused endpoint: POST /api/projects/{project_id}/sheet-sets"}, "fullDescription": {"text": "`backend/routes/sheet_sets.py` declares `POST /api/projects/{project_id}/sheet-sets` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9593c516d54bf6fb", "name": "Unused endpoint: PUT /api/projects/{project_id}/sheet-sets/{set_id}", "shortDescription": {"text": "Unused endpoint: PUT /api/projects/{project_id}/sheet-sets/{set_id}"}, "fullDescription": {"text": "`backend/routes/sheet_sets.py` declares `PUT /api/projects/{project_id}/sheet-sets/{set_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d6535ab3fa74bdf4", "name": "Unused endpoint: DELETE /api/projects/{project_id}/sheet-sets/{set_id}", "shortDescription": {"text": "Unused endpoint: DELETE /api/projects/{project_id}/sheet-sets/{set_id}"}, "fullDescription": {"text": "`backend/routes/sheet_sets.py` declares `DELETE /api/projects/{project_id}/sheet-sets/{set_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3b94923f366fed0e", "name": "Unused endpoint: GET /api/projects", "shortDescription": {"text": "Unused endpoint: GET /api/projects"}, "fullDescription": {"text": "`backend/routes/projects.py` declares `GET /api/projects` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-16a480533217943d", "name": "Unused endpoint: POST /api/projects", "shortDescription": {"text": "Unused endpoint: POST /api/projects"}, "fullDescription": {"text": "`backend/routes/projects.py` declares `POST /api/projects` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cb2dcb5114cd8bdc", "name": "Unused endpoint: GET /api/projects/{project_id}", "shortDescription": {"text": "Unused endpoint: GET /api/projects/{project_id}"}, "fullDescription": {"text": "`backend/routes/projects.py` declares `GET /api/projects/{project_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-753f53a99e9de17c", "name": "Unused endpoint: PUT /api/projects/{project_id}", "shortDescription": {"text": "Unused endpoint: PUT /api/projects/{project_id}"}, "fullDescription": {"text": "`backend/routes/projects.py` declares `PUT /api/projects/{project_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-910e7327fca49aff", "name": "Unused endpoint: DELETE /api/projects/{project_id}", "shortDescription": {"text": "Unused endpoint: DELETE /api/projects/{project_id}"}, "fullDescription": {"text": "`backend/routes/projects.py` declares `DELETE /api/projects/{project_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-07f463353c20146c", "name": "Unused endpoint: POST /api/projects/{project_id}/analyze-assets", "shortDescription": {"text": "Unused endpoint: POST /api/projects/{project_id}/analyze-assets"}, "fullDescription": {"text": "`backend/routes/projects.py` declares `POST /api/projects/{project_id}/analyze-assets` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/25101"}, "properties": {"repository": "cosmofolio23/cosmfolio", "repoUrl": "https://github.com/cosmofolio23/cosmfolio", "branch": "main"}, "results": [{"ruleId": "scanner-1e04fa5a4b844904", "level": "note", "message": {"text": "Possibly dead Python function: init_supabase"}, "properties": {"repobilityId": "ce955ca351dff4cd", "scanner": "scanner-primary", "fingerprint": "1e04fa5a4b844904", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/database.py:170"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-e57e3f705a685159", "level": "note", "message": {"text": "Possibly dead Python function: setup_error_handlers"}, "properties": {"repobilityId": "e73266d63c531ffd", "scanner": "scanner-primary", "fingerprint": "e57e3f705a685159", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/error_handlers.py:145"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-8e9f6a30ffd397a7", "level": "note", "message": {"text": "Possibly dead Python function: create_default_compatibility_mappings"}, "properties": {"repobilityId": "0a586e2592c07c37", "scanner": "scanner-primary", "fingerprint": "8e9f6a30ffd397a7", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/scripts/import_templates.py:209"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-b986a110fb8d0455", "level": "note", "message": {"text": "Possibly dead Python function: check_suspicious"}, "properties": {"repobilityId": "46b94de4f330d411", "scanner": "scanner-primary", "fingerprint": "b986a110fb8d0455", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/middleware/security.py:345"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-10a4ddfb0a43c51a", "level": "note", "message": {"text": "Possibly dead Python function: mark_suspicious"}, "properties": {"repobilityId": "6dda876a69f0d501", "scanner": "scanner-primary", "fingerprint": "10a4ddfb0a43c51a", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/middleware/security.py:349"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6e811f4663fe6df1", "level": "note", "message": {"text": "Possibly dead Python function: rate_limit"}, "properties": {"repobilityId": "ca81e3996cd68a6a", "scanner": "scanner-primary", "fingerprint": "6e811f4663fe6df1", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/middleware/rate_limit.py:233"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-eceb460d72e47f1e", "level": "note", "message": {"text": "Possibly dead Python function: decorator"}, "properties": {"repobilityId": "ffbcbc9bc189af1c", "scanner": "scanner-primary", "fingerprint": "eceb460d72e47f1e", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/middleware/rate_limit.py:243"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-ebd0a68bfdd77ffa", "level": "note", "message": {"text": "Possibly dead Python function: check_budget"}, "properties": {"repobilityId": "2b9451cb7d8ec592", "scanner": "scanner-primary", "fingerprint": "ebd0a68bfdd77ffa", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/middleware/rate_limit.py:349"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d6e69265f43bf1c6", "level": "note", "message": {"text": "Possibly dead Python function: project_hero_image"}, "properties": {"repobilityId": "7a7333de48d1f4ba", "scanner": "scanner-primary", "fingerprint": "d6e69265f43bf1c6", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/portfolio_renderer.py:117"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-b05a1a49e6ca7549", "level": "note", "message": {"text": "Possibly dead Python function: project_grid_3col"}, "properties": {"repobilityId": "d41cb766b3a4daa7", "scanner": "scanner-primary", "fingerprint": "b05a1a49e6ca7549", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/portfolio_renderer.py:137"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-89788762ab7131b1", "level": "note", "message": {"text": "Possibly dead Python function: project_plan_section"}, "properties": {"repobilityId": "dddaf58cd46a695e", "scanner": "scanner-primary", "fingerprint": "89788762ab7131b1", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/portfolio_renderer.py:154"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d671470a772ad2f1", "level": "note", "message": {"text": "Possibly dead Python function: project_asymmetric"}, "properties": {"repobilityId": "a57fefcab3a35552", "scanner": "scanner-primary", "fingerprint": "d671470a772ad2f1", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/portfolio_renderer.py:185"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-0f46d65689c0c4d6", "level": "note", "message": {"text": "Possibly dead Python function: project_masonry"}, "properties": {"repobilityId": "8238ce73ec8f2060", "scanner": "scanner-primary", "fingerprint": "0f46d65689c0c4d6", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/portfolio_renderer.py:223"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2e7e22b902f9f5e2", "level": "note", "message": {"text": "Possibly dead Python function: project_fullbleed"}, "properties": {"repobilityId": "48aa970a34188e42", "scanner": "scanner-primary", "fingerprint": "2e7e22b902f9f5e2", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/portfolio_renderer.py:240"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-b22f88d51bbc10db", "level": "note", "message": {"text": "Possibly dead Python function: project_two_col_text"}, "properties": {"repobilityId": "cbf476d9131a0546", "scanner": "scanner-primary", "fingerprint": "b22f88d51bbc10db", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/portfolio_renderer.py:256"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-23ae23518e4a18d9", "level": "note", "message": {"text": "Possibly dead Python function: project_gallery_wall"}, "properties": {"repobilityId": "301de6c02fc5a351", "scanner": "scanner-primary", "fingerprint": "23ae23518e4a18d9", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/portfolio_renderer.py:282"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-bdb5cb116a3ae1ab", "level": "note", "message": {"text": "Possibly dead Python function: project_blueprint"}, "properties": {"repobilityId": "be004c850e610ab4", "scanner": "scanner-primary", "fingerprint": "bdb5cb116a3ae1ab", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/portfolio_renderer.py:311"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-db0e2b6aaabf99f7", "level": "note", "message": {"text": "Possibly dead Python function: project_story_timeline"}, "properties": {"repobilityId": "b399d158336c1d77", "scanner": "scanner-primary", "fingerprint": "db0e2b6aaabf99f7", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/portfolio_renderer.py:352"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6270c5f7701d9d63", "level": "note", "message": {"text": "Possibly dead Python function: create_upload_session"}, "properties": {"repobilityId": "6335cb29e414f2b3", "scanner": "scanner-primary", "fingerprint": "6270c5f7701d9d63", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/upload.py:220"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-1707d30b4869522e", "level": "note", "message": {"text": "Possibly dead Python function: upload_chunk"}, "properties": {"repobilityId": "6b1537bb49c5bcce", "scanner": "scanner-primary", "fingerprint": "1707d30b4869522e", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/upload.py:241"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-53e220b4ac0f7554", "level": "note", "message": {"text": "Possibly dead Python function: complete_resumable_upload"}, "properties": {"repobilityId": "828d03dfcde995bd", "scanner": "scanner-primary", "fingerprint": "53e220b4ac0f7554", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/upload.py:261"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-558de36b3dd1f76b", "level": "note", "message": {"text": "Possibly dead Python function: cleanup_expired_sessions"}, "properties": {"repobilityId": "71e0198718c0d495", "scanner": "scanner-primary", "fingerprint": "558de36b3dd1f76b", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/upload.py:312"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-28a6e9e83d8018ef", "level": "note", "message": {"text": "Possibly dead Python function: verify_checksum"}, "properties": {"repobilityId": "c7c8aae8d0763ca5", "scanner": "scanner-primary", "fingerprint": "28a6e9e83d8018ef", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/services/upload.py:383"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-ff23ac8700319db1", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/import-templates.js:25"}, "properties": {"repobilityId": "7ab911a28d886ff1", "scanner": "scanner-primary", "fingerprint": "ff23ac8700319db1", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-41c5bed21896aab2", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/setup-tables.js:17"}, "properties": {"repobilityId": "7ba5d4a221a37335", "scanner": "scanner-primary", "fingerprint": "41c5bed21896aab2", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-4c84e2fb57e9c7e0", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/import-direct.js:14"}, "properties": {"repobilityId": "ae48f850e6b3a1ff", "scanner": "scanner-primary", "fingerprint": "4c84e2fb57e9c7e0", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-dd7751afa9019edb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/project/[id]/sheet-set/page.tsx:133"}, "properties": {"repobilityId": "c4b7a463f4fe2d89", "scanner": "scanner-primary", "fingerprint": "dd7751afa9019edb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-23b9a83c933729f2", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/project/[id]/portfolio/[portfolioId]/page.tsx:477"}, "properties": {"repobilityId": "71d503be2da77c69", "scanner": "scanner-primary", "fingerprint": "23b9a83c933729f2", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8c6364e97fb210ba", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 frontend/src/app/dashboard/project/[id]/portfolio/[portfolioId]/page.tsx:549"}, "properties": {"repobilityId": "8849b2cf65cc8b00", "scanner": "scanner-primary", "fingerprint": "8c6364e97fb210ba", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-6e4a134e4d46f7c2", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 frontend/src/app/dashboard/tools/cv/page.tsx:310"}, "properties": {"repobilityId": "2f85b624b114cbf7", "scanner": "scanner-primary", "fingerprint": "6e4a134e4d46f7c2", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-8332388a512d4b80", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/cv/page.tsx:375"}, "properties": {"repobilityId": "a9fa9a1e47b46bdc", "scanner": "scanner-primary", "fingerprint": "8332388a512d4b80", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-01f8a6302b373584", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/concept-diagram/page.tsx:679"}, "properties": {"repobilityId": "a30cc106f8463457", "scanner": "scanner-primary", "fingerprint": "01f8a6302b373584", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-2e1b49c7c1a35856", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/site-analysis/page.tsx:325"}, "properties": {"repobilityId": "42162e4d55dac580", "scanner": "scanner-primary", "fingerprint": "2e1b49c7c1a35856", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-c60a9f20f55f51ef", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/tools/scale-north/page.tsx:165"}, "properties": {"repobilityId": "c45e1e3452f9c2f4", "scanner": "scanner-primary", "fingerprint": "c60a9f20f55f51ef", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a68c4b0cdc766cd9", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/scale-north/page.tsx:141"}, "properties": {"repobilityId": "1f694146c51ac3ee", "scanner": "scanner-primary", "fingerprint": "a68c4b0cdc766cd9", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-7e31c2beff81c0b3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/tools/entourage/page.tsx:287"}, "properties": {"repobilityId": "ecd4d2e878fa0b2f", "scanner": "scanner-primary", "fingerprint": "7e31c2beff81c0b3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-919582c73648e9a0", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/dashboard/tools/entourage/page.tsx:286"}, "properties": {"repobilityId": "0678b625ae63b0e6", "scanner": "scanner-primary", "fingerprint": "919582c73648e9a0", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-5f630131befc2042", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/templates/[id]/editor/page.tsx:872"}, "properties": {"repobilityId": "4b2c48006f12cd84", "scanner": "scanner-primary", "fingerprint": "5f630131befc2042", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2444ac24d0b54cc8", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 frontend/src/app/dashboard/templates/[id]/editor/page.tsx:930"}, "properties": {"repobilityId": "6dcbcd841e9ea339", "scanner": "scanner-primary", "fingerprint": "2444ac24d0b54cc8", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-f6e9202530baf0e4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/library/page.tsx:151"}, "properties": {"repobilityId": "427cf26860e05c5d", "scanner": "scanner-primary", "fingerprint": "f6e9202530baf0e4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-77e9761fa79c62a5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/dashboard/my-portfolios/page.tsx:205"}, "properties": {"repobilityId": "3a566573503d6356", "scanner": "scanner-primary", "fingerprint": "77e9761fa79c62a5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4737cb413d0156da", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/p/[slug]/page.tsx:127"}, "properties": {"repobilityId": "2e49dffdc6d87e53", "scanner": "scanner-primary", "fingerprint": "4737cb413d0156da", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d698a073da137c21", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 frontend/src/components/Modal.tsx:60"}, "properties": {"repobilityId": "3cb02c357d6cefdd", "scanner": "scanner-primary", "fingerprint": "d698a073da137c21", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-af07a89616ca19ec", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/design-system/StylePackGallery.tsx:242"}, "properties": {"repobilityId": "6c3f7e4c0128b710", "scanner": "scanner-primary", "fingerprint": "af07a89616ca19ec", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-661514ccfb754e61", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 frontend/src/components/AssetManager/AssetManager.tsx:367"}, "properties": {"repobilityId": "553abeda1f53acb3", "scanner": "scanner-primary", "fingerprint": "661514ccfb754e61", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-620367e7032d5875", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/AssetManager/AssetGridView.tsx:82"}, "properties": {"repobilityId": "64ade53a3d47927a", "scanner": "scanner-primary", "fingerprint": "620367e7032d5875", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7c1da6109936f161", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 frontend/src/components/AssetManager/AssetVersionHistory.tsx:93"}, "properties": {"repobilityId": "2c384bfa86fe460c", "scanner": "scanner-primary", "fingerprint": "7c1da6109936f161", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-0d5a4c94c75e47b3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/drawingProcessor/DrawingProcessor.tsx:463"}, "properties": {"repobilityId": "0d10b8c96a28f336", "scanner": "scanner-primary", "fingerprint": "0d5a4c94c75e47b3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4ccb06b3b7df10f3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/templates/TemplateMockup.tsx:49"}, "properties": {"repobilityId": "9e038c8469e33ba6", "scanner": "scanner-primary", "fingerprint": "4ccb06b3b7df10f3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-597785c80d0c0553", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/library/LibraryUpload.tsx:164"}, "properties": {"repobilityId": "1eb00717a7152753", "scanner": "scanner-primary", "fingerprint": "597785c80d0c0553", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0662341d51b37264", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 frontend/src/components/ThemeManager/ThemeManager.tsx:376"}, "properties": {"repobilityId": "6647921417f47b70", "scanner": "scanner-primary", "fingerprint": "0662341d51b37264", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-e5bc3723f06466db", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 frontend/src/components/siteAnalysis/MapAnnotator.tsx:192"}, "properties": {"repobilityId": "e5c73414f1d34bd2", "scanner": "scanner-primary", "fingerprint": "e5bc3723f06466db", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-11d404c0925001aa", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/siteAnalysis/MapAnnotator.tsx:349"}, "properties": {"repobilityId": "3610b734a466a670", "scanner": "scanner-primary", "fingerprint": "11d404c0925001aa", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-63e4a527b17f8a83", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetCanvas.tsx:188"}, "properties": {"repobilityId": "ce86a22db47df7fa", "scanner": "scanner-primary", "fingerprint": "63e4a527b17f8a83", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7ffdb47e0eb192cc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetEditor.tsx:214"}, "properties": {"repobilityId": "559da82b2c0de938", "scanner": "scanner-primary", "fingerprint": "7ffdb47e0eb192cc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3ee9082f242a4b2b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetEntouragePanel.tsx:127"}, "properties": {"repobilityId": "e150ad6813c2c465", "scanner": "scanner-primary", "fingerprint": "3ee9082f242a4b2b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-82ad53808b07272b", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/sheetSet/SheetSetEntouragePanel.tsx:126"}, "properties": {"repobilityId": "ec93aee321925915", "scanner": "scanner-primary", "fingerprint": "82ad53808b07272b", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-61f98353942fc773", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetProperties.tsx:64"}, "properties": {"repobilityId": "083258a97eac211a", "scanner": "scanner-primary", "fingerprint": "61f98353942fc773", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7bb44abbc867d567", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/sheetSet/SheetSetNavigator.tsx:94"}, "properties": {"repobilityId": "0caa45a080055a22", "scanner": "scanner-primary", "fingerprint": "7bb44abbc867d567", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f854e1383f84d1a0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/portfolio-wizard/PortfolioWizard.tsx:493"}, "properties": {"repobilityId": "06d7993eac0fe0f6", "scanner": "scanner-primary", "fingerprint": "f854e1383f84d1a0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3ed3cdd8cf509cd4", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/SheetEditor/SheetEditor.tsx:720"}, "properties": {"repobilityId": "d2647fbc0c8bfe53", "scanner": "scanner-primary", "fingerprint": "3ed3cdd8cf509cd4", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-6fca92c2f6c7ec09", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 frontend/src/lib/firebase.ts:165"}, "properties": {"repobilityId": "8afe72f26007cabf", "scanner": "scanner-primary", "fingerprint": "6fca92c2f6c7ec09", "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-e066691601852931", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.11-slim"}, "properties": {"repobilityId": "9c59398aca4a27a5", "scanner": "scanner-primary", "fingerprint": "e066691601852931", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 2}}}]}, {"ruleId": "scanner-1f66ad88286ca30a", "level": "warning", "message": {"text": "Dockerfile runs as root: backend/Dockerfile"}, "properties": {"repobilityId": "7afd2b0e8a8c9eeb", "scanner": "scanner-primary", "fingerprint": "1f66ad88286ca30a", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-8cd20d539467d2c5", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.11-slim"}, "properties": {"repobilityId": "06b87ac9439092d6", "scanner": "scanner-primary", "fingerprint": "8cd20d539467d2c5", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/Dockerfile"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2f717fe6d96535f7", "level": "error", "message": {"text": "Runtime dotenv file present in repo: backend/.env.production"}, "properties": {"repobilityId": "b1baf46a0f8be222", "scanner": "scanner-primary", "fingerprint": "2f717fe6d96535f7", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets", "config", "env-file", "runtime-env", "env_file_with_secret"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/.env.production"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2b76d6e41839a257", "level": "error", "message": {"text": "Possible secret in netlify.toml"}, "properties": {"repobilityId": "4c2c2633e603c8a8", "scanner": "scanner-primary", "fingerprint": "2b76d6e41839a257", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "netlify.toml"}, "region": {"startLine": 11}}}]}, {"ruleId": "scanner-9827255a94b0b676", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in backend/main.py:32"}, "properties": {"repobilityId": "68276992e65b84f9", "scanner": "scanner-primary", "fingerprint": "9827255a94b0b676", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/main.py"}, "region": {"startLine": 32}}}]}, {"ruleId": "scanner-5ea795ffa541ea47", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in backend/middleware/cache_headers.py:153"}, "properties": {"repobilityId": "183e590ea9d56f8f", "scanner": "scanner-primary", "fingerprint": "5ea795ffa541ea47", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/middleware/cache_headers.py"}, "region": {"startLine": 153}}}]}, {"ruleId": "scanner-0416036ae120bf78", "level": "note", "message": {"text": "Insecure pattern 'document_write' in frontend/src/app/dashboard/project/[id]/sheet/page.tsx:343"}, "properties": {"repobilityId": "26b8fc1ce5614776", "scanner": "scanner-primary", "fingerprint": "0416036ae120bf78", "layer": "security", "severity": "low", "confidence": 1.0, "tags": ["owasp", "document_write"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/app/dashboard/project/[id]/sheet/page.tsx"}, "region": {"startLine": 343}}}]}, {"ruleId": "scanner-2b7146e6f5f804fe", "level": "note", "message": {"text": "Insecure pattern 'document_write' in frontend/src/app/dashboard/project/[id]/sheet/editor/page.tsx:42"}, "properties": {"repobilityId": "c34e633e77563783", "scanner": "scanner-primary", "fingerprint": "2b7146e6f5f804fe", "layer": "security", "severity": "low", "confidence": 1.0, "tags": ["owasp", "document_write"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/app/dashboard/project/[id]/sheet/editor/page.tsx"}, "region": {"startLine": 42}}}]}, {"ruleId": "scanner-f5dca1d923f61624", "level": "note", "message": {"text": "Insecure pattern 'document_write' in frontend/src/app/dashboard/tools/cv/page.tsx:220"}, "properties": {"repobilityId": "cb1e18730965744a", "scanner": "scanner-primary", "fingerprint": "f5dca1d923f61624", "layer": "security", "severity": "low", "confidence": 1.0, "tags": ["owasp", "document_write"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/app/dashboard/tools/cv/page.tsx"}, "region": {"startLine": 220}}}]}, {"ruleId": "scanner-535a5713b49f3587", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/cv/page.tsx:375"}, "properties": {"repobilityId": "8dbee75ad107fbba", "scanner": "scanner-primary", "fingerprint": "535a5713b49f3587", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/app/dashboard/tools/cv/page.tsx"}, "region": {"startLine": 375}}}]}, {"ruleId": "scanner-bbfa707bbeb59dea", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/concept-diagram/page.tsx:679"}, "properties": {"repobilityId": "4a5439eee4139e87", "scanner": "scanner-primary", "fingerprint": "bbfa707bbeb59dea", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/app/dashboard/tools/concept-diagram/page.tsx"}, "region": {"startLine": 679}}}]}, {"ruleId": "scanner-05879112a67ad6b5", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/site-analysis/page.tsx:325"}, "properties": {"repobilityId": "b97a2fcb5ccc9b63", "scanner": "scanner-primary", "fingerprint": "05879112a67ad6b5", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/app/dashboard/tools/site-analysis/page.tsx"}, "region": {"startLine": 325}}}]}, {"ruleId": "scanner-fcafbd7e0f7c8245", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/scale-north/page.tsx:141"}, "properties": {"repobilityId": "768d7bc201d12f58", "scanner": "scanner-primary", "fingerprint": "fcafbd7e0f7c8245", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/app/dashboard/tools/scale-north/page.tsx"}, "region": {"startLine": 141}}}]}, {"ruleId": "scanner-eaff8e95eced732c", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/dashboard/tools/entourage/page.tsx:286"}, "properties": {"repobilityId": "0627bec04eae3c3b", "scanner": "scanner-primary", "fingerprint": "eaff8e95eced732c", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/app/dashboard/tools/entourage/page.tsx"}, "region": {"startLine": 286}}}]}, {"ruleId": "scanner-0566da75dec38a0d", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/siteAnalysis/MapAnnotator.tsx:349"}, "properties": {"repobilityId": "7baf045d32e85f6b", "scanner": "scanner-primary", "fingerprint": "0566da75dec38a0d", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/siteAnalysis/MapAnnotator.tsx"}, "region": {"startLine": 349}}}]}, {"ruleId": "scanner-a8a017861c57bb80", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/sheetSet/SheetSetEntouragePanel.tsx:126"}, "properties": {"repobilityId": "f4cc57c5168b21ee", "scanner": "scanner-primary", "fingerprint": "a8a017861c57bb80", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/sheetSet/SheetSetEntouragePanel.tsx"}, "region": {"startLine": 126}}}]}, {"ruleId": "scanner-01097688535ac3bd", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/SheetEditor/SheetEditor.tsx:720"}, "properties": {"repobilityId": "395a6911d696ae35", "scanner": "scanner-primary", "fingerprint": "01097688535ac3bd", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/SheetEditor/SheetEditor.tsx"}, "region": {"startLine": 720}}}]}, {"ruleId": "scanner-5b93e9dda7c31402", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/src/store/auth.ts:37"}, "properties": {"repobilityId": "9c75349ffb0e1582", "scanner": "scanner-primary", "fingerprint": "5b93e9dda7c31402", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/store/auth.ts"}, "region": {"startLine": 37}}}]}, {"ruleId": "scanner-e0f646c6a4f17ab1", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/src/lib/api.ts:34"}, "properties": {"repobilityId": "90843d9d5330409d", "scanner": "scanner-primary", "fingerprint": "e0f646c6a4f17ab1", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/lib/api.ts"}, "region": {"startLine": 34}}}]}, {"ruleId": "scanner-c47b2aed1a1c2af7", "level": "note", "message": {"text": "Very large file: backend/services/portfolio_renderer.py (933 lines)"}, "properties": {"repobilityId": "3a097aaa01a2827c", "scanner": "scanner-primary", "fingerprint": "c47b2aed1a1c2af7", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-15e5f3e3893debd2", "level": "note", "message": {"text": "Very large file: frontend/src/app/dashboard/templates/[id]/editor/page.tsx (1215 lines)"}, "properties": {"repobilityId": "e40090b2d1bc0323", "scanner": "scanner-primary", "fingerprint": "15e5f3e3893debd2", "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": "89e434f445952120", "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": "25be04fbfa4dbe70", "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": "fbc693ef3d8411c0", "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": "3618cd1e62dfcbb1", "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": "0644316dfe07f7e4", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-2c5f98b152cddb6d", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/launch.json"}, "properties": {"repobilityId": "0de48c0f4ab303d8", "scanner": "scanner-primary", "fingerprint": "2c5f98b152cddb6d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/launch.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-505bc666a82f9849", "level": "error", "message": {"text": "Agent instruction/config may expose a secret: .claude/settings.local.json"}, "properties": {"repobilityId": "777970b0fce0a93b", "scanner": "scanner-primary", "fingerprint": "505bc666a82f9849", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["agent-instructions", "secrets", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/settings.local.json"}, "region": {"startLine": 76}}}]}, {"ruleId": "scanner-d990fd6d84724353", "level": "none", "message": {"text": "Commented-code block (7 lines) in backend/tests/test_auth.py:16"}, "properties": {"repobilityId": "540bd28437358c65", "scanner": "scanner-primary", "fingerprint": "d990fd6d84724353", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-6cd57c91ad4fc845", "level": "note", "message": {"text": "Legacy-named symbol `list_objects_v2` in backend/services/storage.py:467"}, "properties": {"repobilityId": "7f16fff9a328aa7e", "scanner": "scanner-primary", "fingerprint": "6cd57c91ad4fc845", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-8728eb3412e0cf4c", "level": "error", "message": {"text": "Blocking `requests.post(...)` inside `async def register` \u2014 backend/routes/auth.py:125"}, "properties": {"repobilityId": "fbc6c727f4c16969", "scanner": "scanner-primary", "fingerprint": "8728eb3412e0cf4c", "layer": "quality", "severity": "high", "confidence": 1.0, "tags": ["integrity", "sync-io-in-async", "performance"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/auth.py"}, "region": {"startLine": 125}}}]}, {"ruleId": "scanner-904f9c4505127869", "level": "error", "message": {"text": "Blocking `requests.post(...)` inside `async def signin` \u2014 backend/routes/auth.py:209"}, "properties": {"repobilityId": "7a5c5ff14f3c313a", "scanner": "scanner-primary", "fingerprint": "904f9c4505127869", "layer": "quality", "severity": "high", "confidence": 1.0, "tags": ["integrity", "sync-io-in-async", "performance"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/auth.py"}, "region": {"startLine": 209}}}]}, {"ruleId": "scanner-06520f59734ac6c3", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/project/[id]/generate/page.tsx:97"}, "properties": {"repobilityId": "d7a2d99ffceeebcb", "scanner": "scanner-primary", "fingerprint": "06520f59734ac6c3", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-f49e23f336672c07", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/project/[id]/portfolio/[portfolioId]/page.tsx:134"}, "properties": {"repobilityId": "64374f9da1cddbb6", "scanner": "scanner-primary", "fingerprint": "f49e23f336672c07", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c64d51c7afb396ab", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/templates/page.tsx:793"}, "properties": {"repobilityId": "4e08988d42208560", "scanner": "scanner-primary", "fingerprint": "c64d51c7afb396ab", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-16cf65689e818b04", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/templates/[id]/editor/page.tsx:202"}, "properties": {"repobilityId": "f0e047c44160a08c", "scanner": "scanner-primary", "fingerprint": "16cf65689e818b04", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-f751d851ee4c214c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/dashboard/portfolio-book/[id]/page.tsx:53"}, "properties": {"repobilityId": "0169f80c2c8bafc6", "scanner": "scanner-primary", "fingerprint": "f751d851ee4c214c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-4b96339e87f85986", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/portfolio-wizard/PortfolioWizard.tsx:94"}, "properties": {"repobilityId": "2060b859e6bce7b6", "scanner": "scanner-primary", "fingerprint": "4b96339e87f85986", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3d9ebb726694fa34", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/PortfolioPreview/PortfolioPreview.tsx:126"}, "properties": {"repobilityId": "9baf0a930003dea9", "scanner": "scanner-primary", "fingerprint": "3d9ebb726694fa34", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3caeeca7d6fe267b", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/presentationExport.ts:242"}, "properties": {"repobilityId": "22d572b150c9e04c", "scanner": "scanner-primary", "fingerprint": "3caeeca7d6fe267b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-be761bc8a3756bf4", "level": "none", "message": {"text": "Commented-code block (5 lines) in frontend/src/lib/assetTaxonomy.ts:139"}, "properties": {"repobilityId": "60795f90d2362c0d", "scanner": "scanner-primary", "fingerprint": "be761bc8a3756bf4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-734233e12427b0f6", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/lib/firebase.ts:44"}, "properties": {"repobilityId": "b330943eec6404ba", "scanner": "scanner-primary", "fingerprint": "734233e12427b0f6", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-022e6399d1ef2beb", "level": "note", "message": {"text": "12 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "7bf4178327da75a2", "scanner": "scanner-primary", "fingerprint": "022e6399d1ef2beb", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-33a6b62e30ce7ab4", "level": "note", "message": {"text": "Near-duplicate function bodies in 6 places"}, "properties": {"repobilityId": "d648c6c2323d31dd", "scanner": "scanner-primary", "fingerprint": "33a6b62e30ce7ab4", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "b0ecb80856dc849d", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "310cb0d71f5b0dfd", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "4a5a6c65c29c1a14", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "ae16e5a3f8fa6298", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "ff6659a4707df524", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "436d71e0e8a2c565", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "f82700b89e0579f3", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "140c05f21d94c13d", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "bc99feb8a0a70e60", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "8680411baa33c73f", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "c8903caefe0b28c8", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-49c98f7cedd9c977", "level": "note", "message": {"text": "Near-duplicate function bodies in 4 places"}, "properties": {"repobilityId": "6c44883dc662744c", "scanner": "scanner-primary", "fingerprint": "49c98f7cedd9c977", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "04c98fe529fc124e", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-49c98f7cedd9c977", "level": "note", "message": {"text": "Near-duplicate function bodies in 4 places"}, "properties": {"repobilityId": "9d6e8058b6eb772d", "scanner": "scanner-primary", "fingerprint": "49c98f7cedd9c977", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "697c29a29e2a46bd", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "d24e15b5fb50e7fd", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "66e0575a0d55f3a4", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "e44b44915d906575", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "f3253c7895f2e71d", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-eb95fa72de198534", "level": "error", "message": {"text": "FastAPI PUT `save_document` without auth dependency \u2014 backend/routes/documents.py:32"}, "properties": {"repobilityId": "1a6ccfaa58b66804", "scanner": "scanner-primary", "fingerprint": "eb95fa72de198534", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/documents.py"}, "region": {"startLine": 32}}}]}, {"ruleId": "scanner-c0a3aaa78c16da68", "level": "error", "message": {"text": "FastAPI POST `check_storage_health` without auth dependency \u2014 backend/routes/documents.py:64"}, "properties": {"repobilityId": "5b3adc8dd314d73d", "scanner": "scanner-primary", "fingerprint": "c0a3aaa78c16da68", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/documents.py"}, "region": {"startLine": 64}}}]}, {"ruleId": "scanner-2a3d52498ae8e873", "level": "error", "message": {"text": "FastAPI POST `export_document_as_pdf` without auth dependency \u2014 backend/routes/documents.py:85"}, "properties": {"repobilityId": "942178d6237cad6b", "scanner": "scanner-primary", "fingerprint": "2a3d52498ae8e873", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/documents.py"}, "region": {"startLine": 85}}}]}, {"ruleId": "scanner-dd1fb7c01f2a0661", "level": "error", "message": {"text": "FastAPI POST `create_project` without auth dependency \u2014 backend/routes/projects.py:23"}, "properties": {"repobilityId": "5648c9ae00eebd77", "scanner": "scanner-primary", "fingerprint": "dd1fb7c01f2a0661", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/projects.py"}, "region": {"startLine": 23}}}]}, {"ruleId": "scanner-c99e306eadd8b4b1", "level": "error", "message": {"text": "FastAPI PUT `update_project` without auth dependency \u2014 backend/routes/projects.py:55"}, "properties": {"repobilityId": "9bd5616a89689684", "scanner": "scanner-primary", "fingerprint": "c99e306eadd8b4b1", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/projects.py"}, "region": {"startLine": 55}}}]}, {"ruleId": "scanner-5c45e862ed6b181d", "level": "error", "message": {"text": "FastAPI DELETE `delete_project` without auth dependency \u2014 backend/routes/projects.py:68"}, "properties": {"repobilityId": "0452f6584a06abbb", "scanner": "scanner-primary", "fingerprint": "5c45e862ed6b181d", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/projects.py"}, "region": {"startLine": 68}}}]}, {"ruleId": "scanner-a8c71168b107f9ce", "level": "error", "message": {"text": "FastAPI POST `analyze_project_assets` without auth dependency \u2014 backend/routes/projects.py:78"}, "properties": {"repobilityId": "7e9f60da859223bc", "scanner": "scanner-primary", "fingerprint": "a8c71168b107f9ce", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/projects.py"}, "region": {"startLine": 78}}}]}, {"ruleId": "scanner-720b6e3da5b485da", "level": "error", "message": {"text": "FastAPI POST `publish_project` without auth dependency \u2014 backend/routes/projects.py:108"}, "properties": {"repobilityId": "f70bf699c702696e", "scanner": "scanner-primary", "fingerprint": "720b6e3da5b485da", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/projects.py"}, "region": {"startLine": 108}}}]}, {"ruleId": "scanner-9a714be8c6d1ade4", "level": "error", "message": {"text": "FastAPI POST `unpublish_project` without auth dependency \u2014 backend/routes/projects.py:142"}, "properties": {"repobilityId": "25e4dd8524a6bfbf", "scanner": "scanner-primary", "fingerprint": "9a714be8c6d1ade4", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/projects.py"}, "region": {"startLine": 142}}}]}, {"ruleId": "scanner-14854a3b80a41a70", "level": "error", "message": {"text": "FastAPI POST `add_feedback` without auth dependency \u2014 backend/routes/sheets.py:445"}, "properties": {"repobilityId": "832a629e89d215fe", "scanner": "scanner-primary", "fingerprint": "14854a3b80a41a70", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/sheets.py"}, "region": {"startLine": 445}}}]}, {"ruleId": "scanner-df599d1a838a5a0c", "level": "error", "message": {"text": "FastAPI POST `signin` without auth dependency \u2014 backend/routes/auth.py:189"}, "properties": {"repobilityId": "6b222c2f8215e837", "scanner": "scanner-primary", "fingerprint": "df599d1a838a5a0c", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/auth.py"}, "region": {"startLine": 189}}}]}, {"ruleId": "scanner-e5ef15bff416a811", "level": "error", "message": {"text": "FastAPI POST `verify_token` without auth dependency \u2014 backend/routes/auth.py:278"}, "properties": {"repobilityId": "83ac4b7287fb5a4f", "scanner": "scanner-primary", "fingerprint": "e5ef15bff416a811", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/auth.py"}, "region": {"startLine": 278}}}]}, {"ruleId": "scanner-836e5ee441781b14", "level": "error", "message": {"text": "FastAPI POST `log_view` without auth dependency \u2014 backend/routes/portfolios.py:703"}, "properties": {"repobilityId": "c32e7e002fd173c0", "scanner": "scanner-primary", "fingerprint": "836e5ee441781b14", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/portfolios.py"}, "region": {"startLine": 703}}}]}, {"ruleId": "scanner-033ee701deb8d84c", "level": "error", "message": {"text": "FastAPI POST `log_share` without auth dependency \u2014 backend/routes/portfolios.py:720"}, "properties": {"repobilityId": "e83a552e5457ca66", "scanner": "scanner-primary", "fingerprint": "033ee701deb8d84c", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/portfolios.py"}, "region": {"startLine": 720}}}]}, {"ruleId": "scanner-74c39dfca1b5dc59", "level": "error", "message": {"text": "FastAPI POST `log_download` without auth dependency \u2014 backend/routes/portfolios.py:737"}, "properties": {"repobilityId": "40339118c2c2d690", "scanner": "scanner-primary", "fingerprint": "74c39dfca1b5dc59", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/routes/portfolios.py"}, "region": {"startLine": 737}}}]}, {"ruleId": "scanner-726c7323cb9275f3", "level": "error", "message": {"text": "FastAPI POST `create_portfolio` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:32"}, "properties": {"repobilityId": "a8e73201ba852b20", "scanner": "scanner-primary", "fingerprint": "726c7323cb9275f3", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/lib/backend/portfolio_api.py"}, "region": {"startLine": 32}}}]}, {"ruleId": "scanner-c4c9335ccdc6bcb3", "level": "error", "message": {"text": "FastAPI PATCH `update_portfolio` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:45"}, "properties": {"repobilityId": "c9a5bb75b435ba70", "scanner": "scanner-primary", "fingerprint": "c4c9335ccdc6bcb3", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/lib/backend/portfolio_api.py"}, "region": {"startLine": 45}}}]}, {"ruleId": "scanner-1c60c84ca18d7780", "level": "error", "message": {"text": "FastAPI DELETE `delete_portfolio` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:52"}, "properties": {"repobilityId": "d1134830851fe1a0", "scanner": "scanner-primary", "fingerprint": "1c60c84ca18d7780", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/lib/backend/portfolio_api.py"}, "region": {"startLine": 52}}}]}, {"ruleId": "scanner-9acb80ba10f25a0a", "level": "error", "message": {"text": "FastAPI POST `create_page` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:60"}, "properties": {"repobilityId": "f86fd1a2c339be01", "scanner": "scanner-primary", "fingerprint": "9acb80ba10f25a0a", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/lib/backend/portfolio_api.py"}, "region": {"startLine": 60}}}]}, {"ruleId": "scanner-15fef30edc7af49f", "level": "error", "message": {"text": "FastAPI POST `batch_create_pages` without auth dependency \u2014 frontend/src/lib/backend/portfolio_api.py:74"}, "properties": {"repobilityId": "3c12647f97395170", "scanner": "scanner-primary", "fingerprint": "15fef30edc7af49f", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/lib/backend/portfolio_api.py"}, "region": {"startLine": 74}}}]}, {"ruleId": "scanner-8a48622297ae6f65", "level": "error", "message": {"text": "Dangling fetch: POST /api/portfolios/${portfolioId}/download (frontend/src/components/ShareModal/ShareModal.tsx:141)"}, "properties": {"repobilityId": "ae794208e83d6d74", "scanner": "scanner-primary", "fingerprint": "8a48622297ae6f65", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-5baa8971ebe192a1", "level": "note", "message": {"text": "Unused endpoint: GET /"}, "properties": {"repobilityId": "9266ee3970fba636", "scanner": "scanner-primary", "fingerprint": "5baa8971ebe192a1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-eb0428442a390121", "level": "note", "message": {"text": "Unused endpoint: GET /docs"}, "properties": {"repobilityId": "35656d649b1559b9", "scanner": "scanner-primary", "fingerprint": "eb0428442a390121", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ccd81e719e804d1f", "level": "note", "message": {"text": "Unused endpoint: PUT /api/projects/{project_id}/document"}, "properties": {"repobilityId": "69487c67e9736db6", "scanner": "scanner-primary", "fingerprint": "ccd81e719e804d1f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8fbd611e44e40747", "level": "note", "message": {"text": "Unused endpoint: GET /api/projects/{project_id}/document"}, "properties": {"repobilityId": "ba473d39adaae235", "scanner": "scanner-primary", "fingerprint": "8fbd611e44e40747", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d8c37f1cb1273669", "level": "note", "message": {"text": "Unused endpoint: POST /api/projects/{project_id}/document/health"}, "properties": {"repobilityId": "5db66c0d07e186ac", "scanner": "scanner-primary", "fingerprint": "d8c37f1cb1273669", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-21f1ccd4e67e692c", "level": "note", "message": {"text": "Unused endpoint: POST /api/projects/{project_id}/document/export-pdf"}, "properties": {"repobilityId": "832fce5f2c515034", "scanner": "scanner-primary", "fingerprint": "21f1ccd4e67e692c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e73f8bc01f6cae3b", "level": "note", "message": {"text": "Unused endpoint: GET /portfolios"}, "properties": {"repobilityId": "61d3960094d2e371", "scanner": "scanner-primary", "fingerprint": "e73f8bc01f6cae3b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-66421035e66ef306", "level": "note", "message": {"text": "Unused endpoint: GET /portfolios/{template_id}"}, "properties": {"repobilityId": "3944c4927fb8f9d2", "scanner": "scanner-primary", "fingerprint": "66421035e66ef306", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3e01def489117c63", "level": "note", "message": {"text": "Unused endpoint: GET /portfolios/categories"}, "properties": {"repobilityId": "f5a0b5f8d9155c22", "scanner": "scanner-primary", "fingerprint": "3e01def489117c63", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-24a8ae7e32d82da6", "level": "note", "message": {"text": "Unused endpoint: GET /sheets"}, "properties": {"repobilityId": "9e5f11ff98555e50", "scanner": "scanner-primary", "fingerprint": "24a8ae7e32d82da6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-770ff7c05343426b", "level": "note", "message": {"text": "Unused endpoint: GET /sheets/{template_id}"}, "properties": {"repobilityId": "557c222dac1e6810", "scanner": "scanner-primary", "fingerprint": "770ff7c05343426b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8439f9aecf4fc9c3", "level": "note", "message": {"text": "Unused endpoint: GET /sheets/types"}, "properties": {"repobilityId": "7f32a8c3219c8111", "scanner": "scanner-primary", "fingerprint": "8439f9aecf4fc9c3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9b50ad1859bcb150", "level": "note", "message": {"text": "Unused endpoint: GET /sheets/formats"}, "properties": {"repobilityId": "8b62eaee0747dcc4", "scanner": "scanner-primary", "fingerprint": "9b50ad1859bcb150", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-92e07935c226add3", "level": "note", "message": {"text": "Unused endpoint: GET /compatibility/{portfolio_id}"}, "properties": {"repobilityId": "626b2976608a9b37", "scanner": "scanner-primary", "fingerprint": "92e07935c226add3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5e88c2bc105d7c89", "level": "note", "message": {"text": "Unused endpoint: POST /portfolios/{template_id}/apply/{portfolio_id}"}, "properties": {"repobilityId": "2029d481ed84eac5", "scanner": "scanner-primary", "fingerprint": "5e88c2bc105d7c89", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cd8dc4599ec52a08", "level": "note", "message": {"text": "Unused endpoint: GET /stats"}, "properties": {"repobilityId": "925d26dd183b96d0", "scanner": "scanner-primary", "fingerprint": "cd8dc4599ec52a08", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7f2fa92b3bfcd9ec", "level": "note", "message": {"text": "Unused endpoint: GET /{portfolio_id}/assets/{asset_id}/versions"}, "properties": {"repobilityId": "8f1ac336009fbe2e", "scanner": "scanner-primary", "fingerprint": "7f2fa92b3bfcd9ec", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-609a5ede22faa740", "level": "note", "message": {"text": "Unused endpoint: GET /{portfolio_id}/assets/{asset_id}/versions/{version_num}"}, "properties": {"repobilityId": "c0fb8b033b558310", "scanner": "scanner-primary", "fingerprint": "609a5ede22faa740", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d117e6e68749a9cb", "level": "note", "message": {"text": "Unused endpoint: POST /{portfolio_id}/assets/{asset_id}/versions/{version_num}/restore"}, "properties": {"repobilityId": "6c6e91e1c5b0c204", "scanner": "scanner-primary", "fingerprint": "d117e6e68749a9cb", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7a8ec053ac4550d6", "level": "note", "message": {"text": "Unused endpoint: GET /{portfolio_id}/assets/{asset_id}/versions/{version_a}/compare/{version_b}"}, "properties": {"repobilityId": "0b281bbe15176510", "scanner": "scanner-primary", "fingerprint": "7a8ec053ac4550d6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-55b2e4b9fcc605e0", "level": "note", "message": {"text": "Unused endpoint: POST /{portfolio_id}/assets/{asset_id}/versions/cleanup"}, "properties": {"repobilityId": "4023272e5b84796f", "scanner": "scanner-primary", "fingerprint": "55b2e4b9fcc605e0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a9823a07cbabf4a7", "level": "note", "message": {"text": "Unused endpoint: GET /{portfolio_id}/versions/statistics"}, "properties": {"repobilityId": "bf715b9dd2c9147f", "scanner": "scanner-primary", "fingerprint": "a9823a07cbabf4a7", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b3eab01e2a828176", "level": "note", "message": {"text": "Unused endpoint: POST /{portfolio_id}/projects/{project_id}/generate-description"}, "properties": {"repobilityId": "b6a9eb66a241622d", "scanner": "scanner-primary", "fingerprint": "b3eab01e2a828176", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ba12b33f9802b84c", "level": "note", "message": {"text": "Unused endpoint: POST /{portfolio_id}/projects/{project_id}/generate-concept"}, "properties": {"repobilityId": "38c7f648b09e6552", "scanner": "scanner-primary", "fingerprint": "ba12b33f9802b84c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ebdc6e9cbd1c0578", "level": "note", "message": {"text": "Unused endpoint: POST /{portfolio_id}/assets/{asset_id}/generate-caption"}, "properties": {"repobilityId": "9359699f2493871d", "scanner": "scanner-primary", "fingerprint": "ebdc6e9cbd1c0578", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1f30ae38192d3bdc", "level": "note", "message": {"text": "Unused endpoint: POST /{portfolio_id}/generate-bio"}, "properties": {"repobilityId": "4445a3b6404d09d4", "scanner": "scanner-primary", "fingerprint": "1f30ae38192d3bdc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7cd6ec7861145955", "level": "note", "message": {"text": "Unused endpoint: POST /{portfolio_id}/projects/{project_id}/suggest-titles"}, "properties": {"repobilityId": "751cd870ea595135", "scanner": "scanner-primary", "fingerprint": "7cd6ec7861145955", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-af58a8cf98426b02", "level": "note", "message": {"text": "Unused endpoint: POST /{portfolio_id}/generate-taglines"}, "properties": {"repobilityId": "86126be177607d09", "scanner": "scanner-primary", "fingerprint": "af58a8cf98426b02", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-688593cffed22a5e", "level": "note", "message": {"text": "Unused endpoint: GET /ai-tones"}, "properties": {"repobilityId": "1a228b22e0b754dc", "scanner": "scanner-primary", "fingerprint": "688593cffed22a5e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4533c42ca419ca8f", "level": "note", "message": {"text": "Unused endpoint: POST /{portfolio_id}/analyze-content"}, "properties": {"repobilityId": "1275d6bf632c39de", "scanner": "scanner-primary", "fingerprint": "4533c42ca419ca8f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a6341bb1599f3948", "level": "note", "message": {"text": "Unused endpoint: POST /{portfolio_id}/improve-text"}, "properties": {"repobilityId": "bb26a2615dad48df", "scanner": "scanner-primary", "fingerprint": "a6341bb1599f3948", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7a009b1a56794f45", "level": "note", "message": {"text": "Unused endpoint: POST /"}, "properties": {"repobilityId": "ce2b3cfe59e0812b", "scanner": "scanner-primary", "fingerprint": "7a009b1a56794f45", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b6272106dd21a6cd", "level": "note", "message": {"text": "Unused endpoint: GET /{portfolio_id}"}, "properties": {"repobilityId": "8512ec613371c94d", "scanner": "scanner-primary", "fingerprint": "b6272106dd21a6cd", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-64ee4fe3c00804e3", "level": "note", "message": {"text": "Unused endpoint: PUT /{portfolio_id}"}, "properties": {"repobilityId": "d8145e989db4c11f", "scanner": "scanner-primary", "fingerprint": "64ee4fe3c00804e3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e8ab9a663becacde", "level": "note", "message": {"text": "Unused endpoint: DELETE /{portfolio_id}"}, "properties": {"repobilityId": "aeeea6bd4f40ed6c", "scanner": "scanner-primary", "fingerprint": "e8ab9a663becacde", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2e7955eca4f1ccef", "level": "note", "message": {"text": "Unused endpoint: GET /{portfolio_id}/settings"}, "properties": {"repobilityId": "29f0407e495fa4eb", "scanner": "scanner-primary", "fingerprint": "2e7955eca4f1ccef", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4c64d9b7bb815257", "level": "note", "message": {"text": "Unused endpoint: PUT /{portfolio_id}/settings"}, "properties": {"repobilityId": "96a5d761bf0ab5e6", "scanner": "scanner-primary", "fingerprint": "4c64d9b7bb815257", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1f6c1a5f4dc7f897", "level": "note", "message": {"text": "Unused endpoint: GET /{portfolio_id}/public"}, "properties": {"repobilityId": "adc88bcf9d47ef36", "scanner": "scanner-primary", "fingerprint": "1f6c1a5f4dc7f897", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fef31f6e07aa8c88", "level": "note", "message": {"text": "Unused endpoint: GET /api/sheet-sets"}, "properties": {"repobilityId": "d57797ba8818b732", "scanner": "scanner-primary", "fingerprint": "fef31f6e07aa8c88", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7322029a79126681", "level": "note", "message": {"text": "Unused endpoint: GET /api/projects/{project_id}/sheet-sets"}, "properties": {"repobilityId": "eb2cd7eb616e0ae3", "scanner": "scanner-primary", "fingerprint": "7322029a79126681", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-dbe7ecbe67a2bfce", "level": "note", "message": {"text": "Unused endpoint: GET /api/projects/{project_id}/sheet-sets/{set_id}"}, "properties": {"repobilityId": "940d51445c74db71", "scanner": "scanner-primary", "fingerprint": "dbe7ecbe67a2bfce", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-dc7eacfc509383e1", "level": "note", "message": {"text": "Unused endpoint: POST /api/projects/{project_id}/sheet-sets"}, "properties": {"repobilityId": "e28d68d9edaf6894", "scanner": "scanner-primary", "fingerprint": "dc7eacfc509383e1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9593c516d54bf6fb", "level": "note", "message": {"text": "Unused endpoint: PUT /api/projects/{project_id}/sheet-sets/{set_id}"}, "properties": {"repobilityId": "2063e7870273b215", "scanner": "scanner-primary", "fingerprint": "9593c516d54bf6fb", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d6535ab3fa74bdf4", "level": "note", "message": {"text": "Unused endpoint: DELETE /api/projects/{project_id}/sheet-sets/{set_id}"}, "properties": {"repobilityId": "d4c86c9cfa087351", "scanner": "scanner-primary", "fingerprint": "d6535ab3fa74bdf4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3b94923f366fed0e", "level": "note", "message": {"text": "Unused endpoint: GET /api/projects"}, "properties": {"repobilityId": "432cf592b6c1b657", "scanner": "scanner-primary", "fingerprint": "3b94923f366fed0e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-16a480533217943d", "level": "note", "message": {"text": "Unused endpoint: POST /api/projects"}, "properties": {"repobilityId": "e3e1f2e7ac900243", "scanner": "scanner-primary", "fingerprint": "16a480533217943d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cb2dcb5114cd8bdc", "level": "note", "message": {"text": "Unused endpoint: GET /api/projects/{project_id}"}, "properties": {"repobilityId": "3399e55da377e130", "scanner": "scanner-primary", "fingerprint": "cb2dcb5114cd8bdc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-753f53a99e9de17c", "level": "note", "message": {"text": "Unused endpoint: PUT /api/projects/{project_id}"}, "properties": {"repobilityId": "e788cccab3214195", "scanner": "scanner-primary", "fingerprint": "753f53a99e9de17c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-910e7327fca49aff", "level": "note", "message": {"text": "Unused endpoint: DELETE /api/projects/{project_id}"}, "properties": {"repobilityId": "b77bf99933f748d0", "scanner": "scanner-primary", "fingerprint": "910e7327fca49aff", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-07f463353c20146c", "level": "note", "message": {"text": "Unused endpoint: POST /api/projects/{project_id}/analyze-assets"}, "properties": {"repobilityId": "9da5bf5ef088af7e", "scanner": "scanner-primary", "fingerprint": "07f463353c20146c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}