fix: Sprint 1 — los 3 showstopper de la auditoría (rutas Next, event loop, N-C1)#60
Merged
Merged
Conversation
… millones Informe consolidado: 3 showstopper (pilar QA-Continuity muerto en runtime, confused-deputy GitHub cross-tenant, webhook que congela el event loop), el diferenciador (cert firmado) roto de 3 formas, y el análisis de negocio (facturar por acta como cambio de modelo). Claude-Session: https://claude.ai/code/session_01X1fZebDm9ABFwLU2v3mq46
…n runtime) endpoints.ts invocaba /api/v2/* sin su route.ts proxy, dejando muerto en runtime todo el pilar QA-Continuity (Conocimiento, Onboarding, Knowledge Graph, Plan de pruebas), media integración Jira, root-cause, briefing y descarga del PDF del certificado — pese al CI verde (ningún test ejercía el proxy). - 18 route.ts nuevos siguiendo el patrón proxyToBackend - proxyBinaryToBackend para el PDF (respuesta binaria, no JSON) - test de paridad automático endpoints.ts <-> route.ts que falla si falta alguno Claude-Session: https://claude.ai/code/session_01X1fZebDm9ABFwLU2v3mq46
…ión GitHub
S3 — El webhook de CI era async def pero ejecutaba trabajo bloqueante (embeddings
torch + I/O) directamente, congelando el único event loop y bloqueando a todos
los tenants. Se extrae el pipeline a _process_ci_artifact y se ejecuta con
run_in_threadpool; Dockerfile arranca con --workers ${WEB_CONCURRENCY:-1}.
S2 (N-C1) — El bind de GitHub aceptaba installation_id arbitrario sin verificar
propiedad: un admin podía apuntar a la instalación de otro cliente y leer/escribir
su repo. Se añade verificación (la cuenta de la instalación debe == owner del repo)
e índice único en BD (migración 021) para que un installation_id no lo reclame
otra org. Residual (race del first-mover sobre tenant no configurado) → pendiente
el setup-redirect con state firmado.
Claude-Session: https://claude.ai/code/session_01X1fZebDm9ABFwLU2v3mq46
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contexto
Auditoría profunda (5 lentes) del 2026-07-02 →
docs/auditoria/2026-07-02-siguiente-nivel/00-informe.md. Este PR arregla los 3 showstopper que bloquean cualquier piloto/demo con datos reales. Basado enmain(no arrastra el trabajo de UX-B).Cambios
🔴 S1 — El pilar QA-Continuity estaba MUERTO en runtime (404), y el CI verde lo escondía
endpoints.tsinvocaba 18 rutas/api/v2/*sin suroute.tsproxy en Next → 404 en runtime en Conocimiento, Onboarding, Knowledge Graph, Plan de pruebas, media integración Jira, root-cause, briefing y descarga del PDF del certificado. El backend los implementa todos; faltaba la capa proxy y ningún test la ejercía.route.tsnuevos (patrónproxyToBackend).proxyBinaryToBackendpara el PDF (binario, no JSON).endpoints.ts ↔ route.tsque falla si vuelve a faltar alguno.🔴 S3 — El webhook de CI congelaba el único event loop
Era
async defpero ejecutaba trabajo bloqueante (embeddings torch + I/O) directamente → un run grande de un cliente bloqueaba a todos los tenants. Pipeline extraído a_process_ci_artifact+run_in_threadpool; Dockerfile con--workers ${WEB_CONCURRENCY:-1}(default 1 por el OOM del embedder, escalable por env).🔴 S2 (N-C1) — Confused-deputy cross-tenant en la GitHub App
El bind aceptaba
installation_idarbitrario sin verificar propiedad → un admin podía apuntar a la instalación de otro cliente y leer/escribir su repo privado. Se añade verificación (la cuenta de la instalación debe coincidir con el owner del repo) + índice único en BD (migración 021) para que uninstallation_idno lo reclame otra org.statefirmado — queda como seguimiento (no cerrado del todo).🧹 Limpieza
Eliminados los archivos/directorios duplicados
... 2(basura de iCloud sync).Test plan
next buildregistra las 18 rutas nuevas sin conflicto de params.lint:cilimpio,tsc --noEmitEXIT=0, 186 tests (incl. paridad).psql "$DATABASE_URL" -f db/migrations/021_github_installation_unique.sql.https://claude.ai/code/session_01X1fZebDm9ABFwLU2v3mq46