{"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-503482a7f1222bbf", "name": "Stray `console.log` in TS/JS \u2014 backend/migrate_categoria.js:35", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrate_categoria.js:35"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6c9efa63a05ca9c4", "name": "Stray `console.log` in TS/JS \u2014 backend/query.js:8", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/query.js:8"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ea1c72d04692be35", "name": "Stray `console.log` in TS/JS \u2014 backend/seed_presupuestos.js:39", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/seed_presupuestos.js:39"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8955f3a7371b666c", "name": "Stray `console.log` in TS/JS \u2014 backend/migrate_ubicacion.js:13", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrate_ubicacion.js:13"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6c873de46cefdc07", "name": "Stray `console.log` in TS/JS \u2014 backend/mailer.js:18", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/mailer.js:18"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b38fa1b5255f3b6c", "name": "Stray `console.log` in TS/JS \u2014 backend/list_tables.js:16", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/list_tables.js:16"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d19c6a4a594a92fc", "name": "Stray `console.log` in TS/JS \u2014 backend/reset_admin_v2.js:16", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/reset_admin_v2.js:16"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-912daf32957f1480", "name": "Stray `console.log` in TS/JS \u2014 backend/notifications.js:18", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/notifications.js:18"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-36099ba9d22c3b50", "name": "Stray `console.log` in TS/JS \u2014 backend/enable_rls.js:5", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/enable_rls.js:5"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-19e4606ec02d75f2", "name": "Stray `console.log` in TS/JS \u2014 backend/index.js:83", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/index.js:83"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-185ab9464e905815", "name": "Stray `console.log` in TS/JS \u2014 backend/migrate_usuarios_notificaciones.js:16", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrate_usuarios_notificaciones.js:16"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a5e881b90bbded42", "name": "Stray `console.log` in TS/JS \u2014 backend/migrate_licencias.js:25", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrate_licencias.js:25"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-abfaadd00dc11d13", "name": "Stray `console.log` in TS/JS \u2014 backend/dump_presupuestos.js:33", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/dump_presupuestos.js:33"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e0fcedc6d796f0f7", "name": "Stray `console.log` in TS/JS \u2014 backend/seed_proveedores.js:151", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/seed_proveedores.js:151"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-42baa8911b1c755b", "name": "Stray `console.log` in TS/JS \u2014 backend/migrate.js:12", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrate.js:12"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-033fa8ccbbf3af6b", "name": "Stray `console.log` in TS/JS \u2014 backend/create_presupuesto_tables.js:11", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/create_presupuesto_tables.js:11"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e10a5594af6f1bac", "name": "Stray `console.log` in TS/JS \u2014 backend/seed_cecos.js:7", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/seed_cecos.js:7"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-373a899499e5934f", "name": "Stray `console.log` in TS/JS \u2014 backend/insert_budget.js:225", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/insert_budget.js:225"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5ed260532cdaa037", "name": "Stray `console.log` in TS/JS \u2014 backend/add_fcm_token.js:6", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/add_fcm_token.js:6"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ca3c637a1aebfa31", "name": "Stray `console.log` in TS/JS \u2014 backend/migrations/run.js:19", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrations/run.js:19"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ace4a79cc6af54ce", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/layout.tsx:339", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/layout.tsx:339"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d7f9421763e1a624", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/page.tsx:410", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/page.tsx:410"}, "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-b163c43b731e31db", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/detalles-solicitud/[id]/components/TabResumen.js:247", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/detalles-solicitud/[id]/components/TabResumen.js:247"}, "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-e113ff0d9982c76e", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/detalles-solicitud/[id]/components/TabCotizaciones.js:", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/detalles-solicitud/[id]/components/TabCotizaciones.js:143"}, "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-3bf97a4e8d300ecc", "name": "TODO/FIXME marker in shipping code \u2014 frontend/app/admin/usuarios/page.tsx:569", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 frontend/app/admin/usuarios/page.tsx:569"}, "fullDescription": {"text": "Track in /reviews or /issues, not as a code comment that rots.\n\nWhy: Drift control \u2014 shouldn't be the same as Quality TODO scanner.\nRule id: fq.todo-marker"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a43636707eb1317e", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/admin/presupuestos/TablaMatricial.tsx:232", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/admin/presupuestos/TablaMatricial.tsx:232"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f0822ed82c71efd0", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/admin/reportes/page.tsx:153", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/admin/reportes/page.tsx:153"}, "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-0598b72e14e60fd3", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/components/NotificationBell.tsx:165", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/components/NotificationBell.tsx:165"}, "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-ac7b710cb9ecb634", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/components/CeCoBudgetRadar.tsx:338", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/components/CeCoBudgetRadar.tsx:338"}, "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-9e5f83ab23f7dd3e", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/seguimiento/page.tsx:546", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/seguimiento/page.tsx:546"}, "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-053795dc7322a0e5", "name": "Possible secret in backend/reset_admin_v2.js", "shortDescription": {"text": "Possible secret in backend/reset_admin_v2.js"}, "fullDescription": {"text": "Detected pattern matching password_literal. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-5a5965e0ce05385e", "name": "Insecure pattern 'local_storage_auth_token' in frontend/app/login/page.js:40", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/app/login/page.js:40"}, "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-e8bf6d4344cded7d", "name": "Insecure pattern 'document_write' in frontend/app/components/imprimirResponsiva.ts:10", "shortDescription": {"text": "Insecure pattern 'document_write' in frontend/app/components/imprimirResponsiva.ts:10"}, "fullDescription": {"text": "Found a known-risky pattern (document_write). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "low", "confidence": 1.0}}, {"id": "scanner-527ec200d00bd174", "name": "Very large file: backend/index.js (2415 lines)", "shortDescription": {"text": "Very large file: backend/index.js (2415 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-07a760cc2fb887d0", "name": "Very large file: frontend/app/seguimiento/page.tsx (1195 lines)", "shortDescription": {"text": "Very large file: frontend/app/seguimiento/page.tsx (1195 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 94 source file(s) (ratio 0.00). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 76 console/debugger/print-style debug statements in non-test source. This is a common fast-generation residue before production cleanup."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-72b2a6250083a784", "name": "Placeholder or mock-heavy implementation detected", "shortDescription": {"text": "Placeholder or mock-heavy implementation detected"}, "fullDescription": {"text": "Found 103 placeholder/mock markers across 23 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-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license, ci, tests. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3423a73b533f84ca", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/mis-solicitudes/page.js:20", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/mis-solicitudes/page.js:20"}, "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-84f2edbe49e8359c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/usuarios/page.tsx:409", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/usuarios/page.tsx:409"}, "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-dca0aedb9c5d166e", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/licencias/page.tsx:25", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/licencias/page.tsx:25"}, "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-b9750c72c511a2f0", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/cecos/page.tsx:133", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/cecos/page.tsx:133"}, "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-97013d8c0ae8dc96", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/proveedores/page.tsx:155", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/proveedores/page.tsx:155"}, "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-65c095100e8c8344", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/presupuestos/page.tsx:154", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/presupuestos/page.tsx:154"}, "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-5aaa526e3aa7ed68", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/reportes/page.tsx:29", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/reportes/page.tsx:29"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-87c5c55d1c73f8c4", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/aprobaciones/page.js:27", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/aprobaciones/page.js:27"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-13be2a62044df271", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/inventario/page.js:80", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/inventario/page.js:80"}, "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-40ba26b159fa5fc5", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/components/AIAssistant.tsx:56", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/components/AIAssistant.tsx:56"}, "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-365346e05291287c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/nueva-solicitud/page.js:86", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/nueva-solicitud/page.js:86"}, "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-af022f937dd5b7fd", "name": "9 env vars used in code but missing from .env.example", "shortDescription": {"text": "9 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `CORS_ORIGINS`, `DB_SSL_CA`, `DB_SSL_REJECT_UNAUTHORIZED`, `NEXT_PUBLIC_API_URL`, `NODE_ENV`, `SMTP_HOST`, `SMTP_PASS`, `SMTP_PORT` + 1 more. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/25276"}, "properties": {"repository": "davidgza9/sistema-compras-ti", "repoUrl": "https://github.com/davidgza9/sistema-compras-ti", "branch": "main"}, "results": [{"ruleId": "scanner-503482a7f1222bbf", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrate_categoria.js:35"}, "properties": {"repobilityId": "f932f826279ee687", "scanner": "scanner-primary", "fingerprint": "503482a7f1222bbf", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-6c9efa63a05ca9c4", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/query.js:8"}, "properties": {"repobilityId": "1bda6e35457420b5", "scanner": "scanner-primary", "fingerprint": "6c9efa63a05ca9c4", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-ea1c72d04692be35", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/seed_presupuestos.js:39"}, "properties": {"repobilityId": "3bae245a23d70a9b", "scanner": "scanner-primary", "fingerprint": "ea1c72d04692be35", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-8955f3a7371b666c", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrate_ubicacion.js:13"}, "properties": {"repobilityId": "949ebcad8dbda2a7", "scanner": "scanner-primary", "fingerprint": "8955f3a7371b666c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-6c873de46cefdc07", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/mailer.js:18"}, "properties": {"repobilityId": "3c31fbfd97b9f678", "scanner": "scanner-primary", "fingerprint": "6c873de46cefdc07", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-b38fa1b5255f3b6c", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/list_tables.js:16"}, "properties": {"repobilityId": "af5492fd44148198", "scanner": "scanner-primary", "fingerprint": "b38fa1b5255f3b6c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-d19c6a4a594a92fc", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/reset_admin_v2.js:16"}, "properties": {"repobilityId": "4ad1049831a3ebe5", "scanner": "scanner-primary", "fingerprint": "d19c6a4a594a92fc", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-912daf32957f1480", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/notifications.js:18"}, "properties": {"repobilityId": "afcf06e5f357cfa2", "scanner": "scanner-primary", "fingerprint": "912daf32957f1480", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-36099ba9d22c3b50", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/enable_rls.js:5"}, "properties": {"repobilityId": "433166425fc4b837", "scanner": "scanner-primary", "fingerprint": "36099ba9d22c3b50", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-19e4606ec02d75f2", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/index.js:83"}, "properties": {"repobilityId": "0d1fe9bac94cd015", "scanner": "scanner-primary", "fingerprint": "19e4606ec02d75f2", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-185ab9464e905815", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrate_usuarios_notificaciones.js:16"}, "properties": {"repobilityId": "2b6399694cec0087", "scanner": "scanner-primary", "fingerprint": "185ab9464e905815", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-a5e881b90bbded42", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrate_licencias.js:25"}, "properties": {"repobilityId": "1058e6a07a09ec6c", "scanner": "scanner-primary", "fingerprint": "a5e881b90bbded42", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-abfaadd00dc11d13", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/dump_presupuestos.js:33"}, "properties": {"repobilityId": "5a17d82c373b195b", "scanner": "scanner-primary", "fingerprint": "abfaadd00dc11d13", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-e0fcedc6d796f0f7", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/seed_proveedores.js:151"}, "properties": {"repobilityId": "7ec03ab5d5598cb6", "scanner": "scanner-primary", "fingerprint": "e0fcedc6d796f0f7", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-42baa8911b1c755b", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrate.js:12"}, "properties": {"repobilityId": "2770a9ba3db61437", "scanner": "scanner-primary", "fingerprint": "42baa8911b1c755b", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-033fa8ccbbf3af6b", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/create_presupuesto_tables.js:11"}, "properties": {"repobilityId": "ca90d0ed8125a6a7", "scanner": "scanner-primary", "fingerprint": "033fa8ccbbf3af6b", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-e10a5594af6f1bac", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/seed_cecos.js:7"}, "properties": {"repobilityId": "c187b7f8ad096922", "scanner": "scanner-primary", "fingerprint": "e10a5594af6f1bac", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-373a899499e5934f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/insert_budget.js:225"}, "properties": {"repobilityId": "c726615550658d6e", "scanner": "scanner-primary", "fingerprint": "373a899499e5934f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-5ed260532cdaa037", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/add_fcm_token.js:6"}, "properties": {"repobilityId": "91648501ab49bb05", "scanner": "scanner-primary", "fingerprint": "5ed260532cdaa037", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-ca3c637a1aebfa31", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/migrations/run.js:19"}, "properties": {"repobilityId": "5f79ec1f7ea7e3b2", "scanner": "scanner-primary", "fingerprint": "ca3c637a1aebfa31", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-ace4a79cc6af54ce", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/layout.tsx:339"}, "properties": {"repobilityId": "cd60befb94adbc42", "scanner": "scanner-primary", "fingerprint": "ace4a79cc6af54ce", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d7f9421763e1a624", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/page.tsx:410"}, "properties": {"repobilityId": "d6399cfd43dfe522", "scanner": "scanner-primary", "fingerprint": "d7f9421763e1a624", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b163c43b731e31db", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/detalles-solicitud/[id]/components/TabResumen.js:247"}, "properties": {"repobilityId": "1012c1eb53e2bb6b", "scanner": "scanner-primary", "fingerprint": "b163c43b731e31db", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e113ff0d9982c76e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/detalles-solicitud/[id]/components/TabCotizaciones.js:143"}, "properties": {"repobilityId": "e504050d7dd9bf12", "scanner": "scanner-primary", "fingerprint": "e113ff0d9982c76e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3bf97a4e8d300ecc", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 frontend/app/admin/usuarios/page.tsx:569"}, "properties": {"repobilityId": "322615080c3951c9", "scanner": "scanner-primary", "fingerprint": "3bf97a4e8d300ecc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-a43636707eb1317e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/admin/presupuestos/TablaMatricial.tsx:232"}, "properties": {"repobilityId": "a9a2bcf4449c4442", "scanner": "scanner-primary", "fingerprint": "a43636707eb1317e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f0822ed82c71efd0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/admin/reportes/page.tsx:153"}, "properties": {"repobilityId": "ddc91e2b600870b5", "scanner": "scanner-primary", "fingerprint": "f0822ed82c71efd0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0598b72e14e60fd3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/components/NotificationBell.tsx:165"}, "properties": {"repobilityId": "4c1854a8976dbac7", "scanner": "scanner-primary", "fingerprint": "0598b72e14e60fd3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ac7b710cb9ecb634", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/components/CeCoBudgetRadar.tsx:338"}, "properties": {"repobilityId": "bd1a0145f6d0135f", "scanner": "scanner-primary", "fingerprint": "ac7b710cb9ecb634", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9e5f83ab23f7dd3e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/seguimiento/page.tsx:546"}, "properties": {"repobilityId": "8f7a55dee6ec099b", "scanner": "scanner-primary", "fingerprint": "9e5f83ab23f7dd3e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-053795dc7322a0e5", "level": "error", "message": {"text": "Possible secret in backend/reset_admin_v2.js"}, "properties": {"repobilityId": "415320cf9e953695", "scanner": "scanner-primary", "fingerprint": "053795dc7322a0e5", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/reset_admin_v2.js"}, "region": {"startLine": 12}}}]}, {"ruleId": "scanner-5a5965e0ce05385e", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/app/login/page.js:40"}, "properties": {"repobilityId": "e98543992d498cbe", "scanner": "scanner-primary", "fingerprint": "5a5965e0ce05385e", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/app/login/page.js"}, "region": {"startLine": 40}}}]}, {"ruleId": "scanner-e8bf6d4344cded7d", "level": "note", "message": {"text": "Insecure pattern 'document_write' in frontend/app/components/imprimirResponsiva.ts:10"}, "properties": {"repobilityId": "8d4ae4095fbe6deb", "scanner": "scanner-primary", "fingerprint": "e8bf6d4344cded7d", "layer": "security", "severity": "low", "confidence": 1.0, "tags": ["owasp", "document_write"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/app/components/imprimirResponsiva.ts"}, "region": {"startLine": 10}}}]}, {"ruleId": "scanner-527ec200d00bd174", "level": "note", "message": {"text": "Very large file: backend/index.js (2415 lines)"}, "properties": {"repobilityId": "2f185f1dc910197b", "scanner": "scanner-primary", "fingerprint": "527ec200d00bd174", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-07a760cc2fb887d0", "level": "note", "message": {"text": "Very large file: frontend/app/seguimiento/page.tsx (1195 lines)"}, "properties": {"repobilityId": "4bdd80033d7dd27c", "scanner": "scanner-primary", "fingerprint": "07a760cc2fb887d0", "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": "e31a86a402c5c752", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "d86fd208f43032d0", "scanner": "scanner-primary", "fingerprint": "3ab5d313dda8e5f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["debug", "cleanup", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-72b2a6250083a784", "level": "warning", "message": {"text": "Placeholder or mock-heavy implementation detected"}, "properties": {"repobilityId": "d887be6055011cc6", "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": "c11fef1cbfa9489e", "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": "727d2571596f54df", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "809cc928a6827dc0", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3423a73b533f84ca", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/mis-solicitudes/page.js:20"}, "properties": {"repobilityId": "034c5e0a42234839", "scanner": "scanner-primary", "fingerprint": "3423a73b533f84ca", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-84f2edbe49e8359c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/usuarios/page.tsx:409"}, "properties": {"repobilityId": "765b52877ebe69ff", "scanner": "scanner-primary", "fingerprint": "84f2edbe49e8359c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-dca0aedb9c5d166e", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/licencias/page.tsx:25"}, "properties": {"repobilityId": "976a814086fd5a52", "scanner": "scanner-primary", "fingerprint": "dca0aedb9c5d166e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-b9750c72c511a2f0", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/cecos/page.tsx:133"}, "properties": {"repobilityId": "f356ddec0c9fd6a2", "scanner": "scanner-primary", "fingerprint": "b9750c72c511a2f0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-97013d8c0ae8dc96", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/proveedores/page.tsx:155"}, "properties": {"repobilityId": "5de2f1aef37d6c13", "scanner": "scanner-primary", "fingerprint": "97013d8c0ae8dc96", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-65c095100e8c8344", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/presupuestos/page.tsx:154"}, "properties": {"repobilityId": "4dc9a14ea6cb4f83", "scanner": "scanner-primary", "fingerprint": "65c095100e8c8344", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-5aaa526e3aa7ed68", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/admin/reportes/page.tsx:29"}, "properties": {"repobilityId": "251781231d0c1258", "scanner": "scanner-primary", "fingerprint": "5aaa526e3aa7ed68", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-87c5c55d1c73f8c4", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/aprobaciones/page.js:27"}, "properties": {"repobilityId": "371c04d10a2f4356", "scanner": "scanner-primary", "fingerprint": "87c5c55d1c73f8c4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-13be2a62044df271", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/inventario/page.js:80"}, "properties": {"repobilityId": "3957d1508a4307f4", "scanner": "scanner-primary", "fingerprint": "13be2a62044df271", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-40ba26b159fa5fc5", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/components/AIAssistant.tsx:56"}, "properties": {"repobilityId": "35a330559a5a5948", "scanner": "scanner-primary", "fingerprint": "40ba26b159fa5fc5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-365346e05291287c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/app/nueva-solicitud/page.js:86"}, "properties": {"repobilityId": "ac1263a903bb7482", "scanner": "scanner-primary", "fingerprint": "365346e05291287c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-af022f937dd5b7fd", "level": "note", "message": {"text": "9 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "5597384795dea7a4", "scanner": "scanner-primary", "fingerprint": "af022f937dd5b7fd", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}]}]}