{"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-e8bd34e4a9949a43", "name": "Stray `console.log` in TS/JS \u2014 scripts/seed-demo-accounts.ts:520", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed-demo-accounts.ts:520"}, "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-175af46cb9a28138", "name": "Stray `console.log` in TS/JS \u2014 scripts/setup-dynamodb.ts:19", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/setup-dynamodb.ts:19"}, "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-8ebdc5e31b3223e3", "name": "`truncate` class without `title=` for hover reveal \u2014 components/discover-section.tsx:253", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/discover-section.tsx:253"}, "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-8a8f54792ba575b4", "name": "`truncate` class without `title=` for hover reveal \u2014 components/navigation.tsx:262", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/navigation.tsx:262"}, "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-7d40545cb9a45822", "name": "`truncate` class without `title=` for hover reveal \u2014 components/saved-recipes-screen.tsx:172", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/saved-recipes-screen.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-1cc324c473961b47", "name": "`truncate` class without `title=` for hover reveal \u2014 components/collection-modal.tsx:119", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/collection-modal.tsx:119"}, "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-cf4fb903290f47fb", "name": "`truncate` class without `title=` for hover reveal \u2014 components/vision-review-screen.tsx:166", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/vision-review-screen.tsx:166"}, "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-95ae0c8512e95479", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 components/ui/chart.tsx:83", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 components/ui/chart.tsx:83"}, "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-8c70781a2f587184", "name": "Stray `console.log` in TS/JS \u2014 app/api/scan-ingredients/route.ts:21", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 app/api/scan-ingredients/route.ts:21"}, "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-72f0191db4b5c771", "name": "Stray `console.log` in TS/JS \u2014 app/api/insights/route.ts:188", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 app/api/insights/route.ts:188"}, "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-2fdb5356375fcaf6", "name": "Stray `console.log` in TS/JS \u2014 app/api/drink-pairings/route.ts:47", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 app/api/drink-pairings/route.ts:47"}, "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-dac7a616d2a07d3d", "name": "Stray `console.log` in TS/JS \u2014 lib/api.ts:106", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 lib/api.ts:106"}, "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-6492ed4ce4b177dd", "name": "Stray `console.log` in TS/JS \u2014 lambda/vision-scanner/index.js:93", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 lambda/vision-scanner/index.js:93"}, "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-038f95f510f35674", "name": "Insecure pattern 'dangerous_innerhtml' in components/ui/chart.tsx:83", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in components/ui/chart.tsx:83"}, "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-4b235dff16a74ebd", "name": "Insecure pattern 'cors_wildcard' in lambda/vision-scanner/index.js:186", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in lambda/vision-scanner/index.js:186"}, "fullDescription": {"text": "Found a known-risky pattern (cors_wildcard). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-fe2db51e6b41a74f", "name": "Insecure pattern 'cors_wildcard' in lambda/barcode-scanner/index.js:146", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in lambda/barcode-scanner/index.js:146"}, "fullDescription": {"text": "Found a known-risky pattern (cors_wildcard). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-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-b0b9ef8e4c610057", "name": "Very large file: components/generated-recipe-screen.tsx (1217 lines)", "shortDescription": {"text": "Very large file: components/generated-recipe-screen.tsx (1217 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-0f2454c5a586b717", "name": "Very large file: components/ingredients-screen.tsx (1073 lines)", "shortDescription": {"text": "Very large file: components/ingredients-screen.tsx (1073 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8d155a7f0df43e31", "name": "Node manifest has dependencies but no lockfile: lambda/taste-profile-writer/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: lambda/taste-profile-writer/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-b49b63e3f0ce3f41", "name": "Node manifest has dependencies but no lockfile: lambda/feedback-processor/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: lambda/feedback-processor/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-4b27af74581d1bdc", "name": "Node manifest has dependencies but no lockfile: lambda/vision-scanner/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: lambda/vision-scanner/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 133 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 35 placeholder/mock markers across 16 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, 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-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-4d2d33a758d807c2", "name": "Commented-code block (5 lines) in app/api/insights/route.ts:27", "shortDescription": {"text": "Commented-code block (5 lines) in app/api/insights/route.ts:27"}, "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-261526bdfdd6f0eb", "name": "Commented-code block (5 lines) in app/api/user/saved-recipes/route.ts:50", "shortDescription": {"text": "Commented-code block (5 lines) in app/api/user/saved-recipes/route.ts:50"}, "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-9410ef05d37bb3a3", "name": "Commented-code block (5 lines) in app/api/generate-recipe/route.ts:334", "shortDescription": {"text": "Commented-code block (5 lines) in app/api/generate-recipe/route.ts:334"}, "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-2cc17317bd38c0bd", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/auth-client.ts:111", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/auth-client.ts:111"}, "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-2e3acc0585690051", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/share-recipe.ts:7", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/share-recipe.ts:7"}, "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-34797c704d67ec3f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/__tests__/nudge-brief.test.ts:210", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/__tests__/nudge-brief.test.ts:210"}, "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-43cea5935dfd64ab", "name": "Legacy-named symbol `misoOld` in lib/__tests__/drift-profile.test.ts:88", "shortDescription": {"text": "Legacy-named symbol `misoOld` in lib/__tests__/drift-profile.test.ts:88"}, "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-57a2f1fd4a6d7cba", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-profile.ts:27", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-profile.ts:27"}, "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-8b3870c31cae03b9", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-insights.ts:21", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-insights.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-b59d524ff7ad533d", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-submit-feedback.ts:15", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-submit-feedback.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-8e8a13c9199cfcd7", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-recipe-brief.ts:11", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-recipe-brief.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-c69eea3e5b835977", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-substitutes.ts:28", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-substitutes.ts: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-2e2098550811c1e8", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-migrate-guest.ts:13", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-migrate-guest.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-c906de044f1f11af", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-update-collection.ts:10", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-update-collection.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-5d59e61a09f5f2f1", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-scan-barcode.ts:13", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-scan-barcode.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-6924bdb9141854be", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-recipe-safe-explain.ts:18", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-recipe-safe-explain.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-2d4dc08fab12538f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-drink-pairings.ts:19", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-drink-pairings.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-c889b92db1a72b92", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-history.ts:9", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-history.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-119709193cb87fe2", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-delete-collection.ts:9", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-delete-collection.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-80522f2ed36406af", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-ingredient-search.ts:5", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-ingredient-search.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-0fe8193499b9bf7c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-create-collection.ts:10", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-create-collection.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-4c47a973818c45e4", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-save-recipe.ts:9", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-save-recipe.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-10389b748784c47e", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-disliked-patterns.ts:10", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-disliked-patterns.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-71676c0c7b06f0ed", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-update-profile.ts:26", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-update-profile.ts:26"}, "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-b46ad99c9019b0a6", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-recipe-pairings.ts:13", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-recipe-pairings.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-78cab93b540ff975", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-unsave-recipe.ts:9", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-unsave-recipe.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-b686b06571e4bbee", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-complete-onboarding.ts:9", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-complete-onboarding.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-1d0cccb4a31f2be7", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-saved-recipes.ts:9", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-saved-recipes.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-c56ea7bb30a945a0", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-submit-survey.ts:11", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-submit-survey.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-eee79bbee6c4f774", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-collections.ts:9", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-collections.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-68998da3ac31fa71", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-generate-recipe.ts:17", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-generate-recipe.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-5d02084fe743c0c0", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-add-to-history.ts:9", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-add-to-history.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}}]}}, "automationDetails": {"id": "repobility/17698"}, "properties": {"repository": "RachelBurman/Fabel", "repoUrl": "https://github.com/RachelBurman/Fabel", "branch": "main"}, "results": [{"ruleId": "scanner-e8bd34e4a9949a43", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed-demo-accounts.ts:520"}, "properties": {"repobilityId": "4ba372eab8b68508", "scanner": "scanner-primary", "fingerprint": "e8bd34e4a9949a43", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-175af46cb9a28138", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/setup-dynamodb.ts:19"}, "properties": {"repobilityId": "c07ac9f05eb50d48", "scanner": "scanner-primary", "fingerprint": "175af46cb9a28138", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-8ebdc5e31b3223e3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/discover-section.tsx:253"}, "properties": {"repobilityId": "77f050519907f8d6", "scanner": "scanner-primary", "fingerprint": "8ebdc5e31b3223e3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8a8f54792ba575b4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/navigation.tsx:262"}, "properties": {"repobilityId": "0296dcb32a535e28", "scanner": "scanner-primary", "fingerprint": "8a8f54792ba575b4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7d40545cb9a45822", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/saved-recipes-screen.tsx:172"}, "properties": {"repobilityId": "00410ae0c48ea642", "scanner": "scanner-primary", "fingerprint": "7d40545cb9a45822", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1cc324c473961b47", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/collection-modal.tsx:119"}, "properties": {"repobilityId": "e9dc82410302c785", "scanner": "scanner-primary", "fingerprint": "1cc324c473961b47", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cf4fb903290f47fb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/vision-review-screen.tsx:166"}, "properties": {"repobilityId": "06d1464406d43a08", "scanner": "scanner-primary", "fingerprint": "cf4fb903290f47fb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-95ae0c8512e95479", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 components/ui/chart.tsx:83"}, "properties": {"repobilityId": "dd1e3f2d87b6f488", "scanner": "scanner-primary", "fingerprint": "95ae0c8512e95479", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-8c70781a2f587184", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 app/api/scan-ingredients/route.ts:21"}, "properties": {"repobilityId": "fc9357bf8f4e98cd", "scanner": "scanner-primary", "fingerprint": "8c70781a2f587184", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-72f0191db4b5c771", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 app/api/insights/route.ts:188"}, "properties": {"repobilityId": "22b084767adeca6c", "scanner": "scanner-primary", "fingerprint": "72f0191db4b5c771", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-2fdb5356375fcaf6", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 app/api/drink-pairings/route.ts:47"}, "properties": {"repobilityId": "7cc9fb341486b1c6", "scanner": "scanner-primary", "fingerprint": "2fdb5356375fcaf6", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-dac7a616d2a07d3d", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 lib/api.ts:106"}, "properties": {"repobilityId": "9893fced4a0811f8", "scanner": "scanner-primary", "fingerprint": "dac7a616d2a07d3d", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-6492ed4ce4b177dd", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 lambda/vision-scanner/index.js:93"}, "properties": {"repobilityId": "b30540bf6cec5864", "scanner": "scanner-primary", "fingerprint": "6492ed4ce4b177dd", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-038f95f510f35674", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in components/ui/chart.tsx:83"}, "properties": {"repobilityId": "c41c7626c87bbabe", "scanner": "scanner-primary", "fingerprint": "038f95f510f35674", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "components/ui/chart.tsx"}, "region": {"startLine": 83}}}]}, {"ruleId": "scanner-4b235dff16a74ebd", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in lambda/vision-scanner/index.js:186"}, "properties": {"repobilityId": "536bccb40239b83e", "scanner": "scanner-primary", "fingerprint": "4b235dff16a74ebd", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "lambda/vision-scanner/index.js"}, "region": {"startLine": 186}}}]}, {"ruleId": "scanner-fe2db51e6b41a74f", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in lambda/barcode-scanner/index.js:146"}, "properties": {"repobilityId": "63340e72b91d7230", "scanner": "scanner-primary", "fingerprint": "fe2db51e6b41a74f", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "lambda/barcode-scanner/index.js"}, "region": {"startLine": 146}}}]}, {"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-b0b9ef8e4c610057", "level": "note", "message": {"text": "Very large file: components/generated-recipe-screen.tsx (1217 lines)"}, "properties": {"repobilityId": "29867ea30f2ce446", "scanner": "scanner-primary", "fingerprint": "b0b9ef8e4c610057", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-0f2454c5a586b717", "level": "note", "message": {"text": "Very large file: components/ingredients-screen.tsx (1073 lines)"}, "properties": {"repobilityId": "454f77794c88b708", "scanner": "scanner-primary", "fingerprint": "0f2454c5a586b717", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "f1f027ac99257a1f", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-8d155a7f0df43e31", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: lambda/taste-profile-writer/package.json"}, "properties": {"repobilityId": "e200ce6a9339cac1", "scanner": "scanner-primary", "fingerprint": "8d155a7f0df43e31", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "lambda/taste-profile-writer/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-b49b63e3f0ce3f41", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: lambda/feedback-processor/package.json"}, "properties": {"repobilityId": "9ca0ebb85c33b680", "scanner": "scanner-primary", "fingerprint": "b49b63e3f0ce3f41", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "lambda/feedback-processor/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-4b27af74581d1bdc", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: lambda/vision-scanner/package.json"}, "properties": {"repobilityId": "48ba602eca3bc25c", "scanner": "scanner-primary", "fingerprint": "4b27af74581d1bdc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "lambda/vision-scanner/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "54a11550ad5b248c", "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": "09da0f15a26f92ed", "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": "4cac2308940b64f3", "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": "a3225c48227cb268", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "ebb0e6d6d7bd5df1", "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": "dc9fccdf027317b0", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-4d2d33a758d807c2", "level": "none", "message": {"text": "Commented-code block (5 lines) in app/api/insights/route.ts:27"}, "properties": {"repobilityId": "a3badacad81670b2", "scanner": "scanner-primary", "fingerprint": "4d2d33a758d807c2", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-261526bdfdd6f0eb", "level": "none", "message": {"text": "Commented-code block (5 lines) in app/api/user/saved-recipes/route.ts:50"}, "properties": {"repobilityId": "b60baba0c2652544", "scanner": "scanner-primary", "fingerprint": "261526bdfdd6f0eb", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-9410ef05d37bb3a3", "level": "none", "message": {"text": "Commented-code block (5 lines) in app/api/generate-recipe/route.ts:334"}, "properties": {"repobilityId": "907f4336390448ff", "scanner": "scanner-primary", "fingerprint": "9410ef05d37bb3a3", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2cc17317bd38c0bd", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/auth-client.ts:111"}, "properties": {"repobilityId": "3fca6ed7a584ca77", "scanner": "scanner-primary", "fingerprint": "2cc17317bd38c0bd", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-2e3acc0585690051", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/share-recipe.ts:7"}, "properties": {"repobilityId": "39ac41db88ff8d58", "scanner": "scanner-primary", "fingerprint": "2e3acc0585690051", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-34797c704d67ec3f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/__tests__/nudge-brief.test.ts:210"}, "properties": {"repobilityId": "01338b2cccfea4d3", "scanner": "scanner-primary", "fingerprint": "34797c704d67ec3f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-43cea5935dfd64ab", "level": "note", "message": {"text": "Legacy-named symbol `misoOld` in lib/__tests__/drift-profile.test.ts:88"}, "properties": {"repobilityId": "d515faffbda92cf6", "scanner": "scanner-primary", "fingerprint": "43cea5935dfd64ab", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-57a2f1fd4a6d7cba", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-profile.ts:27"}, "properties": {"repobilityId": "194ddc370a0c177b", "scanner": "scanner-primary", "fingerprint": "57a2f1fd4a6d7cba", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8b3870c31cae03b9", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-insights.ts:21"}, "properties": {"repobilityId": "2782ded06fee605d", "scanner": "scanner-primary", "fingerprint": "8b3870c31cae03b9", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-b59d524ff7ad533d", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-submit-feedback.ts:15"}, "properties": {"repobilityId": "568489ced8dcb4e4", "scanner": "scanner-primary", "fingerprint": "b59d524ff7ad533d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8e8a13c9199cfcd7", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-recipe-brief.ts:11"}, "properties": {"repobilityId": "2ecf475112fc5f30", "scanner": "scanner-primary", "fingerprint": "8e8a13c9199cfcd7", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c69eea3e5b835977", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-substitutes.ts:28"}, "properties": {"repobilityId": "5d0da1cca2ca698a", "scanner": "scanner-primary", "fingerprint": "c69eea3e5b835977", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-2e2098550811c1e8", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-migrate-guest.ts:13"}, "properties": {"repobilityId": "4e7b3b6306930302", "scanner": "scanner-primary", "fingerprint": "2e2098550811c1e8", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c906de044f1f11af", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-update-collection.ts:10"}, "properties": {"repobilityId": "af98eed7449c18bc", "scanner": "scanner-primary", "fingerprint": "c906de044f1f11af", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-5d59e61a09f5f2f1", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-scan-barcode.ts:13"}, "properties": {"repobilityId": "fc7859d64c1ec9b2", "scanner": "scanner-primary", "fingerprint": "5d59e61a09f5f2f1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-6924bdb9141854be", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-recipe-safe-explain.ts:18"}, "properties": {"repobilityId": "1f3bc397fc0bb08a", "scanner": "scanner-primary", "fingerprint": "6924bdb9141854be", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-2d4dc08fab12538f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-drink-pairings.ts:19"}, "properties": {"repobilityId": "abaac42088e7a03c", "scanner": "scanner-primary", "fingerprint": "2d4dc08fab12538f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c889b92db1a72b92", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-history.ts:9"}, "properties": {"repobilityId": "407dca207b89e7be", "scanner": "scanner-primary", "fingerprint": "c889b92db1a72b92", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-119709193cb87fe2", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-delete-collection.ts:9"}, "properties": {"repobilityId": "420b66b76c6a495a", "scanner": "scanner-primary", "fingerprint": "119709193cb87fe2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-80522f2ed36406af", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-ingredient-search.ts:5"}, "properties": {"repobilityId": "9d9322bdab813f58", "scanner": "scanner-primary", "fingerprint": "80522f2ed36406af", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-0fe8193499b9bf7c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-create-collection.ts:10"}, "properties": {"repobilityId": "b0f06a180b56df14", "scanner": "scanner-primary", "fingerprint": "0fe8193499b9bf7c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-4c47a973818c45e4", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-save-recipe.ts:9"}, "properties": {"repobilityId": "12e3003cee241181", "scanner": "scanner-primary", "fingerprint": "4c47a973818c45e4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-10389b748784c47e", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-disliked-patterns.ts:10"}, "properties": {"repobilityId": "2ddffe631e4be564", "scanner": "scanner-primary", "fingerprint": "10389b748784c47e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-71676c0c7b06f0ed", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-update-profile.ts:26"}, "properties": {"repobilityId": "a687e8e9e8ea033b", "scanner": "scanner-primary", "fingerprint": "71676c0c7b06f0ed", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-b46ad99c9019b0a6", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-recipe-pairings.ts:13"}, "properties": {"repobilityId": "1749d6eb47601e50", "scanner": "scanner-primary", "fingerprint": "b46ad99c9019b0a6", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-78cab93b540ff975", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-unsave-recipe.ts:9"}, "properties": {"repobilityId": "4089e0706b7aad09", "scanner": "scanner-primary", "fingerprint": "78cab93b540ff975", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-b686b06571e4bbee", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-complete-onboarding.ts:9"}, "properties": {"repobilityId": "d1d7c9162b37643c", "scanner": "scanner-primary", "fingerprint": "b686b06571e4bbee", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-1d0cccb4a31f2be7", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-saved-recipes.ts:9"}, "properties": {"repobilityId": "9a052b6112d9f1b4", "scanner": "scanner-primary", "fingerprint": "1d0cccb4a31f2be7", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c56ea7bb30a945a0", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-submit-survey.ts:11"}, "properties": {"repobilityId": "31d74c6aa98ccfac", "scanner": "scanner-primary", "fingerprint": "c56ea7bb30a945a0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-eee79bbee6c4f774", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-collections.ts:9"}, "properties": {"repobilityId": "46ab6733888cdaa7", "scanner": "scanner-primary", "fingerprint": "eee79bbee6c4f774", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-68998da3ac31fa71", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-generate-recipe.ts:17"}, "properties": {"repobilityId": "599b66b0edf13130", "scanner": "scanner-primary", "fingerprint": "68998da3ac31fa71", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-5d02084fe743c0c0", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/hooks/use-add-to-history.ts:9"}, "properties": {"repobilityId": "d9294ecbf42544cc", "scanner": "scanner-primary", "fingerprint": "5d02084fe743c0c0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}]}]}