{"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-87319e9c078f001a", "name": "Possibly dead Python function: db_for_read", "shortDescription": {"text": "Possibly dead Python function: db_for_read"}, "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-d4486c999a00bfaa", "name": "Possibly dead Python function: db_for_write", "shortDescription": {"text": "Possibly dead Python function: db_for_write"}, "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-7479ec258d6dbbca", "name": "Possibly dead Python function: allow_relation", "shortDescription": {"text": "Possibly dead Python function: allow_relation"}, "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-eecfde167a41603a", "name": "Possibly dead Python function: allow_migrate", "shortDescription": {"text": "Possibly dead Python function: allow_migrate"}, "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-14b8dea6eb651705", "name": "Possibly dead Python function: handle_starttag", "shortDescription": {"text": "Possibly dead Python function: handle_starttag"}, "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-4b3a47b74411cde4", "name": "Possibly dead Python function: handle_endtag", "shortDescription": {"text": "Possibly dead Python function: handle_endtag"}, "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-2c76b78f612b2eab", "name": "Possibly dead Python function: handle_data", "shortDescription": {"text": "Possibly dead Python function: handle_data"}, "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-36c881adc1f00673", "name": "Possibly dead Python function: list_blogs", "shortDescription": {"text": "Possibly dead Python function: list_blogs"}, "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-df76f1f6f55bd710", "name": "Possibly dead Python function: authenticate_header", "shortDescription": {"text": "Possibly dead Python function: authenticate_header"}, "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-e36528edea7e3494", "name": "Possibly dead Python function: allow_request", "shortDescription": {"text": "Possibly dead Python function: allow_request"}, "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-29c45a8ade99c429", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/PublicAuditPage.tsx:355", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/PublicAuditPage.tsx:355"}, "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-a1e07770d3cadefe", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/components/LandingRenderer.tsx:153", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/components/LandingRenderer.tsx:153"}, "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-6c8328a48c2c3fdd", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/MultiDomainCompare.tsx:182", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/MultiDomainCompare.tsx:182"}, "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-e93fa3fcd4234030", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/SearchTrendsPanel.tsx:225", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/SearchTrendsPanel.tsx:225"}, "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-74311b7c483913ca", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/PageBreadcrumb.tsx:45", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/PageBreadcrumb.tsx:45"}, "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-4365388cb5361077", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/LandingPage.tsx:1395", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/LandingPage.tsx:1395"}, "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-d284a11d6516602f", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/ImageInsertDialog.tsx:268", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/ImageInsertDialog.tsx:268"}, "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-0215bf44b1f84008", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/OnboardingExternalPage.tsx:451", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/OnboardingExternalPage.tsx:451"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-5161d76b8748e5ea", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/components/OnboardingExternalPage.tsx:200", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/components/OnboardingExternalPage.tsx:200"}, "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-461cce895a64c8e1", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/SiteSelector.tsx:205", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/SiteSelector.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-62ffc330d7ef3f71", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/SEOAnalyzer.tsx:1547", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/SEOAnalyzer.tsx:1547"}, "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-649095ac8ef81f44", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/components/MarkdownPreview.tsx:29", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/components/MarkdownPreview.tsx:29"}, "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-45e155323c77181c", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/BillingPage.tsx:393", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/BillingPage.tsx:393"}, "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-74b0e7bb02ab34de", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/BrandingPreview.tsx:127", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/BrandingPreview.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-ad8f1386f4f054e1", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/DashboardSidebar.tsx:105", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/DashboardSidebar.tsx:105"}, "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-fa0357b4f4a94f8e", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/ApiKeysPage.tsx:232", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/ApiKeysPage.tsx:232"}, "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-c5d9dcb34bd0d673", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/JobsDock.tsx:151", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/JobsDock.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-4b9a9c04278d1a00", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/PlagiarismCard.tsx:196", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/PlagiarismCard.tsx:196"}, "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-b2edcd933ebcd967", "name": "TODO/FIXME marker in shipping code \u2014 marketing/components/dashboard/KeywordTrackerPage.tsx:402", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 marketing/components/dashboard/KeywordTrackerPage.tsx:402"}, "fullDescription": {"text": "Track in /reviews or /issues, not as a code comment that rots.\n\nWhy: Drift control \u2014 shouldn't be the same as Quality TODO scanner.\nRule id: fq.todo-marker"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-23a638b0561343db", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/OverviewPage.tsx:330", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/OverviewPage.tsx:330"}, "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-175cc2f9ebc29938", "name": "TODO/FIXME marker in shipping code \u2014 marketing/components/dashboard/OverviewPage.tsx:23", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 marketing/components/dashboard/OverviewPage.tsx:23"}, "fullDescription": {"text": "Track in /reviews or /issues, not as a code comment that rots.\n\nWhy: Drift control \u2014 shouldn't be the same as Quality TODO scanner.\nRule id: fq.todo-marker"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f0924afc653bad90", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ImageGalleryPage.tsx:193", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ImageGalleryPage.tsx:193"}, "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-b3f25c9b6d78017b", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/BrokenLinksPage.tsx:239", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/BrokenLinksPage.tsx:239"}, "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-379d73d7e277e3bc", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ArticlesPage.tsx:292", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ArticlesPage.tsx:292"}, "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-b4d4744e30cc50f6", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/SerpAnalyzerPage.tsx:344", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/SerpAnalyzerPage.tsx:344"}, "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-25842d654fb283c7", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ContentBrief.tsx:332", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ContentBrief.tsx:332"}, "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-2c66be7f6d7601bd", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/TopicClustersPage.tsx:339", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/TopicClustersPage.tsx:339"}, "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-ef9727942d1378fd", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/BulkAuditPage.tsx:405", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/BulkAuditPage.tsx:405"}, "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-1851637b24e4b327", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/AiVisibilityPage.tsx:555", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/AiVisibilityPage.tsx:555"}, "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-3e795ad1ec3b0086", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/SiteAuditPage.tsx:462", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/SiteAuditPage.tsx:462"}, "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-ca854d2c4cddd66c", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ProofCard.tsx:172", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ProofCard.tsx:172"}, "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-5c54ed6854e01891", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/MultiSiteHealthTable.tsx:230", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/MultiSiteHealthTable.tsx:230"}, "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-0942c0184651df0d", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ContentDecayPage.tsx:408", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ContentDecayPage.tsx:408"}, "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-1b624536a8815fda", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/HreflangCard.tsx:120", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/HreflangCard.tsx:120"}, "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-28f43cc1f1d6a72b", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/CommunityQuestionsPanel.tsx:139", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/CommunityQuestionsPanel.tsx:139"}, "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-d34536aa70418886", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/RecommendationsPanel.tsx:116", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/RecommendationsPanel.tsx:116"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1ed2681f675ba715", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/LinkGraphPage.tsx:172", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/LinkGraphPage.tsx:172"}, "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-029da1874087d510", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/PostEditorPage.tsx:1262", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/PostEditorPage.tsx:1262"}, "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-4cbdc0410a4a6f8c", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/WeeklyDigestPage.tsx:192", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/WeeklyDigestPage.tsx:192"}, "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-c608aa1c79bfa176", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/settings/Memory.tsx:134", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/settings/Memory.tsx:134"}, "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-b4a450c99902cafe", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/settings/SettingsLayoutClient.tsx:54", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/settings/SettingsLayoutClient.tsx:54"}, "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-3fa401ff1b2bc0e7", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/editor/TermUsageTracker.tsx:134", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/editor/TermUsageTracker.tsx:134"}, "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-64f86006386cea98", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/editor/TermMapHeatmap.tsx:118", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/editor/TermMapHeatmap.tsx:118"}, "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-65a1401c3a1d0606", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/app/blog/[slug]/page.tsx:149", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/app/blog/[slug]/page.tsx:149"}, "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-c85d4d0eeb7c2647", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/app/dashboard/overview/page.tsx:146", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/app/dashboard/overview/page.tsx:146"}, "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-c6035142adbc35cc", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/app/proof/[token]/page.tsx:116", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/app/proof/[token]/page.tsx:116"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-36c438c74f6c1786", "name": "`truncate` class without `title=` for hover reveal \u2014 marketing/app/rapport/[token]/page.tsx:177", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/app/rapport/[token]/page.tsx:177"}, "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-46b2a8879be807a1", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 public-blog/src/app/layout.tsx:50", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 public-blog/src/app/layout.tsx:50"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-24f03cac06a8dbc4", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 public-blog/src/app/[slug]/page.tsx:109", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 public-blog/src/app/[slug]/page.tsx:109"}, "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-1607cf625ad846bd", "name": "Insecure pattern 'dangerous_innerhtml' in marketing/components/LandingRenderer.tsx:153", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in marketing/components/LandingRenderer.tsx:153"}, "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-1aebf6551771ba89", "name": "Insecure pattern 'dangerous_innerhtml' in marketing/components/OnboardingExternalPage.tsx:200", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in marketing/components/OnboardingExternalPage.tsx:200"}, "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-e4b226f0b7eb2a68", "name": "Insecure pattern 'dangerous_innerhtml' in marketing/components/MarkdownPreview.tsx:29", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in marketing/components/MarkdownPreview.tsx:29"}, "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-f29217468242bd63", "name": "Insecure pattern 'dangerous_innerhtml' in marketing/app/blog/[slug]/page.tsx:149", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in marketing/app/blog/[slug]/page.tsx:149"}, "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-f58e198ed27298c1", "name": "Insecure pattern 'dangerous_innerhtml' in public-blog/src/app/layout.tsx:50", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in public-blog/src/app/layout.tsx:50"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3d1a0275291860de", "name": "Insecure pattern 'dangerous_innerhtml' in public-blog/src/app/[slug]/page.tsx:109", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in public-blog/src/app/[slug]/page.tsx:109"}, "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-cec4dd3e9c943e3d", "name": "Insecure pattern 'local_storage_auth_token' in cypress/support/commands.ts:53", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in cypress/support/commands.ts:53"}, "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-4ef70ed9275d55cb", "name": "Insecure pattern 'dangerous_innerhtml' in backend/sites_mgmt/prompt_export.py:99", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in backend/sites_mgmt/prompt_export.py:99"}, "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-ead5f67d12157a1e", "name": "Possible secret in backend/sites_mgmt/management/commands/seed_demo_users.py", "shortDescription": {"text": "Possible secret in backend/sites_mgmt/management/commands/seed_demo_users.py"}, "fullDescription": {"text": "Detected pattern matching password_literal. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-61a26bb0710a3ec5", "name": "package.json defines install-time lifecycle scripts", "shortDescription": {"text": "package.json defines install-time lifecycle scripts"}, "fullDescription": {"text": "preinstall/install/postinstall/prepare scripts execute during dependency installation. Review them carefully for network calls, obfuscation, shell execution, or credential access."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4601e3ad3bb28677", "name": "No CI/CD pipelines detected", "shortDescription": {"text": "No CI/CD pipelines detected"}, "fullDescription": {"text": "No GitHub Actions, GitLab CI, or CircleCI configs found. Without CI you can't gate deploys on tests/lints."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-174f099ab7bb1e33", "name": "Very large file: marketing/components/LandingPage.tsx (1610 lines)", "shortDescription": {"text": "Very large file: marketing/components/LandingPage.tsx (1610 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-65143362069953d2", "name": "Very large file: marketing/components/SEOAnalyzer.tsx (2618 lines)", "shortDescription": {"text": "Very large file: marketing/components/SEOAnalyzer.tsx (2618 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-7699a4f40c3ce070", "name": "Very large file: marketing/components/dashboard/PostEditorPage.tsx (1539 lines)", "shortDescription": {"text": "Very large file: marketing/components/dashboard/PostEditorPage.tsx (1539 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-c4c7274e5df23ce7", "name": "Very large file: backend/sites_mgmt/article_generator.py (1979 lines)", "shortDescription": {"text": "Very large file: backend/sites_mgmt/article_generator.py (1979 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-09acfebfa3bb8967", "name": "Very large file: backend/sites_mgmt/views.py (10572 lines)", "shortDescription": {"text": "Very large file: backend/sites_mgmt/views.py (10572 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-c8535acb45da9053", "name": "Very large file: backend/sites_mgmt/models.py (1563 lines)", "shortDescription": {"text": "Very large file: backend/sites_mgmt/models.py (1563 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-8c5e1730c15cc3da", "name": "Very large file: backend/sites_mgmt/api_v1.py (3611 lines)", "shortDescription": {"text": "Very large file: backend/sites_mgmt/api_v1.py (3611 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": "5 test file(s) for 342 source file(s) (ratio 0.01). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-564780bb7771be39", "name": "Node manifest has dependencies but no lockfile: n8n-node/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: n8n-node/package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-df2eb3c8382c6924", "name": "Node manifest has dependencies but no lockfile: public-blog/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: public-blog/package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 11 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 147 placeholder/mock markers across 57 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-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, ci, tests, lockfile. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license, ci, tests, lockfile. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-6c8756cce52ebacb", "name": "Commented-code block (6 lines) in marketing/next.config.ts:7", "shortDescription": {"text": "Commented-code block (6 lines) in marketing/next.config.ts:7"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f1a556c99593c031", "name": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/components/OnboardingExternalPage.tsx:53", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/components/OnboardingExternalPage.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-0481386b612c4e34", "name": "Commented-code block (7 lines) in marketing/components/StatsCard.tsx:107", "shortDescription": {"text": "Commented-code block (7 lines) in marketing/components/StatsCard.tsx:107"}, "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-56f743f44486c928", "name": "Commented-code block (5 lines) in marketing/components/dashboard/KeywordTrackerPage.tsx:400", "shortDescription": {"text": "Commented-code block (5 lines) in marketing/components/dashboard/KeywordTrackerPage.tsx:400"}, "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-313bc095a8195631", "name": "Commented-code block (9 lines) in marketing/components/dashboard/OverviewPage.tsx:100", "shortDescription": {"text": "Commented-code block (9 lines) in marketing/components/dashboard/OverviewPage.tsx:100"}, "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-e3e1805bbd576d14", "name": "Commented-code block (5 lines) in marketing/components/dashboard/AIGeneratorPage.tsx:174", "shortDescription": {"text": "Commented-code block (5 lines) in marketing/components/dashboard/AIGeneratorPage.tsx:174"}, "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-dc5210567e1b8011", "name": "Commented-code block (5 lines) in marketing/components/dashboard/SiteAuditPage.tsx:151", "shortDescription": {"text": "Commented-code block (5 lines) in marketing/components/dashboard/SiteAuditPage.tsx:151"}, "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-6cd88bb27e1dafdb", "name": "Commented-code block (5 lines) in marketing/components/dashboard/ContentDecayPage.tsx:81", "shortDescription": {"text": "Commented-code block (5 lines) in marketing/components/dashboard/ContentDecayPage.tsx:81"}, "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-2d9b5715624fd418", "name": "Commented-code block (5 lines) in marketing/app/auth/[provider]/callback/page.tsx:10", "shortDescription": {"text": "Commented-code block (5 lines) in marketing/app/auth/[provider]/callback/page.tsx:10"}, "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-e7850ccbbe30eaf4", "name": "Commented-code block (8 lines) in marketing/lib/api-client.ts:1048", "shortDescription": {"text": "Commented-code block (8 lines) in marketing/lib/api-client.ts:1048"}, "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-08ba09d3a12a8ad4", "name": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/api-client.ts:92", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/api-client.ts:92"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1ad182c21f31a2ce", "name": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/blog-api.ts:5", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/blog-api.ts:5"}, "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-d06169c690fb387b", "name": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/sites-api.ts:48", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/sites-api.ts:48"}, "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-4f0b0ded48dce93b", "name": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/report-api.ts:36", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/report-api.ts:36"}, "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-4128dc84a588ac47", "name": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/proof-api.ts:43", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/proof-api.ts:43"}, "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-779599e69352d1c2", "name": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/landing-api.ts:69", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/landing-api.ts:69"}, "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-c398806b008300bc", "name": "Commented-code block (5 lines) in marketing/context/AuthContext.tsx:31", "shortDescription": {"text": "Commented-code block (5 lines) in marketing/context/AuthContext.tsx:31"}, "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-d60b0aac7ab76198", "name": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/context/JobsContext.tsx:29", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/context/JobsContext.tsx:29"}, "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-9fa6c34cda12e2b8", "name": "Commented-code block (5 lines) in mcp-server/src/api.ts:862", "shortDescription": {"text": "Commented-code block (5 lines) in mcp-server/src/api.ts:862"}, "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-c31cdfa3cd5e26e9", "name": "Commented-code block (6 lines) in mcp-server/src/http.ts:54", "shortDescription": {"text": "Commented-code block (6 lines) in mcp-server/src/http.ts:54"}, "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-0de2f0436be30180", "name": "Commented-code block (6 lines) in cypress/support/commands.ts:46", "shortDescription": {"text": "Commented-code block (6 lines) in cypress/support/commands.ts:46"}, "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-0bfabb05f90f8114", "name": "Stub function `db_for_write` (body is just `pass`/`return`) \u2014 backend/config/db_router.py:15", "shortDescription": {"text": "Stub function `db_for_write` (body is just `pass`/`return`) \u2014 backend/config/db_router.py:15"}, "fullDescription": {"text": "Likely an AI scaffold that was never filled in. Remove or implement."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b7a8b0c25fc1ce86", "name": "Commented-code block (6 lines) in backend/config/auth_views.py:18", "shortDescription": {"text": "Commented-code block (6 lines) in backend/config/auth_views.py:18"}, "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-31ef55e4f88981d9", "name": "Commented-code block (6 lines) in backend/config/authentication.py:5", "shortDescription": {"text": "Commented-code block (6 lines) in backend/config/authentication.py:5"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-eaeb52cb190557ca", "name": "Commented-code block (7 lines) in backend/config/social_auth_views.py:32", "shortDescription": {"text": "Commented-code block (7 lines) in backend/config/social_auth_views.py:32"}, "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-3165393257737bd9", "name": "Commented-code block (8 lines) in backend/config/settings.py:141", "shortDescription": {"text": "Commented-code block (8 lines) in backend/config/settings.py:141"}, "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-f4b5b5b1d41717b6", "name": "Legacy-named symbol `api_v1` in backend/sites_mgmt/urls.py:42", "shortDescription": {"text": "Legacy-named symbol `api_v1` in backend/sites_mgmt/urls.py:42"}, "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-f4bb043b4a21ab74", "name": "Network/subprocess call without timeout or try/except \u2014 backend/sites_mgmt/article_generator.py:654", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/sites_mgmt/article_generator.py:654"}, "fullDescription": {"text": "`requests.post(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-8afbb1e8d43c57a8", "name": "Legacy-named symbol `api_v1` in backend/sites_mgmt/views.py:10416", "shortDescription": {"text": "Legacy-named symbol `api_v1` in backend/sites_mgmt/views.py:10416"}, "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-1ad23ea8ff6078f4", "name": "Commented-code block (7 lines) in backend/sites_mgmt/views.py:239", "shortDescription": {"text": "Commented-code block (7 lines) in backend/sites_mgmt/views.py:239"}, "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-cb303eb38615953b", "name": "Likely N+1 query: `for cat in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:951", "shortDescription": {"text": "Likely N+1 query: `for cat in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:951"}, "fullDescription": {"text": "The loop iterates a Django queryset and accesses `cat.posts.using` per row, which fires an additional database query each iteration. Add `.select_related('<fk_field>')` for FK / O2O relations or `.prefetch_related('<m2m_or_reverse>')` for many-related lookups, to load everything in 1-2 queries instead of N."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-78091aa850fc7f45", "name": "Likely N+1 query: `for p in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:7842", "shortDescription": {"text": "Likely N+1 query: `for p in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:7842"}, "fullDescription": {"text": "The loop iterates a Django queryset and accesses `p.published_at.isoformat` per row, which fires an additional database query each iteration. Add `.select_related('<fk_field>')` for FK / O2O relations or `.prefetch_related('<m2m_or_reverse>')` for many-related lookups, to load everything in 1-2 queries instead of N."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-63a08245fac4b1a7", "name": "Likely N+1 query: `for p in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:7861", "shortDescription": {"text": "Likely N+1 query: `for p in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:7861"}, "fullDescription": {"text": "The loop iterates a Django queryset and accesses `p.published_at.isoformat` per row, which fires an additional database query each iteration. Add `.select_related('<fk_field>')` for FK / O2O relations or `.prefetch_related('<m2m_or_reverse>')` for many-related lookups, to load everything in 1-2 queries instead of N."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f4378c34abc104f5", "name": "Likely N+1 query: `for m in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:8589", "shortDescription": {"text": "Likely N+1 query: `for m in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:8589"}, "fullDescription": {"text": "The loop iterates a Django queryset and accesses `m.updated_at.isoformat` per row, which fires an additional database query each iteration. Add `.select_related('<fk_field>')` for FK / O2O relations or `.prefetch_related('<m2m_or_reverse>')` for many-related lookups, to load everything in 1-2 queries instead of N."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-bde487d78f2cb6e9", "name": "Network/subprocess call without timeout or try/except \u2014 backend/sites_mgmt/landing_generator.py:57", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/sites_mgmt/landing_generator.py:57"}, "fullDescription": {"text": "`requests.post(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d3df4d91125b2aa1", "name": "Commented-code block (5 lines) in backend/sites_mgmt/strategic_opportunities.py:71", "shortDescription": {"text": "Commented-code block (5 lines) in backend/sites_mgmt/strategic_opportunities.py:71"}, "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-b3d855cb046a3398", "name": "Commented-code block (5 lines) in backend/sites_mgmt/shopify_adapter.py:406", "shortDescription": {"text": "Commented-code block (5 lines) in backend/sites_mgmt/shopify_adapter.py:406"}, "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-c92a8eca3e8193a1", "name": "Legacy-named symbol `embed_calls_v1` in backend/sites_mgmt/tests_memory.py:213", "shortDescription": {"text": "Legacy-named symbol `embed_calls_v1` in backend/sites_mgmt/tests_memory.py:213"}, "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-e80c3b7d44675630", "name": "Commented-code block (5 lines) in backend/sites_mgmt/models.py:253", "shortDescription": {"text": "Commented-code block (5 lines) in backend/sites_mgmt/models.py:253"}, "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-86f6d38a008f769d", "name": "Legacy-named symbol `api_v1` in backend/sites_mgmt/api_v1.py:124", "shortDescription": {"text": "Legacy-named symbol `api_v1` in backend/sites_mgmt/api_v1.py:124"}, "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-145d4e2925a0dd84", "name": "Commented-code block (6 lines) in backend/sites_mgmt/api_v1.py:132", "shortDescription": {"text": "Commented-code block (6 lines) in backend/sites_mgmt/api_v1.py:132"}, "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-4fc72d0bf05014dc", "name": "Network/subprocess call without timeout or try/except \u2014 backend/sites_mgmt/api_v1.py:1564", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/sites_mgmt/api_v1.py:1564"}, "fullDescription": {"text": "`requests.post(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-26b089d84055bdf5", "name": "Likely N+1 query: `for p in \u2026` triggers a query per row \u2014 backend/sites_mgmt/api_v1.py:3199", "shortDescription": {"text": "Likely N+1 query: `for p in \u2026` triggers a query per row \u2014 backend/sites_mgmt/api_v1.py:3199"}, "fullDescription": {"text": "The loop iterates a Django queryset and accesses `p.results.all` per row, which fires an additional database query each iteration. Add `.select_related('<fk_field>')` for FK / O2O relations or `.prefetch_related('<m2m_or_reverse>')` for many-related lookups, to load everything in 1-2 queries instead of N."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4b160fb99beb0795", "name": "Likely N+1 query: `for post in \u2026` triggers a query per row \u2014 backend/sites_mgmt/management/commands/attribution_snapshot", "shortDescription": {"text": "Likely N+1 query: `for post in \u2026` triggers a query per row \u2014 backend/sites_mgmt/management/commands/attribution_snapshot.py:73"}, "fullDescription": {"text": "The loop iterates a Django queryset and accesses `post.site.gsc_property_url` per row, which fires an additional database query each iteration. Add `.select_related('<fk_field>')` for FK / O2O relations or `.prefetch_related('<m2m_or_reverse>')` for many-related lookups, to load everything in 1-2 queries instead of N."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a5417a5f0affce13", "name": "52 env vars used in code but missing from .env.example", "shortDescription": {"text": "52 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `ANTHROPIC_API_KEY`, `AUTH_COOKIE_DOMAIN`, `BLOG_DASHBOARD_API_BASE`, `BLOG_DASHBOARD_TOKEN`, `DATABASE_URL`, `DEFAULT_FROM_EMAIL`, `EMAIL_BACKEND`, `EMAIL_HOST` + 44 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-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/blog/models.py:save, backend/blog/models.py:save\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-0027e313ade46c8f", "name": "Near-duplicate function bodies in 7 places", "shortDescription": {"text": "Near-duplicate function bodies in 7 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/config/auth_views.py:post, backend/config/auth_views.py:post, backend/config/auth_views.py:post, backend/config/auth_views.py:post\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-c73146f509615396", "name": "Near-duplicate function bodies in 43 places", "shortDescription": {"text": "Near-duplicate function bodies in 43 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/sites_mgmt/views.py:get_site_for_user, backend/sites_mgmt/views.py:get, backend/sites_mgmt/views.py:get, backend/sites_mgmt/views.py:get\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-c8659acb65313f19", "name": "Near-duplicate function bodies in 60 places", "shortDescription": {"text": "Near-duplicate function bodies in 60 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/sites_mgmt/views.py:post, backend/sites_mgmt/views.py:post, backend/sites_mgmt/views.py:post, backend/sites_mgmt/views.py:post\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-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/sites_mgmt/views.py:delete, backend/sites_mgmt/views.py:delete, backend/sites_mgmt/views.py:delete, backend/sites_mgmt/views.py:delete\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-02525d39071dd2c7", "name": "Near-duplicate function bodies in 5 places", "shortDescription": {"text": "Near-duplicate function bodies in 5 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/sites_mgmt/views_proof.py:get, backend/sites_mgmt/views_proof.py:get, backend/sites_mgmt/views_proof.py:get, backend/sites_mgmt/views_proof.py:get\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/sites_mgmt/tests_proof_loop.py:setUp, backend/sites_mgmt/tests_proof_loop.py:setUp, backend/sites_mgmt/tests_proof_loop.py:setUp, backend/sites_mgmt/tests_proof_loop.py:setUp\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-a0310aec627cfbe3", "name": "Near-duplicate function bodies in 26 places", "shortDescription": {"text": "Near-duplicate function bodies in 26 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/sites_mgmt/api_v1.py:get_rate, backend/sites_mgmt/api_v1.py:get, backend/sites_mgmt/api_v1.py:get, backend/sites_mgmt/api_v1.py:get\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-69b5379230a2294f", "name": "Near-duplicate function bodies in 37 places", "shortDescription": {"text": "Near-duplicate function bodies in 37 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/sites_mgmt/api_v1.py:post, backend/sites_mgmt/api_v1.py:post, backend/sites_mgmt/api_v1.py:post, backend/sites_mgmt/api_v1.py:post\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-cbdbb157c2c7b1db", "name": "Frontend route `/blog/:slug` has no Link/navigate to it \u2014 marketing/components/OnboardingExternalPage.tsx", "shortDescription": {"text": "Frontend route `/blog/:slug` has no Link/navigate to it \u2014 marketing/components/OnboardingExternalPage.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3b93da3535fa34e2", "name": "Django CBV `CookieTokenObtainPairView` lacks `LoginRequiredMixin` \u2014 backend/config/auth_views.py:46", "shortDescription": {"text": "Django CBV `CookieTokenObtainPairView` lacks `LoginRequiredMixin` \u2014 backend/config/auth_views.py:46"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-93b5fe4f5a856c85", "name": "Django CBV `CookieTokenRefreshView` lacks `LoginRequiredMixin` \u2014 backend/config/auth_views.py:66", "shortDescription": {"text": "Django CBV `CookieTokenRefreshView` lacks `LoginRequiredMixin` \u2014 backend/config/auth_views.py:66"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-40da82888570fbeb", "name": "Django CBV `V1GenerateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:389", "shortDescription": {"text": "Django CBV `V1GenerateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:389"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-09f5d2bef038bf2a", "name": "Django CBV `V1GenerateSisterArticleView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:475", "shortDescription": {"text": "Django CBV `V1GenerateSisterArticleView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:475"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-198363cb5e780c76", "name": "Django CBV `V1AuditView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:558", "shortDescription": {"text": "Django CBV `V1AuditView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:558"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-751995d8921afe59", "name": "Django CBV `V1BriefView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:582", "shortDescription": {"text": "Django CBV `V1BriefView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:582"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1e0cc50e2ebf4c6e", "name": "Django CBV `V1KeywordsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:594", "shortDescription": {"text": "Django CBV `V1KeywordsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:594"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e9c1d8bc91759df9", "name": "Django CBV `V1RankSnapshotView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:628", "shortDescription": {"text": "Django CBV `V1RankSnapshotView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:628"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-64d3eced23793bee", "name": "Django CBV `V1DigestView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:639", "shortDescription": {"text": "Django CBV `V1DigestView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:639"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3c918b96d23ad118", "name": "Django CBV `V1SiteDetailView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:763", "shortDescription": {"text": "Django CBV `V1SiteDetailView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:763"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4ed2d5622d623491", "name": "Django CBV `V1SiteUpdateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:789", "shortDescription": {"text": "Django CBV `V1SiteUpdateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:789"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-8c21b575cbf71858", "name": "Django CBV `V1ArticleCreateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:816", "shortDescription": {"text": "Django CBV `V1ArticleCreateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:816"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-bc8d4aadd1faec9f", "name": "Django CBV `V1ArticleMutateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:863", "shortDescription": {"text": "Django CBV `V1ArticleMutateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:863"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9c0408cccef71f61", "name": "Django CBV `V1KeywordTrackView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1031", "shortDescription": {"text": "Django CBV `V1KeywordTrackView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1031"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-5babe7876f59fa94", "name": "Django CBV `V1KeywordUntrackView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1073", "shortDescription": {"text": "Django CBV `V1KeywordUntrackView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1073"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d6b0e89998ed3cc5", "name": "Django CBV `V1CompetitorsAnalyzeView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1101", "shortDescription": {"text": "Django CBV `V1CompetitorsAnalyzeView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1101"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d22e26b8e7321324", "name": "Django CBV `V1ContentDecayView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1109", "shortDescription": {"text": "Django CBV `V1ContentDecayView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1109"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-c592a4e7d7cf278e", "name": "Django CBV `V1BrokenLinksView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1118", "shortDescription": {"text": "Django CBV `V1BrokenLinksView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1118"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-23692712a9ba2090", "name": "Django CBV `V1HreflangCheckView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1127", "shortDescription": {"text": "Django CBV `V1HreflangCheckView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1127"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-39a0b1c1602a8bfd", "name": "Django CBV `V1CannibalizationView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1135", "shortDescription": {"text": "Django CBV `V1CannibalizationView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1135"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-247ad53422188f83", "name": "Django CBV `V1LinkSuggestionsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1144", "shortDescription": {"text": "Django CBV `V1LinkSuggestionsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1144"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-bd365304cd1bab62", "name": "Django CBV `V1BulkAuditView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1153", "shortDescription": {"text": "Django CBV `V1BulkAuditView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1153"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b2a301398a1a7c70", "name": "Django CBV `V1ReadabilityView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1162", "shortDescription": {"text": "Django CBV `V1ReadabilityView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1162"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-36dea908e18495f6", "name": "Django CBV `V1PlagiarismView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1170", "shortDescription": {"text": "Django CBV `V1PlagiarismView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1170"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-441e63aedd5dc17e", "name": "Django CBV `V1GSCQueriesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1178", "shortDescription": {"text": "Django CBV `V1GSCQueriesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1178"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-cb746e5395672b57", "name": "Django CBV `V1AutopilotConfigView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1187", "shortDescription": {"text": "Django CBV `V1AutopilotConfigView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1187"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-44464527975e2dd0", "name": "Django CBV `V1AutopilotRunView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1201", "shortDescription": {"text": "Django CBV `V1AutopilotRunView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1201"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f48a2b4a728dc9b1", "name": "Django CBV `V1MemoriesListView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1210", "shortDescription": {"text": "Django CBV `V1MemoriesListView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1210"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-cb4cc53cbee815e9", "name": "Django CBV `V1MemoryDetailView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1228", "shortDescription": {"text": "Django CBV `V1MemoryDetailView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1228"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-496b023b8f6192b7", "name": "Django CBV `V1MemoryRebuildView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1237", "shortDescription": {"text": "Django CBV `V1MemoryRebuildView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1237"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f377d72edaf8624a", "name": "Django CBV `V1ProofSummaryView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1246", "shortDescription": {"text": "Django CBV `V1ProofSummaryView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1246"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e70c01d0bc1fecfd", "name": "Django CBV `V1ProofAttributionView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1255", "shortDescription": {"text": "Django CBV `V1ProofAttributionView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1255"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-eff4994da0ee0477", "name": "Django CBV `V1SuggestKeywordsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1283", "shortDescription": {"text": "Django CBV `V1SuggestKeywordsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1283"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-12f60d8ba25d7dd4", "name": "Django CBV `V1SuggestCompetitorsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1292", "shortDescription": {"text": "Django CBV `V1SuggestCompetitorsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1292"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-62243ec2b28a12c0", "name": "Django CBV `V1PageSpeedView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1309", "shortDescription": {"text": "Django CBV `V1PageSpeedView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1309"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-bbeb076576d0f3ca", "name": "Django CBV `V1PAAView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1317", "shortDescription": {"text": "Django CBV `V1PAAView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1317"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-22616cd04b62b27c", "name": "Django CBV `V1ClassifyIntentView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1393", "shortDescription": {"text": "Django CBV `V1ClassifyIntentView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1393"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6b70d95cfd179090", "name": "Django CBV `V1ProposeKeywordStrategyView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1617", "shortDescription": {"text": "Django CBV `V1ProposeKeywordStrategyView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1617"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-79350394ced9cb9c", "name": "Django CBV `V1ApproveStrategyView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1692", "shortDescription": {"text": "Django CBV `V1ApproveStrategyView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1692"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6d259890c58204eb", "name": "Django CBV `V1CreateLandingView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1796", "shortDescription": {"text": "Django CBV `V1CreateLandingView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1796"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ed48f604d36f8401", "name": "Django CBV `V1GenerateLandingView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1860", "shortDescription": {"text": "Django CBV `V1GenerateLandingView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1860"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7971883028bd3fa5", "name": "Django CBV `V1LinkPagesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1938", "shortDescription": {"text": "Django CBV `V1LinkPagesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1938"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-12a537b798f735b0", "name": "Django CBV `V1CheckRenderabilityView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:2654", "shortDescription": {"text": "Django CBV `V1CheckRenderabilityView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:2654"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-cfd95bdda7ad4ec7", "name": "Django CBV `V1LinkOpportunitiesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:2775", "shortDescription": {"text": "Django CBV `V1LinkOpportunitiesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:2775"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9d9c202411a3b7fd", "name": "Django CBV `V1SerpAnalyzeView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:2862", "shortDescription": {"text": "Django CBV `V1SerpAnalyzeView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:2862"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6370eb55e5724758", "name": "Django CBV `V1AiVisibilityPromptsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3187", "shortDescription": {"text": "Django CBV `V1AiVisibilityPromptsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3187"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7124f9b5a95c72b4", "name": "Django CBV `V1AiVisibilityRunView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3256", "shortDescription": {"text": "Django CBV `V1AiVisibilityRunView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3256"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0d623f718dcbb9cb", "name": "Django CBV `V1StrategicOpportunitiesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3333", "shortDescription": {"text": "Django CBV `V1StrategicOpportunitiesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3333"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-17cdadc4beac04fc", "name": "Django CBV `V1StrategicOpportunitiesRefreshView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3373", "shortDescription": {"text": "Django CBV `V1StrategicOpportunitiesRefreshView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3373"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-af3b8af4d45a243a", "name": "Django CBV `V1StrategicOpportunityActionView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3442", "shortDescription": {"text": "Django CBV `V1StrategicOpportunityActionView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3442"}, "fullDescription": {"text": "Class-based view defines mutating methods (post/put/delete) without inheriting `LoginRequiredMixin`. If auth is enforced via `dispatch()` override or middleware, dismiss this finding."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2932e0a90ed10243", "name": "Dangling fetch: GET https://api.gridar.app/api/sites/${siteId}/sitemap.xml (marketing/components/OnboardingExternalPage.", "shortDescription": {"text": "Dangling fetch: GET https://api.gridar.app/api/sites/${siteId}/sitemap.xml (marketing/components/OnboardingExternalPage.tsx:295)"}, "fullDescription": {"text": "`marketing/components/OnboardingExternalPage.tsx:295` calls `GET https://api.gridar.app/api/sites/${siteId}/sitemap.xml` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/api.gridar.app/api/sites/<p>/sitemap.xml`\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-4571b1dc018a7218", "name": "Dangling fetch: GET https://api.gridar.app/api/sites/${siteId}/rss.xml (marketing/components/OnboardingExternalPage.tsx:", "shortDescription": {"text": "Dangling fetch: GET https://api.gridar.app/api/sites/${siteId}/rss.xml (marketing/components/OnboardingExternalPage.tsx:310)"}, "fullDescription": {"text": "`marketing/components/OnboardingExternalPage.tsx:310` calls `GET https://api.gridar.app/api/sites/${siteId}/rss.xml` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/api.gridar.app/api/sites/<p>/rss.xml`\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-a26b1553cae95613", "name": "Dangling fetch: GET /me/ (mcp-server/src/api.ts:80)", "shortDescription": {"text": "Dangling fetch: GET /me/ (mcp-server/src/api.ts:80)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:80` calls `GET /me/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/me`\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-721f5ec06eae9745", "name": "Dangling fetch: GET /sites/${siteId}/articles/${suffix} (mcp-server/src/api.ts:116)", "shortDescription": {"text": "Dangling fetch: GET /sites/${siteId}/articles/${suffix} (mcp-server/src/api.ts:116)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:116` calls `GET /sites/${siteId}/articles/${suffix}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/articles/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-bafd748040877339", "name": "Dangling fetch: GET /sites/${siteId}/articles/${encodeURIComponent(slug)}/ (mcp-server/src/api.ts:130)", "shortDescription": {"text": "Dangling fetch: GET /sites/${siteId}/articles/${encodeURIComponent(slug)}/ (mcp-server/src/api.ts:130)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:130` calls `GET /sites/${siteId}/articles/${encodeURIComponent(slug)}/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/articles/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-dfce98f037ebcabd", "name": "Dangling fetch: POST /sites/${siteId}/generate/ (mcp-server/src/api.ts:155)", "shortDescription": {"text": "Dangling fetch: POST /sites/${siteId}/generate/ (mcp-server/src/api.ts:155)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:155` calls `POST /sites/${siteId}/generate/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/generate`\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-650b2225936c2fc0", "name": "Dangling fetch: POST /audit/ (mcp-server/src/api.ts:186)", "shortDescription": {"text": "Dangling fetch: POST /audit/ (mcp-server/src/api.ts:186)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:186` calls `POST /audit/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/audit`\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-6e74cf6cbc8d35a2", "name": "Dangling fetch: POST /brief/ (mcp-server/src/api.ts:193)", "shortDescription": {"text": "Dangling fetch: POST /brief/ (mcp-server/src/api.ts:193)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:193` calls `POST /brief/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/brief`\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-35a49a7bb18aa776", "name": "Dangling fetch: GET /sites/${siteId}/keywords/ (mcp-server/src/api.ts:203)", "shortDescription": {"text": "Dangling fetch: GET /sites/${siteId}/keywords/ (mcp-server/src/api.ts:203)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:203` calls `GET /sites/${siteId}/keywords/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/keywords`\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-d432926fb12acd53", "name": "Dangling fetch: POST /sites/${siteId}/keywords/snapshot/ (mcp-server/src/api.ts:216)", "shortDescription": {"text": "Dangling fetch: POST /sites/${siteId}/keywords/snapshot/ (mcp-server/src/api.ts:216)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:216` calls `POST /sites/${siteId}/keywords/snapshot/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/keywords/snapshot`\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-2e84c4d60269538f", "name": "Dangling fetch: POST /sites/${siteId}/serp-analyze/ (mcp-server/src/api.ts:314)", "shortDescription": {"text": "Dangling fetch: POST /sites/${siteId}/serp-analyze/ (mcp-server/src/api.ts:314)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:314` calls `POST /sites/${siteId}/serp-analyze/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/serp-analyze`\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-8a1d7d786a76462b", "name": "Dangling fetch: DELETE /sites/${siteId}/memories/${memoryId}/ (mcp-server/src/api.ts:436)", "shortDescription": {"text": "Dangling fetch: DELETE /sites/${siteId}/memories/${memoryId}/ (mcp-server/src/api.ts:436)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:436` calls `DELETE /sites/${siteId}/memories/${memoryId}/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/memories/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-b97cdae3c2f6f083", "name": "Dangling fetch: POST /classify-intent/ (mcp-server/src/api.ts:524)", "shortDescription": {"text": "Dangling fetch: POST /classify-intent/ (mcp-server/src/api.ts:524)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:524` calls `POST /classify-intent/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/classify-intent`\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-bf51753a014208e7", "name": "Dangling fetch: POST /sites/${siteId}/keyword-strategy/ (mcp-server/src/api.ts:539)", "shortDescription": {"text": "Dangling fetch: POST /sites/${siteId}/keyword-strategy/ (mcp-server/src/api.ts:539)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:539` calls `POST /sites/${siteId}/keyword-strategy/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/keyword-strategy`\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-701dcdc99240240a", "name": "Dangling fetch: POST /sites/${siteId}/keyword-strategy/${strategyId}/approve/ (mcp-server/src/api.ts:561)", "shortDescription": {"text": "Dangling fetch: POST /sites/${siteId}/keyword-strategy/${strategyId}/approve/ (mcp-server/src/api.ts:561)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:561` calls `POST /sites/${siteId}/keyword-strategy/${strategyId}/approve/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/keyword-strategy/<p>/approve`\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-173f5cadb58711af", "name": "Dangling fetch: POST /sites/${siteId}/landings/manual/ (mcp-server/src/api.ts:597)", "shortDescription": {"text": "Dangling fetch: POST /sites/${siteId}/landings/manual/ (mcp-server/src/api.ts:597)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:597` calls `POST /sites/${siteId}/landings/manual/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/landings/manual`\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-2be1d593685f2405", "name": "Dangling fetch: POST /sites/${siteId}/link-pages/ (mcp-server/src/api.ts:635)", "shortDescription": {"text": "Dangling fetch: POST /sites/${siteId}/link-pages/ (mcp-server/src/api.ts:635)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:635` calls `POST /sites/${siteId}/link-pages/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/link-pages`\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-6291fe69953d7a41", "name": "Dangling fetch: GET /sites/${siteId}/seo-score/ (mcp-server/src/api.ts:650)", "shortDescription": {"text": "Dangling fetch: GET /sites/${siteId}/seo-score/ (mcp-server/src/api.ts:650)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:650` calls `GET /sites/${siteId}/seo-score/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/seo-score`\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-e69dd8246a2c1b71", "name": "Dangling fetch: POST /link-opportunities/ (mcp-server/src/api.ts:701)", "shortDescription": {"text": "Dangling fetch: POST /link-opportunities/ (mcp-server/src/api.ts:701)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:701` calls `POST /link-opportunities/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/link-opportunities`\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-742dd09664580b08", "name": "Dangling fetch: POST /sites/${siteId}/ai-visibility/run/ (mcp-server/src/api.ts:748)", "shortDescription": {"text": "Dangling fetch: POST /sites/${siteId}/ai-visibility/run/ (mcp-server/src/api.ts:748)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:748` calls `POST /sites/${siteId}/ai-visibility/run/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/ai-visibility/run`\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-545d423bdcd2112c", "name": "Dangling fetch: POST /sites/${siteId}/strategic-opportunities/refresh/ (mcp-server/src/api.ts:833)", "shortDescription": {"text": "Dangling fetch: POST /sites/${siteId}/strategic-opportunities/refresh/ (mcp-server/src/api.ts:833)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:833` calls `POST /sites/${siteId}/strategic-opportunities/refresh/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/strategic-opportunities/refresh`\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-0cfe2c2a650e2e84", "name": "Dangling fetch: POST /sites/${siteId}/strategic-opportunities/${opportunityId}/${action}/ (mcp-server/src/api.ts:850)", "shortDescription": {"text": "Dangling fetch: POST /sites/${siteId}/strategic-opportunities/${opportunityId}/${action}/ (mcp-server/src/api.ts:850)"}, "fullDescription": {"text": "`mcp-server/src/api.ts:850` calls `POST /sites/${siteId}/strategic-opportunities/${opportunityId}/${action}/` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/sites/<p>/strategic-opportunities/<p>/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-7309bf2446873ccc", "name": "Unused endpoint: ANY /admin/", "shortDescription": {"text": "Unused endpoint: ANY /admin/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /admin/` 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-036c9d8ea8c84aa4", "name": "Unused endpoint: ANY /api/auth/token/", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/token/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /api/auth/token/` 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-7ccfdfb0d23bb024", "name": "Unused endpoint: ANY /api/auth/token/refresh/", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/token/refresh/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /api/auth/token/refresh/` 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-e0f4083d667c135a", "name": "Unused endpoint: ANY /api/auth/logout/", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/logout/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /api/auth/logout/` 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-fcb921a7cdd0182a", "name": "Unused endpoint: ANY /api/auth/check-email/", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/check-email/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /api/auth/check-email/` 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-2b9ab53458f72d57", "name": "Unused endpoint: ANY /api/auth/register/", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/register/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /api/auth/register/` 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-1857e81d2a5de324", "name": "Unused endpoint: ANY /api/auth/password/reset/request/", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/password/reset/request/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /api/auth/password/reset/request/` 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-5fa921e3acc957fa", "name": "Unused endpoint: ANY /api/auth/password/reset/confirm/", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/password/reset/confirm/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /api/auth/password/reset/confirm/` 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-6ee9a66cbe83716c", "name": "Unused endpoint: ANY /api/auth/google/", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/google/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /api/auth/google/` 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-365bca60da3206a4", "name": "Unused endpoint: ANY /api/auth/github/", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/github/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /api/auth/github/` 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-61e5291ec5a39cb6", "name": "Unused endpoint: ANY /accounts/", "shortDescription": {"text": "Unused endpoint: ANY /accounts/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /accounts/` 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-ce0a9b4397331ef4", "name": "Unused endpoint: ANY /api/", "shortDescription": {"text": "Unused endpoint: ANY /api/"}, "fullDescription": {"text": "`backend/config/urls.py` declares `ANY /api/` 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-69f11e4f376a4fc2", "name": "Unused endpoint: ANY /api/auth/me/", "shortDescription": {"text": "Unused endpoint: ANY /api/auth/me/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/auth/me/` 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-d040b2a82dc41e14", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/posts/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/posts/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/posts/` 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-2ca9c719d9049ebb", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/posts/<slug:slug>/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/posts/<slug:slug>/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/posts/<slug:slug>/` 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-1e8e4ab0d9c3f217", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/stats/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/stats/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/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-07633d3f76421521", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/categories/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/categories/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/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-f491f25af713a16a", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/tags/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/tags/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/tags/` 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-04d43a684bd91fa8", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/cannibalization/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/cannibalization/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/cannibalization/` 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-6acc0a3a3b26bd49", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/audit-all/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/audit-all/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/audit-all/` 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-f20d06de50bda902", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/keywords/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/keywords/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/keywords/` 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-c6c6e9fa31a47f4a", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/keywords/reclassify/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/keywords/reclassify/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/keywords/reclassify/` 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-640121bde8bd3d5b", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/keywords/<int:pk>/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/keywords/<int:pk>/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/keywords/<int:pk>/` 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-d31914999027b788", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/rank-snapshot/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/rank-snapshot/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/rank-snapshot/` 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-06041a2d8b289bec", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/rank-history/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/rank-history/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/rank-history/` 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-3f827d0e73baf349", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/content-decay/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/content-decay/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/content-decay/` 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-d661bf41633e10ee", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/topic-clusters/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/topic-clusters/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/topic-clusters/` 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-471d54e8c6d046f1", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/link-graph/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/link-graph/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/link-graph/` 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-78560b69b1c82c1f", "name": "Unused endpoint: ANY /api/readability/", "shortDescription": {"text": "Unused endpoint: ANY /api/readability/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/readability/` 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-f9fae32780834547", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/redirects/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/redirects/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/redirects/` 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-b3495a4ea1a79d0c", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/redirects/<int:pk>/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/redirects/<int:pk>/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/redirects/<int:pk>/` 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-1f60e4afcc977632", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/broken-links/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/broken-links/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/broken-links/` 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-e7b2b33b04f11a01", "name": "Unused endpoint: ANY /api/community-questions/", "shortDescription": {"text": "Unused endpoint: ANY /api/community-questions/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/community-questions/` 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-89597be6b34f99e4", "name": "Unused endpoint: ANY /api/lexicon-check/", "shortDescription": {"text": "Unused endpoint: ANY /api/lexicon-check/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/lexicon-check/` 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-bfadd7efaaf78fc9", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/local-business-schema/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/local-business-schema/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/local-business-schema/` 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-6a3e41358b4f9483", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/person-schema/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/person-schema/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/person-schema/` 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-a7b30f42f350ee04", "name": "Unused endpoint: ANY /api/trends/", "shortDescription": {"text": "Unused endpoint: ANY /api/trends/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/trends/` 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-42000d1cf6fd1bd6", "name": "Unused endpoint: ANY /api/image-suggest/", "shortDescription": {"text": "Unused endpoint: ANY /api/image-suggest/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/image-suggest/` 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-3209979011902235", "name": "Unused endpoint: ANY /api/multi-domain-stats/", "shortDescription": {"text": "Unused endpoint: ANY /api/multi-domain-stats/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/multi-domain-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-fc9821ff405843a1", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/weekly-digest/", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/weekly-digest/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/weekly-digest/` 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-2c5842fd6a8b8ac3", "name": "Unused endpoint: ANY /api/wp/discover/", "shortDescription": {"text": "Unused endpoint: ANY /api/wp/discover/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/wp/discover/` 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-ed9bcde29a00b248", "name": "Unused endpoint: ANY /api/wp/connect/", "shortDescription": {"text": "Unused endpoint: ANY /api/wp/connect/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/wp/connect/` 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-33d5354f26eedb3b", "name": "Unused endpoint: ANY /api/shopify/discover/", "shortDescription": {"text": "Unused endpoint: ANY /api/shopify/discover/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/shopify/discover/` 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-4381135f36836f33", "name": "Unused endpoint: ANY /api/shopify/connect/", "shortDescription": {"text": "Unused endpoint: ANY /api/shopify/connect/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/shopify/connect/` 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-851e6fb90bf03fc1", "name": "Unused endpoint: ANY /api/webflow/discover/", "shortDescription": {"text": "Unused endpoint: ANY /api/webflow/discover/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/webflow/discover/` 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-5bc89ce6a0380b7c", "name": "Unused endpoint: ANY /api/webflow/collections/", "shortDescription": {"text": "Unused endpoint: ANY /api/webflow/collections/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/webflow/collections/` 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-39675b7567a48324", "name": "Unused endpoint: ANY /api/webflow/connect/", "shortDescription": {"text": "Unused endpoint: ANY /api/webflow/connect/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/webflow/connect/` 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-c645f0b68a2bf9fa", "name": "Unused endpoint: ANY /api/branding/scan/", "shortDescription": {"text": "Unused endpoint: ANY /api/branding/scan/"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/branding/scan/` 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-6dc1718b8f716246", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/sitemap.xml", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/sitemap.xml"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/sitemap.xml` 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-6b436303751cb001", "name": "Unused endpoint: ANY /api/sites/<int:site_id>/rss.xml", "shortDescription": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/rss.xml"}, "fullDescription": {"text": "`backend/sites_mgmt/urls.py` declares `ANY /api/sites/<int:site_id>/rss.xml` 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/21440"}, "properties": {"repository": "TokDar2410621/blog-dashboard", "repoUrl": "https://github.com/TokDar2410621/blog-dashboard", "branch": "main"}, "results": [{"ruleId": "scanner-87319e9c078f001a", "level": "note", "message": {"text": "Possibly dead Python function: db_for_read"}, "properties": {"repobilityId": "025ed583d1e7418d", "scanner": "scanner-primary", "fingerprint": "87319e9c078f001a", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/config/db_router.py:11"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d4486c999a00bfaa", "level": "note", "message": {"text": "Possibly dead Python function: db_for_write"}, "properties": {"repobilityId": "4f16c6f02c42e1d3", "scanner": "scanner-primary", "fingerprint": "d4486c999a00bfaa", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/config/db_router.py:15"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-7479ec258d6dbbca", "level": "note", "message": {"text": "Possibly dead Python function: allow_relation"}, "properties": {"repobilityId": "e551503bfecfe1fb", "scanner": "scanner-primary", "fingerprint": "7479ec258d6dbbca", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/config/db_router.py:18"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-eecfde167a41603a", "level": "note", "message": {"text": "Possibly dead Python function: allow_migrate"}, "properties": {"repobilityId": "e12bb8d2306cba1e", "scanner": "scanner-primary", "fingerprint": "eecfde167a41603a", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/config/db_router.py:21"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-14b8dea6eb651705", "level": "note", "message": {"text": "Possibly dead Python function: handle_starttag"}, "properties": {"repobilityId": "3bf216d149959ebf", "scanner": "scanner-primary", "fingerprint": "14b8dea6eb651705", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/branding_scanner.py:119"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-4b3a47b74411cde4", "level": "note", "message": {"text": "Possibly dead Python function: handle_endtag"}, "properties": {"repobilityId": "7eb6f3decafc1766", "scanner": "scanner-primary", "fingerprint": "4b3a47b74411cde4", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/branding_scanner.py:155"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2c76b78f612b2eab", "level": "note", "message": {"text": "Possibly dead Python function: handle_data"}, "properties": {"repobilityId": "3a673a278f4fc1e6", "scanner": "scanner-primary", "fingerprint": "2c76b78f612b2eab", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/branding_scanner.py:163"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-36c881adc1f00673", "level": "note", "message": {"text": "Possibly dead Python function: list_blogs"}, "properties": {"repobilityId": "5e5f972a3036e4c7", "scanner": "scanner-primary", "fingerprint": "36c881adc1f00673", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/shopify_adapter.py:183"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-df76f1f6f55bd710", "level": "note", "message": {"text": "Possibly dead Python function: authenticate_header"}, "properties": {"repobilityId": "ee7351f4b3967891", "scanner": "scanner-primary", "fingerprint": "df76f1f6f55bd710", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py:106"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-e36528edea7e3494", "level": "note", "message": {"text": "Possibly dead Python function: allow_request"}, "properties": {"repobilityId": "74f93e8f4ccaa681", "scanner": "scanner-primary", "fingerprint": "e36528edea7e3494", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py:131"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-29c45a8ade99c429", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/PublicAuditPage.tsx:355"}, "properties": {"repobilityId": "4cf0dccce8726e35", "scanner": "scanner-primary", "fingerprint": "29c45a8ade99c429", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a1e07770d3cadefe", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/components/LandingRenderer.tsx:153"}, "properties": {"repobilityId": "1ec7ffbb94d3bf3d", "scanner": "scanner-primary", "fingerprint": "a1e07770d3cadefe", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-6c8328a48c2c3fdd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/MultiDomainCompare.tsx:182"}, "properties": {"repobilityId": "b83ca5abf90b2f98", "scanner": "scanner-primary", "fingerprint": "6c8328a48c2c3fdd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e93fa3fcd4234030", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/SearchTrendsPanel.tsx:225"}, "properties": {"repobilityId": "ce41108b69b6f47e", "scanner": "scanner-primary", "fingerprint": "e93fa3fcd4234030", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-74311b7c483913ca", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/PageBreadcrumb.tsx:45"}, "properties": {"repobilityId": "8ab1da374c0ccfb6", "scanner": "scanner-primary", "fingerprint": "74311b7c483913ca", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4365388cb5361077", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/LandingPage.tsx:1395"}, "properties": {"repobilityId": "2ad270c176dcd47a", "scanner": "scanner-primary", "fingerprint": "4365388cb5361077", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d284a11d6516602f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/ImageInsertDialog.tsx:268"}, "properties": {"repobilityId": "83a29cc9fa03fc92", "scanner": "scanner-primary", "fingerprint": "d284a11d6516602f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0215bf44b1f84008", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/OnboardingExternalPage.tsx:451"}, "properties": {"repobilityId": "e2540e9590455312", "scanner": "scanner-primary", "fingerprint": "0215bf44b1f84008", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5161d76b8748e5ea", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/components/OnboardingExternalPage.tsx:200"}, "properties": {"repobilityId": "9148ec1e490f3920", "scanner": "scanner-primary", "fingerprint": "5161d76b8748e5ea", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-461cce895a64c8e1", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/SiteSelector.tsx:205"}, "properties": {"repobilityId": "e038bc19bc047b5b", "scanner": "scanner-primary", "fingerprint": "461cce895a64c8e1", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-62ffc330d7ef3f71", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/SEOAnalyzer.tsx:1547"}, "properties": {"repobilityId": "872032808f6d5f2c", "scanner": "scanner-primary", "fingerprint": "62ffc330d7ef3f71", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-649095ac8ef81f44", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/components/MarkdownPreview.tsx:29"}, "properties": {"repobilityId": "06e7fdbbb75c2fc0", "scanner": "scanner-primary", "fingerprint": "649095ac8ef81f44", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-45e155323c77181c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/BillingPage.tsx:393"}, "properties": {"repobilityId": "036e53f964097546", "scanner": "scanner-primary", "fingerprint": "45e155323c77181c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-74b0e7bb02ab34de", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/BrandingPreview.tsx:127"}, "properties": {"repobilityId": "b7b129a7d8bca1e4", "scanner": "scanner-primary", "fingerprint": "74b0e7bb02ab34de", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ad8f1386f4f054e1", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/DashboardSidebar.tsx:105"}, "properties": {"repobilityId": "2ba8dc60126b4cf2", "scanner": "scanner-primary", "fingerprint": "ad8f1386f4f054e1", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-fa0357b4f4a94f8e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/ApiKeysPage.tsx:232"}, "properties": {"repobilityId": "8647940817cb9965", "scanner": "scanner-primary", "fingerprint": "fa0357b4f4a94f8e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c5d9dcb34bd0d673", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/JobsDock.tsx:151"}, "properties": {"repobilityId": "b7390483c59afd85", "scanner": "scanner-primary", "fingerprint": "c5d9dcb34bd0d673", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4b9a9c04278d1a00", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/PlagiarismCard.tsx:196"}, "properties": {"repobilityId": "523805557de62369", "scanner": "scanner-primary", "fingerprint": "4b9a9c04278d1a00", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b2edcd933ebcd967", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 marketing/components/dashboard/KeywordTrackerPage.tsx:402"}, "properties": {"repobilityId": "a887dddd5cfec540", "scanner": "scanner-primary", "fingerprint": "b2edcd933ebcd967", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-23a638b0561343db", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/OverviewPage.tsx:330"}, "properties": {"repobilityId": "fd342353998136f9", "scanner": "scanner-primary", "fingerprint": "23a638b0561343db", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-175cc2f9ebc29938", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 marketing/components/dashboard/OverviewPage.tsx:23"}, "properties": {"repobilityId": "b4ff6d104d827d18", "scanner": "scanner-primary", "fingerprint": "175cc2f9ebc29938", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-f0924afc653bad90", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ImageGalleryPage.tsx:193"}, "properties": {"repobilityId": "cdef7812e21cc532", "scanner": "scanner-primary", "fingerprint": "f0924afc653bad90", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b3f25c9b6d78017b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/BrokenLinksPage.tsx:239"}, "properties": {"repobilityId": "30d94b91934737d0", "scanner": "scanner-primary", "fingerprint": "b3f25c9b6d78017b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-379d73d7e277e3bc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ArticlesPage.tsx:292"}, "properties": {"repobilityId": "3e6af835ec53661a", "scanner": "scanner-primary", "fingerprint": "379d73d7e277e3bc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b4d4744e30cc50f6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/SerpAnalyzerPage.tsx:344"}, "properties": {"repobilityId": "520c19d1687799c5", "scanner": "scanner-primary", "fingerprint": "b4d4744e30cc50f6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-25842d654fb283c7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ContentBrief.tsx:332"}, "properties": {"repobilityId": "94e7b45448fbc27a", "scanner": "scanner-primary", "fingerprint": "25842d654fb283c7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2c66be7f6d7601bd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/TopicClustersPage.tsx:339"}, "properties": {"repobilityId": "da0c329190bf6c51", "scanner": "scanner-primary", "fingerprint": "2c66be7f6d7601bd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ef9727942d1378fd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/BulkAuditPage.tsx:405"}, "properties": {"repobilityId": "d7311661d11bf4ac", "scanner": "scanner-primary", "fingerprint": "ef9727942d1378fd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1851637b24e4b327", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/AiVisibilityPage.tsx:555"}, "properties": {"repobilityId": "317c500cb6d864b2", "scanner": "scanner-primary", "fingerprint": "1851637b24e4b327", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3e795ad1ec3b0086", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/SiteAuditPage.tsx:462"}, "properties": {"repobilityId": "27c0512d974c8f82", "scanner": "scanner-primary", "fingerprint": "3e795ad1ec3b0086", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ca854d2c4cddd66c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ProofCard.tsx:172"}, "properties": {"repobilityId": "3b1361d7a3e9837e", "scanner": "scanner-primary", "fingerprint": "ca854d2c4cddd66c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5c54ed6854e01891", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/MultiSiteHealthTable.tsx:230"}, "properties": {"repobilityId": "cdfff78a2c3ddb87", "scanner": "scanner-primary", "fingerprint": "5c54ed6854e01891", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0942c0184651df0d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/ContentDecayPage.tsx:408"}, "properties": {"repobilityId": "e709f4753c8f4bee", "scanner": "scanner-primary", "fingerprint": "0942c0184651df0d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1b624536a8815fda", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/HreflangCard.tsx:120"}, "properties": {"repobilityId": "f0a9f67f1bca77e0", "scanner": "scanner-primary", "fingerprint": "1b624536a8815fda", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-28f43cc1f1d6a72b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/CommunityQuestionsPanel.tsx:139"}, "properties": {"repobilityId": "2454cbf89de0c951", "scanner": "scanner-primary", "fingerprint": "28f43cc1f1d6a72b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d34536aa70418886", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/RecommendationsPanel.tsx:116"}, "properties": {"repobilityId": "10a4dbbe88555b04", "scanner": "scanner-primary", "fingerprint": "d34536aa70418886", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1ed2681f675ba715", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/LinkGraphPage.tsx:172"}, "properties": {"repobilityId": "f21627bfcda02bd5", "scanner": "scanner-primary", "fingerprint": "1ed2681f675ba715", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-029da1874087d510", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/PostEditorPage.tsx:1262"}, "properties": {"repobilityId": "9dcba6ecc341ef58", "scanner": "scanner-primary", "fingerprint": "029da1874087d510", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4cbdc0410a4a6f8c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/WeeklyDigestPage.tsx:192"}, "properties": {"repobilityId": "966006850c5cc381", "scanner": "scanner-primary", "fingerprint": "4cbdc0410a4a6f8c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c608aa1c79bfa176", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/settings/Memory.tsx:134"}, "properties": {"repobilityId": "cc3367958c6798a7", "scanner": "scanner-primary", "fingerprint": "c608aa1c79bfa176", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b4a450c99902cafe", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/dashboard/settings/SettingsLayoutClient.tsx:54"}, "properties": {"repobilityId": "41e696ca0928708f", "scanner": "scanner-primary", "fingerprint": "b4a450c99902cafe", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3fa401ff1b2bc0e7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/editor/TermUsageTracker.tsx:134"}, "properties": {"repobilityId": "6bb77a664904e840", "scanner": "scanner-primary", "fingerprint": "3fa401ff1b2bc0e7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-64f86006386cea98", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/components/editor/TermMapHeatmap.tsx:118"}, "properties": {"repobilityId": "3f4d92d05b556c45", "scanner": "scanner-primary", "fingerprint": "64f86006386cea98", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-65a1401c3a1d0606", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 marketing/app/blog/[slug]/page.tsx:149"}, "properties": {"repobilityId": "87b8bea180744fe7", "scanner": "scanner-primary", "fingerprint": "65a1401c3a1d0606", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-c85d4d0eeb7c2647", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/app/dashboard/overview/page.tsx:146"}, "properties": {"repobilityId": "5b0ce42c20ba7b1f", "scanner": "scanner-primary", "fingerprint": "c85d4d0eeb7c2647", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c6035142adbc35cc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/app/proof/[token]/page.tsx:116"}, "properties": {"repobilityId": "9b028de828b8eb1a", "scanner": "scanner-primary", "fingerprint": "c6035142adbc35cc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-36c438c74f6c1786", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 marketing/app/rapport/[token]/page.tsx:177"}, "properties": {"repobilityId": "1ad5cf7846b35a25", "scanner": "scanner-primary", "fingerprint": "36c438c74f6c1786", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-46b2a8879be807a1", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 public-blog/src/app/layout.tsx:50"}, "properties": {"repobilityId": "5ce8df268eac66ea", "scanner": "scanner-primary", "fingerprint": "46b2a8879be807a1", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-24f03cac06a8dbc4", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 public-blog/src/app/[slug]/page.tsx:109"}, "properties": {"repobilityId": "66a5b22e2940dc6d", "scanner": "scanner-primary", "fingerprint": "24f03cac06a8dbc4", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-1607cf625ad846bd", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in marketing/components/LandingRenderer.tsx:153"}, "properties": {"repobilityId": "c3b51394059dbe65", "scanner": "scanner-primary", "fingerprint": "1607cf625ad846bd", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "marketing/components/LandingRenderer.tsx"}, "region": {"startLine": 153}}}]}, {"ruleId": "scanner-1aebf6551771ba89", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in marketing/components/OnboardingExternalPage.tsx:200"}, "properties": {"repobilityId": "11adecab8f64a04a", "scanner": "scanner-primary", "fingerprint": "1aebf6551771ba89", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "marketing/components/OnboardingExternalPage.tsx"}, "region": {"startLine": 200}}}]}, {"ruleId": "scanner-e4b226f0b7eb2a68", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in marketing/components/MarkdownPreview.tsx:29"}, "properties": {"repobilityId": "2716e352c6b40317", "scanner": "scanner-primary", "fingerprint": "e4b226f0b7eb2a68", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "marketing/components/MarkdownPreview.tsx"}, "region": {"startLine": 29}}}]}, {"ruleId": "scanner-f29217468242bd63", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in marketing/app/blog/[slug]/page.tsx:149"}, "properties": {"repobilityId": "228e2ce9dd807c61", "scanner": "scanner-primary", "fingerprint": "f29217468242bd63", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "marketing/app/blog/[slug]/page.tsx"}, "region": {"startLine": 149}}}]}, {"ruleId": "scanner-f58e198ed27298c1", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in public-blog/src/app/layout.tsx:50"}, "properties": {"repobilityId": "c7c029f6e2ee46bb", "scanner": "scanner-primary", "fingerprint": "f58e198ed27298c1", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public-blog/src/app/layout.tsx"}, "region": {"startLine": 50}}}]}, {"ruleId": "scanner-3d1a0275291860de", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in public-blog/src/app/[slug]/page.tsx:109"}, "properties": {"repobilityId": "9854bf7366a8f4c9", "scanner": "scanner-primary", "fingerprint": "3d1a0275291860de", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public-blog/src/app/[slug]/page.tsx"}, "region": {"startLine": 109}}}]}, {"ruleId": "scanner-cec4dd3e9c943e3d", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in cypress/support/commands.ts:53"}, "properties": {"repobilityId": "21a9b8223e833701", "scanner": "scanner-primary", "fingerprint": "cec4dd3e9c943e3d", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "cypress/support/commands.ts"}, "region": {"startLine": 53}}}]}, {"ruleId": "scanner-4ef70ed9275d55cb", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in backend/sites_mgmt/prompt_export.py:99"}, "properties": {"repobilityId": "bd3705156013c594", "scanner": "scanner-primary", "fingerprint": "4ef70ed9275d55cb", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/prompt_export.py"}, "region": {"startLine": 99}}}]}, {"ruleId": "scanner-ead5f67d12157a1e", "level": "error", "message": {"text": "Possible secret in backend/sites_mgmt/management/commands/seed_demo_users.py"}, "properties": {"repobilityId": "3f626af5b71632e4", "scanner": "scanner-primary", "fingerprint": "ead5f67d12157a1e", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/management/commands/seed_demo_users.py"}, "region": {"startLine": 30}}}]}, {"ruleId": "scanner-61a26bb0710a3ec5", "level": "note", "message": {"text": "package.json defines install-time lifecycle scripts"}, "properties": {"repobilityId": "665ff722494321f8", "scanner": "scanner-primary", "fingerprint": "61a26bb0710a3ec5", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "npm", "install-scripts"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "mcp-server/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-4601e3ad3bb28677", "level": "warning", "message": {"text": "No CI/CD pipelines detected"}, "properties": {"repobilityId": "c3ee439bce2bc51e", "scanner": "scanner-primary", "fingerprint": "4601e3ad3bb28677", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-174f099ab7bb1e33", "level": "note", "message": {"text": "Very large file: marketing/components/LandingPage.tsx (1610 lines)"}, "properties": {"repobilityId": "3066f3cfd27f3d50", "scanner": "scanner-primary", "fingerprint": "174f099ab7bb1e33", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-65143362069953d2", "level": "note", "message": {"text": "Very large file: marketing/components/SEOAnalyzer.tsx (2618 lines)"}, "properties": {"repobilityId": "9352ba5c91c3c572", "scanner": "scanner-primary", "fingerprint": "65143362069953d2", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-7699a4f40c3ce070", "level": "note", "message": {"text": "Very large file: marketing/components/dashboard/PostEditorPage.tsx (1539 lines)"}, "properties": {"repobilityId": "61b5a7aa80b1a781", "scanner": "scanner-primary", "fingerprint": "7699a4f40c3ce070", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-c4c7274e5df23ce7", "level": "note", "message": {"text": "Very large file: backend/sites_mgmt/article_generator.py (1979 lines)"}, "properties": {"repobilityId": "76a525a995ff2526", "scanner": "scanner-primary", "fingerprint": "c4c7274e5df23ce7", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-09acfebfa3bb8967", "level": "note", "message": {"text": "Very large file: backend/sites_mgmt/views.py (10572 lines)"}, "properties": {"repobilityId": "0a38527d8c865eb5", "scanner": "scanner-primary", "fingerprint": "09acfebfa3bb8967", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-c8535acb45da9053", "level": "note", "message": {"text": "Very large file: backend/sites_mgmt/models.py (1563 lines)"}, "properties": {"repobilityId": "2957bfe1a16875e5", "scanner": "scanner-primary", "fingerprint": "c8535acb45da9053", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-8c5e1730c15cc3da", "level": "note", "message": {"text": "Very large file: backend/sites_mgmt/api_v1.py (3611 lines)"}, "properties": {"repobilityId": "eddf1e92580f990b", "scanner": "scanner-primary", "fingerprint": "8c5e1730c15cc3da", "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": "9c9db49d035b3668", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-564780bb7771be39", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: n8n-node/package.json"}, "properties": {"repobilityId": "26a0784434bd53b1", "scanner": "scanner-primary", "fingerprint": "564780bb7771be39", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "n8n-node/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-df2eb3c8382c6924", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: public-blog/package.json"}, "properties": {"repobilityId": "028298b6f0174026", "scanner": "scanner-primary", "fingerprint": "df2eb3c8382c6924", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public-blog/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "41daf4d3ee538078", "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": "7c0a17ab4e92ceca", "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": "f9440d9a04a8604b", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "warning", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "495a57acb651a32e", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "aeb67cc7a5615f7f", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "f9c7d1dbbbe7f654", "scanner": "scanner-primary", "fingerprint": "ea8f3013f588db25", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-8424db9c75e04ba4", "level": "none", "message": {"text": "Very short observed git history"}, "properties": {"repobilityId": "bde3308009904346", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-6c8756cce52ebacb", "level": "none", "message": {"text": "Commented-code block (6 lines) in marketing/next.config.ts:7"}, "properties": {"repobilityId": "9b6cebdf73782e06", "scanner": "scanner-primary", "fingerprint": "6c8756cce52ebacb", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-f1a556c99593c031", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/components/OnboardingExternalPage.tsx:53"}, "properties": {"repobilityId": "b5751194d95a5c56", "scanner": "scanner-primary", "fingerprint": "f1a556c99593c031", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-0481386b612c4e34", "level": "none", "message": {"text": "Commented-code block (7 lines) in marketing/components/StatsCard.tsx:107"}, "properties": {"repobilityId": "a870ad464ce6de64", "scanner": "scanner-primary", "fingerprint": "0481386b612c4e34", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-56f743f44486c928", "level": "none", "message": {"text": "Commented-code block (5 lines) in marketing/components/dashboard/KeywordTrackerPage.tsx:400"}, "properties": {"repobilityId": "a79eb9a4d86a41dc", "scanner": "scanner-primary", "fingerprint": "56f743f44486c928", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-313bc095a8195631", "level": "none", "message": {"text": "Commented-code block (9 lines) in marketing/components/dashboard/OverviewPage.tsx:100"}, "properties": {"repobilityId": "97544634aacef326", "scanner": "scanner-primary", "fingerprint": "313bc095a8195631", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e3e1805bbd576d14", "level": "none", "message": {"text": "Commented-code block (5 lines) in marketing/components/dashboard/AIGeneratorPage.tsx:174"}, "properties": {"repobilityId": "adcff5efc95acafb", "scanner": "scanner-primary", "fingerprint": "e3e1805bbd576d14", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-dc5210567e1b8011", "level": "none", "message": {"text": "Commented-code block (5 lines) in marketing/components/dashboard/SiteAuditPage.tsx:151"}, "properties": {"repobilityId": "7aaf613b91a2bbdc", "scanner": "scanner-primary", "fingerprint": "dc5210567e1b8011", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-6cd88bb27e1dafdb", "level": "none", "message": {"text": "Commented-code block (5 lines) in marketing/components/dashboard/ContentDecayPage.tsx:81"}, "properties": {"repobilityId": "ec5b57251b95a95e", "scanner": "scanner-primary", "fingerprint": "6cd88bb27e1dafdb", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2d9b5715624fd418", "level": "none", "message": {"text": "Commented-code block (5 lines) in marketing/app/auth/[provider]/callback/page.tsx:10"}, "properties": {"repobilityId": "cff386917c692f8f", "scanner": "scanner-primary", "fingerprint": "2d9b5715624fd418", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e7850ccbbe30eaf4", "level": "none", "message": {"text": "Commented-code block (8 lines) in marketing/lib/api-client.ts:1048"}, "properties": {"repobilityId": "5f795a1ac7d057bb", "scanner": "scanner-primary", "fingerprint": "e7850ccbbe30eaf4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-08ba09d3a12a8ad4", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/api-client.ts:92"}, "properties": {"repobilityId": "60d2b790a8a06419", "scanner": "scanner-primary", "fingerprint": "08ba09d3a12a8ad4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-1ad182c21f31a2ce", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/blog-api.ts:5"}, "properties": {"repobilityId": "ef6cb5cd8d115310", "scanner": "scanner-primary", "fingerprint": "1ad182c21f31a2ce", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d06169c690fb387b", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/sites-api.ts:48"}, "properties": {"repobilityId": "9ff3b7efe9201722", "scanner": "scanner-primary", "fingerprint": "d06169c690fb387b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-4f0b0ded48dce93b", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/report-api.ts:36"}, "properties": {"repobilityId": "281a73370e1135fc", "scanner": "scanner-primary", "fingerprint": "4f0b0ded48dce93b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-4128dc84a588ac47", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/proof-api.ts:43"}, "properties": {"repobilityId": "ce8a3757961fb94d", "scanner": "scanner-primary", "fingerprint": "4128dc84a588ac47", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-779599e69352d1c2", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/lib/landing-api.ts:69"}, "properties": {"repobilityId": "a4e4b21d4f9e4a5b", "scanner": "scanner-primary", "fingerprint": "779599e69352d1c2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c398806b008300bc", "level": "none", "message": {"text": "Commented-code block (5 lines) in marketing/context/AuthContext.tsx:31"}, "properties": {"repobilityId": "00328b759c63e7b6", "scanner": "scanner-primary", "fingerprint": "c398806b008300bc", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-d60b0aac7ab76198", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 marketing/context/JobsContext.tsx:29"}, "properties": {"repobilityId": "97a58c927c93e368", "scanner": "scanner-primary", "fingerprint": "d60b0aac7ab76198", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-9fa6c34cda12e2b8", "level": "none", "message": {"text": "Commented-code block (5 lines) in mcp-server/src/api.ts:862"}, "properties": {"repobilityId": "acbb478242ec138e", "scanner": "scanner-primary", "fingerprint": "9fa6c34cda12e2b8", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c31cdfa3cd5e26e9", "level": "none", "message": {"text": "Commented-code block (6 lines) in mcp-server/src/http.ts:54"}, "properties": {"repobilityId": "edf10298742bdf41", "scanner": "scanner-primary", "fingerprint": "c31cdfa3cd5e26e9", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-0de2f0436be30180", "level": "none", "message": {"text": "Commented-code block (6 lines) in cypress/support/commands.ts:46"}, "properties": {"repobilityId": "4be43f78716f2dca", "scanner": "scanner-primary", "fingerprint": "0de2f0436be30180", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-0bfabb05f90f8114", "level": "note", "message": {"text": "Stub function `db_for_write` (body is just `pass`/`return`) \u2014 backend/config/db_router.py:15"}, "properties": {"repobilityId": "d7c9b02f3e1c20e3", "scanner": "scanner-primary", "fingerprint": "0bfabb05f90f8114", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "empty-handler", "dead-code"]}}, {"ruleId": "scanner-b7a8b0c25fc1ce86", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/config/auth_views.py:18"}, "properties": {"repobilityId": "01d563d069751a75", "scanner": "scanner-primary", "fingerprint": "b7a8b0c25fc1ce86", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-31ef55e4f88981d9", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/config/authentication.py:5"}, "properties": {"repobilityId": "96510c20e9c329ab", "scanner": "scanner-primary", "fingerprint": "31ef55e4f88981d9", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-eaeb52cb190557ca", "level": "none", "message": {"text": "Commented-code block (7 lines) in backend/config/social_auth_views.py:32"}, "properties": {"repobilityId": "7fa2c55c85bf1811", "scanner": "scanner-primary", "fingerprint": "eaeb52cb190557ca", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3165393257737bd9", "level": "none", "message": {"text": "Commented-code block (8 lines) in backend/config/settings.py:141"}, "properties": {"repobilityId": "3d8d797e50ac1b4a", "scanner": "scanner-primary", "fingerprint": "3165393257737bd9", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-f4b5b5b1d41717b6", "level": "note", "message": {"text": "Legacy-named symbol `api_v1` in backend/sites_mgmt/urls.py:42"}, "properties": {"repobilityId": "884d5035b24c4835", "scanner": "scanner-primary", "fingerprint": "f4b5b5b1d41717b6", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-f4bb043b4a21ab74", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/sites_mgmt/article_generator.py:654"}, "properties": {"repobilityId": "fbec527136ad2637", "scanner": "scanner-primary", "fingerprint": "f4bb043b4a21ab74", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8afbb1e8d43c57a8", "level": "note", "message": {"text": "Legacy-named symbol `api_v1` in backend/sites_mgmt/views.py:10416"}, "properties": {"repobilityId": "89c092d5b27fed40", "scanner": "scanner-primary", "fingerprint": "8afbb1e8d43c57a8", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-1ad23ea8ff6078f4", "level": "none", "message": {"text": "Commented-code block (7 lines) in backend/sites_mgmt/views.py:239"}, "properties": {"repobilityId": "4e319675b256aeff", "scanner": "scanner-primary", "fingerprint": "1ad23ea8ff6078f4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-cb303eb38615953b", "level": "warning", "message": {"text": "Likely N+1 query: `for cat in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:951"}, "properties": {"repobilityId": "9c71776cdf464a5d", "scanner": "scanner-primary", "fingerprint": "cb303eb38615953b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "n-plus-one", "performance"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/views.py"}, "region": {"startLine": 951}}}]}, {"ruleId": "scanner-78091aa850fc7f45", "level": "warning", "message": {"text": "Likely N+1 query: `for p in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:7842"}, "properties": {"repobilityId": "986619acb98636bb", "scanner": "scanner-primary", "fingerprint": "78091aa850fc7f45", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "n-plus-one", "performance"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/views.py"}, "region": {"startLine": 7842}}}]}, {"ruleId": "scanner-63a08245fac4b1a7", "level": "warning", "message": {"text": "Likely N+1 query: `for p in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:7861"}, "properties": {"repobilityId": "d8d55c8578b7a4b3", "scanner": "scanner-primary", "fingerprint": "63a08245fac4b1a7", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "n-plus-one", "performance"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/views.py"}, "region": {"startLine": 7861}}}]}, {"ruleId": "scanner-f4378c34abc104f5", "level": "warning", "message": {"text": "Likely N+1 query: `for m in \u2026` triggers a query per row \u2014 backend/sites_mgmt/views.py:8589"}, "properties": {"repobilityId": "cff246f577d5a832", "scanner": "scanner-primary", "fingerprint": "f4378c34abc104f5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "n-plus-one", "performance"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/views.py"}, "region": {"startLine": 8589}}}]}, {"ruleId": "scanner-bde487d78f2cb6e9", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/sites_mgmt/landing_generator.py:57"}, "properties": {"repobilityId": "53133f7f4213c538", "scanner": "scanner-primary", "fingerprint": "bde487d78f2cb6e9", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d3df4d91125b2aa1", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/sites_mgmt/strategic_opportunities.py:71"}, "properties": {"repobilityId": "1678143e79cd93c4", "scanner": "scanner-primary", "fingerprint": "d3df4d91125b2aa1", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b3d855cb046a3398", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/sites_mgmt/shopify_adapter.py:406"}, "properties": {"repobilityId": "7344144712429be3", "scanner": "scanner-primary", "fingerprint": "b3d855cb046a3398", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c92a8eca3e8193a1", "level": "note", "message": {"text": "Legacy-named symbol `embed_calls_v1` in backend/sites_mgmt/tests_memory.py:213"}, "properties": {"repobilityId": "b5062de02e773228", "scanner": "scanner-primary", "fingerprint": "c92a8eca3e8193a1", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-e80c3b7d44675630", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/sites_mgmt/models.py:253"}, "properties": {"repobilityId": "314b224fdb37bd7a", "scanner": "scanner-primary", "fingerprint": "e80c3b7d44675630", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-86f6d38a008f769d", "level": "note", "message": {"text": "Legacy-named symbol `api_v1` in backend/sites_mgmt/api_v1.py:124"}, "properties": {"repobilityId": "a65c442bee0761ad", "scanner": "scanner-primary", "fingerprint": "86f6d38a008f769d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-145d4e2925a0dd84", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/sites_mgmt/api_v1.py:132"}, "properties": {"repobilityId": "7dd87cb5672cbfa9", "scanner": "scanner-primary", "fingerprint": "145d4e2925a0dd84", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4fc72d0bf05014dc", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/sites_mgmt/api_v1.py:1564"}, "properties": {"repobilityId": "aec9762836f26105", "scanner": "scanner-primary", "fingerprint": "4fc72d0bf05014dc", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-26b089d84055bdf5", "level": "warning", "message": {"text": "Likely N+1 query: `for p in \u2026` triggers a query per row \u2014 backend/sites_mgmt/api_v1.py:3199"}, "properties": {"repobilityId": "0d1b3c20da09ea00", "scanner": "scanner-primary", "fingerprint": "26b089d84055bdf5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "n-plus-one", "performance"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 3199}}}]}, {"ruleId": "scanner-4b160fb99beb0795", "level": "warning", "message": {"text": "Likely N+1 query: `for post in \u2026` triggers a query per row \u2014 backend/sites_mgmt/management/commands/attribution_snapshot.py:73"}, "properties": {"repobilityId": "cf204c0d2d6ab579", "scanner": "scanner-primary", "fingerprint": "4b160fb99beb0795", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "n-plus-one", "performance"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/management/commands/attribution_snapshot.py"}, "region": {"startLine": 73}}}]}, {"ruleId": "scanner-a5417a5f0affce13", "level": "note", "message": {"text": "52 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "39c9352136098d82", "scanner": "scanner-primary", "fingerprint": "a5417a5f0affce13", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "035f80311150f000", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-0027e313ade46c8f", "level": "note", "message": {"text": "Near-duplicate function bodies in 7 places"}, "properties": {"repobilityId": "bcd32edc42e4f016", "scanner": "scanner-primary", "fingerprint": "0027e313ade46c8f", "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": "b99f8535f76098f7", "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": "0ab8c7044b05d257", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-c73146f509615396", "level": "note", "message": {"text": "Near-duplicate function bodies in 43 places"}, "properties": {"repobilityId": "fdb622acd2f18c1e", "scanner": "scanner-primary", "fingerprint": "c73146f509615396", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-c8659acb65313f19", "level": "note", "message": {"text": "Near-duplicate function bodies in 60 places"}, "properties": {"repobilityId": "d0db4405842aceab", "scanner": "scanner-primary", "fingerprint": "c8659acb65313f19", "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": "64339b1b1caecb47", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-33a6b62e30ce7ab4", "level": "note", "message": {"text": "Near-duplicate function bodies in 6 places"}, "properties": {"repobilityId": "4bbdfdbd84f81d1b", "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": "582e0492c4b8a0c3", "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": "7475eb554ab77496", "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": "dcdd055448051f1d", "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": "c37dd8f9712208c5", "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": "6c6eb6b4def62e08", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-02525d39071dd2c7", "level": "note", "message": {"text": "Near-duplicate function bodies in 5 places"}, "properties": {"repobilityId": "83d084ec5a211226", "scanner": "scanner-primary", "fingerprint": "02525d39071dd2c7", "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": "44dbfde759702ad8", "scanner": "scanner-primary", "fingerprint": "49c98f7cedd9c977", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-a0310aec627cfbe3", "level": "note", "message": {"text": "Near-duplicate function bodies in 26 places"}, "properties": {"repobilityId": "5923741b08847c88", "scanner": "scanner-primary", "fingerprint": "a0310aec627cfbe3", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-69b5379230a2294f", "level": "note", "message": {"text": "Near-duplicate function bodies in 37 places"}, "properties": {"repobilityId": "7970edd622729372", "scanner": "scanner-primary", "fingerprint": "69b5379230a2294f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-02525d39071dd2c7", "level": "note", "message": {"text": "Near-duplicate function bodies in 5 places"}, "properties": {"repobilityId": "3c5920fec2365d44", "scanner": "scanner-primary", "fingerprint": "02525d39071dd2c7", "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": "91fb74f63658cae7", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-cbdbb157c2c7b1db", "level": "warning", "message": {"text": "Frontend route `/blog/:slug` has no Link/navigate to it \u2014 marketing/components/OnboardingExternalPage.tsx"}, "properties": {"repobilityId": "7626630c8d28d7c4", "scanner": "scanner-primary", "fingerprint": "cbdbb157c2c7b1db", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-3b93da3535fa34e2", "level": "warning", "message": {"text": "Django CBV `CookieTokenObtainPairView` lacks `LoginRequiredMixin` \u2014 backend/config/auth_views.py:46"}, "properties": {"repobilityId": "e212ccc567f715a1", "scanner": "scanner-primary", "fingerprint": "3b93da3535fa34e2", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/config/auth_views.py"}, "region": {"startLine": 46}}}]}, {"ruleId": "scanner-93b5fe4f5a856c85", "level": "warning", "message": {"text": "Django CBV `CookieTokenRefreshView` lacks `LoginRequiredMixin` \u2014 backend/config/auth_views.py:66"}, "properties": {"repobilityId": "44722a1d03367c3f", "scanner": "scanner-primary", "fingerprint": "93b5fe4f5a856c85", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/config/auth_views.py"}, "region": {"startLine": 66}}}]}, {"ruleId": "scanner-40da82888570fbeb", "level": "warning", "message": {"text": "Django CBV `V1GenerateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:389"}, "properties": {"repobilityId": "7d07b7643f79e05e", "scanner": "scanner-primary", "fingerprint": "40da82888570fbeb", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 389}}}]}, {"ruleId": "scanner-09f5d2bef038bf2a", "level": "warning", "message": {"text": "Django CBV `V1GenerateSisterArticleView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:475"}, "properties": {"repobilityId": "6fb3d88929bc7f14", "scanner": "scanner-primary", "fingerprint": "09f5d2bef038bf2a", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 475}}}]}, {"ruleId": "scanner-198363cb5e780c76", "level": "warning", "message": {"text": "Django CBV `V1AuditView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:558"}, "properties": {"repobilityId": "2520558b4983db7a", "scanner": "scanner-primary", "fingerprint": "198363cb5e780c76", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 558}}}]}, {"ruleId": "scanner-751995d8921afe59", "level": "warning", "message": {"text": "Django CBV `V1BriefView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:582"}, "properties": {"repobilityId": "54e72d153c26ed5d", "scanner": "scanner-primary", "fingerprint": "751995d8921afe59", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 582}}}]}, {"ruleId": "scanner-1e0cc50e2ebf4c6e", "level": "warning", "message": {"text": "Django CBV `V1KeywordsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:594"}, "properties": {"repobilityId": "19ad62b5d877b243", "scanner": "scanner-primary", "fingerprint": "1e0cc50e2ebf4c6e", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 594}}}]}, {"ruleId": "scanner-e9c1d8bc91759df9", "level": "warning", "message": {"text": "Django CBV `V1RankSnapshotView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:628"}, "properties": {"repobilityId": "6a2b885b2ac85c08", "scanner": "scanner-primary", "fingerprint": "e9c1d8bc91759df9", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 628}}}]}, {"ruleId": "scanner-64d3eced23793bee", "level": "warning", "message": {"text": "Django CBV `V1DigestView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:639"}, "properties": {"repobilityId": "a383baabe63b981a", "scanner": "scanner-primary", "fingerprint": "64d3eced23793bee", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 639}}}]}, {"ruleId": "scanner-3c918b96d23ad118", "level": "warning", "message": {"text": "Django CBV `V1SiteDetailView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:763"}, "properties": {"repobilityId": "9e06186a9030b5aa", "scanner": "scanner-primary", "fingerprint": "3c918b96d23ad118", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 763}}}]}, {"ruleId": "scanner-4ed2d5622d623491", "level": "warning", "message": {"text": "Django CBV `V1SiteUpdateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:789"}, "properties": {"repobilityId": "2901acca634b02ab", "scanner": "scanner-primary", "fingerprint": "4ed2d5622d623491", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 789}}}]}, {"ruleId": "scanner-8c21b575cbf71858", "level": "warning", "message": {"text": "Django CBV `V1ArticleCreateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:816"}, "properties": {"repobilityId": "8e63404a257b03b4", "scanner": "scanner-primary", "fingerprint": "8c21b575cbf71858", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 816}}}]}, {"ruleId": "scanner-bc8d4aadd1faec9f", "level": "warning", "message": {"text": "Django CBV `V1ArticleMutateView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:863"}, "properties": {"repobilityId": "a06143004929830b", "scanner": "scanner-primary", "fingerprint": "bc8d4aadd1faec9f", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 863}}}]}, {"ruleId": "scanner-9c0408cccef71f61", "level": "warning", "message": {"text": "Django CBV `V1KeywordTrackView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1031"}, "properties": {"repobilityId": "51adde4dfb842160", "scanner": "scanner-primary", "fingerprint": "9c0408cccef71f61", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1031}}}]}, {"ruleId": "scanner-5babe7876f59fa94", "level": "warning", "message": {"text": "Django CBV `V1KeywordUntrackView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1073"}, "properties": {"repobilityId": "5c79db3b17b05230", "scanner": "scanner-primary", "fingerprint": "5babe7876f59fa94", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1073}}}]}, {"ruleId": "scanner-d6b0e89998ed3cc5", "level": "warning", "message": {"text": "Django CBV `V1CompetitorsAnalyzeView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1101"}, "properties": {"repobilityId": "feb31435dae6ebe6", "scanner": "scanner-primary", "fingerprint": "d6b0e89998ed3cc5", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1101}}}]}, {"ruleId": "scanner-d22e26b8e7321324", "level": "warning", "message": {"text": "Django CBV `V1ContentDecayView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1109"}, "properties": {"repobilityId": "e5e086e4f44b2f42", "scanner": "scanner-primary", "fingerprint": "d22e26b8e7321324", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1109}}}]}, {"ruleId": "scanner-c592a4e7d7cf278e", "level": "warning", "message": {"text": "Django CBV `V1BrokenLinksView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1118"}, "properties": {"repobilityId": "f6af73dc66069df5", "scanner": "scanner-primary", "fingerprint": "c592a4e7d7cf278e", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1118}}}]}, {"ruleId": "scanner-23692712a9ba2090", "level": "warning", "message": {"text": "Django CBV `V1HreflangCheckView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1127"}, "properties": {"repobilityId": "66d06f82eafd6029", "scanner": "scanner-primary", "fingerprint": "23692712a9ba2090", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1127}}}]}, {"ruleId": "scanner-39a0b1c1602a8bfd", "level": "warning", "message": {"text": "Django CBV `V1CannibalizationView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1135"}, "properties": {"repobilityId": "ce9ee752459d5f1a", "scanner": "scanner-primary", "fingerprint": "39a0b1c1602a8bfd", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1135}}}]}, {"ruleId": "scanner-247ad53422188f83", "level": "warning", "message": {"text": "Django CBV `V1LinkSuggestionsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1144"}, "properties": {"repobilityId": "e7af2c3c753a444b", "scanner": "scanner-primary", "fingerprint": "247ad53422188f83", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1144}}}]}, {"ruleId": "scanner-bd365304cd1bab62", "level": "warning", "message": {"text": "Django CBV `V1BulkAuditView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1153"}, "properties": {"repobilityId": "cc61115e7af54bc1", "scanner": "scanner-primary", "fingerprint": "bd365304cd1bab62", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1153}}}]}, {"ruleId": "scanner-b2a301398a1a7c70", "level": "warning", "message": {"text": "Django CBV `V1ReadabilityView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1162"}, "properties": {"repobilityId": "4f3f49cee59b9d40", "scanner": "scanner-primary", "fingerprint": "b2a301398a1a7c70", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1162}}}]}, {"ruleId": "scanner-36dea908e18495f6", "level": "warning", "message": {"text": "Django CBV `V1PlagiarismView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1170"}, "properties": {"repobilityId": "78b82084e9ad3d19", "scanner": "scanner-primary", "fingerprint": "36dea908e18495f6", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1170}}}]}, {"ruleId": "scanner-441e63aedd5dc17e", "level": "warning", "message": {"text": "Django CBV `V1GSCQueriesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1178"}, "properties": {"repobilityId": "7c6b8a0ffc6b70c7", "scanner": "scanner-primary", "fingerprint": "441e63aedd5dc17e", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1178}}}]}, {"ruleId": "scanner-cb746e5395672b57", "level": "warning", "message": {"text": "Django CBV `V1AutopilotConfigView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1187"}, "properties": {"repobilityId": "3eb62609f6305418", "scanner": "scanner-primary", "fingerprint": "cb746e5395672b57", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1187}}}]}, {"ruleId": "scanner-44464527975e2dd0", "level": "warning", "message": {"text": "Django CBV `V1AutopilotRunView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1201"}, "properties": {"repobilityId": "ef8a7cf5fbfb362f", "scanner": "scanner-primary", "fingerprint": "44464527975e2dd0", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1201}}}]}, {"ruleId": "scanner-f48a2b4a728dc9b1", "level": "warning", "message": {"text": "Django CBV `V1MemoriesListView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1210"}, "properties": {"repobilityId": "87dcd4c3db598f8e", "scanner": "scanner-primary", "fingerprint": "f48a2b4a728dc9b1", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1210}}}]}, {"ruleId": "scanner-cb4cc53cbee815e9", "level": "warning", "message": {"text": "Django CBV `V1MemoryDetailView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1228"}, "properties": {"repobilityId": "831aa7522443f3c7", "scanner": "scanner-primary", "fingerprint": "cb4cc53cbee815e9", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1228}}}]}, {"ruleId": "scanner-496b023b8f6192b7", "level": "warning", "message": {"text": "Django CBV `V1MemoryRebuildView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1237"}, "properties": {"repobilityId": "c5d8c1c6acc4d902", "scanner": "scanner-primary", "fingerprint": "496b023b8f6192b7", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1237}}}]}, {"ruleId": "scanner-f377d72edaf8624a", "level": "warning", "message": {"text": "Django CBV `V1ProofSummaryView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1246"}, "properties": {"repobilityId": "9d13b75c0b5eac23", "scanner": "scanner-primary", "fingerprint": "f377d72edaf8624a", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1246}}}]}, {"ruleId": "scanner-e70c01d0bc1fecfd", "level": "warning", "message": {"text": "Django CBV `V1ProofAttributionView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1255"}, "properties": {"repobilityId": "dcfcc88eb8c46096", "scanner": "scanner-primary", "fingerprint": "e70c01d0bc1fecfd", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1255}}}]}, {"ruleId": "scanner-eff4994da0ee0477", "level": "warning", "message": {"text": "Django CBV `V1SuggestKeywordsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1283"}, "properties": {"repobilityId": "3245ef3021d2fba2", "scanner": "scanner-primary", "fingerprint": "eff4994da0ee0477", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1283}}}]}, {"ruleId": "scanner-12f60d8ba25d7dd4", "level": "warning", "message": {"text": "Django CBV `V1SuggestCompetitorsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1292"}, "properties": {"repobilityId": "3633a7c98fa5f933", "scanner": "scanner-primary", "fingerprint": "12f60d8ba25d7dd4", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1292}}}]}, {"ruleId": "scanner-62243ec2b28a12c0", "level": "warning", "message": {"text": "Django CBV `V1PageSpeedView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1309"}, "properties": {"repobilityId": "8f9476ac61789649", "scanner": "scanner-primary", "fingerprint": "62243ec2b28a12c0", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1309}}}]}, {"ruleId": "scanner-bbeb076576d0f3ca", "level": "warning", "message": {"text": "Django CBV `V1PAAView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1317"}, "properties": {"repobilityId": "6fa12db967f73f09", "scanner": "scanner-primary", "fingerprint": "bbeb076576d0f3ca", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1317}}}]}, {"ruleId": "scanner-22616cd04b62b27c", "level": "warning", "message": {"text": "Django CBV `V1ClassifyIntentView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1393"}, "properties": {"repobilityId": "8691bb93e7bdce3b", "scanner": "scanner-primary", "fingerprint": "22616cd04b62b27c", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1393}}}]}, {"ruleId": "scanner-6b70d95cfd179090", "level": "warning", "message": {"text": "Django CBV `V1ProposeKeywordStrategyView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1617"}, "properties": {"repobilityId": "c13ae26eebcedb31", "scanner": "scanner-primary", "fingerprint": "6b70d95cfd179090", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1617}}}]}, {"ruleId": "scanner-79350394ced9cb9c", "level": "warning", "message": {"text": "Django CBV `V1ApproveStrategyView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1692"}, "properties": {"repobilityId": "8e645f30f72ed3ff", "scanner": "scanner-primary", "fingerprint": "79350394ced9cb9c", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1692}}}]}, {"ruleId": "scanner-6d259890c58204eb", "level": "warning", "message": {"text": "Django CBV `V1CreateLandingView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1796"}, "properties": {"repobilityId": "3618299ec92c0a16", "scanner": "scanner-primary", "fingerprint": "6d259890c58204eb", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1796}}}]}, {"ruleId": "scanner-ed48f604d36f8401", "level": "warning", "message": {"text": "Django CBV `V1GenerateLandingView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1860"}, "properties": {"repobilityId": "c1325b51993368d0", "scanner": "scanner-primary", "fingerprint": "ed48f604d36f8401", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1860}}}]}, {"ruleId": "scanner-7971883028bd3fa5", "level": "warning", "message": {"text": "Django CBV `V1LinkPagesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:1938"}, "properties": {"repobilityId": "77c3268510f22150", "scanner": "scanner-primary", "fingerprint": "7971883028bd3fa5", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 1938}}}]}, {"ruleId": "scanner-12a537b798f735b0", "level": "warning", "message": {"text": "Django CBV `V1CheckRenderabilityView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:2654"}, "properties": {"repobilityId": "91026944566fbd4e", "scanner": "scanner-primary", "fingerprint": "12a537b798f735b0", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 2654}}}]}, {"ruleId": "scanner-cfd95bdda7ad4ec7", "level": "warning", "message": {"text": "Django CBV `V1LinkOpportunitiesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:2775"}, "properties": {"repobilityId": "7ff7085967f214e4", "scanner": "scanner-primary", "fingerprint": "cfd95bdda7ad4ec7", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 2775}}}]}, {"ruleId": "scanner-9d9c202411a3b7fd", "level": "warning", "message": {"text": "Django CBV `V1SerpAnalyzeView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:2862"}, "properties": {"repobilityId": "32ac841c7a2eb28a", "scanner": "scanner-primary", "fingerprint": "9d9c202411a3b7fd", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 2862}}}]}, {"ruleId": "scanner-6370eb55e5724758", "level": "warning", "message": {"text": "Django CBV `V1AiVisibilityPromptsView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3187"}, "properties": {"repobilityId": "d3d232f523a460ed", "scanner": "scanner-primary", "fingerprint": "6370eb55e5724758", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 3187}}}]}, {"ruleId": "scanner-7124f9b5a95c72b4", "level": "warning", "message": {"text": "Django CBV `V1AiVisibilityRunView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3256"}, "properties": {"repobilityId": "52eab5bbadd250c2", "scanner": "scanner-primary", "fingerprint": "7124f9b5a95c72b4", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 3256}}}]}, {"ruleId": "scanner-0d623f718dcbb9cb", "level": "warning", "message": {"text": "Django CBV `V1StrategicOpportunitiesView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3333"}, "properties": {"repobilityId": "1db2190195eb1443", "scanner": "scanner-primary", "fingerprint": "0d623f718dcbb9cb", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 3333}}}]}, {"ruleId": "scanner-17cdadc4beac04fc", "level": "warning", "message": {"text": "Django CBV `V1StrategicOpportunitiesRefreshView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3373"}, "properties": {"repobilityId": "152400c8897d5768", "scanner": "scanner-primary", "fingerprint": "17cdadc4beac04fc", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 3373}}}]}, {"ruleId": "scanner-af3b8af4d45a243a", "level": "warning", "message": {"text": "Django CBV `V1StrategicOpportunityActionView` lacks `LoginRequiredMixin` \u2014 backend/sites_mgmt/api_v1.py:3442"}, "properties": {"repobilityId": "8c19aaf03e92f971", "scanner": "scanner-primary", "fingerprint": "af3b8af4d45a243a", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["auth", "auth.django.unauth_view"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/sites_mgmt/api_v1.py"}, "region": {"startLine": 3442}}}]}, {"ruleId": "scanner-2932e0a90ed10243", "level": "error", "message": {"text": "Dangling fetch: GET https://api.gridar.app/api/sites/${siteId}/sitemap.xml (marketing/components/OnboardingExternalPage.tsx:295)"}, "properties": {"repobilityId": "cd5fed9f5ee92a74", "scanner": "scanner-primary", "fingerprint": "2932e0a90ed10243", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-4571b1dc018a7218", "level": "error", "message": {"text": "Dangling fetch: GET https://api.gridar.app/api/sites/${siteId}/rss.xml (marketing/components/OnboardingExternalPage.tsx:310)"}, "properties": {"repobilityId": "51b16821c1a6a2c4", "scanner": "scanner-primary", "fingerprint": "4571b1dc018a7218", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-a26b1553cae95613", "level": "error", "message": {"text": "Dangling fetch: GET /me/ (mcp-server/src/api.ts:80)"}, "properties": {"repobilityId": "3d8bb8864ffcd58f", "scanner": "scanner-primary", "fingerprint": "a26b1553cae95613", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-721f5ec06eae9745", "level": "error", "message": {"text": "Dangling fetch: GET /sites/${siteId}/articles/${suffix} (mcp-server/src/api.ts:116)"}, "properties": {"repobilityId": "efcc4ae7487cf90f", "scanner": "scanner-primary", "fingerprint": "721f5ec06eae9745", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-bafd748040877339", "level": "error", "message": {"text": "Dangling fetch: GET /sites/${siteId}/articles/${encodeURIComponent(slug)}/ (mcp-server/src/api.ts:130)"}, "properties": {"repobilityId": "72ee9d24ba4ea959", "scanner": "scanner-primary", "fingerprint": "bafd748040877339", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-dfce98f037ebcabd", "level": "error", "message": {"text": "Dangling fetch: POST /sites/${siteId}/generate/ (mcp-server/src/api.ts:155)"}, "properties": {"repobilityId": "c78b3ad1427c0b29", "scanner": "scanner-primary", "fingerprint": "dfce98f037ebcabd", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-650b2225936c2fc0", "level": "error", "message": {"text": "Dangling fetch: POST /audit/ (mcp-server/src/api.ts:186)"}, "properties": {"repobilityId": "b90902c46e59833e", "scanner": "scanner-primary", "fingerprint": "650b2225936c2fc0", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-6e74cf6cbc8d35a2", "level": "error", "message": {"text": "Dangling fetch: POST /brief/ (mcp-server/src/api.ts:193)"}, "properties": {"repobilityId": "936b4a265908dd8a", "scanner": "scanner-primary", "fingerprint": "6e74cf6cbc8d35a2", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-35a49a7bb18aa776", "level": "error", "message": {"text": "Dangling fetch: GET /sites/${siteId}/keywords/ (mcp-server/src/api.ts:203)"}, "properties": {"repobilityId": "b4da4dcc0de99da5", "scanner": "scanner-primary", "fingerprint": "35a49a7bb18aa776", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-d432926fb12acd53", "level": "error", "message": {"text": "Dangling fetch: POST /sites/${siteId}/keywords/snapshot/ (mcp-server/src/api.ts:216)"}, "properties": {"repobilityId": "09a5a5b3e1971210", "scanner": "scanner-primary", "fingerprint": "d432926fb12acd53", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-2e84c4d60269538f", "level": "error", "message": {"text": "Dangling fetch: POST /sites/${siteId}/serp-analyze/ (mcp-server/src/api.ts:314)"}, "properties": {"repobilityId": "16f8cf5eff4dbe2e", "scanner": "scanner-primary", "fingerprint": "2e84c4d60269538f", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-8a1d7d786a76462b", "level": "error", "message": {"text": "Dangling fetch: DELETE /sites/${siteId}/memories/${memoryId}/ (mcp-server/src/api.ts:436)"}, "properties": {"repobilityId": "e109f5dfbf2ddc39", "scanner": "scanner-primary", "fingerprint": "8a1d7d786a76462b", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-b97cdae3c2f6f083", "level": "error", "message": {"text": "Dangling fetch: POST /classify-intent/ (mcp-server/src/api.ts:524)"}, "properties": {"repobilityId": "7b191962cc79f30f", "scanner": "scanner-primary", "fingerprint": "b97cdae3c2f6f083", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-bf51753a014208e7", "level": "error", "message": {"text": "Dangling fetch: POST /sites/${siteId}/keyword-strategy/ (mcp-server/src/api.ts:539)"}, "properties": {"repobilityId": "78f3817c58b499d1", "scanner": "scanner-primary", "fingerprint": "bf51753a014208e7", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-701dcdc99240240a", "level": "error", "message": {"text": "Dangling fetch: POST /sites/${siteId}/keyword-strategy/${strategyId}/approve/ (mcp-server/src/api.ts:561)"}, "properties": {"repobilityId": "153a1b9561aaa992", "scanner": "scanner-primary", "fingerprint": "701dcdc99240240a", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-173f5cadb58711af", "level": "error", "message": {"text": "Dangling fetch: POST /sites/${siteId}/landings/manual/ (mcp-server/src/api.ts:597)"}, "properties": {"repobilityId": "d0fdf6c3bdc2af4d", "scanner": "scanner-primary", "fingerprint": "173f5cadb58711af", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-2be1d593685f2405", "level": "error", "message": {"text": "Dangling fetch: POST /sites/${siteId}/link-pages/ (mcp-server/src/api.ts:635)"}, "properties": {"repobilityId": "d66af64a4e4449b9", "scanner": "scanner-primary", "fingerprint": "2be1d593685f2405", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-6291fe69953d7a41", "level": "error", "message": {"text": "Dangling fetch: GET /sites/${siteId}/seo-score/ (mcp-server/src/api.ts:650)"}, "properties": {"repobilityId": "5b9ddfc2b98440c6", "scanner": "scanner-primary", "fingerprint": "6291fe69953d7a41", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-e69dd8246a2c1b71", "level": "error", "message": {"text": "Dangling fetch: POST /link-opportunities/ (mcp-server/src/api.ts:701)"}, "properties": {"repobilityId": "5681ed3d20a49de5", "scanner": "scanner-primary", "fingerprint": "e69dd8246a2c1b71", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-742dd09664580b08", "level": "error", "message": {"text": "Dangling fetch: POST /sites/${siteId}/ai-visibility/run/ (mcp-server/src/api.ts:748)"}, "properties": {"repobilityId": "4d756610d96d01f1", "scanner": "scanner-primary", "fingerprint": "742dd09664580b08", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-545d423bdcd2112c", "level": "error", "message": {"text": "Dangling fetch: POST /sites/${siteId}/strategic-opportunities/refresh/ (mcp-server/src/api.ts:833)"}, "properties": {"repobilityId": "bd5c98fdb2586290", "scanner": "scanner-primary", "fingerprint": "545d423bdcd2112c", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-0cfe2c2a650e2e84", "level": "error", "message": {"text": "Dangling fetch: POST /sites/${siteId}/strategic-opportunities/${opportunityId}/${action}/ (mcp-server/src/api.ts:850)"}, "properties": {"repobilityId": "237bf1a376a7ca42", "scanner": "scanner-primary", "fingerprint": "0cfe2c2a650e2e84", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-7309bf2446873ccc", "level": "note", "message": {"text": "Unused endpoint: ANY /admin/"}, "properties": {"repobilityId": "1d47feb43791c5ac", "scanner": "scanner-primary", "fingerprint": "7309bf2446873ccc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-036c9d8ea8c84aa4", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/token/"}, "properties": {"repobilityId": "582a418513010ae8", "scanner": "scanner-primary", "fingerprint": "036c9d8ea8c84aa4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7ccfdfb0d23bb024", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/token/refresh/"}, "properties": {"repobilityId": "c79616ca7783ee4c", "scanner": "scanner-primary", "fingerprint": "7ccfdfb0d23bb024", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e0f4083d667c135a", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/logout/"}, "properties": {"repobilityId": "2328b0e4c6595823", "scanner": "scanner-primary", "fingerprint": "e0f4083d667c135a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fcb921a7cdd0182a", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/check-email/"}, "properties": {"repobilityId": "83136a98ccff521b", "scanner": "scanner-primary", "fingerprint": "fcb921a7cdd0182a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2b9ab53458f72d57", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/register/"}, "properties": {"repobilityId": "77f44ac488af4022", "scanner": "scanner-primary", "fingerprint": "2b9ab53458f72d57", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1857e81d2a5de324", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/password/reset/request/"}, "properties": {"repobilityId": "7ed123e5ca6a0f8d", "scanner": "scanner-primary", "fingerprint": "1857e81d2a5de324", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5fa921e3acc957fa", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/password/reset/confirm/"}, "properties": {"repobilityId": "59019375ef949026", "scanner": "scanner-primary", "fingerprint": "5fa921e3acc957fa", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6ee9a66cbe83716c", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/google/"}, "properties": {"repobilityId": "c62eb336839a13a1", "scanner": "scanner-primary", "fingerprint": "6ee9a66cbe83716c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-365bca60da3206a4", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/github/"}, "properties": {"repobilityId": "922c24baa77b07fb", "scanner": "scanner-primary", "fingerprint": "365bca60da3206a4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-61e5291ec5a39cb6", "level": "note", "message": {"text": "Unused endpoint: ANY /accounts/"}, "properties": {"repobilityId": "a9f107496e30461e", "scanner": "scanner-primary", "fingerprint": "61e5291ec5a39cb6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ce0a9b4397331ef4", "level": "note", "message": {"text": "Unused endpoint: ANY /api/"}, "properties": {"repobilityId": "809fe7d9b9a87180", "scanner": "scanner-primary", "fingerprint": "ce0a9b4397331ef4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-69f11e4f376a4fc2", "level": "note", "message": {"text": "Unused endpoint: ANY /api/auth/me/"}, "properties": {"repobilityId": "50c845b43f1d8d79", "scanner": "scanner-primary", "fingerprint": "69f11e4f376a4fc2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d040b2a82dc41e14", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/posts/"}, "properties": {"repobilityId": "c7f984b79feb29a3", "scanner": "scanner-primary", "fingerprint": "d040b2a82dc41e14", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2ca9c719d9049ebb", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/posts/<slug:slug>/"}, "properties": {"repobilityId": "55b88419fe1e232c", "scanner": "scanner-primary", "fingerprint": "2ca9c719d9049ebb", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1e8e4ab0d9c3f217", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/stats/"}, "properties": {"repobilityId": "1812abcaa4a9a96a", "scanner": "scanner-primary", "fingerprint": "1e8e4ab0d9c3f217", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-07633d3f76421521", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/categories/"}, "properties": {"repobilityId": "9e35d190335096a3", "scanner": "scanner-primary", "fingerprint": "07633d3f76421521", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f491f25af713a16a", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/tags/"}, "properties": {"repobilityId": "69b110f0b984a1bd", "scanner": "scanner-primary", "fingerprint": "f491f25af713a16a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-04d43a684bd91fa8", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/cannibalization/"}, "properties": {"repobilityId": "8177ca7a31b2bc29", "scanner": "scanner-primary", "fingerprint": "04d43a684bd91fa8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6acc0a3a3b26bd49", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/audit-all/"}, "properties": {"repobilityId": "ad2ee448c7252b30", "scanner": "scanner-primary", "fingerprint": "6acc0a3a3b26bd49", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f20d06de50bda902", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/keywords/"}, "properties": {"repobilityId": "679c239e4a81784c", "scanner": "scanner-primary", "fingerprint": "f20d06de50bda902", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c6c6e9fa31a47f4a", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/keywords/reclassify/"}, "properties": {"repobilityId": "ec49e93e4be53c3b", "scanner": "scanner-primary", "fingerprint": "c6c6e9fa31a47f4a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-640121bde8bd3d5b", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/keywords/<int:pk>/"}, "properties": {"repobilityId": "e7f2e6c008f2ccc7", "scanner": "scanner-primary", "fingerprint": "640121bde8bd3d5b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d31914999027b788", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/rank-snapshot/"}, "properties": {"repobilityId": "48f5497e8194f35c", "scanner": "scanner-primary", "fingerprint": "d31914999027b788", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-06041a2d8b289bec", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/rank-history/"}, "properties": {"repobilityId": "bdbf0231a0aaf079", "scanner": "scanner-primary", "fingerprint": "06041a2d8b289bec", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3f827d0e73baf349", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/content-decay/"}, "properties": {"repobilityId": "4e6978364210d63d", "scanner": "scanner-primary", "fingerprint": "3f827d0e73baf349", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d661bf41633e10ee", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/topic-clusters/"}, "properties": {"repobilityId": "58a42f46b3aa055f", "scanner": "scanner-primary", "fingerprint": "d661bf41633e10ee", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-471d54e8c6d046f1", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/link-graph/"}, "properties": {"repobilityId": "30cc5bdec60e1209", "scanner": "scanner-primary", "fingerprint": "471d54e8c6d046f1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-78560b69b1c82c1f", "level": "note", "message": {"text": "Unused endpoint: ANY /api/readability/"}, "properties": {"repobilityId": "6cca9dac4ff87b4f", "scanner": "scanner-primary", "fingerprint": "78560b69b1c82c1f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f9fae32780834547", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/redirects/"}, "properties": {"repobilityId": "d0983c4f42cedd7b", "scanner": "scanner-primary", "fingerprint": "f9fae32780834547", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b3495a4ea1a79d0c", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/redirects/<int:pk>/"}, "properties": {"repobilityId": "f45331730de87280", "scanner": "scanner-primary", "fingerprint": "b3495a4ea1a79d0c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1f60e4afcc977632", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/broken-links/"}, "properties": {"repobilityId": "2a07b7a92f8831e8", "scanner": "scanner-primary", "fingerprint": "1f60e4afcc977632", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e7b2b33b04f11a01", "level": "note", "message": {"text": "Unused endpoint: ANY /api/community-questions/"}, "properties": {"repobilityId": "a3cd5dfe3561cf03", "scanner": "scanner-primary", "fingerprint": "e7b2b33b04f11a01", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-89597be6b34f99e4", "level": "note", "message": {"text": "Unused endpoint: ANY /api/lexicon-check/"}, "properties": {"repobilityId": "426d4974ef6bc51a", "scanner": "scanner-primary", "fingerprint": "89597be6b34f99e4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-bfadd7efaaf78fc9", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/local-business-schema/"}, "properties": {"repobilityId": "47ca36a6e94eec13", "scanner": "scanner-primary", "fingerprint": "bfadd7efaaf78fc9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6a3e41358b4f9483", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/person-schema/"}, "properties": {"repobilityId": "56488dd7e1ddcaa0", "scanner": "scanner-primary", "fingerprint": "6a3e41358b4f9483", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a7b30f42f350ee04", "level": "note", "message": {"text": "Unused endpoint: ANY /api/trends/"}, "properties": {"repobilityId": "c88931b3311317be", "scanner": "scanner-primary", "fingerprint": "a7b30f42f350ee04", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-42000d1cf6fd1bd6", "level": "note", "message": {"text": "Unused endpoint: ANY /api/image-suggest/"}, "properties": {"repobilityId": "ce1939867811e13b", "scanner": "scanner-primary", "fingerprint": "42000d1cf6fd1bd6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3209979011902235", "level": "note", "message": {"text": "Unused endpoint: ANY /api/multi-domain-stats/"}, "properties": {"repobilityId": "3b2cd3023f4af995", "scanner": "scanner-primary", "fingerprint": "3209979011902235", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fc9821ff405843a1", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/weekly-digest/"}, "properties": {"repobilityId": "a3f157218bc2bf10", "scanner": "scanner-primary", "fingerprint": "fc9821ff405843a1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2c5842fd6a8b8ac3", "level": "note", "message": {"text": "Unused endpoint: ANY /api/wp/discover/"}, "properties": {"repobilityId": "92dc940f8fdb92db", "scanner": "scanner-primary", "fingerprint": "2c5842fd6a8b8ac3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ed9bcde29a00b248", "level": "note", "message": {"text": "Unused endpoint: ANY /api/wp/connect/"}, "properties": {"repobilityId": "68083926bb3da389", "scanner": "scanner-primary", "fingerprint": "ed9bcde29a00b248", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-33d5354f26eedb3b", "level": "note", "message": {"text": "Unused endpoint: ANY /api/shopify/discover/"}, "properties": {"repobilityId": "d2ecf734f97eb65e", "scanner": "scanner-primary", "fingerprint": "33d5354f26eedb3b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4381135f36836f33", "level": "note", "message": {"text": "Unused endpoint: ANY /api/shopify/connect/"}, "properties": {"repobilityId": "568faef09133fa69", "scanner": "scanner-primary", "fingerprint": "4381135f36836f33", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-851e6fb90bf03fc1", "level": "note", "message": {"text": "Unused endpoint: ANY /api/webflow/discover/"}, "properties": {"repobilityId": "a7e0453b1025554d", "scanner": "scanner-primary", "fingerprint": "851e6fb90bf03fc1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5bc89ce6a0380b7c", "level": "note", "message": {"text": "Unused endpoint: ANY /api/webflow/collections/"}, "properties": {"repobilityId": "a5addc06b50bace7", "scanner": "scanner-primary", "fingerprint": "5bc89ce6a0380b7c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-39675b7567a48324", "level": "note", "message": {"text": "Unused endpoint: ANY /api/webflow/connect/"}, "properties": {"repobilityId": "07b459c48fff4211", "scanner": "scanner-primary", "fingerprint": "39675b7567a48324", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c645f0b68a2bf9fa", "level": "note", "message": {"text": "Unused endpoint: ANY /api/branding/scan/"}, "properties": {"repobilityId": "46136391c4a48139", "scanner": "scanner-primary", "fingerprint": "c645f0b68a2bf9fa", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6dc1718b8f716246", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/sitemap.xml"}, "properties": {"repobilityId": "7914e9643f5c7f47", "scanner": "scanner-primary", "fingerprint": "6dc1718b8f716246", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6b436303751cb001", "level": "note", "message": {"text": "Unused endpoint: ANY /api/sites/<int:site_id>/rss.xml"}, "properties": {"repobilityId": "6478c6d056e4787e", "scanner": "scanner-primary", "fingerprint": "6b436303751cb001", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}