{"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-6ae5f823be369727", "name": "Possibly dead Python function: require_manager", "shortDescription": {"text": "Possibly dead Python function: require_manager"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-133dfdb49edb4392", "name": "Possibly dead Python function: update_loyalty_object", "shortDescription": {"text": "Possibly dead Python function: update_loyalty_object"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d03c276e2138a5c2", "name": "Possibly dead Python function: count_saved_passes", "shortDescription": {"text": "Possibly dead Python function: count_saved_passes"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0f5d8e3ef9ff062a", "name": "Possibly dead Python function: broadcast_class_message", "shortDescription": {"text": "Possibly dead Python function: broadcast_class_message"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0781fbc4c721a7f4", "name": "Possibly dead Python function: create_loyalty_class_if_needed", "shortDescription": {"text": "Possibly dead Python function: create_loyalty_class_if_needed"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8297e4ba9443de74", "name": "Possibly dead Python function: render_frittes_stamps", "shortDescription": {"text": "Possibly dead Python function: render_frittes_stamps"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-adafbfa10498a927", "name": "Possibly dead Python function: complete_profile_for_phone", "shortDescription": {"text": "Possibly dead Python function: complete_profile_for_phone"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-75608ecceef2693b", "name": "Possibly dead Python function: send_redemption_email", "shortDescription": {"text": "Possibly dead Python function: send_redemption_email"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-10b7d1d490bb6506", "name": "Possibly dead Python function: upgrade", "shortDescription": {"text": "Possibly dead Python function: upgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6e71924957118666", "name": "Possibly dead Python function: downgrade", "shortDescription": {"text": "Possibly dead Python function: downgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9649ee14980ea3ed", "name": "Possibly dead Python function: upgrade", "shortDescription": {"text": "Possibly dead Python function: upgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7395f32799d3754f", "name": "Possibly dead Python function: downgrade", "shortDescription": {"text": "Possibly dead Python function: downgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-54c67719a740a802", "name": "Possibly dead Python function: upgrade", "shortDescription": {"text": "Possibly dead Python function: upgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-29ec4a1266ee0544", "name": "Possibly dead Python function: downgrade", "shortDescription": {"text": "Possibly dead Python function: downgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-43101a378a9f9227", "name": "Possibly dead Python function: upgrade", "shortDescription": {"text": "Possibly dead Python function: upgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-150b14b2a1507ca4", "name": "Possibly dead Python function: downgrade", "shortDescription": {"text": "Possibly dead Python function: downgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3b70906a23466d53", "name": "Possibly dead Python function: upgrade", "shortDescription": {"text": "Possibly dead Python function: upgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-168d1e301796c898", "name": "Possibly dead Python function: downgrade", "shortDescription": {"text": "Possibly dead Python function: downgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e9fd7a7e3d6ee3bc", "name": "Possibly dead Python function: upgrade", "shortDescription": {"text": "Possibly dead Python function: upgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a6a23dd3b3ebe87a", "name": "Possibly dead Python function: downgrade", "shortDescription": {"text": "Possibly dead Python function: downgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c9172f8e629f55d7", "name": "Possibly dead Python function: upgrade", "shortDescription": {"text": "Possibly dead Python function: upgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b069f0f1933bf076", "name": "Possibly dead Python function: downgrade", "shortDescription": {"text": "Possibly dead Python function: downgrade"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-56cd6a65fee77240", "name": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-loyalty/components/celebration-overlay.tsx:228", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-loyalty/components/celebration-overlay.tsx:228"}, "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-396732b4e90a55b4", "name": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-loyalty/components/wallet-pass.tsx:251", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-loyalty/components/wallet-pass.tsx:251"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-50879b0394801081", "name": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-loyalty/app/page.tsx:292", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-loyalty/app/page.tsx:292"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-23028cc73f107f39", "name": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-pos/app/admin/page.tsx:515", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-pos/app/admin/page.tsx:515"}, "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-f177648ce5ef1247", "name": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-pos/app/carta/page.tsx:342", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-pos/app/carta/page.tsx:342"}, "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-763dd01d25260dda", "name": "Insecure pattern 'local_storage_auth_token' in frontends/frittes-pos/app/login/page.tsx:42", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontends/frittes-pos/app/login/page.tsx:42"}, "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-3bbed5e0380d809d", "name": "Very large file: frontends/frittes-pos/app/admin/page.tsx (1493 lines)", "shortDescription": {"text": "Very large file: frontends/frittes-pos/app/admin/page.tsx (1493 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "0 test file(s) for 89 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-72b2a6250083a784", "name": "Placeholder or mock-heavy implementation detected", "shortDescription": {"text": "Placeholder or mock-heavy implementation detected"}, "fullDescription": {"text": "Found 46 placeholder/mock markers across 12 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. 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-a60141141bb9924f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontends/frittes-loyalty/public/sw.js:50", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontends/frittes-loyalty/public/sw.js:50"}, "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-aba3b1b22b262e56", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontends/frittes-pos/app/proximidad/page.tsx:169", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontends/frittes-pos/app/proximidad/page.tsx:169"}, "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-492d0c140cd23710", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontends/frittes-pos/public/sw.js:47", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontends/frittes-pos/public/sw.js:47"}, "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-b35bdc650e996e65", "name": "Legacy-named symbol `model_copy` in backend/app/config.py:102", "shortDescription": {"text": "Legacy-named symbol `model_copy` in backend/app/config.py:102"}, "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-c37d1c8cdf5e7156", "name": "Commented-code block (6 lines) in backend/app/loyalty/router.py:372", "shortDescription": {"text": "Commented-code block (6 lines) in backend/app/loyalty/router.py:372"}, "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-f9b3968ecce2acec", "name": "Commented-code block (5 lines) in backend/app/loyalty/wallet_stamps.py:48", "shortDescription": {"text": "Commented-code block (5 lines) in backend/app/loyalty/wallet_stamps.py:48"}, "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-2eafc3188c36bb02", "name": "3 env vars used in code but missing from .env.example", "shortDescription": {"text": "3 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `NEXT_RUNTIME`, `NODE_ENV`, `RAILWAY_API_URL`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-2c04133e54348533", "name": "Near-duplicate function bodies in 2 places", "shortDescription": {"text": "Near-duplicate function bodies in 2 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/app/loyalty/admin_router.py:announce_status, backend/app/loyalty/admin_router.py:announce\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0bc749714f5da9f4", "name": "FastAPI POST `dev_login` without auth dependency \u2014 backend/app/loyalty/router.py:83", "shortDescription": {"text": "FastAPI POST `dev_login` without auth dependency \u2014 backend/app/loyalty/router.py:83"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-8a2ceb21767cf6d3", "name": "FastAPI POST `request_otp` without auth dependency \u2014 backend/app/loyalty/router.py:112", "shortDescription": {"text": "FastAPI POST `request_otp` without auth dependency \u2014 backend/app/loyalty/router.py:112"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-ca8be27149a3b727", "name": "FastAPI POST `verify_otp` without auth dependency \u2014 backend/app/loyalty/router.py:121", "shortDescription": {"text": "FastAPI POST `verify_otp` without auth dependency \u2014 backend/app/loyalty/router.py:121"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-d9fd6ec8eb43b04b", "name": "FastAPI POST `email_login` without auth dependency \u2014 backend/app/loyalty/router.py:149", "shortDescription": {"text": "FastAPI POST `email_login` without auth dependency \u2014 backend/app/loyalty/router.py:149"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-1d6ce6dee4dee87b", "name": "FastAPI POST `sign_out` without auth dependency \u2014 backend/app/loyalty/router.py:206", "shortDescription": {"text": "FastAPI POST `sign_out` without auth dependency \u2014 backend/app/loyalty/router.py:206"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-3c7163170b7bdbac", "name": "FastAPI POST `staff_login` without auth dependency \u2014 backend/app/loyalty/router.py:344", "shortDescription": {"text": "FastAPI POST `staff_login` without auth dependency \u2014 backend/app/loyalty/router.py:344"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-711f4ce507fdb632", "name": "FastAPI POST `accrue` without auth dependency \u2014 backend/app/loyalty/router.py:357", "shortDescription": {"text": "FastAPI POST `accrue` without auth dependency \u2014 backend/app/loyalty/router.py:357"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-45cc51946141a6bb", "name": "FastAPI POST `redeem` without auth dependency \u2014 backend/app/loyalty/router.py:405", "shortDescription": {"text": "FastAPI POST `redeem` without auth dependency \u2014 backend/app/loyalty/router.py:405"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-9b266ea231d59892", "name": "FastAPI POST `request_password_reset` without auth dependency \u2014 backend/app/loyalty/router.py:455", "shortDescription": {"text": "FastAPI POST `request_password_reset` without auth dependency \u2014 backend/app/loyalty/router.py:455"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-8a55e9c7e1e26aac", "name": "FastAPI POST `confirm_password_reset` without auth dependency \u2014 backend/app/loyalty/router.py:478", "shortDescription": {"text": "FastAPI POST `confirm_password_reset` without auth dependency \u2014 backend/app/loyalty/router.py:478"}, "fullDescription": {"text": "`@router.post` decorator with no `Depends(get_current_user)` or auth-shaped dependency in its signature. Mutating endpoints should require authentication unless explicitly public."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-536f94feb97f43d1", "name": "Dangling fetch: POST /loyalty/staff/auth/login (frontends/frittes-pos/lib/api.ts:74)", "shortDescription": {"text": "Dangling fetch: POST /loyalty/staff/auth/login (frontends/frittes-pos/lib/api.ts:74)"}, "fullDescription": {"text": "`frontends/frittes-pos/lib/api.ts:74` calls `POST /loyalty/staff/auth/login` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/loyalty/staff/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-e26ef6462de59c97", "name": "Dangling fetch: POST /loyalty/transactions/accrue (frontends/frittes-pos/lib/api.ts:81)", "shortDescription": {"text": "Dangling fetch: POST /loyalty/transactions/accrue (frontends/frittes-pos/lib/api.ts:81)"}, "fullDescription": {"text": "`frontends/frittes-pos/lib/api.ts:81` calls `POST /loyalty/transactions/accrue` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/loyalty/transactions/accrue`\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-50475e7c8484d267", "name": "Dangling fetch: POST /loyalty/transactions/redeem (frontends/frittes-pos/lib/api.ts:89)", "shortDescription": {"text": "Dangling fetch: POST /loyalty/transactions/redeem (frontends/frittes-pos/lib/api.ts:89)"}, "fullDescription": {"text": "`frontends/frittes-pos/lib/api.ts:89` calls `POST /loyalty/transactions/redeem` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/loyalty/transactions/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-40cfe7a96219a3c2", "name": "Dangling fetch: GET /loyalty/admin/proximity (frontends/frittes-pos/lib/api.ts:103)", "shortDescription": {"text": "Dangling fetch: GET /loyalty/admin/proximity (frontends/frittes-pos/lib/api.ts:103)"}, "fullDescription": {"text": "`frontends/frittes-pos/lib/api.ts:103` calls `GET /loyalty/admin/proximity` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/loyalty/admin/proximity`\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-a02407bc874a30f2", "name": "Dangling fetch: PATCH /loyalty/admin/proximity (frontends/frittes-pos/lib/api.ts:110)", "shortDescription": {"text": "Dangling fetch: PATCH /loyalty/admin/proximity (frontends/frittes-pos/lib/api.ts:110)"}, "fullDescription": {"text": "`frontends/frittes-pos/lib/api.ts:110` calls `PATCH /loyalty/admin/proximity` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/loyalty/admin/proximity`\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-96d8e0285c4c89c1", "name": "Dangling fetch: GET /loyalty/admin/announce (frontends/frittes-pos/lib/api.ts:125)", "shortDescription": {"text": "Dangling fetch: GET /loyalty/admin/announce (frontends/frittes-pos/lib/api.ts:125)"}, "fullDescription": {"text": "`frontends/frittes-pos/lib/api.ts:125` calls `GET /loyalty/admin/announce` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/loyalty/admin/announce`\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-6246c0f45f6fe417", "name": "Dangling fetch: POST /loyalty/admin/announce (frontends/frittes-pos/lib/api.ts:133)", "shortDescription": {"text": "Dangling fetch: POST /loyalty/admin/announce (frontends/frittes-pos/lib/api.ts:133)"}, "fullDescription": {"text": "`frontends/frittes-pos/lib/api.ts:133` calls `POST /loyalty/admin/announce` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/loyalty/admin/announce`\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-ba37cc2d00b4a0f6", "name": "Dangling fetch: GET /loyalty/admin/menu (frontends/frittes-pos/lib/api.ts:164)", "shortDescription": {"text": "Dangling fetch: GET /loyalty/admin/menu (frontends/frittes-pos/lib/api.ts:164)"}, "fullDescription": {"text": "`frontends/frittes-pos/lib/api.ts:164` calls `GET /loyalty/admin/menu` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/loyalty/admin/menu`\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-425025da31cf1448", "name": "Dangling fetch: PUT /loyalty/admin/menu (frontends/frittes-pos/lib/api.ts:171)", "shortDescription": {"text": "Dangling fetch: PUT /loyalty/admin/menu (frontends/frittes-pos/lib/api.ts:171)"}, "fullDescription": {"text": "`frontends/frittes-pos/lib/api.ts:171` calls `PUT /loyalty/admin/menu` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/loyalty/admin/menu`\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-b3d29925dee8bcc0", "name": "Unused endpoint: POST /customers", "shortDescription": {"text": "Unused endpoint: POST /customers"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /customers` 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-b2d21770371f71a3", "name": "Unused endpoint: POST /auth/dev-login", "shortDescription": {"text": "Unused endpoint: POST /auth/dev-login"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /auth/dev-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-42798645ef4ffb83", "name": "Unused endpoint: POST /auth/request-otp", "shortDescription": {"text": "Unused endpoint: POST /auth/request-otp"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /auth/request-otp` 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-3dea452e5c617331", "name": "Unused endpoint: POST /auth/verify-otp", "shortDescription": {"text": "Unused endpoint: POST /auth/verify-otp"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /auth/verify-otp` 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-5bfe1b1a7a9851b6", "name": "Unused endpoint: POST /auth/email-login", "shortDescription": {"text": "Unused endpoint: POST /auth/email-login"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /auth/email-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-a7522b26dda74c02", "name": "Unused endpoint: GET /customers/check", "shortDescription": {"text": "Unused endpoint: GET /customers/check"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `GET /customers/check` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-144994146ef9f32d", "name": "Unused endpoint: GET /customers/me", "shortDescription": {"text": "Unused endpoint: GET /customers/me"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `GET /customers/me` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-306351319fc67778", "name": "Unused endpoint: POST /auth/sign-out", "shortDescription": {"text": "Unused endpoint: POST /auth/sign-out"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /auth/sign-out` 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-276e4233e33db078", "name": "Unused endpoint: GET /qr-tokens", "shortDescription": {"text": "Unused endpoint: GET /qr-tokens"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `GET /qr-tokens` 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-8f812a636962327c", "name": "Unused endpoint: GET /passes/google/status", "shortDescription": {"text": "Unused endpoint: GET /passes/google/status"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `GET /passes/google/status` 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-8e144a20b5aad692", "name": "Unused endpoint: GET /passes/google/me", "shortDescription": {"text": "Unused endpoint: GET /passes/google/me"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `GET /passes/google/me` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6dae7152d2591a4e", "name": "Unused endpoint: GET /public/wallet/{customer_id}/stamps.png", "shortDescription": {"text": "Unused endpoint: GET /public/wallet/{customer_id}/stamps.png"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `GET /public/wallet/{customer_id}/stamps.png` 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-be32f8b61506b903", "name": "Unused endpoint: GET /program-config", "shortDescription": {"text": "Unused endpoint: GET /program-config"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `GET /program-config` 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-0b5c8ce7418455ae", "name": "Unused endpoint: POST /staff/auth/login", "shortDescription": {"text": "Unused endpoint: POST /staff/auth/login"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /staff/auth/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-f2e1cffc9a30cd8e", "name": "Unused endpoint: POST /transactions/accrue", "shortDescription": {"text": "Unused endpoint: POST /transactions/accrue"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /transactions/accrue` 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-2efe8bfa948c4a08", "name": "Unused endpoint: POST /transactions/redeem", "shortDescription": {"text": "Unused endpoint: POST /transactions/redeem"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /transactions/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-1973d376f900170f", "name": "Unused endpoint: POST /staff/auth/request-password-reset", "shortDescription": {"text": "Unused endpoint: POST /staff/auth/request-password-reset"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /staff/auth/request-password-reset` 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-872106c5fe7cfbc6", "name": "Unused endpoint: POST /staff/auth/confirm-password-reset", "shortDescription": {"text": "Unused endpoint: POST /staff/auth/confirm-password-reset"}, "fullDescription": {"text": "`backend/app/loyalty/router.py` declares `POST /staff/auth/confirm-password-reset` 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-61f0efb0d470c859", "name": "Unused endpoint: GET /public/menu", "shortDescription": {"text": "Unused endpoint: GET /public/menu"}, "fullDescription": {"text": "`backend/app/loyalty/menu_router.py` declares `GET /public/menu` 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-3c86c61ea2ac47cf", "name": "Unused endpoint: GET /admin/menu", "shortDescription": {"text": "Unused endpoint: GET /admin/menu"}, "fullDescription": {"text": "`backend/app/loyalty/menu_router.py` declares `GET /admin/menu` 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-5e9f2f54e945e990", "name": "Unused endpoint: PUT /admin/menu", "shortDescription": {"text": "Unused endpoint: PUT /admin/menu"}, "fullDescription": {"text": "`backend/app/loyalty/menu_router.py` declares `PUT /admin/menu` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cd8dc4599ec52a08", "name": "Unused endpoint: GET /stats", "shortDescription": {"text": "Unused endpoint: GET /stats"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `GET /stats` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-357ca5f864c53253", "name": "Unused endpoint: GET /top-customers", "shortDescription": {"text": "Unused endpoint: GET /top-customers"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `GET /top-customers` 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-5d37888bca1a0620", "name": "Unused endpoint: GET /customers", "shortDescription": {"text": "Unused endpoint: GET /customers"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `GET /customers` 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-61991f5f3b4ba61c", "name": "Unused endpoint: POST /customers/{customer_id}/redeem", "shortDescription": {"text": "Unused endpoint: POST /customers/{customer_id}/redeem"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `POST /customers/{customer_id}/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-ece9bdd393834bfd", "name": "Unused endpoint: POST /customers/{customer_id}/adjust-stamps", "shortDescription": {"text": "Unused endpoint: POST /customers/{customer_id}/adjust-stamps"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `POST /customers/{customer_id}/adjust-stamps` 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-52f939032aab887f", "name": "Unused endpoint: GET /transactions", "shortDescription": {"text": "Unused endpoint: GET /transactions"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `GET /transactions` 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-a6f48e60c30777ab", "name": "Unused endpoint: GET /config", "shortDescription": {"text": "Unused endpoint: GET /config"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `GET /config` 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-d440aecec5450ba4", "name": "Unused endpoint: GET /tiers", "shortDescription": {"text": "Unused endpoint: GET /tiers"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `GET /tiers` 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-9d28346a41bc8742", "name": "Unused endpoint: PUT /tiers", "shortDescription": {"text": "Unused endpoint: PUT /tiers"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `PUT /tiers` 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-2bd68d61cc9afa6d", "name": "Unused endpoint: GET /levels", "shortDescription": {"text": "Unused endpoint: GET /levels"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `GET /levels` 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-ed41933e0255ca94", "name": "Unused endpoint: PUT /levels", "shortDescription": {"text": "Unused endpoint: PUT /levels"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `PUT /levels` 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-4cff4b2e8c2f239b", "name": "Unused endpoint: PATCH /config", "shortDescription": {"text": "Unused endpoint: PATCH /config"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `PATCH /config` 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-8dc3604aad441973", "name": "Unused endpoint: GET /staff", "shortDescription": {"text": "Unused endpoint: GET /staff"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `GET /staff` 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-19b2faca53374659", "name": "Unused endpoint: POST /staff", "shortDescription": {"text": "Unused endpoint: POST /staff"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `POST /staff` 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-b66fe9cb5b6b9eb1", "name": "Unused endpoint: PATCH /staff/{staff_id}", "shortDescription": {"text": "Unused endpoint: PATCH /staff/{staff_id}"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `PATCH /staff/{staff_id}` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3f4f5b6cec340308", "name": "Unused endpoint: GET /proximity", "shortDescription": {"text": "Unused endpoint: GET /proximity"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `GET /proximity` 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-2481be9ade171849", "name": "Unused endpoint: PATCH /proximity", "shortDescription": {"text": "Unused endpoint: PATCH /proximity"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `PATCH /proximity` 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-a2b12a503776b6d9", "name": "Unused endpoint: GET /announce", "shortDescription": {"text": "Unused endpoint: GET /announce"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `GET /announce` 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-45160e99258829e8", "name": "Unused endpoint: POST /announce", "shortDescription": {"text": "Unused endpoint: POST /announce"}, "fullDescription": {"text": "`backend/app/loyalty/admin_router.py` declares `POST /announce` 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/20423"}, "properties": {"repository": "subimeDev/FrittesRancagua-", "repoUrl": "https://github.com/subimeDev/FrittesRancagua-", "branch": "main"}, "results": [{"ruleId": "scanner-6ae5f823be369727", "level": "note", "message": {"text": "Possibly dead Python function: require_manager"}, "properties": {"repobilityId": "c7b449123ab14744", "scanner": "scanner-primary", "fingerprint": "6ae5f823be369727", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/admin_router.py:29"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-133dfdb49edb4392", "level": "note", "message": {"text": "Possibly dead Python function: update_loyalty_object"}, "properties": {"repobilityId": "1d32737f0762050a", "scanner": "scanner-primary", "fingerprint": "133dfdb49edb4392", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/google_wallet.py:383"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d03c276e2138a5c2", "level": "note", "message": {"text": "Possibly dead Python function: count_saved_passes"}, "properties": {"repobilityId": "e665be06323f1d95", "scanner": "scanner-primary", "fingerprint": "d03c276e2138a5c2", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/google_wallet.py:456"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-0f5d8e3ef9ff062a", "level": "note", "message": {"text": "Possibly dead Python function: broadcast_class_message"}, "properties": {"repobilityId": "c64cdcec909683f8", "scanner": "scanner-primary", "fingerprint": "0f5d8e3ef9ff062a", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/google_wallet.py:485"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-0781fbc4c721a7f4", "level": "note", "message": {"text": "Possibly dead Python function: create_loyalty_class_if_needed"}, "properties": {"repobilityId": "7fc8723839eeeeed", "scanner": "scanner-primary", "fingerprint": "0781fbc4c721a7f4", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/google_wallet.py:513"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-8297e4ba9443de74", "level": "note", "message": {"text": "Possibly dead Python function: render_frittes_stamps"}, "properties": {"repobilityId": "78b382d7d617f8b8", "scanner": "scanner-primary", "fingerprint": "8297e4ba9443de74", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/wallet_stamps.py:484"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-adafbfa10498a927", "level": "note", "message": {"text": "Possibly dead Python function: complete_profile_for_phone"}, "properties": {"repobilityId": "77c2410bac2fce8b", "scanner": "scanner-primary", "fingerprint": "adafbfa10498a927", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/service.py:290"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-75608ecceef2693b", "level": "note", "message": {"text": "Possibly dead Python function: send_redemption_email"}, "properties": {"repobilityId": "9bb0d80bc69788a4", "scanner": "scanner-primary", "fingerprint": "75608ecceef2693b", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/service.py:357"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-10b7d1d490bb6506", "level": "note", "message": {"text": "Possibly dead Python function: upgrade"}, "properties": {"repobilityId": "cf0b8e5e6e2f8bc4", "scanner": "scanner-primary", "fingerprint": "10b7d1d490bb6506", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0001_initial.py:18"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6e71924957118666", "level": "note", "message": {"text": "Possibly dead Python function: downgrade"}, "properties": {"repobilityId": "c03debbf11efa0c5", "scanner": "scanner-primary", "fingerprint": "6e71924957118666", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0001_initial.py:75"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-9649ee14980ea3ed", "level": "note", "message": {"text": "Possibly dead Python function: upgrade"}, "properties": {"repobilityId": "cf0b8e5e6e2f8bc4", "scanner": "scanner-primary", "fingerprint": "9649ee14980ea3ed", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0003_restaurant_config.py:18"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-7395f32799d3754f", "level": "note", "message": {"text": "Possibly dead Python function: downgrade"}, "properties": {"repobilityId": "c03debbf11efa0c5", "scanner": "scanner-primary", "fingerprint": "7395f32799d3754f", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0003_restaurant_config.py:29"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-54c67719a740a802", "level": "note", "message": {"text": "Possibly dead Python function: upgrade"}, "properties": {"repobilityId": "cf0b8e5e6e2f8bc4", "scanner": "scanner-primary", "fingerprint": "54c67719a740a802", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0002_pending_otps.py:17"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-29ec4a1266ee0544", "level": "note", "message": {"text": "Possibly dead Python function: downgrade"}, "properties": {"repobilityId": "c03debbf11efa0c5", "scanner": "scanner-primary", "fingerprint": "29ec4a1266ee0544", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0002_pending_otps.py:26"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-43101a378a9f9227", "level": "note", "message": {"text": "Possibly dead Python function: upgrade"}, "properties": {"repobilityId": "cf0b8e5e6e2f8bc4", "scanner": "scanner-primary", "fingerprint": "43101a378a9f9227", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0006_proximity.py:22"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-150b14b2a1507ca4", "level": "note", "message": {"text": "Possibly dead Python function: downgrade"}, "properties": {"repobilityId": "c03debbf11efa0c5", "scanner": "scanner-primary", "fingerprint": "150b14b2a1507ca4", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0006_proximity.py:31"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3b70906a23466d53", "level": "note", "message": {"text": "Possibly dead Python function: upgrade"}, "properties": {"repobilityId": "cf0b8e5e6e2f8bc4", "scanner": "scanner-primary", "fingerprint": "3b70906a23466d53", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0007_menu.py:21"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-168d1e301796c898", "level": "note", "message": {"text": "Possibly dead Python function: downgrade"}, "properties": {"repobilityId": "c03debbf11efa0c5", "scanner": "scanner-primary", "fingerprint": "168d1e301796c898", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0007_menu.py:49"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-e9fd7a7e3d6ee3bc", "level": "note", "message": {"text": "Possibly dead Python function: upgrade"}, "properties": {"repobilityId": "cf0b8e5e6e2f8bc4", "scanner": "scanner-primary", "fingerprint": "e9fd7a7e3d6ee3bc", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0004_reward_tiers.py:21"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-a6a23dd3b3ebe87a", "level": "note", "message": {"text": "Possibly dead Python function: downgrade"}, "properties": {"repobilityId": "c03debbf11efa0c5", "scanner": "scanner-primary", "fingerprint": "a6a23dd3b3ebe87a", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0004_reward_tiers.py:59"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-c9172f8e629f55d7", "level": "note", "message": {"text": "Possibly dead Python function: upgrade"}, "properties": {"repobilityId": "cf0b8e5e6e2f8bc4", "scanner": "scanner-primary", "fingerprint": "c9172f8e629f55d7", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0005_card_levels.py:31"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-b069f0f1933bf076", "level": "note", "message": {"text": "Possibly dead Python function: downgrade"}, "properties": {"repobilityId": "c03debbf11efa0c5", "scanner": "scanner-primary", "fingerprint": "b069f0f1933bf076", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/alembic/versions/0005_card_levels.py:67"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-56cd6a65fee77240", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-loyalty/components/celebration-overlay.tsx:228"}, "properties": {"repobilityId": "b7ac2d5f515d16b0", "scanner": "scanner-primary", "fingerprint": "56cd6a65fee77240", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-396732b4e90a55b4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-loyalty/components/wallet-pass.tsx:251"}, "properties": {"repobilityId": "661d57b05b081bae", "scanner": "scanner-primary", "fingerprint": "396732b4e90a55b4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-50879b0394801081", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-loyalty/app/page.tsx:292"}, "properties": {"repobilityId": "9bdae47635bcfadd", "scanner": "scanner-primary", "fingerprint": "50879b0394801081", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-23028cc73f107f39", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-pos/app/admin/page.tsx:515"}, "properties": {"repobilityId": "fb60d97a43ac8379", "scanner": "scanner-primary", "fingerprint": "23028cc73f107f39", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f177648ce5ef1247", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontends/frittes-pos/app/carta/page.tsx:342"}, "properties": {"repobilityId": "0f4f691fbc925cb5", "scanner": "scanner-primary", "fingerprint": "f177648ce5ef1247", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-763dd01d25260dda", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontends/frittes-pos/app/login/page.tsx:42"}, "properties": {"repobilityId": "8053e302bcafacba", "scanner": "scanner-primary", "fingerprint": "763dd01d25260dda", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontends/frittes-pos/app/login/page.tsx"}, "region": {"startLine": 42}}}]}, {"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-3bbed5e0380d809d", "level": "note", "message": {"text": "Very large file: frontends/frittes-pos/app/admin/page.tsx (1493 lines)"}, "properties": {"repobilityId": "c4fe2fa8ef6a5e62", "scanner": "scanner-primary", "fingerprint": "3bbed5e0380d809d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-6893a6c8b0861585", "level": "warning", "message": {"text": "Very low test-to-source ratio"}, "properties": {"repobilityId": "54a7de3f06314bf0", "scanner": "scanner-primary", "fingerprint": "6893a6c8b0861585", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "coverage"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "507f00bbc0c067fa", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-72b2a6250083a784", "level": "warning", "message": {"text": "Placeholder or mock-heavy implementation detected"}, "properties": {"repobilityId": "1749530a5bfc85ad", "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": "6117e9f6cf0494ea", "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": "08e30e09fb7a09e5", "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": "cfcfc25f582c6dbc", "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": "446dc04ce9b1703b", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-a60141141bb9924f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontends/frittes-loyalty/public/sw.js:50"}, "properties": {"repobilityId": "e3998c4bc353d11c", "scanner": "scanner-primary", "fingerprint": "a60141141bb9924f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-aba3b1b22b262e56", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontends/frittes-pos/app/proximidad/page.tsx:169"}, "properties": {"repobilityId": "b14b1260fa571f6f", "scanner": "scanner-primary", "fingerprint": "aba3b1b22b262e56", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-492d0c140cd23710", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontends/frittes-pos/public/sw.js:47"}, "properties": {"repobilityId": "fa98aa7c2ffded40", "scanner": "scanner-primary", "fingerprint": "492d0c140cd23710", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-b35bdc650e996e65", "level": "note", "message": {"text": "Legacy-named symbol `model_copy` in backend/app/config.py:102"}, "properties": {"repobilityId": "945c636e9a065345", "scanner": "scanner-primary", "fingerprint": "b35bdc650e996e65", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-c37d1c8cdf5e7156", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/app/loyalty/router.py:372"}, "properties": {"repobilityId": "beeb6bfbf4eec301", "scanner": "scanner-primary", "fingerprint": "c37d1c8cdf5e7156", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-f9b3968ecce2acec", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/app/loyalty/wallet_stamps.py:48"}, "properties": {"repobilityId": "3f990609ab95eb44", "scanner": "scanner-primary", "fingerprint": "f9b3968ecce2acec", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2eafc3188c36bb02", "level": "none", "message": {"text": "3 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "bd934ba112b02ffa", "scanner": "scanner-primary", "fingerprint": "2eafc3188c36bb02", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "2b6342d80bf76bb4", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "0f034694f7795ccc", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-0bc749714f5da9f4", "level": "error", "message": {"text": "FastAPI POST `dev_login` without auth dependency \u2014 backend/app/loyalty/router.py:83"}, "properties": {"repobilityId": "f737f2ff2c4c1126", "scanner": "scanner-primary", "fingerprint": "0bc749714f5da9f4", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/router.py"}, "region": {"startLine": 83}}}]}, {"ruleId": "scanner-8a2ceb21767cf6d3", "level": "error", "message": {"text": "FastAPI POST `request_otp` without auth dependency \u2014 backend/app/loyalty/router.py:112"}, "properties": {"repobilityId": "cc75d1bddf0bff39", "scanner": "scanner-primary", "fingerprint": "8a2ceb21767cf6d3", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/router.py"}, "region": {"startLine": 112}}}]}, {"ruleId": "scanner-ca8be27149a3b727", "level": "error", "message": {"text": "FastAPI POST `verify_otp` without auth dependency \u2014 backend/app/loyalty/router.py:121"}, "properties": {"repobilityId": "0993ccda3e586cc8", "scanner": "scanner-primary", "fingerprint": "ca8be27149a3b727", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/router.py"}, "region": {"startLine": 121}}}]}, {"ruleId": "scanner-d9fd6ec8eb43b04b", "level": "error", "message": {"text": "FastAPI POST `email_login` without auth dependency \u2014 backend/app/loyalty/router.py:149"}, "properties": {"repobilityId": "caef84dd8b86de68", "scanner": "scanner-primary", "fingerprint": "d9fd6ec8eb43b04b", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/router.py"}, "region": {"startLine": 149}}}]}, {"ruleId": "scanner-1d6ce6dee4dee87b", "level": "error", "message": {"text": "FastAPI POST `sign_out` without auth dependency \u2014 backend/app/loyalty/router.py:206"}, "properties": {"repobilityId": "e3e894cc24760054", "scanner": "scanner-primary", "fingerprint": "1d6ce6dee4dee87b", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/router.py"}, "region": {"startLine": 206}}}]}, {"ruleId": "scanner-3c7163170b7bdbac", "level": "error", "message": {"text": "FastAPI POST `staff_login` without auth dependency \u2014 backend/app/loyalty/router.py:344"}, "properties": {"repobilityId": "d5be1e20add8c06b", "scanner": "scanner-primary", "fingerprint": "3c7163170b7bdbac", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/router.py"}, "region": {"startLine": 344}}}]}, {"ruleId": "scanner-711f4ce507fdb632", "level": "error", "message": {"text": "FastAPI POST `accrue` without auth dependency \u2014 backend/app/loyalty/router.py:357"}, "properties": {"repobilityId": "aa4905a85ced83e6", "scanner": "scanner-primary", "fingerprint": "711f4ce507fdb632", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/router.py"}, "region": {"startLine": 357}}}]}, {"ruleId": "scanner-45cc51946141a6bb", "level": "error", "message": {"text": "FastAPI POST `redeem` without auth dependency \u2014 backend/app/loyalty/router.py:405"}, "properties": {"repobilityId": "aafca9e2051c1247", "scanner": "scanner-primary", "fingerprint": "45cc51946141a6bb", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/router.py"}, "region": {"startLine": 405}}}]}, {"ruleId": "scanner-9b266ea231d59892", "level": "error", "message": {"text": "FastAPI POST `request_password_reset` without auth dependency \u2014 backend/app/loyalty/router.py:455"}, "properties": {"repobilityId": "b762bb247742b98f", "scanner": "scanner-primary", "fingerprint": "9b266ea231d59892", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/router.py"}, "region": {"startLine": 455}}}]}, {"ruleId": "scanner-8a55e9c7e1e26aac", "level": "error", "message": {"text": "FastAPI POST `confirm_password_reset` without auth dependency \u2014 backend/app/loyalty/router.py:478"}, "properties": {"repobilityId": "9d97cec43909d717", "scanner": "scanner-primary", "fingerprint": "8a55e9c7e1e26aac", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.fastapi.unauth_mutation"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/loyalty/router.py"}, "region": {"startLine": 478}}}]}, {"ruleId": "scanner-536f94feb97f43d1", "level": "error", "message": {"text": "Dangling fetch: POST /loyalty/staff/auth/login (frontends/frittes-pos/lib/api.ts:74)"}, "properties": {"repobilityId": "1a0f4d54d0b321ba", "scanner": "scanner-primary", "fingerprint": "536f94feb97f43d1", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-e26ef6462de59c97", "level": "error", "message": {"text": "Dangling fetch: POST /loyalty/transactions/accrue (frontends/frittes-pos/lib/api.ts:81)"}, "properties": {"repobilityId": "75a569f875e41af9", "scanner": "scanner-primary", "fingerprint": "e26ef6462de59c97", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-50475e7c8484d267", "level": "error", "message": {"text": "Dangling fetch: POST /loyalty/transactions/redeem (frontends/frittes-pos/lib/api.ts:89)"}, "properties": {"repobilityId": "7c0903adfc6152d4", "scanner": "scanner-primary", "fingerprint": "50475e7c8484d267", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-40cfe7a96219a3c2", "level": "error", "message": {"text": "Dangling fetch: GET /loyalty/admin/proximity (frontends/frittes-pos/lib/api.ts:103)"}, "properties": {"repobilityId": "8e933e751f60248b", "scanner": "scanner-primary", "fingerprint": "40cfe7a96219a3c2", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-a02407bc874a30f2", "level": "error", "message": {"text": "Dangling fetch: PATCH /loyalty/admin/proximity (frontends/frittes-pos/lib/api.ts:110)"}, "properties": {"repobilityId": "a76309e3e3089182", "scanner": "scanner-primary", "fingerprint": "a02407bc874a30f2", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-96d8e0285c4c89c1", "level": "error", "message": {"text": "Dangling fetch: GET /loyalty/admin/announce (frontends/frittes-pos/lib/api.ts:125)"}, "properties": {"repobilityId": "e210d2462e5f0cb1", "scanner": "scanner-primary", "fingerprint": "96d8e0285c4c89c1", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-6246c0f45f6fe417", "level": "error", "message": {"text": "Dangling fetch: POST /loyalty/admin/announce (frontends/frittes-pos/lib/api.ts:133)"}, "properties": {"repobilityId": "c068317344f41dde", "scanner": "scanner-primary", "fingerprint": "6246c0f45f6fe417", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-ba37cc2d00b4a0f6", "level": "error", "message": {"text": "Dangling fetch: GET /loyalty/admin/menu (frontends/frittes-pos/lib/api.ts:164)"}, "properties": {"repobilityId": "1e1c3b484c94f460", "scanner": "scanner-primary", "fingerprint": "ba37cc2d00b4a0f6", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-425025da31cf1448", "level": "error", "message": {"text": "Dangling fetch: PUT /loyalty/admin/menu (frontends/frittes-pos/lib/api.ts:171)"}, "properties": {"repobilityId": "4703d6a3337feffb", "scanner": "scanner-primary", "fingerprint": "425025da31cf1448", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-b3d29925dee8bcc0", "level": "note", "message": {"text": "Unused endpoint: POST /customers"}, "properties": {"repobilityId": "118549ca301afa63", "scanner": "scanner-primary", "fingerprint": "b3d29925dee8bcc0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b2d21770371f71a3", "level": "note", "message": {"text": "Unused endpoint: POST /auth/dev-login"}, "properties": {"repobilityId": "f03e260d5fe59ff8", "scanner": "scanner-primary", "fingerprint": "b2d21770371f71a3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-42798645ef4ffb83", "level": "note", "message": {"text": "Unused endpoint: POST /auth/request-otp"}, "properties": {"repobilityId": "628d6ec9ed575292", "scanner": "scanner-primary", "fingerprint": "42798645ef4ffb83", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3dea452e5c617331", "level": "note", "message": {"text": "Unused endpoint: POST /auth/verify-otp"}, "properties": {"repobilityId": "8ee359d70900876d", "scanner": "scanner-primary", "fingerprint": "3dea452e5c617331", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5bfe1b1a7a9851b6", "level": "note", "message": {"text": "Unused endpoint: POST /auth/email-login"}, "properties": {"repobilityId": "40c3d807b25ca77c", "scanner": "scanner-primary", "fingerprint": "5bfe1b1a7a9851b6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a7522b26dda74c02", "level": "note", "message": {"text": "Unused endpoint: GET /customers/check"}, "properties": {"repobilityId": "2e5668c06369bd0e", "scanner": "scanner-primary", "fingerprint": "a7522b26dda74c02", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-144994146ef9f32d", "level": "note", "message": {"text": "Unused endpoint: GET /customers/me"}, "properties": {"repobilityId": "fbdbf4d39158ffae", "scanner": "scanner-primary", "fingerprint": "144994146ef9f32d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-306351319fc67778", "level": "note", "message": {"text": "Unused endpoint: POST /auth/sign-out"}, "properties": {"repobilityId": "efa5f94bdd6fadb8", "scanner": "scanner-primary", "fingerprint": "306351319fc67778", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-276e4233e33db078", "level": "note", "message": {"text": "Unused endpoint: GET /qr-tokens"}, "properties": {"repobilityId": "57d82ceaa7b72076", "scanner": "scanner-primary", "fingerprint": "276e4233e33db078", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8f812a636962327c", "level": "note", "message": {"text": "Unused endpoint: GET /passes/google/status"}, "properties": {"repobilityId": "2bc2422f1272cc29", "scanner": "scanner-primary", "fingerprint": "8f812a636962327c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8e144a20b5aad692", "level": "note", "message": {"text": "Unused endpoint: GET /passes/google/me"}, "properties": {"repobilityId": "e1dc384f4c1dd5f0", "scanner": "scanner-primary", "fingerprint": "8e144a20b5aad692", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6dae7152d2591a4e", "level": "note", "message": {"text": "Unused endpoint: GET /public/wallet/{customer_id}/stamps.png"}, "properties": {"repobilityId": "1484ec9eaeb46f38", "scanner": "scanner-primary", "fingerprint": "6dae7152d2591a4e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-be32f8b61506b903", "level": "note", "message": {"text": "Unused endpoint: GET /program-config"}, "properties": {"repobilityId": "319e36ba053b9c0c", "scanner": "scanner-primary", "fingerprint": "be32f8b61506b903", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0b5c8ce7418455ae", "level": "note", "message": {"text": "Unused endpoint: POST /staff/auth/login"}, "properties": {"repobilityId": "76d659c74525ca3b", "scanner": "scanner-primary", "fingerprint": "0b5c8ce7418455ae", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f2e1cffc9a30cd8e", "level": "note", "message": {"text": "Unused endpoint: POST /transactions/accrue"}, "properties": {"repobilityId": "5aaaf05087a98dd4", "scanner": "scanner-primary", "fingerprint": "f2e1cffc9a30cd8e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2efe8bfa948c4a08", "level": "note", "message": {"text": "Unused endpoint: POST /transactions/redeem"}, "properties": {"repobilityId": "ba237ce4a779ea2e", "scanner": "scanner-primary", "fingerprint": "2efe8bfa948c4a08", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1973d376f900170f", "level": "note", "message": {"text": "Unused endpoint: POST /staff/auth/request-password-reset"}, "properties": {"repobilityId": "0bbce235353ff270", "scanner": "scanner-primary", "fingerprint": "1973d376f900170f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-872106c5fe7cfbc6", "level": "note", "message": {"text": "Unused endpoint: POST /staff/auth/confirm-password-reset"}, "properties": {"repobilityId": "e591ca0bd19f7ed1", "scanner": "scanner-primary", "fingerprint": "872106c5fe7cfbc6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-61f0efb0d470c859", "level": "note", "message": {"text": "Unused endpoint: GET /public/menu"}, "properties": {"repobilityId": "ca1d4d4eb4022b4a", "scanner": "scanner-primary", "fingerprint": "61f0efb0d470c859", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3c86c61ea2ac47cf", "level": "note", "message": {"text": "Unused endpoint: GET /admin/menu"}, "properties": {"repobilityId": "00f96ab9d5e39d66", "scanner": "scanner-primary", "fingerprint": "3c86c61ea2ac47cf", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5e9f2f54e945e990", "level": "note", "message": {"text": "Unused endpoint: PUT /admin/menu"}, "properties": {"repobilityId": "c0369d75ae59826f", "scanner": "scanner-primary", "fingerprint": "5e9f2f54e945e990", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cd8dc4599ec52a08", "level": "note", "message": {"text": "Unused endpoint: GET /stats"}, "properties": {"repobilityId": "1364d07903ee2b52", "scanner": "scanner-primary", "fingerprint": "cd8dc4599ec52a08", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-357ca5f864c53253", "level": "note", "message": {"text": "Unused endpoint: GET /top-customers"}, "properties": {"repobilityId": "148896baf9db54aa", "scanner": "scanner-primary", "fingerprint": "357ca5f864c53253", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5d37888bca1a0620", "level": "note", "message": {"text": "Unused endpoint: GET /customers"}, "properties": {"repobilityId": "0b905951eee5078b", "scanner": "scanner-primary", "fingerprint": "5d37888bca1a0620", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-61991f5f3b4ba61c", "level": "note", "message": {"text": "Unused endpoint: POST /customers/{customer_id}/redeem"}, "properties": {"repobilityId": "00a3072d8554ef13", "scanner": "scanner-primary", "fingerprint": "61991f5f3b4ba61c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ece9bdd393834bfd", "level": "note", "message": {"text": "Unused endpoint: POST /customers/{customer_id}/adjust-stamps"}, "properties": {"repobilityId": "4e135f4cb08896aa", "scanner": "scanner-primary", "fingerprint": "ece9bdd393834bfd", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-52f939032aab887f", "level": "note", "message": {"text": "Unused endpoint: GET /transactions"}, "properties": {"repobilityId": "d4bf48edaf15c785", "scanner": "scanner-primary", "fingerprint": "52f939032aab887f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a6f48e60c30777ab", "level": "note", "message": {"text": "Unused endpoint: GET /config"}, "properties": {"repobilityId": "dd2cbdcac8d6ce84", "scanner": "scanner-primary", "fingerprint": "a6f48e60c30777ab", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d440aecec5450ba4", "level": "note", "message": {"text": "Unused endpoint: GET /tiers"}, "properties": {"repobilityId": "0db0cb44255d715b", "scanner": "scanner-primary", "fingerprint": "d440aecec5450ba4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9d28346a41bc8742", "level": "note", "message": {"text": "Unused endpoint: PUT /tiers"}, "properties": {"repobilityId": "beb71827342e0674", "scanner": "scanner-primary", "fingerprint": "9d28346a41bc8742", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2bd68d61cc9afa6d", "level": "note", "message": {"text": "Unused endpoint: GET /levels"}, "properties": {"repobilityId": "a29b93258a0b31d7", "scanner": "scanner-primary", "fingerprint": "2bd68d61cc9afa6d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ed41933e0255ca94", "level": "note", "message": {"text": "Unused endpoint: PUT /levels"}, "properties": {"repobilityId": "77222b1fd36d7f63", "scanner": "scanner-primary", "fingerprint": "ed41933e0255ca94", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4cff4b2e8c2f239b", "level": "note", "message": {"text": "Unused endpoint: PATCH /config"}, "properties": {"repobilityId": "621135411df11767", "scanner": "scanner-primary", "fingerprint": "4cff4b2e8c2f239b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8dc3604aad441973", "level": "note", "message": {"text": "Unused endpoint: GET /staff"}, "properties": {"repobilityId": "baf171ffebf4381b", "scanner": "scanner-primary", "fingerprint": "8dc3604aad441973", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-19b2faca53374659", "level": "note", "message": {"text": "Unused endpoint: POST /staff"}, "properties": {"repobilityId": "c8d6cf3600e5e6d6", "scanner": "scanner-primary", "fingerprint": "19b2faca53374659", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b66fe9cb5b6b9eb1", "level": "note", "message": {"text": "Unused endpoint: PATCH /staff/{staff_id}"}, "properties": {"repobilityId": "b75077d440daa124", "scanner": "scanner-primary", "fingerprint": "b66fe9cb5b6b9eb1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3f4f5b6cec340308", "level": "note", "message": {"text": "Unused endpoint: GET /proximity"}, "properties": {"repobilityId": "8c87e3f3067d9d1e", "scanner": "scanner-primary", "fingerprint": "3f4f5b6cec340308", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2481be9ade171849", "level": "note", "message": {"text": "Unused endpoint: PATCH /proximity"}, "properties": {"repobilityId": "2945cb90985e250d", "scanner": "scanner-primary", "fingerprint": "2481be9ade171849", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a2b12a503776b6d9", "level": "note", "message": {"text": "Unused endpoint: GET /announce"}, "properties": {"repobilityId": "cedf737994a95e49", "scanner": "scanner-primary", "fingerprint": "a2b12a503776b6d9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-45160e99258829e8", "level": "note", "message": {"text": "Unused endpoint: POST /announce"}, "properties": {"repobilityId": "37352361e1e1e574", "scanner": "scanner-primary", "fingerprint": "45160e99258829e8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}