CreaRack-SL

La Ayuda en español no abría ningún artículo: el filtro de seguridad T9 solo aceptaba wiki/, no wiki-es/

Cuándo

Desde el 01-09-2026 hasta el fix del 14-09-2026 (v1.132.3, PR #533) — 13 días. Detectado en la ronda de mantenimiento del 13-09 y registrado como task #308 del Gestor.

Síntomas visibles

Con la sesión de usuario en español, el panel de Ayuda listaba perfectamente los 69 títulos traducidos (GET /api/help/wiki funcionaba), pero ningún artículo se podía abrir: cualquier clic devolvía “Error loading article” (GET /api/help/article respondía 403). El fallo era binario — 0 de 69 — y afectaba solo a la sesión en español; en inglés todo seguía abriendo con normalidad.

Causa raíz

Dos piezas del mismo módulo, escritas en momentos distintos, dejaron de encajar:

  1. El listado (_apply_language, sesión 137) reescribe las rutas de los artículos a wiki-es/crearack--*.md cuando la sesión está en español — comportamiento correcto y ya existente desde hace meses.
  2. El filtro de seguridad T9 (_HELP_ARTICLE_RE en core/api_help.py:38, introducido en v1.100.0 para cerrar una fuga real: un usuario autenticado podía leer documentación interna del workspace vía read_guide pasando cualquier ruta) solo aceptaba el patrón wiki/crearack--*.md. La carpeta traducida wiki-es/ no estaba en la whitelist.

El resultado: el endpoint que lista artículos entregaba una ruta (wiki-es/...) que el endpoint que abre artículos rechazaba de forma sistemática. El filtro de seguridad era correcto en su objetivo — impedir la lectura de rutas fuera de la Ayuda de usuario — pero no contempló que la carpeta traducida llevaba dos meses y medio sirviendo contenido legítimo.

Ninguno de los dos lados tenía un test que uniera listado + apertura: tests/api/test_tanda9_security.py solo probaba la ruta inglesa, y tests/api/test_help.py solo probaba el listado por separado.

Fix aplicado

Commit cc37a5336d01310341ae1dcbb533e0090efcafb0 (PR #533, v1.132.3):

  1. _HELP_ARTICLE_RE pasa a ^(?:src/content/)?wiki(?:-es)?/crearack--[a-z0-9-]+\.md$ — acepta wiki-es/ con las mismas exigencias que wiki/ (prefijo crearack--, extensión .md, sin ..). La doc interna del workspace sigue vetada bajo ambas carpetas.
  2. Test de contrato “lo que listo, lo puedo abrir” (test_help_list_then_open_contract, parametrizado en inglés y español): pide el listado, coge la primera ruta devuelta y la abre — exige 200, nunca 403. Este es el test que faltaba y que habría cazado la regresión el mismo día que nació.
  3. Test negativo en la carpeta traducida (test_help_article_rechaza_ruta_interna_en_carpeta_es): confirma que wiki-es/decision--*.md (doc interna bajo la carpeta ES) sigue devolviendo 403 — el fix amplía la whitelist, no la debilita.

Límite honesto: el fix está verificado por test automático; la sonda de la task #308 (comprobar los 69 artículos en ambos idiomas contra producción tras el deploy) queda pendiente y su resultado se registra en la propia tarea.

Lecciones

  • Un filtro de seguridad y un rewrite de rutas son dos mitades de un contrato que hay que testear juntas, no por separado. Cada mitad por su lado pasaba sus tests; la combinación llevaba 13 días rota sin que ninguna alarma saltara — el fallo es silencioso porque un 403 no es un error de servidor, es “funcionando como se diseñó” para una ruta que el propio sistema acababa de entregar.
  • Tercer incidente del mismo patrón en el puente de la Ayuda en menos de 4 meses: [[incident—20260512—cf-access-help-widget-403]] (auth), [[incident—20260823—help-es-json-error-como-articulo]] (payload de error servido como contenido) y este (whitelist incompleta). Los tres comparten la forma: dos piezas que se escribieron en sesiones distintas y que solo se validan juntas cuando alguien prueba el camino completo en español.
  • Un endurecimiento de seguridad (T9, v1.100.0) necesita repasar TODOS los caminos legítimos existentes en el momento de escribirlo, no solo el caso que motivó el cierre de la fuga.

Preventivos futuros

  • El test de contrato añadido (test_help_list_then_open_contract) corre en CI para EN y ES en cada PR — cualquier futura carpeta de idioma (wiki-fr/, etc.) que no esté en la whitelist lo hará fallar antes de mergear.
  • Pendiente de decisión de equipo (no bloqueante de este fix): una sonda periódica contra producción que liste y abra una muestra de artículos en cada idioma habría detectado el 0/69 el mismo 01-09 en vez de 13 días después.

Véase también

  • [[entity—core—service—api-help]]
  • [[entity—core—endpoint—api-help-wiki]]
  • [[incident—20260823—help-es-json-error-como-articulo]]
  • [[incident—20260512—cf-access-help-widget-403]]
  • [[crearack-tech—guides—help-widget-bridge]]
  • [[feature—core—help-widget-i4]]