{"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-6112a8908cd06518", "name": "Stray `console.log` in TS/JS \u2014 apps/api/src/index.ts:34", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/api/src/index.ts:34"}, "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-f242d26b0574f142", "name": "Stray `console.log` in TS/JS \u2014 apps/api/src/db.ts:12", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/api/src/db.ts:12"}, "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-7513649aaac619b1", "name": "Stray `console.log` in TS/JS \u2014 apps/api/src/wallet/apple.ts:109", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/api/src/wallet/apple.ts:109"}, "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-0bbb0dafbac0b849", "name": "Stray `console.log` in TS/JS \u2014 apps/api/src/routes/apple-wallet-service.ts:135", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/api/src/routes/apple-wallet-service.ts:135"}, "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-3e9619eedc53e46c", "name": "Stray `console.log` in TS/JS \u2014 apps/web/src/app/api/wallet/v1/log/route.ts:9", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/web/src/app/api/wallet/v1/log/route.ts:9"}, "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-8cfd0df43653c0c6", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/page.tsx:209", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/page.tsx:209"}, "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-eec2ad6732ba54f0", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/inventory/page.tsx:174", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/inventory/page.tsx:174"}, "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-842eab5f8caed4c1", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/pos/page.tsx:232", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/pos/page.tsx:232"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-7b206966fe9e9b65", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/reports/page.tsx:138", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/reports/page.tsx:138"}, "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-aa5acaa49eb8315b", "name": "Containers defined but no K8s/orchestration manifest found", "shortDescription": {"text": "Containers defined but no K8s/orchestration manifest found"}, "fullDescription": {"text": "Repo has Dockerfiles/compose but no Kubernetes/Nomad manifests. If the target deployment is K8s, the manifests may live in a separate ops repo."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1055200b84ac14ea", "name": "Insecure pattern 'cors_wildcard' in apps/api/src/index.ts:14", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in apps/api/src/index.ts:14"}, "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-ee4a0a3a0be0d6cf", "name": "Insecure pattern 'local_storage_auth_token' in apps/web/src/app/admin/login/page.tsx:43", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in apps/web/src/app/admin/login/page.tsx:43"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-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-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "0 test file(s) for 65 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-b06b8d86f24c77f9", "name": "Node manifest has dependencies but no lockfile: apps/api/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: apps/api/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-4a9eb7dc7c6e3880", "name": "Node manifest has dependencies but no lockfile: apps/web/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: apps/web/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 6 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 22 placeholder/mock markers across 8 source files. This often means the repo looks complete while core flows still use generated scaffolding or fake data."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, ci, tests, lockfile. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license, ci, tests, lockfile. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-aca9eb2a0174a543", "name": "Legacy-named symbol `stamps_old` in apps/api/src/routes/admin.ts:80", "shortDescription": {"text": "Legacy-named symbol `stamps_old` in apps/api/src/routes/admin.ts:80"}, "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-c12a89d3fc97bb75", "name": "Commented-code block (5 lines) in apps/web/src/app/api/admin/reports/route.ts:32", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/app/api/admin/reports/route.ts:32"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-3f223ae6e8149f6b", "name": "Commented-code block (5 lines) in apps/web/src/app/api/admin/products/route.ts:61", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/app/api/admin/products/route.ts:61"}, "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-3f8d53a8aa4b1ab0", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/app/admin/pos/page.tsx:430", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/app/admin/pos/page.tsx:430"}, "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-2cc786bfe1e148a5", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/app/register/page.tsx:61", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/app/register/page.tsx:61"}, "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-d0847862e52e30e9", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/lib/admin-fetch.ts:29", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/lib/admin-fetch.ts:29"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-5021e4f7100a9099", "name": "Legacy-named symbol `bunsik_ramen_loyalty_v1` in apps/web/src/lib/google-wallet.ts:7", "shortDescription": {"text": "Legacy-named symbol `bunsik_ramen_loyalty_v1` in apps/web/src/lib/google-wallet.ts:7"}, "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-d674952f93cafebf", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/lib/google-wallet.ts:40", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/lib/google-wallet.ts:40"}, "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-59b992d62d86a65a", "name": "25 env vars used in code but missing from .env.example", "shortDescription": {"text": "25 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `ADMIN_SETUP_SECRET`, `APPLE_APNS_KEY_BASE64`, `APPLE_AUTH_TOKEN`, `APPLE_CERT_PASSWORD`, `APPLE_KEY_ID`, `APPLE_PASS_CERT`, `APPLE_PASS_KEY`, `APPLE_PASS_TYPE_ID` + 17 more. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-51b4bc04bd986714", "name": "Dangling fetch: POST /api/auth/login (apps/web/src/app/admin/login/page.tsx:33)", "shortDescription": {"text": "Dangling fetch: POST /api/auth/login (apps/web/src/app/admin/login/page.tsx:33)"}, "fullDescription": {"text": "`apps/web/src/app/admin/login/page.tsx:33` calls `POST /api/auth/login` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/auth/login`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-c418ab996c0e08c0", "name": "Dangling fetch: GET /api/loyalty/clients/${clientId} (apps/web/src/app/admin/clients/[clientId]/page.tsx:22)", "shortDescription": {"text": "Dangling fetch: GET /api/loyalty/clients/${clientId} (apps/web/src/app/admin/clients/[clientId]/page.tsx:22)"}, "fullDescription": {"text": "`apps/web/src/app/admin/clients/[clientId]/page.tsx:22` calls `GET /api/loyalty/clients/${clientId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/loyalty/clients/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-dae16b4be12fc493", "name": "Dangling fetch: POST /api/admin/clients (apps/web/src/app/admin/pos/page.tsx:430)", "shortDescription": {"text": "Dangling fetch: POST /api/admin/clients (apps/web/src/app/admin/pos/page.tsx:430)"}, "fullDescription": {"text": "`apps/web/src/app/admin/pos/page.tsx:430` calls `POST /api/admin/clients` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/admin/clients`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-b6077f864d328abc", "name": "Dangling fetch: POST /api/auth/setup-admin (apps/web/src/app/admin/setup/page.tsx:21)", "shortDescription": {"text": "Dangling fetch: POST /api/auth/setup-admin (apps/web/src/app/admin/setup/page.tsx:21)"}, "fullDescription": {"text": "`apps/web/src/app/admin/setup/page.tsx:21` calls `POST /api/auth/setup-admin` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/auth/setup-admin`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-c5add721a2cafa1d", "name": "Dangling fetch: GET /api/loyalty/clients/${clientId} (apps/web/src/app/card/[clientId]/page.tsx:28)", "shortDescription": {"text": "Dangling fetch: GET /api/loyalty/clients/${clientId} (apps/web/src/app/card/[clientId]/page.tsx:28)"}, "fullDescription": {"text": "`apps/web/src/app/card/[clientId]/page.tsx:28` calls `GET /api/loyalty/clients/${clientId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/loyalty/clients/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-23a953fc7a10d30e", "name": "Dangling fetch: GET /api/loyalty/clients/${dbClientId}/google-wallet (apps/web/src/app/card/[clientId]/page.tsx:81)", "shortDescription": {"text": "Dangling fetch: GET /api/loyalty/clients/${dbClientId}/google-wallet (apps/web/src/app/card/[clientId]/page.tsx:81)"}, "fullDescription": {"text": "`apps/web/src/app/card/[clientId]/page.tsx:81` calls `GET /api/loyalty/clients/${dbClientId}/google-wallet` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/loyalty/clients/<p>/google-wallet`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-0f4aeae298e199a6", "name": "Dangling fetch: POST /api/loyalty/clients/${dbClientId}/redeem (apps/web/src/app/card/[clientId]/page.tsx:105)", "shortDescription": {"text": "Dangling fetch: POST /api/loyalty/clients/${dbClientId}/redeem (apps/web/src/app/card/[clientId]/page.tsx:105)"}, "fullDescription": {"text": "`apps/web/src/app/card/[clientId]/page.tsx:105` calls `POST /api/loyalty/clients/${dbClientId}/redeem` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/loyalty/clients/<p>/redeem`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-806cdc00675fda6a", "name": "Dangling fetch: POST /api/loyalty/lookup (apps/web/src/app/register/page.tsx:47)", "shortDescription": {"text": "Dangling fetch: POST /api/loyalty/lookup (apps/web/src/app/register/page.tsx:47)"}, "fullDescription": {"text": "`apps/web/src/app/register/page.tsx:47` calls `POST /api/loyalty/lookup` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/loyalty/lookup`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-6fedf45a3cee6f95", "name": "Dangling fetch: POST /api/admin/clients (apps/web/src/app/register/page.tsx:61)", "shortDescription": {"text": "Dangling fetch: POST /api/admin/clients (apps/web/src/app/register/page.tsx:61)"}, "fullDescription": {"text": "`apps/web/src/app/register/page.tsx:61` calls `POST /api/admin/clients` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/admin/clients`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-a88c1884a94001a2", "name": "Dangling fetch: POST https://oauth2.googleapis.com/token (apps/web/src/lib/google-wallet.ts:40)", "shortDescription": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (apps/web/src/lib/google-wallet.ts:40)"}, "fullDescription": {"text": "`apps/web/src/lib/google-wallet.ts:40` calls `POST https://oauth2.googleapis.com/token` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/https:/oauth2.googleapis.com/token`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-e3fb06b89c3e8192", "name": "Unused endpoint: USE /api/loyalty/assets", "shortDescription": {"text": "Unused endpoint: USE /api/loyalty/assets"}, "fullDescription": {"text": "`apps/api/src/index.ts` declares `USE /api/loyalty/assets` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4756b4c4da7d2088", "name": "Unused endpoint: GET /api/health", "shortDescription": {"text": "Unused endpoint: GET /api/health"}, "fullDescription": {"text": "`apps/api/src/index.ts` declares `GET /api/health` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6eb452fbfb454d20", "name": "Unused endpoint: USE /api/auth", "shortDescription": {"text": "Unused endpoint: USE /api/auth"}, "fullDescription": {"text": "`apps/api/src/index.ts` declares `USE /api/auth` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d93a530ce10d47d9", "name": "Unused endpoint: USE /api/admin", "shortDescription": {"text": "Unused endpoint: USE /api/admin"}, "fullDescription": {"text": "`apps/api/src/index.ts` declares `USE /api/admin` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-fc1ae453f0ad8587", "name": "Unused endpoint: USE /api/loyalty", "shortDescription": {"text": "Unused endpoint: USE /api/loyalty"}, "fullDescription": {"text": "`apps/api/src/index.ts` declares `USE /api/loyalty` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6653c30a2e4a0b5e", "name": "Unused endpoint: USE /api/wallet/v1", "shortDescription": {"text": "Unused endpoint: USE /api/wallet/v1"}, "fullDescription": {"text": "`apps/api/src/index.ts` declares `USE /api/wallet/v1` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-fa3d6a5bbdca1b6f", "name": "Unused endpoint: GET /clients/search/:name", "shortDescription": {"text": "Unused endpoint: GET /clients/search/:name"}, "fullDescription": {"text": "`apps/api/src/routes/loyalty.ts` declares `GET /clients/search/:name` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9c87000fdfc814a0", "name": "Unused endpoint: GET /clients/:clientId", "shortDescription": {"text": "Unused endpoint: GET /clients/:clientId"}, "fullDescription": {"text": "`apps/api/src/routes/loyalty.ts` declares `GET /clients/:clientId` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e5f46977752ae816", "name": "Unused endpoint: GET /clients/:clientId/apple-wallet", "shortDescription": {"text": "Unused endpoint: GET /clients/:clientId/apple-wallet"}, "fullDescription": {"text": "`apps/api/src/routes/loyalty.ts` declares `GET /clients/:clientId/apple-wallet` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-fe636a60f7a0f630", "name": "Unused endpoint: GET /clients/:clientId/google-wallet", "shortDescription": {"text": "Unused endpoint: GET /clients/:clientId/google-wallet"}, "fullDescription": {"text": "`apps/api/src/routes/loyalty.ts` declares `GET /clients/:clientId/google-wallet` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e838622a29f8a318", "name": "Unused endpoint: POST /clients/:clientId/redeem", "shortDescription": {"text": "Unused endpoint: POST /clients/:clientId/redeem"}, "fullDescription": {"text": "`apps/api/src/routes/loyalty.ts` declares `POST /clients/:clientId/redeem` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-618721b912bad1c2", "name": "Unused endpoint: POST /login", "shortDescription": {"text": "Unused endpoint: POST /login"}, "fullDescription": {"text": "`apps/api/src/routes/auth.ts` declares `POST /login` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7d1bf1f2decf762e", "name": "Unused endpoint: POST /devices/:deviceId/registrations/:passTypeId/:serialNumber", "shortDescription": {"text": "Unused endpoint: POST /devices/:deviceId/registrations/:passTypeId/:serialNumber"}, "fullDescription": {"text": "`apps/api/src/routes/apple-wallet-service.ts` declares `POST /devices/:deviceId/registrations/:passTypeId/:serialNumber` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e8888764725c9f98", "name": "Unused endpoint: DELETE /devices/:deviceId/registrations/:passTypeId/:serialNumber", "shortDescription": {"text": "Unused endpoint: DELETE /devices/:deviceId/registrations/:passTypeId/:serialNumber"}, "fullDescription": {"text": "`apps/api/src/routes/apple-wallet-service.ts` declares `DELETE /devices/:deviceId/registrations/:passTypeId/:serialNumber` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1484238d0c675bfc", "name": "Unused endpoint: GET /devices/:deviceId/registrations/:passTypeId", "shortDescription": {"text": "Unused endpoint: GET /devices/:deviceId/registrations/:passTypeId"}, "fullDescription": {"text": "`apps/api/src/routes/apple-wallet-service.ts` declares `GET /devices/:deviceId/registrations/:passTypeId` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5046470347986593", "name": "Unused endpoint: GET /passes/:passTypeId/:serialNumber", "shortDescription": {"text": "Unused endpoint: GET /passes/:passTypeId/:serialNumber"}, "fullDescription": {"text": "`apps/api/src/routes/apple-wallet-service.ts` declares `GET /passes/:passTypeId/:serialNumber` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-059430d5f3ac5090", "name": "Unused endpoint: POST /log", "shortDescription": {"text": "Unused endpoint: POST /log"}, "fullDescription": {"text": "`apps/api/src/routes/apple-wallet-service.ts` declares `POST /log` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0729b84d4e27d0b9", "name": "Unused endpoint: GET /clients", "shortDescription": {"text": "Unused endpoint: GET /clients"}, "fullDescription": {"text": "`apps/api/src/routes/admin.ts` declares `GET /clients` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-23b0643f613389f0", "name": "Unused endpoint: POST /clients/:id/stamp", "shortDescription": {"text": "Unused endpoint: POST /clients/:id/stamp"}, "fullDescription": {"text": "`apps/api/src/routes/admin.ts` declares `POST /clients/:id/stamp` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a22e4396af9d5790", "name": "Unused endpoint: POST /clients", "shortDescription": {"text": "Unused endpoint: POST /clients"}, "fullDescription": {"text": "`apps/api/src/routes/admin.ts` declares `POST /clients` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/18768"}, "properties": {"repository": "said019/Urban-Eats", "repoUrl": "https://github.com/said019/Urban-Eats", "branch": "main"}, "results": [{"ruleId": "scanner-6112a8908cd06518", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/api/src/index.ts:34"}, "properties": {"repobilityId": "a178156af585d748", "scanner": "scanner-primary", "fingerprint": "6112a8908cd06518", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-f242d26b0574f142", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/api/src/db.ts:12"}, "properties": {"repobilityId": "3effcbab2c60f8f1", "scanner": "scanner-primary", "fingerprint": "f242d26b0574f142", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-7513649aaac619b1", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/api/src/wallet/apple.ts:109"}, "properties": {"repobilityId": "098f78a7ea3e3662", "scanner": "scanner-primary", "fingerprint": "7513649aaac619b1", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-0bbb0dafbac0b849", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/api/src/routes/apple-wallet-service.ts:135"}, "properties": {"repobilityId": "4de138b185e82752", "scanner": "scanner-primary", "fingerprint": "0bbb0dafbac0b849", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-3e9619eedc53e46c", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/web/src/app/api/wallet/v1/log/route.ts:9"}, "properties": {"repobilityId": "942169777bdb6c67", "scanner": "scanner-primary", "fingerprint": "3e9619eedc53e46c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-8cfd0df43653c0c6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/page.tsx:209"}, "properties": {"repobilityId": "50efa0c08d598c01", "scanner": "scanner-primary", "fingerprint": "8cfd0df43653c0c6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-eec2ad6732ba54f0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/inventory/page.tsx:174"}, "properties": {"repobilityId": "b52cf77a39ea7452", "scanner": "scanner-primary", "fingerprint": "eec2ad6732ba54f0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-842eab5f8caed4c1", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/pos/page.tsx:232"}, "properties": {"repobilityId": "f78faf09f8f41841", "scanner": "scanner-primary", "fingerprint": "842eab5f8caed4c1", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7b206966fe9e9b65", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/admin/reports/page.tsx:138"}, "properties": {"repobilityId": "4cd1e27b1cb4b959", "scanner": "scanner-primary", "fingerprint": "7b206966fe9e9b65", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-aa5acaa49eb8315b", "level": "note", "message": {"text": "Containers defined but no K8s/orchestration manifest found"}, "properties": {"repobilityId": "b230ea9b68736081", "scanner": "scanner-primary", "fingerprint": "aa5acaa49eb8315b", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["coverage", "deployment"]}}, {"ruleId": "scanner-1055200b84ac14ea", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in apps/api/src/index.ts:14"}, "properties": {"repobilityId": "3ca37d88226c999f", "scanner": "scanner-primary", "fingerprint": "1055200b84ac14ea", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/api/src/index.ts"}, "region": {"startLine": 14}}}]}, {"ruleId": "scanner-ee4a0a3a0be0d6cf", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in apps/web/src/app/admin/login/page.tsx:43"}, "properties": {"repobilityId": "d8bad95242668fbd", "scanner": "scanner-primary", "fingerprint": "ee4a0a3a0be0d6cf", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/web/src/app/admin/login/page.tsx"}, "region": {"startLine": 43}}}]}, {"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-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": "9e2b6c46478a3886", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-b06b8d86f24c77f9", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: apps/api/package.json"}, "properties": {"repobilityId": "ce77cd34ed0306d4", "scanner": "scanner-primary", "fingerprint": "b06b8d86f24c77f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/api/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-4a9eb7dc7c6e3880", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: apps/web/package.json"}, "properties": {"repobilityId": "6c1704bf24cf19ac", "scanner": "scanner-primary", "fingerprint": "4a9eb7dc7c6e3880", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/web/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "eea4e833cb2a111a", "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": "b62a79448b90366f", "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": "2e9dec80ae9727a4", "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": "180320a44891ba06", "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": "cffc5cdd7517a861", "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": "edcb34d5d6730097", "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": "510adb122fbbad40", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-aca9eb2a0174a543", "level": "note", "message": {"text": "Legacy-named symbol `stamps_old` in apps/api/src/routes/admin.ts:80"}, "properties": {"repobilityId": "1770fc4ee13ec310", "scanner": "scanner-primary", "fingerprint": "aca9eb2a0174a543", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-c12a89d3fc97bb75", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/app/api/admin/reports/route.ts:32"}, "properties": {"repobilityId": "7d498fefd81b2461", "scanner": "scanner-primary", "fingerprint": "c12a89d3fc97bb75", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3f223ae6e8149f6b", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/app/api/admin/products/route.ts:61"}, "properties": {"repobilityId": "1d58ed05c534ac30", "scanner": "scanner-primary", "fingerprint": "3f223ae6e8149f6b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3f8d53a8aa4b1ab0", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/app/admin/pos/page.tsx:430"}, "properties": {"repobilityId": "26a9688af4770cf2", "scanner": "scanner-primary", "fingerprint": "3f8d53a8aa4b1ab0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-2cc786bfe1e148a5", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/app/register/page.tsx:61"}, "properties": {"repobilityId": "9bfabc00c1529e94", "scanner": "scanner-primary", "fingerprint": "2cc786bfe1e148a5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d0847862e52e30e9", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/lib/admin-fetch.ts:29"}, "properties": {"repobilityId": "ac6e89153d82edde", "scanner": "scanner-primary", "fingerprint": "d0847862e52e30e9", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-5021e4f7100a9099", "level": "note", "message": {"text": "Legacy-named symbol `bunsik_ramen_loyalty_v1` in apps/web/src/lib/google-wallet.ts:7"}, "properties": {"repobilityId": "bc9fe0d604a7b63b", "scanner": "scanner-primary", "fingerprint": "5021e4f7100a9099", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-d674952f93cafebf", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/lib/google-wallet.ts:40"}, "properties": {"repobilityId": "05fa0117814730f8", "scanner": "scanner-primary", "fingerprint": "d674952f93cafebf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-59b992d62d86a65a", "level": "note", "message": {"text": "25 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "58b9516d72ffa8ba", "scanner": "scanner-primary", "fingerprint": "59b992d62d86a65a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-51b4bc04bd986714", "level": "error", "message": {"text": "Dangling fetch: POST /api/auth/login (apps/web/src/app/admin/login/page.tsx:33)"}, "properties": {"repobilityId": "056df312284d194e", "scanner": "scanner-primary", "fingerprint": "51b4bc04bd986714", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-c418ab996c0e08c0", "level": "error", "message": {"text": "Dangling fetch: GET /api/loyalty/clients/${clientId} (apps/web/src/app/admin/clients/[clientId]/page.tsx:22)"}, "properties": {"repobilityId": "0c3be68f57c11134", "scanner": "scanner-primary", "fingerprint": "c418ab996c0e08c0", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-dae16b4be12fc493", "level": "error", "message": {"text": "Dangling fetch: POST /api/admin/clients (apps/web/src/app/admin/pos/page.tsx:430)"}, "properties": {"repobilityId": "23bce677ab18a745", "scanner": "scanner-primary", "fingerprint": "dae16b4be12fc493", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-b6077f864d328abc", "level": "error", "message": {"text": "Dangling fetch: POST /api/auth/setup-admin (apps/web/src/app/admin/setup/page.tsx:21)"}, "properties": {"repobilityId": "b7a8b49a6832f447", "scanner": "scanner-primary", "fingerprint": "b6077f864d328abc", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-c5add721a2cafa1d", "level": "error", "message": {"text": "Dangling fetch: GET /api/loyalty/clients/${clientId} (apps/web/src/app/card/[clientId]/page.tsx:28)"}, "properties": {"repobilityId": "e9e05d97a72bdf9b", "scanner": "scanner-primary", "fingerprint": "c5add721a2cafa1d", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-23a953fc7a10d30e", "level": "error", "message": {"text": "Dangling fetch: GET /api/loyalty/clients/${dbClientId}/google-wallet (apps/web/src/app/card/[clientId]/page.tsx:81)"}, "properties": {"repobilityId": "e468777e11c3fff2", "scanner": "scanner-primary", "fingerprint": "23a953fc7a10d30e", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-0f4aeae298e199a6", "level": "error", "message": {"text": "Dangling fetch: POST /api/loyalty/clients/${dbClientId}/redeem (apps/web/src/app/card/[clientId]/page.tsx:105)"}, "properties": {"repobilityId": "d93477e6b6ed8b40", "scanner": "scanner-primary", "fingerprint": "0f4aeae298e199a6", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-806cdc00675fda6a", "level": "error", "message": {"text": "Dangling fetch: POST /api/loyalty/lookup (apps/web/src/app/register/page.tsx:47)"}, "properties": {"repobilityId": "f309460d0e9a828c", "scanner": "scanner-primary", "fingerprint": "806cdc00675fda6a", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-6fedf45a3cee6f95", "level": "error", "message": {"text": "Dangling fetch: POST /api/admin/clients (apps/web/src/app/register/page.tsx:61)"}, "properties": {"repobilityId": "9ae1aa63ec5ce906", "scanner": "scanner-primary", "fingerprint": "6fedf45a3cee6f95", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-a88c1884a94001a2", "level": "error", "message": {"text": "Dangling fetch: POST https://oauth2.googleapis.com/token (apps/web/src/lib/google-wallet.ts:40)"}, "properties": {"repobilityId": "b55063c4b1b125cd", "scanner": "scanner-primary", "fingerprint": "a88c1884a94001a2", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-e3fb06b89c3e8192", "level": "note", "message": {"text": "Unused endpoint: USE /api/loyalty/assets"}, "properties": {"repobilityId": "3d57a95af693cb6f", "scanner": "scanner-primary", "fingerprint": "e3fb06b89c3e8192", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4756b4c4da7d2088", "level": "note", "message": {"text": "Unused endpoint: GET /api/health"}, "properties": {"repobilityId": "273a9c4a06c02ef2", "scanner": "scanner-primary", "fingerprint": "4756b4c4da7d2088", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6eb452fbfb454d20", "level": "note", "message": {"text": "Unused endpoint: USE /api/auth"}, "properties": {"repobilityId": "ca90d9959dfedd33", "scanner": "scanner-primary", "fingerprint": "6eb452fbfb454d20", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d93a530ce10d47d9", "level": "note", "message": {"text": "Unused endpoint: USE /api/admin"}, "properties": {"repobilityId": "f5f3702b6a1d6b22", "scanner": "scanner-primary", "fingerprint": "d93a530ce10d47d9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fc1ae453f0ad8587", "level": "note", "message": {"text": "Unused endpoint: USE /api/loyalty"}, "properties": {"repobilityId": "0afc777c6d917c82", "scanner": "scanner-primary", "fingerprint": "fc1ae453f0ad8587", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6653c30a2e4a0b5e", "level": "note", "message": {"text": "Unused endpoint: USE /api/wallet/v1"}, "properties": {"repobilityId": "3049653f11dc12de", "scanner": "scanner-primary", "fingerprint": "6653c30a2e4a0b5e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fa3d6a5bbdca1b6f", "level": "note", "message": {"text": "Unused endpoint: GET /clients/search/:name"}, "properties": {"repobilityId": "db435e0567e5768c", "scanner": "scanner-primary", "fingerprint": "fa3d6a5bbdca1b6f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9c87000fdfc814a0", "level": "note", "message": {"text": "Unused endpoint: GET /clients/:clientId"}, "properties": {"repobilityId": "c83b48c0622c0986", "scanner": "scanner-primary", "fingerprint": "9c87000fdfc814a0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e5f46977752ae816", "level": "note", "message": {"text": "Unused endpoint: GET /clients/:clientId/apple-wallet"}, "properties": {"repobilityId": "b28e86fec9163a66", "scanner": "scanner-primary", "fingerprint": "e5f46977752ae816", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fe636a60f7a0f630", "level": "note", "message": {"text": "Unused endpoint: GET /clients/:clientId/google-wallet"}, "properties": {"repobilityId": "6adeec31c1335509", "scanner": "scanner-primary", "fingerprint": "fe636a60f7a0f630", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e838622a29f8a318", "level": "note", "message": {"text": "Unused endpoint: POST /clients/:clientId/redeem"}, "properties": {"repobilityId": "585ae7d58950bd95", "scanner": "scanner-primary", "fingerprint": "e838622a29f8a318", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-618721b912bad1c2", "level": "note", "message": {"text": "Unused endpoint: POST /login"}, "properties": {"repobilityId": "fc5f131b36853471", "scanner": "scanner-primary", "fingerprint": "618721b912bad1c2", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7d1bf1f2decf762e", "level": "note", "message": {"text": "Unused endpoint: POST /devices/:deviceId/registrations/:passTypeId/:serialNumber"}, "properties": {"repobilityId": "a3a52dea7f540561", "scanner": "scanner-primary", "fingerprint": "7d1bf1f2decf762e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e8888764725c9f98", "level": "note", "message": {"text": "Unused endpoint: DELETE /devices/:deviceId/registrations/:passTypeId/:serialNumber"}, "properties": {"repobilityId": "3a25666066bc0d1f", "scanner": "scanner-primary", "fingerprint": "e8888764725c9f98", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1484238d0c675bfc", "level": "note", "message": {"text": "Unused endpoint: GET /devices/:deviceId/registrations/:passTypeId"}, "properties": {"repobilityId": "0cf74786673503b2", "scanner": "scanner-primary", "fingerprint": "1484238d0c675bfc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5046470347986593", "level": "note", "message": {"text": "Unused endpoint: GET /passes/:passTypeId/:serialNumber"}, "properties": {"repobilityId": "26c5e7c7a233e9e0", "scanner": "scanner-primary", "fingerprint": "5046470347986593", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-059430d5f3ac5090", "level": "note", "message": {"text": "Unused endpoint: POST /log"}, "properties": {"repobilityId": "f72dedf8f5a356ce", "scanner": "scanner-primary", "fingerprint": "059430d5f3ac5090", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0729b84d4e27d0b9", "level": "note", "message": {"text": "Unused endpoint: GET /clients"}, "properties": {"repobilityId": "55fbfc2084ee460d", "scanner": "scanner-primary", "fingerprint": "0729b84d4e27d0b9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-23b0643f613389f0", "level": "note", "message": {"text": "Unused endpoint: POST /clients/:id/stamp"}, "properties": {"repobilityId": "1cbca6c8fe1f0753", "scanner": "scanner-primary", "fingerprint": "23b0643f613389f0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a22e4396af9d5790", "level": "note", "message": {"text": "Unused endpoint: POST /clients"}, "properties": {"repobilityId": "edbd24b7d2a09436", "scanner": "scanner-primary", "fingerprint": "a22e4396af9d5790", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}