metis-desk/docs/playwright-mcp.md

300 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Playwright MCP mediante Docker
## Arquitectura y alcance
Codex arranca el servidor `playwright` definido en [`.codex/config.toml`](../.codex/config.toml). El cliente y el servidor intercambian JSON-RPC por stdin/stdout; Chromium headless se ejecuta dentro de la imagen oficial de Microsoft. No se instala un navegador en WSL ni se publica un puerto MCP.
```text
Codex ── stdio ── docker run ── Playwright MCP + Chromium headless
│ red host
▼
http://localhost:5173
│ Vite /api
▼
http://127.0.0.1:3001
│
MariaDB local :3307
```
5173 es el puerto habitual de Vite, no una constante impuesta por el proyecto: `apps/web/vite.config.ts` no fija `port` ni `strictPort`. Siempre comprobar la dirección anunciada al arrancar. El puerto 3001 corresponde a la API y no sirve la interfaz.
La configuración utiliza `--network=host` para que Chromium alcance el frontend mediante el mismo origen local que utiliza Metis. No monta el repositorio, archivos `.env`, perfiles del navegador ni el socket Docker dentro del contenedor. `--isolated` mantiene el perfil en memoria y `--rm` retira el contenedor al terminar. El directorio de salida de MCP está dentro del contenedor y es efímero. `--shm-size=1g` reserva capacidad de memoria compartida para Chromium, sin preasignar ese consumo.
La imagen oficial ejecuta Chromium sin su sandbox interno; el contenedor y la red host no son una frontera adecuada para visitar contenido no confiable. No añadir `--privileged`. La configuración está destinada a la aplicación local y no introduce un servicio MCP accesible por HTTP. Véase la [documentación oficial de Microsoft](https://github.com/microsoft/playwright-mcp).
## Requisitos y portabilidad WSL2
- WSL2 con Ubuntu 24.04 o equivalente, con el repositorio en el filesystem Linux.
- Node.js 24.x y PNPM según `packageManager` de `package.json`, para ejecutar Metis.
- Docker CLI y acceso a un daemon Linux desde el mismo usuario que ejecuta Codex. Comprobar `docker version`, `docker context show` y `docker info`.
- Python 3.11 o posterior para el comprobador incluido; utiliza solamente la biblioteca estándar. Ubuntu 24.04 proporciona Python 3.12.
- Acceso a `mcr.microsoft.com` para descargar la imagen, espacio para sus capas y la aplicación arrancada antes de navegar.
Python y Docker son requisitos del host. El instalador no utiliza sudo, no instala un daemon, no cambia grupos de usuarios ni habilita servicios del sistema: evita entrar en conflicto con Docker Desktop o un Engine ya existente. En Ubuntu 24.04, si falta Python, instalarlo explícitamente con `sudo apt-get update` y `sudo apt-get install python3`. Preparar Docker Engine local o Docker Desktop con integración WSL antes de ejecutar el instalador; Metis ya utiliza Docker para MariaDB. Si falta un requisito, el script termina con error y una indicación, sin anunciar una instalación completa.
Con Docker Engine dentro de la misma distribución WSL, la red host comparte directamente la red de esa distribución. Es el escenario probado aquí.
Con Docker Desktop, activar la integración con la distribución WSL y, en Docker Desktop 4.34 o posterior, **Settings → Resources → Network → Enable host networking**, aplicar y reiniciar. Requiere contenedores Linux; comprobar la conectividad con el procedimiento de este documento. Las condiciones y limitaciones están descritas en [Docker: host network driver](https://docs.docker.com/engine/network/drivers/host/). No se ha validado Docker Desktop en esta entrega.
Un contexto Docker remoto comparte la red del host del daemon, no la del terminal WSL que ejecuta el comando. No asumir que `localhost` corresponde entonces a Metis. Usar un daemon local compatible con esta configuración o diseñar y verificar la conectividad específica antes de utilizarla.
## Configuración MCP versionada
Hay una única entrada de proyecto, `mcp_servers.playwright`, con `command = "docker"` y transporte stdio implícito. No usar `-t`: asignar una TTY rompe la separación del protocolo. Tampoco añadir `-p`, `--port` ni un servidor HTTP MCP para este caso.
Imagen fijada:
```text
mcr.microsoft.com/playwright/mcp:v0.0.83@sha256:690763cbb437ee7233f538a953bb5390bf03791eb5c965b471e59d17a6132fcb
```
El 21 de octubre de 2026 se contrastaron el tag `v0.0.83` y el digest mediante `docker buildx imagetools inspect` contra Microsoft Container Registry. El digest identifica el índice multi-arquitectura, con manifiestos Linux amd64 y arm64; no obliga a usar una arquitectura concreta. La ejecución arm64 queda pendiente de validación.
Los plazos de arranque y de herramientas son 120 segundos. Descargar la imagen antes de iniciar Codex para que una conexión lenta no consuma el plazo de arranque.
Codex admite configuración local en `.codex/config.toml` y solo la carga en proyectos de confianza. Abrir este repositorio como proyecto de confianza y reiniciar la sesión después de cambiar la configuración. Comprobar `/mcp` en el cliente o `codex mcp list --json` desde la raíz. Debe aparecer un único `playwright` habilitado con transporte stdio. No ejecutar `codex mcp add` para duplicarlo en la configuración global. Referencias: [MCP en Codex](https://developers.openai.com/codex/mcp/) y [configuración de Codex](https://developers.openai.com/codex/config-basic/).
## Instalación en un equipo nuevo
Desde bash dentro de WSL, en la raíz del clon:
```bash
node --version
pnpm --version
python3 --version
docker version
docker context show
pnpm install --frozen-lockfile
```
Preparar la herramienta permanente de auditoría:
```bash
bash scripts/setup-playwright-wsl.sh
```
Se puede ejecutar desde cualquier directorio indicando la ruta del script; localiza el clon mediante su propia ubicación, sin rutas de usuario prefijadas. Requiere WSL2 y Python 3.11+, valida Docker Linux y lee la referencia de `.codex/config.toml`. Si la imagen exacta existe, la reutiliza; si falta, la descarga. No sobrescribe configuraciones ni instala paquetes de producción.
Después abre un endpoint temporal en `127.0.0.1` con un puerto asignado por el sistema y comprueba que el contenedor lo alcanza. Ese endpoint solo devuelve un token de diagnóstico y no sirve archivos. En el mismo contenedor arranca Chromium con la biblioteca Playwright incluida en la imagen y el canal `chromium`, igual que MCP. Se comprueba así la compatibilidad efectiva de navegador y biblioteca, además de la red host. El contenedor y el endpoint se retiran al terminar. Una segunda ejecución repite las comprobaciones sin reinstalar nada.
No ejecutar `npx playwright install` en el host ni instalar versiones separadas de Playwright: el servidor y los binarios compatibles se distribuyen juntos, fijados por el digest. En esta imagen el canal `chromium` utiliza el navegador completo en modo headless; un `chromium.launch()` sin canal intenta usar un headless shell que la imagen no incluye.
El instalador no arranca Metis ni valida la interfaz: completar la comprobación real descrita a continuación y abrir una nueva sesión Codex en el repositorio de confianza.
## Ejecución de Metis para auditorías y verificación
Preparar la base con `pnpm db:up`, según [puesta en marcha](puesta-en-marcha.md). Esto conserva el volumen y genera la configuración local si falta. No copiar secretos entre equipos ni versionar `.env`.
Para una comprobación aislada de datos reales, arrancar la API sobre la base de pruebas desde otra terminal WSL:
```bash
cd apps/server
DB_NAME=metis_desk_test NODE_ENV=test APP_ORIGIN=http://localhost:5173 PORT=3001 \
node --env-file=../../.env --import tsx src/index.ts
```
El arranque aplica las migraciones y la preparación normal a esa base de pruebas. No ejecutar dos API en el mismo puerto. En otra terminal, desde la raíz, arrancar Vite con un puerto explícito para esta comprobación:
```bash
pnpm --filter @metis/web exec vite --host 127.0.0.1 --port 5173 --strictPort
```
Si el puerto está ocupado, detener únicamente el proceso propio o elegir otro puerto y actualizar coherentemente el `APP_ORIGIN` de la API de prueba. Si se cambia el puerto de la API, proporcionar también `API_PROXY_TARGET` a Vite. Para el uso habitual, `pnpm dev` sigue siendo el procedimiento del proyecto; no sustituye el aislamiento de datos exigido para pruebas con persistencia.
Con ambos procesos disponibles:
```bash
python3 scripts/check-playwright-mcp.py http://localhost:5173
```
El argumento es obligatorio: indicar la URL real, sin credenciales. El comprobador lee la configuración versionada, arranca un contenedor temporal con ella, negocia MCP, descubre herramientas y ejecuta `browser_navigate`, `browser_evaluate` y `browser_take_screenshot`. Espera un formulario real de acceso/configuración y comprueba el título de Metis Desk y el user agent de Chromium headless. No envía formularios ni crea usuarios. Es una prueba de conexión y renderizado inicial, no una suite funcional de pantallas autenticadas.
El comprobador elimina exclusivamente su propio contenedor al terminar, incluso ante un fallo normal del cliente. No requiere un SDK MCP, Playwright instalado en WSL ni un navegador local. Después de la comprobación, detener las terminales de API y Vite con Ctrl+C si solo se arrancaron para ella.
## Clientes Codex y alternativa sin configuración global
La documentación oficial describe la configuración MCP compartida entre clientes del mismo host y la configuración de proyecto para repositorios de confianza. Esto no prueba que cualquier versión o sesión abierta haya cargado sus herramientas. Windows y WSL pueden tener instalaciones, permisos, PATH y configuraciones efectivas distintos. Referencias: [MCP](https://developers.openai.com/codex/mcp/), [configuración](https://developers.openai.com/codex/config-basic/) y [entornos Windows y WSL](https://developers.openai.com/codex/windows/).
| Cliente | Uso recomendado y alcance comprobado |
| --- | --- |
| Codex CLI en WSL | Lanzarlo desde el clon de confianza y comprobar `codex mcp list --json` y `/mcp` en la nueva sesión. CLI 0.114.0 reconoce aquí una única entrada de proyecto. El listado valida configuración; no sustituye una llamada real a sus herramientas. |
| Extensión de VS Code | Abrir el clon mediante Remote WSL y comprobar que Codex y Docker se ejecutan en esa distribución. Reiniciar la sesión tras cambios y revisar las herramientas disponibles. La extensión no se ha ejecutado ni validado en esta entrega. |
| Codex Desktop | Confirmar el host de ejecución del agente y del servidor MCP, el proyecto abierto y la configuración efectiva de esa versión. Un terminal integrado WSL no demuestra que un proceso MCP se lance en WSL. No se ha validado Desktop ni se afirma que todas sus versiones carguen correctamente la entrada de proyecto. Si no lo hace, usar el CLI WSL con la alternativa siguiente. |
| Sesión de agente ya abierta | La configuración puede aparecer en `mcp list` sin estar expuesta en su catálogo de herramientas. En esta sesión no se exponen herramientas Playwright directamente: las capturas se verifican con el cliente stdio independiente. Reabrir la sesión y comprobar `/mcp` antes de atribuir una prueba al cliente Codex. |
Si el cliente no carga el servidor del proyecto, el lanzador alternativo lee la misma entrada y la pasa al CLI mediante overrides `-c` válidos únicamente para ese proceso:
```bash
bash scripts/codex-playwright-wsl.sh mcp list --json
bash scripts/codex-playwright-wsl.sh
```
Localiza la raíz del clon, mantiene el nombre `playwright` y conserva el resto de ajustes del usuario. No escribe configuración global, no cambia `CODEX_HOME`, no copia autenticación y no requiere duplicar tags ni digests en el lanzador. Conserva stdin, terminal y señales para su uso interactivo. Los argumentos adicionales se pasan al CLI, por ejemplo `-c 'service_tier="fast"'` para la incompatibilidad concreta descrita en resolución de errores. `METIS_CODEX_BIN` permite seleccionar explícitamente otro ejecutable del CLI cuando el comando del PATH tenga problemas con su empaquetado; no se fija una ruta personal en Git.
Este mecanismo alternativo inicia el CLI; no registra automáticamente herramientas en la extensión o Desktop. Si sus políticas administradas impiden ejecutar Docker, resolver los permisos con el administrador: el lanzador no evita esas restricciones. El comprobador Python permite verificar stdio y la captura independientemente de la carga de herramientas del cliente, sin afirmar que con ello Desktop o la extensión estén validados.
## Auditorías visuales autenticadas
### Autenticación existente y decisión
No hay usuarios de desarrollo predeterminados. La instalación real se configura mediante `/api/auth/bootstrap`, que crea un administrador inicial protegido; `/api/users` permite a ese administrador crear usuarios ordinarios. No existe un catálogo general de roles: la gestión de usuarios requiere ser el administrador inicial, mientras el usuario ordinario puede acceder al espacio de soporte.
`/api/auth/login` comprueba la contraseña mediante scrypt y renueva la sesión. MariaDB guarda las sesiones; la cookie `metis.sid` es HttpOnly, SameSite=Strict y dura ocho horas. En producción también es Secure. No se guarda un token de acceso en localStorage. `/api/auth/session` proporciona el token CSRF y las operaciones de escritura exigen ese token y el origen configurado. `/api/auth/logout` destruye la sesión y elimina la cookie. El servidor comprueba usuario activo y versión de autenticación; la protección de datos no depende solo de las redirecciones del cliente. Véase [usuarios y acceso](usuarios-y-acceso.md).
El proyecto dispone de `metis_desk_test` y fixtures de integración, pero algunas pruebas limpian tablas o fabrican sesiones para probar contratos concretos. **No ejecutar esas pruebas para preparar una auditoría visual**: tampoco se utiliza la base de pruebas existente.
`scripts/visual-audit.py` prepara una instalación desechable mediante los endpoints públicos reales:
1. Crea un contenedor MariaDB independiente, con un volumen anónimo, nombre aleatorio, puerto libre publicado solo en `127.0.0.1`, `metis_desk_test` y contraseñas aleatorias.
2. Arranca la API existente con esa conexión, un secreto de sesión aleatorio y `NODE_ENV=test`. No carga `.env` ni acepta una conexión de base de datos suministrada por el usuario.
3. Ejecuta el bootstrap normal y crea un usuario ordinario, una compañía sintética y un portátil a través de HTTP con sesión y CSRF válidos. El administrador solo sirve para preparar esta instalación temporal: no se conserva en ninguna base existente.
4. Cierra la sesión de preparación. Arranca Vite en otro puerto libre, con el proxy y `APP_ORIGIN` alineados automáticamente.
5. Playwright MCP abre el formulario real, rellena las credenciales generadas y pulsa Entrar. Comprueba la identidad ordinaria y el rechazo 403 de `/api/users`.
6. Abre listado, ficha y edición del activo; captura las pantallas y cancela el diálogo sin guardar. Exporta la sesión obtenida y verifica su reutilización desde otro contenedor MCP.
No se añaden endpoints de acceso especial, cookies fabricadas, excepciones de autorización ni cambios en código de negocio. MariaDB utiliza el índice oficial fijado en el script, contrastado con el registro: `mariadb:11.8@sha256:6422478cb8e159f080fb1d8ccf65101e26fe51385787fde7d16c3b165a331f15`. Al actualizarlo, verificar el nuevo índice y repetir ambas modalidades. La imagen MCP sigue procediendo de `.codex/config.toml`.
### Preparación en otro WSL
Se necesitan los mismos requisitos de este documento, las dependencias del proyecto y Docker con acceso a Microsoft Container Registry y Docker Hub. Desde la raíz del clon:
```bash
pnpm install --frozen-lockfile
bash scripts/setup-playwright-wsl.sh
python3 scripts/visual-audit.py --check
```
Este procedimiento no necesita `pnpm db:up`, una copia de `.env` ni datos reales. `--check` ejecuta el recorrido, comprueba que logout devuelve 200 y que después el acceso protegido devuelve 401, y retira los servicios. Conserva capturas y un informe sin cookies; termina con código distinto de cero si falla. No valida por sí solo la exposición de las herramientas en un cliente Codex concreto.
### Mantener una sesión disponible para Codex
En una terminal WSL, desde el clon:
```bash
python3 scripts/visual-audit.py
```
Esperar el mensaje de verificación. El proceso imprime la URL exacta del inventario temporal y el comando para otra terminal, con su ruta real de sesión. Copiar ese comando, que tiene esta forma:
```bash
METIS_PLAYWRIGHT_STORAGE_STATE=.artifacts/playwright/authenticated-ID/session.json \
bash scripts/codex-playwright-wsl.sh
```
Sustituir `authenticated-ID` por el directorio que imprime el proceso. Las rutas relativas se resuelven contra la raíz del clon. Si se necesita el override de compatibilidad de la CLI antigua, añadir `-c 'service_tier="fast"'` al lanzador. No fijar rutas personales ni versiones duplicadas en la configuración global.
El lanzador mantiene la entrada `playwright` y añade solamente para ese proceso un montaje de solo lectura del archivo y `--storage-state`. Usa el UID/GID del usuario WSL para leer el archivo privado sin cambiar sus permisos. Comprueba que sea un archivo propio con permisos restringidos dentro de `.artifacts/playwright` y que contenga únicamente cookies de sesión locales de Metis. Sin la variable, conserva el comportamiento habitual sin sesión precargada. No modifica `.codex/config.toml` ni el archivo global.
Abrir una sesión nueva y comprobar `/mcp`. Navegar a **la URL temporal impresa**, no a la instancia habitual en 5173. Mantener abierto `visual-audit.py` durante el trabajo. El modo interactivo conserva la sesión; no ejecuta la prueba final de logout porque la invalidaría para Codex.
Cerrar primero la sesión de auditoría de Codex y después pulsar Ctrl+C en el proceso preparador. Se detienen sus grupos de procesos de API/Vite, se retira su contenedor y volumen anónimo y se elimina `session.json`. No se detiene MariaDB del proyecto ni se borran bases existentes. Cada ejecución genera un entorno nuevo; no reutiliza ni resetea datos de ejecuciones anteriores.
### Credenciales, sesiones y evidencia
- Las contraseñas del administrador y usuario son aleatorias y permanecen en memoria. El archivo temporal necesario para arrancar MariaDB se crea con modo 0600 y se elimina al arrancar el contenedor. No se imprimen credenciales, cookies, tokens ni resultados de rellenado del formulario.
- El directorio de ejecución tiene modo 0700 y `session.json`, modo 0600. La sesión es sensible aunque corresponda a datos sintéticos; no copiarla a mensajes ni guardarla en Git. Este tratamiento sigue el modelo de [estado autenticado de Playwright](https://playwright.dev/docs/auth).
- El directorio `.artifacts/playwright/` ya está excluido de Git. No guardar estados de navegador en otras ubicaciones. El archivo contiene el estado de una sesión real, no un mecanismo alternativo de autenticación; su validez depende del servidor y de la sesión persistida.
- Se guardan `00-login.png`, `01-authenticated.png`, `02-assets.png`, `03-detail.png`, `04-dialog.png`, `report.json` y los logs locales de API/Vite. Las capturas son del viewport, para conservar una composición legible en una aplicación con scroll interno. El informe contiene rutas, identificadores sintéticos, resultados y hashes de capturas, nunca cookies o contraseñas.
- Revisar las imágenes antes de afirmar una inspección visual. El recorrido solo comprueba acceso y navegación básica; no repite la auditoría UI/UX completa.
### Diagnóstico y límites
Si falla el arranque, revisar `api.log` y `vite.log` del directorio indicado. Los cuerpos de errores HTTP y los resultados de herramientas de login no se vuelcan, porque pueden repetir información de sesión. El plazo de disponibilidad está acotado y las esperas de interfaz usan los elementos reales de Playwright.
Tras terminar el preparador, su archivo de sesión deja de existir. Si se cierra sesión desde un cliente, también se invalida para otros contextos que compartan esa cookie; volver a preparar el entorno. No reutilizar estados caducados ni intentar recuperar credenciales desde los logs.
Una terminación forzada con SIGKILL o un fallo del daemon puede impedir el cleanup. Identificar los contenedores propios con `docker ps -a --filter name=metis-visual-` y sus volúmenes; retirar únicamente el nombre exacto de la ejecución afectada mediante `docker rm -f -v NOMBRE_DEL_CONTENEDOR_DE_AUDITORIA`. No usar limpiezas globales, `compose down -v` ni borrar el volumen de Metis. Las sesiones que queden en directorios de ejecuciones interrumpidas también deben retirarse.
La base es desechable, pero una auditoría sigue siendo de lectura salvo que la tarea autorice probar guardados. El conjunto inicial solo contiene una compañía y un activo: otras pantallas pueden necesitar fixtures adicionales explícitas. El usuario ordinario no permite auditar administración de usuarios. La sesión preparada se utiliza con el CLI WSL; no se ha comprobado su carga en extensión o Desktop. Tampoco se ha ejecutado esta modalidad en Docker Desktop o ARM. No hay navegador instalado en WSL ni cambios de seguridad de producción.
## Conectividad y origen
La URL del navegador y `APP_ORIGIN` deben coincidir exactamente en esquema, host y puerto. `localhost` y `127.0.0.1` son orígenes distintos aunque alcancen el mismo servicio. Si se usa el origen LAN del proyecto, comprobar ese origen y la configuración de la API; no desactivar sus protecciones.
La alternativa de Docker bridge con `host.docker.internal:host-gateway` no es equivalente: cambia el host del navegador y puede requerir ajustes de escucha, hosts admitidos por Vite y `APP_ORIGIN`. Por eso esta integración utiliza red host y no añade excepciones amplias en Vite ni modifica la configuración de negocio.
Comprobaciones locales útiles:
```bash
ss -ltnp
curl --fail --silent --output /dev/null http://localhost:5173/
docker ps --format '{{.Names}}\t{{.Image}}\t{{.Ports}}'
```
Que `curl` funcione en WSL no demuestra por sí solo que Chromium acceda desde Docker. El comprobador MCP es la verificación completa de ese recorrido.
## Capturas y evidencia
La salida predeterminada del comprobador es:
- `.artifacts/playwright/metis-desk.png`: imagen recibida del MCP, validada como PNG con dimensiones positivas.
- `.artifacts/playwright/metis-desk.json`: imagen Docker, versión del servidor, protocolo, herramientas disponibles, URL, dimensiones, tamaño, SHA-256, resultado de inspección de página y mensajes de consola de nivel error.
Este directorio se excluye de Git porque las capturas pueden contener información de la aplicación. Se puede elegir otro destino con `--output`, pero mantener la evidencia fuera del versionado. No guardar contraseñas, cookies ni perfiles persistentes. En una sesión interactiva, usar la imagen devuelta por `browser_take_screenshot`; los archivos que el servidor escriba en `/tmp/metis-desk-playwright` permanecen dentro del contenedor y se pierden al retirarlo.
Abrir e inspeccionar el PNG antes de afirmar una revisión visual. La cabecera PNG, la existencia de un formulario y un snapshot accesible no prueban que la composición visual sea correcta. Para auditar cambios, comprobar además tamaños de pantalla, teclado, foco y estados pertinentes mediante las herramientas MCP; documentar únicamente escenarios ejecutados. No crear usuarios o modificar datos reales como parte de una auditoría sin autorización específica.
## Resolución de errores
| Síntoma | Comprobación y solución |
| --- | --- |
| Docker no responde o deniega acceso al socket | Arrancar el daemon y comprobar acceso del usuario de Codex. En entornos con sandbox, la herramienta puede necesitar autorización para Docker y conexiones locales. No resolverlo con `chmod 777` del socket. |
| El instalador rechaza el entorno | Ejecutarlo en WSL2 con Python 3.11+, Docker Linux y `timeout` disponibles. Instalar los requisitos explícitamente; no se ejecuta sudo automáticamente. |
| El instalador falla al comprobar red host | Activar host networking en Docker Desktop compatible, comprobar el contexto y repetirlo. El endpoint de diagnóstico no depende de que Metis esté arrancado. |
| Descarga cortada o arranque MCP agotado | Reintentar `docker pull` con la misma referencia fijada; Docker reutiliza las capas descargadas. Descargar antes de iniciar el MCP. No cambiar a `latest` para esquivar el fallo. |
| `ERR_CONNECTION_REFUSED` | Confirmar Vite, puerto anunciado y contexto Docker. En Desktop, comprobar la opción de red host y la integración WSL. |
| Página cargada pero error de `/api` | Confirmar API en 3001 y proxy de Vite. El HTML de Vite puede responder aunque la API esté parada. |
| Formularios rechazados por origen | Alinear URL del navegador y `APP_ORIGIN`. No desactivar la comprobación de origen. |
| Vite arranca en otro puerto | Consultar su salida; para la prueba, usar `--port` y `--strictPort` y alinear la API. |
| No aparece el servidor en Codex | Abrir el repositorio de confianza, revisar TOML, reiniciar sesión y comprobar `/mcp`. No duplicarlo globalmente. |
| `auth_status: unsupported` en el listado CLI | Es normal para este servidor stdio sin OAuth; no implica fallo de Chromium. |
| CLI antigua rechaza `service_tier = "default"` | Se observó con Codex CLI 0.114.0 y una configuración global preexistente. Para el diagnóstico se usó `codex -c 'service_tier="fast"' mcp list --json`, sin modificarla. Preferir una CLI compatible; el override es solo para esa invocación. |
| El comprobador no encuentra un formulario | Está orientado al acceso/configuración inicial con perfil aislado. Revisar que sea Metis y que la API funcione; no sustituir el backend por HTML simulado para dar la prueba por superada. |
| Se corta el cliente abruptamente | Revisar contenedores `metis-desk-playwright-check-*` con `docker ps` y retirar únicamente el contenedor propio que haya quedado huérfano. |
## Actualización de la imagen
1. Elegir un tag estable publicado por Microsoft. Consultar las versiones reales, no inventar tags ni digests.
2. Ejecutar `docker buildx imagetools inspect mcr.microsoft.com/playwright/mcp:<tag>` y comprobar el digest del índice y las plataformas. Si no está disponible Buildx, consultar el manifiesto con herramientas del registro antes de actualizar.
3. Sustituir la referencia `tag@sha256:...` únicamente en `.codex/config.toml` y actualizar la referencia informativa de este documento. Mantener el índice multi-arquitectura.
4. Descargar esa referencia, comprobar su ayuda y ejecutar el comprobador contra Metis. Abrir la captura, verificar las herramientas necesarias y revisar posibles cambios de flags.
5. Reiniciar Codex y comprobar que reconoce una sola entrada. Versionar configuración y documentación; conservar las capturas fuera de Git.
La fijación por digest impide que un movimiento del tag sustituya silenciosamente la imagen utilizada. No hay actualización automática a `latest`.
## Verificación de esta entrega
Comprobación ejecutada el 21 de octubre de 2026:
- Docker Engine 29.7.2, contexto local `default`, Linux amd64 dentro de WSL. La descarga sufrió tres cortes de conexión; el siguiente `docker pull` por digest terminó correctamente. Se inició un diagnóstico alternativo de descarga directa, pero no se importó ni reconstruyó la imagen: la prueba utilizó la imagen obtenida por Docker.
- Digest del índice verificado en el registro y en la imagen descargada. Se comprobó su punto de entrada real, el usuario `node` y la ayuda de sus flags.
- Una única entrada `playwright` reconocida por Codex CLI. Se utilizó el override de compatibilidad descrito para la CLI 0.114.0, sin cambiar su configuración global. Los cambios se activan en el cliente al abrir una nueva sesión del proyecto.
- Vite en `127.0.0.1:5173`, navegación en `http://localhost:5173`, API en `127.0.0.1:3001` con `APP_ORIGIN=http://localhost:5173` y `DB_NAME=metis_desk_test`. No se enviaron formularios ni se crearon usuarios.
- Negociación MCP `2025-06-18`, 25 herramientas y servidor que se identifica como `Playwright`, versión `1.64.0-alpha-1790635538000`. Esta versión informada por el protocolo es distinta del tag de distribución Docker `v0.0.83`.
- Navegación real a `/login`, título `Metis Desk` y user agent `HeadlessChrome/155.0.0.0`. Captura recibida por MCP: PNG de 1280×720, 33 549 bytes, SHA-256 `43d892c90d7ddb4befdae69637231c4f8f45112f300856684919493163f9e565`. Se abrió e inspeccionó: muestra la pantalla de acceso con los campos vacíos.
- La consola registró un 404 de `/favicon.ico`, conservado en el informe local. No impidió el renderizado ni se modificó código de aplicación para corregirlo.
- Se retiraron los contenedores MCP temporales y se detuvieron la API y Vite arrancados para esta comprobación. Se conservó el contenedor de MariaDB existente y la imagen descargada en la caché Docker.
- Se comprobó la sintaxis Python y TOML, el rechazo de URLs con credenciales y la exclusión de artefactos de Git. No se ejecutaron typecheck, lint, tests ni build del negocio porque los cambios se limitan a configuración, documentación y el comprobador independiente.
La comprobación inicial no cubrió sesiones autenticadas ni formularios de negocio; su ampliación figura más abajo. Responsive y accesibilidad completa, Docker Desktop y ejecución arm64 siguen pendientes de validación. La existencia de sus opciones o manifiestos no equivale a una prueba en esas plataformas.
### Ampliación del procedimiento WSL
En el mismo entorno se ejecutó `bash scripts/setup-playwright-wsl.sh` dos veces, con código de salida cero en ambas: reutilizó la imagen y comprobó red host y Chromium `155.0.8059.12`. Se validaron la sintaxis de ambos scripts con `bash -n`, `--help` y el rechazo de argumentos desconocidos con salida 2. No se simuló un WSL recién instalado ni se volvió a descargar la imagen: el camino de descarga ya se había comprobado durante la integración inicial.
Se contrastó el listado real del CLI 0.114.0 con y sin el lanzador alternativo: ambos muestran una sola entrada `playwright`. Se mantuvo el override puntual de `service_tier`, sin modificar configuración global. También se comprobó con un ejecutable de diagnóstico que el lanzador serializa overrides TOML válidos, funciona desde otro directorio y conserva stdin; no se atribuye esa comprobación a una sesión interactiva completa de Codex.
Se repitió la navegación real mediante `scripts/check-playwright-mcp.py` contra API de prueba y Vite: devolvió las 25 herramientas y la misma captura PNG de acceso, que se abrió e inspeccionó. Se registró de nuevo el 404 del favicon. La disponibilidad directa de las herramientas en esta sesión de agente, la extensión y Desktop permanece sin validar; el comprobador stdio y la carga de configuración del CLI son evidencias separadas.
### Verificación de acceso autenticado
Ejecutada el 21 de octubre de 2026, con Docker Engine local en WSL amd64:
- `python3 scripts/visual-audit.py --check`: login desde el formulario real, usuario ordinario, inventario, enlace a ficha, diálogo de edición y cancelación. Se generaron las cinco capturas y se comprobó la reutilización de la sesión desde otro contenedor. Se verificaron 401 sin autenticar, 403 en gestión de usuarios y logout 200 seguido de acceso protegido 401.
- `python3 scripts/visual-audit.py`: mismo recorrido en modalidad mantenida, con capturas de viewport de 1280×900 abiertas e inspeccionadas. Se verificaron permisos 0700 del directorio y 0600 de la sesión.
- El CLI 0.114.0 reconoció una sola entrada `playwright` con el montaje privado de solo lectura. Se tomó la configuración producida realmente por el lanzador y se inició con ella otro MCP: abrió el listado autenticado correctamente. Esto valida configuración y transporte; no afirma haber ejecutado una conversación interactiva nueva en Codex ni haber probado la extensión o Desktop.
- `python3 scripts/visual-audit.test.py`: seis pruebas correctas de comportamiento habitual, montaje privado, conservación de stdin, rechazo de permisos abiertos, cookies remotas, rutas externas y sesión inexistente. `bash -n`, sintaxis Python y `git diff --check`: correctos. No se ejecutaron pruebas ni compilaciones de negocio, cuyo código no se modifica.
- Al cerrar con SIGINT se detuvieron los servicios temporales, se retiró el contenedor desechable y se borraron los archivos de sesión y credenciales. Se comprobó que el contenedor MariaDB previo seguía disponible y que no quedaban contenedores `metis-visual-*`.
Las imágenes e informes están bajo el directorio local de ejecución y excluidos de Git. La prueba no guarda ediciones del activo ni repite una auditoría visual completa.