{"version": "2.1.0", "$schema": "https://json.schemastore.org/sarif-2.1.0.json", "runs": [{"tool": {"driver": {"name": "Repobility", "informationUri": "https://repobility.com", "rules": [{"id": "scanner-bead75b0f9233e05", "name": "No API endpoints detected", "shortDescription": {"text": "No API endpoints detected"}, "fullDescription": {"text": "The scanner did not find FastAPI/Flask/Express/NestJS/GraphQL/gRPC routes. If this repo exposes APIs, the framework may be unsupported."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "info", "confidence": 1.0}}, {"id": "scanner-8484a5c2b7ec3ae8", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/layout/header.tsx:16", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/layout/header.tsx:16"}, "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-6f4ab94a6936d173", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/ui/kpi-card.tsx:37", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/ui/kpi-card.tsx:37"}, "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-aaca4d40052f2d2a", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/projects/page.tsx:195", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/projects/page.tsx:195"}, "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-2e0909b39f77644c", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/klaviyo/page.tsx:251", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/klaviyo/page.tsx:251"}, "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-ebd4d933c9d095fc", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/ads/page.tsx:503", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/ads/page.tsx:503"}, "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-c36b303292b8002e", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/objectives/page.tsx:234", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/objectives/page.tsx:234"}, "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-9cf4cb009258f4fb", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/chat/page.tsx:288", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/chat/page.tsx:288"}, "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-d03bd8e8c37ff2a2", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/chat/playground/page.tsx:172", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/chat/playground/page.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-ce7f7964bc0ef058", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/chat/knowledge/page.tsx:243", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/chat/knowledge/page.tsx:243"}, "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-a9c5cbd701e7073f", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/influencers/[id]/page.tsx:384", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/influencers/[id]/page.tsx:384"}, "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-e736b2c39a9e9a19", "name": "Stray `console.log` in TS/JS \u2014 src/lib/integrations/shopify.ts:195", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/integrations/shopify.ts:195"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-166dff3c3df6a10e", "name": "ORM models found but no DB engine detected", "shortDescription": {"text": "ORM models found but no DB engine detected"}, "fullDescription": {"text": "The repo defines tables/models but no DB connection string was found. Likely lives in env vars or a config file the scanner didn't read."}, "properties": {"scanner": "scanner-primary", "layer": "data", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4601e3ad3bb28677", "name": "No CI/CD pipelines detected", "shortDescription": {"text": "No CI/CD pipelines detected"}, "fullDescription": {"text": "No GitHub Actions, GitLab CI, or CircleCI configs found. Without CI you can't gate deploys on tests/lints."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3da21b176af96bd8", "name": "Very large file: src/app/influencers/page.tsx (1379 lines)", "shortDescription": {"text": "Very large file: src/app/influencers/page.tsx (1379 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": "0 test file(s) for 134 source file(s) (ratio 0.00). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 15 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 27 placeholder/mock markers across 10 source files. This often means the repo looks complete while core flows still use generated scaffolding or fake data."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9d79c4077342a7d0", "name": "Runtime service client appears to use placeholder configuration", "shortDescription": {"text": "Runtime service client appears to use placeholder configuration"}, "fullDescription": {"text": "A runtime source file appears to wire Supabase/Firebase/AI/payment-style clients to placeholder URLs, keys, or fallback values. In the Fable corpus this often means the UI/API shape is present while the backend service is not actually configured."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, ci, tests. 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. 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-8b02081eded4a290", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/import-historical-shopify.mjs:58", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/import-historical-shopify.mjs:58"}, "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-e5cdc8db92003b93", "name": "Commented-code block (5 lines) in src/middleware.ts:4", "shortDescription": {"text": "Commented-code block (5 lines) in src/middleware.ts:4"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1df8593c1fcfb3ad", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/users/page.tsx:28", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/users/page.tsx:28"}, "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-d4fe7e44cb696f59", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/pnl/page.tsx:113", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/pnl/page.tsx:113"}, "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-3c46864236c86287", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/projects/page.tsx:543", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/projects/page.tsx:543"}, "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-66a7a8fb83460b5a", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/google/callback/route.ts:11", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/google/callback/route.ts:11"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-40aa12fd79b57882", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/users/route.ts:19", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/users/route.ts:19"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7ab94de19c9e177f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/klaviyo/sync/route.ts:15", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/klaviyo/sync/route.ts:15"}, "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-c6522730009b377d", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/meta/sync/route.ts:21", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/meta/sync/route.ts:21"}, "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-a2a56b977d8b1d4b", "name": "Commented-code block (5 lines) in src/app/api/influencers/codes/route.ts:56", "shortDescription": {"text": "Commented-code block (5 lines) in src/app/api/influencers/codes/route.ts:56"}, "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-ca07e5d458b0624e", "name": "Commented-code block (6 lines) in src/app/api/context/route.ts:6", "shortDescription": {"text": "Commented-code block (6 lines) in src/app/api/context/route.ts:6"}, "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-6bedcf4c5f7e0d6f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/ads/page.tsx:162", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/ads/page.tsx:162"}, "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-1dbfa46480ad72a9", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/objectives/page.tsx:69", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/objectives/page.tsx: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-ba321aaaf1755026", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/chat/knowledge/page.tsx:103", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/chat/knowledge/page.tsx:103"}, "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-4a3663f73954384e", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/influencers/page.tsx:195", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/influencers/page.tsx:195"}, "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-0f2520c0e17a4d07", "name": "Commented-code block (5 lines) in src/lib/codes-server.ts:17", "shortDescription": {"text": "Commented-code block (5 lines) in src/lib/codes-server.ts:17"}, "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-d6c5146fc919efd6", "name": "Commented-code block (5 lines) in src/lib/codes.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in src/lib/codes.ts:1"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-aa7adc2daea778f6", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/generosite.ts:10", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/generosite.ts:10"}, "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-091a62581378c5fc", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/klaviyo.ts:9", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/klaviyo.ts:9"}, "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-bc5057db25918f5d", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/shopify.ts:13", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/shopify.ts:13"}, "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-e014a5a9365b7942", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/google-ads.ts:18", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/google-ads.ts:18"}, "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-602e1d333c77256f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/meta.ts:17", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/meta.ts:17"}, "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-eb5f8ab94aaf297b", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/mistral.ts:10", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/mistral.ts:10"}, "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-8540c548d24c5959", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/shopify-orders.ts:73", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/shopify-orders.ts:73"}, "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-3d14040b00c9766e", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/shopify-products.ts:55", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/shopify-products.ts:55"}, "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-8a3e0f37be61ab30", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/admin-fetch.ts:9", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/admin-fetch.ts:9"}, "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-0b9b2f8ee5aca44d", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/llm.ts:21", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/llm.ts:21"}, "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-250f57e8a1dbd3c5", "name": "4 env vars used in code but missing from .env.example", "shortDescription": {"text": "4 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `CHAT_ADMIN_SECRET`, `CRON_SECRET`, `MISTRAL_API_KEY`, `NEXT_PUBLIC_CHAT_ADMIN_SECRET`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/18310"}, "properties": {"repository": "robinallainmkg/talika-ecommerce", "repoUrl": "https://github.com/robinallainmkg/talika-ecommerce", "branch": "main"}, "results": [{"ruleId": "scanner-bead75b0f9233e05", "level": "none", "message": {"text": "No API endpoints detected"}, "properties": {"repobilityId": "0f8bb852027c38f8", "scanner": "scanner-primary", "fingerprint": "bead75b0f9233e05", "layer": "api", "severity": "info", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-8484a5c2b7ec3ae8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/layout/header.tsx:16"}, "properties": {"repobilityId": "92963ab1fa04caed", "scanner": "scanner-primary", "fingerprint": "8484a5c2b7ec3ae8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6f4ab94a6936d173", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/ui/kpi-card.tsx:37"}, "properties": {"repobilityId": "a67579e79d922280", "scanner": "scanner-primary", "fingerprint": "6f4ab94a6936d173", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-aaca4d40052f2d2a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/projects/page.tsx:195"}, "properties": {"repobilityId": "ffcc96d964b43e7b", "scanner": "scanner-primary", "fingerprint": "aaca4d40052f2d2a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2e0909b39f77644c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/klaviyo/page.tsx:251"}, "properties": {"repobilityId": "9deac287a03408fe", "scanner": "scanner-primary", "fingerprint": "2e0909b39f77644c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ebd4d933c9d095fc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/ads/page.tsx:503"}, "properties": {"repobilityId": "d97c29c05f512d4d", "scanner": "scanner-primary", "fingerprint": "ebd4d933c9d095fc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c36b303292b8002e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/objectives/page.tsx:234"}, "properties": {"repobilityId": "7a657f148ee97e36", "scanner": "scanner-primary", "fingerprint": "c36b303292b8002e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9cf4cb009258f4fb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/chat/page.tsx:288"}, "properties": {"repobilityId": "288f13fe158d901f", "scanner": "scanner-primary", "fingerprint": "9cf4cb009258f4fb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d03bd8e8c37ff2a2", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/chat/playground/page.tsx:172"}, "properties": {"repobilityId": "0671d701513ecd7b", "scanner": "scanner-primary", "fingerprint": "d03bd8e8c37ff2a2", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ce7f7964bc0ef058", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/chat/knowledge/page.tsx:243"}, "properties": {"repobilityId": "ea317ff3dfd375e6", "scanner": "scanner-primary", "fingerprint": "ce7f7964bc0ef058", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a9c5cbd701e7073f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/influencers/[id]/page.tsx:384"}, "properties": {"repobilityId": "355f038fef198d62", "scanner": "scanner-primary", "fingerprint": "a9c5cbd701e7073f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e736b2c39a9e9a19", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/lib/integrations/shopify.ts:195"}, "properties": {"repobilityId": "1ac4aa4689ab9e32", "scanner": "scanner-primary", "fingerprint": "e736b2c39a9e9a19", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-166dff3c3df6a10e", "level": "warning", "message": {"text": "ORM models found but no DB engine detected"}, "properties": {"repobilityId": "cda36de65e114635", "scanner": "scanner-primary", "fingerprint": "166dff3c3df6a10e", "layer": "data", "severity": "medium", "confidence": 1.0, "tags": ["coverage"]}}, {"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-3da21b176af96bd8", "level": "note", "message": {"text": "Very large file: src/app/influencers/page.tsx (1379 lines)"}, "properties": {"repobilityId": "e724235afbae3240", "scanner": "scanner-primary", "fingerprint": "3da21b176af96bd8", "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": "e61131029196fd47", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "a21e147c2923df4d", "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": "94664bc77adbf6c8", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-9d79c4077342a7d0", "level": "warning", "message": {"text": "Runtime service client appears to use placeholder configuration"}, "properties": {"repobilityId": "3cdf087cf0ec1540", "scanner": "scanner-primary", "fingerprint": "9d79c4077342a7d0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "runtime-config", "service-client", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "53e77c6ba50626bf", "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": "9bbfd626e7fed283", "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": "e01bfddcd28fe1c1", "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": "355eb1f6cf19e66f", "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": "f2bc89998af462d7", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-8b02081eded4a290", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/import-historical-shopify.mjs:58"}, "properties": {"repobilityId": "ebad39fab2327a8e", "scanner": "scanner-primary", "fingerprint": "8b02081eded4a290", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e5cdc8db92003b93", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/middleware.ts:4"}, "properties": {"repobilityId": "f4f6c34c36cd1481", "scanner": "scanner-primary", "fingerprint": "e5cdc8db92003b93", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1df8593c1fcfb3ad", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/users/page.tsx:28"}, "properties": {"repobilityId": "f5ca457c9e601fa7", "scanner": "scanner-primary", "fingerprint": "1df8593c1fcfb3ad", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d4fe7e44cb696f59", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/pnl/page.tsx:113"}, "properties": {"repobilityId": "5870e48f462493c3", "scanner": "scanner-primary", "fingerprint": "d4fe7e44cb696f59", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3c46864236c86287", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/projects/page.tsx:543"}, "properties": {"repobilityId": "4ed8018954fa20e8", "scanner": "scanner-primary", "fingerprint": "3c46864236c86287", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-66a7a8fb83460b5a", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/google/callback/route.ts:11"}, "properties": {"repobilityId": "3ba5e16027717244", "scanner": "scanner-primary", "fingerprint": "66a7a8fb83460b5a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-40aa12fd79b57882", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/users/route.ts:19"}, "properties": {"repobilityId": "4f6c68dcf9b15aae", "scanner": "scanner-primary", "fingerprint": "40aa12fd79b57882", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-7ab94de19c9e177f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/klaviyo/sync/route.ts:15"}, "properties": {"repobilityId": "51f30a4ba537e4ea", "scanner": "scanner-primary", "fingerprint": "7ab94de19c9e177f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c6522730009b377d", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/meta/sync/route.ts:21"}, "properties": {"repobilityId": "dd8c592973379390", "scanner": "scanner-primary", "fingerprint": "c6522730009b377d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-a2a56b977d8b1d4b", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/app/api/influencers/codes/route.ts:56"}, "properties": {"repobilityId": "9b0c2ba36abaea12", "scanner": "scanner-primary", "fingerprint": "a2a56b977d8b1d4b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-ca07e5d458b0624e", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/app/api/context/route.ts:6"}, "properties": {"repobilityId": "f8cff597bc304d51", "scanner": "scanner-primary", "fingerprint": "ca07e5d458b0624e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-6bedcf4c5f7e0d6f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/ads/page.tsx:162"}, "properties": {"repobilityId": "d6772897bbf3459d", "scanner": "scanner-primary", "fingerprint": "6bedcf4c5f7e0d6f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-1dbfa46480ad72a9", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/objectives/page.tsx:69"}, "properties": {"repobilityId": "3a84ba594d054a2c", "scanner": "scanner-primary", "fingerprint": "1dbfa46480ad72a9", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ba321aaaf1755026", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/chat/knowledge/page.tsx:103"}, "properties": {"repobilityId": "3d3a6d8e538e5d56", "scanner": "scanner-primary", "fingerprint": "ba321aaaf1755026", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-4a3663f73954384e", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/influencers/page.tsx:195"}, "properties": {"repobilityId": "1bca348fcb2b2c8d", "scanner": "scanner-primary", "fingerprint": "4a3663f73954384e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-0f2520c0e17a4d07", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/lib/codes-server.ts:17"}, "properties": {"repobilityId": "c8f15804983dd36c", "scanner": "scanner-primary", "fingerprint": "0f2520c0e17a4d07", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-d6c5146fc919efd6", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/lib/codes.ts:1"}, "properties": {"repobilityId": "e1aa18f5a7f77c22", "scanner": "scanner-primary", "fingerprint": "d6c5146fc919efd6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-aa7adc2daea778f6", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/generosite.ts:10"}, "properties": {"repobilityId": "86ba2a8a4a8bb83f", "scanner": "scanner-primary", "fingerprint": "aa7adc2daea778f6", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-091a62581378c5fc", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/klaviyo.ts:9"}, "properties": {"repobilityId": "d779e7f1d34b42eb", "scanner": "scanner-primary", "fingerprint": "091a62581378c5fc", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-bc5057db25918f5d", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/shopify.ts:13"}, "properties": {"repobilityId": "4420887566b031ae", "scanner": "scanner-primary", "fingerprint": "bc5057db25918f5d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e014a5a9365b7942", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/google-ads.ts:18"}, "properties": {"repobilityId": "2c9e1b487c051290", "scanner": "scanner-primary", "fingerprint": "e014a5a9365b7942", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-602e1d333c77256f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/integrations/meta.ts:17"}, "properties": {"repobilityId": "5f785e4e76ebd713", "scanner": "scanner-primary", "fingerprint": "602e1d333c77256f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-eb5f8ab94aaf297b", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/mistral.ts:10"}, "properties": {"repobilityId": "1be127a71c75b517", "scanner": "scanner-primary", "fingerprint": "eb5f8ab94aaf297b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8540c548d24c5959", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/shopify-orders.ts:73"}, "properties": {"repobilityId": "77ec2ba39de71673", "scanner": "scanner-primary", "fingerprint": "8540c548d24c5959", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3d14040b00c9766e", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/shopify-products.ts:55"}, "properties": {"repobilityId": "e09be6134bb47507", "scanner": "scanner-primary", "fingerprint": "3d14040b00c9766e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8a3e0f37be61ab30", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/admin-fetch.ts:9"}, "properties": {"repobilityId": "c8fb809237a611c8", "scanner": "scanner-primary", "fingerprint": "8a3e0f37be61ab30", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-0b9b2f8ee5aca44d", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/lib/chat/llm.ts:21"}, "properties": {"repobilityId": "1d09948fac7ac6f0", "scanner": "scanner-primary", "fingerprint": "0b9b2f8ee5aca44d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-250f57e8a1dbd3c5", "level": "none", "message": {"text": "4 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "57584f22b735b5ee", "scanner": "scanner-primary", "fingerprint": "250f57e8a1dbd3c5", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}]}]}