test: full test suite (Vitest + pgTAP + Playwright) + TDD plan restructure
Add a 4-layer test stack covering RLS, triggers, and UI flows for Fases 0–2a, then restructure every plan file so future fases start with tests and end with a verification gate. Test suite - packages/test-utils: Vitest integration tests signing HS256 JWTs via jose so each test acts as a specific seed user (createClientAs + createAdminClient) - supabase/tests: pgTAP for accept_invitation(), item_frequency trigger, and promote-on-admin-leave; each file self-installs pgtap extension - apps/web/tests: Playwright E2E with live Keycloak login per test (storageState caching doesn't rehydrate Supabase's session state reliably) - just test-all chains the three suites; test-db forwards POSTGRES_PASSWORD as PGPASSWORD with ON_ERROR_STOP=1 so failures abort the chain Supabase auth gotcha - PostgREST queries inside onAuthStateChange deadlock on GoTrue's navigator.locks auth lock (getAccessToken → getSession → initializePromise waits on the same lock that's held during event dispatch). Fix is two defenses: a pass-through lock in $lib/supabase, and a setTimeout(0) defer in root +layout.svelte to push loadUserCollectives out of the callback's microtask chain. Either alone is insufficient; both together unblock the Playwright suite. Env key rotation - apps/web/.env.development had a stale demo anon key signed with a different secret than root .env; Vite inlined that into the browser bundle so Kong (which uses the root .env value) rejected every request with 401. Aligned the two files and added a memory entry to flag this for the next rotation. Plan restructure (TDD) - Every fase now opens with X.0 Tests primero and closes with X.Z Verificación final. Completed fases (0, 1, 2a) show the pattern retroactively with the tests that currently cover them; pending fases (2b, 3, 4) list the tests to write before implementation. Docs - CLAUDE.md status line reports 54 + 12 + 15 = 81 green tests, adds gotchas #11 (auth-lock deadlock) and #12 (no storageState caching) - README.md adds a TDD methodology section and the test-all command - .gitignore excludes Playwright's generated reports and auth state 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
### Fase 0 — Infraestructura y Entornos
|
||||
### Fase 0 — Infraestructura y Entornos ✅
|
||||
**Estado: Completa**
|
||||
**Duración estimada: 1–2 semanas**
|
||||
**Objetivo: tener los dos entornos funcionando antes de escribir producto.**
|
||||
|
||||
> **Nota sobre el patrón TDD:** desde la Fase 1 en adelante, cada fase abre con una sección `X.0 Tests primero` y cierra con `X.Z Verificación final`. La Fase 0 no sigue ese patrón porque es puro bootstrapping de infraestructura; su "test" es que `just dev` arranque la stack y `just test-all` (introducido en una fase posterior) pueda ejecutarse sin errores de conexión.
|
||||
|
||||
#### 0.1 Variables de entorno
|
||||
|
||||
Todas las variables viven en `.env.dev` (dev) y `.env.production` (prod, fuera del repo). El fichero `.env.example` documenta cada variable con su propósito.
|
||||
@@ -79,7 +82,7 @@ B2_APPLICATION_KEY=...
|
||||
|
||||
#### 0.2 Entorno de desarrollo local
|
||||
|
||||
- [ ] `docker-compose.dev.yml` con todos los servicios:
|
||||
- [x] `docker-compose.dev.yml` con todos los servicios:
|
||||
- **PostgreSQL 15** — puerto `5432`
|
||||
- **Supabase Auth (GoTrue)** — configurado con Keycloak como OIDC externo
|
||||
- **Supabase Realtime** — puerto `4000`
|
||||
@@ -87,14 +90,14 @@ B2_APPLICATION_KEY=...
|
||||
- **Kong API Gateway** — puerto `54321` (entrada principal de Supabase)
|
||||
- **Supabase Studio** — puerto `54323`
|
||||
- **Keycloak 24** — puerto `8080`, arranca con `--import-realm keycloak/realm-export.json`
|
||||
- [ ] `keycloak/realm-export.json` — realm `colectivo` preconfigurado con:
|
||||
- [x] `keycloak/realm-export.json` — realm `colectivo` preconfigurado con:
|
||||
- Client `colectivo-web` (public, PKCE habilitado, redirect URIs para dev)
|
||||
- **5 usuarios de prueba** creados y listos (ver tabla abajo)
|
||||
- Roles de realm: `app-user` (asignado a todos por defecto)
|
||||
- [ ] SvelteKit dev server en puerto `5173`, apuntando a variables de `.env.dev`
|
||||
- [ ] `supabase/seed.sql` — crea los usuarios de prueba en `auth.users` con los mismos UUIDs que Keycloak, un colectivo de ejemplo, listas e ítems
|
||||
- [ ] Generación automática de tipos TypeScript: `supabase gen types typescript`
|
||||
- [ ] `Justfile` con `just dev`, `just db-reset`, `just db-types`, `just kc-export`, `just kc-open`
|
||||
- [x] SvelteKit dev server en puerto `5173`, apuntando a variables de `.env.dev`
|
||||
- [x] `supabase/seed.sql` — crea los usuarios de prueba en `auth.users` con los mismos UUIDs que Keycloak, un colectivo de ejemplo, listas e ítems
|
||||
- [x] Generación automática de tipos TypeScript: `supabase gen types typescript`
|
||||
- [x] `Justfile` con `just dev`, `just db-reset`, `just db-types`, `just kc-export`, `just kc-open`
|
||||
|
||||
**Usuarios de prueba en Keycloak (dev):**
|
||||
|
||||
@@ -112,16 +115,16 @@ B2_APPLICATION_KEY=...
|
||||
|
||||
> **El entorno de producción ya está montado y dockerizado.** Keycloak, nginx y su PostgreSQL propio ya están operativos. Esta sección cubre únicamente lo que hay que añadir.
|
||||
|
||||
- [ ] Incorporar los servicios de Supabase al `docker-compose.prod.yml` existente:
|
||||
- [x] Incorporar los servicios de Supabase al `docker-compose.prod.yml` existente:
|
||||
- PostgreSQL dedicado para Supabase — contenedor independiente, volumen propio, **no compartir con Keycloak**
|
||||
- GoTrue (Auth), Realtime, Storage, Kong en la red interna Docker existente
|
||||
- Kong expuesto en un puerto interno (ej: `127.0.0.1:54321`) — nginx hace proxy hacia él, no expuesto directamente
|
||||
- [ ] Añadir el contenedor SvelteKit al compose, escuchando en un puerto interno (ej: `127.0.0.1:3000`) — nginx hace proxy hacia él
|
||||
- [ ] Configurar nginx externamente (fuera del repo) para los nuevos servicios — ver bloques de ejemplo abajo
|
||||
- [ ] Exportar el realm `colectivo` desde dev (`just kc-export`) e importarlo en el Keycloak de producción via Admin Console — sin `--import-realm` en prod
|
||||
- [ ] `.env.production` en el VPS con todas las variables (ver sección 0.1), fuera del repo
|
||||
- [ ] Scripts de backup — ver sección **0.6 Sistema de Backups** para el detalle completo
|
||||
- [ ] Script de deploy: `ssh vps "cd /app && git pull && docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d --no-deps web"`
|
||||
- [x] Añadir el contenedor SvelteKit al compose, escuchando en un puerto interno (ej: `127.0.0.1:3000`) — nginx hace proxy hacia él
|
||||
- [x] Configurar nginx externamente (fuera del repo) para los nuevos servicios — ver bloques de ejemplo abajo
|
||||
- [x] Exportar el realm `colectivo` desde dev (`just kc-export`) e importarlo en el Keycloak de producción via Admin Console — sin `--import-realm` en prod
|
||||
- [x] `.env.production` en el VPS con todas las variables (ver sección 0.1), fuera del repo
|
||||
- [x] Scripts de backup — ver sección **0.6 Sistema de Backups** para el detalle completo
|
||||
- [x] Script de deploy: `ssh vps "cd /app && git pull && docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d --no-deps web"`
|
||||
- `--no-deps web` para actualizar solo el contenedor SvelteKit sin reiniciar Supabase ni Keycloak
|
||||
|
||||
##### Configuración nginx de referencia
|
||||
@@ -265,15 +268,15 @@ server {
|
||||
|
||||
#### 0.4 CI/CD
|
||||
|
||||
- [ ] `ci.yml`: lint + typecheck + tests unitarios en cada PR
|
||||
- [ ] `deploy.yml`: build de imagen SvelteKit → GitHub Container Registry → deploy vía SSH en merge a `main`
|
||||
- [ ] Secrets de GitHub: `SSH_KEY`, `VPS_HOST`, `GHCR_TOKEN`
|
||||
- [x] `ci.yml`: lint + typecheck + tests unitarios en cada PR
|
||||
- [x] `deploy.yml`: build de imagen SvelteKit → GitHub Container Registry → deploy vía SSH en merge a `main`
|
||||
- [x] Secrets de GitHub: `SSH_KEY`, `VPS_HOST`, `GHCR_TOKEN`
|
||||
|
||||
#### 0.5 Monorepo
|
||||
|
||||
- [ ] Turborepo configurado con pipeline `build → test → deploy`
|
||||
- [ ] `packages/types` como paquete interno
|
||||
- [ ] `apps/web` consumiendo `packages/types`
|
||||
- [x] Turborepo configurado con pipeline `build → test → deploy`
|
||||
- [x] `packages/types` como paquete interno
|
||||
- [x] `apps/web` consumiendo `packages/types`
|
||||
|
||||
#### 0.6 Sistema de Backups
|
||||
|
||||
@@ -359,13 +362,13 @@ Un solo entry en cron. El script decide internamente si es daily, weekly o month
|
||||
|
||||
##### Tareas de la Fase 0
|
||||
|
||||
- [ ] Crear volumen Docker (o directorio montado) en `BACKUP_LOCAL_DIR` con permisos correctos
|
||||
- [ ] Implementar `backup.sh` con soporte para supabase y keycloak, compresión y subida opcional a B2
|
||||
- [ ] Implementar `backup-cron.sh` con lógica de rotación y purga por tipo
|
||||
- [ ] Implementar `restore.sh` con confirmación, parada de servicios y resumen post-restauración
|
||||
- [ ] Configurar crontab en el host del VPS
|
||||
- [ ] Verificar backup completo: ejecutar `backup.sh supabase`, comprobar fichero generado, ejecutar `restore.sh` en un entorno de prueba
|
||||
- [ ] Verificar purga: crear backups de prueba con fechas antiguas, ejecutar `backup-cron.sh`, confirmar que se eliminan los que exceden la retención
|
||||
- [x] Crear volumen Docker (o directorio montado) en `BACKUP_LOCAL_DIR` con permisos correctos
|
||||
- [x] Implementar `backup.sh` con soporte para supabase y keycloak, compresión y subida opcional a B2
|
||||
- [x] Implementar `backup-cron.sh` con lógica de rotación y purga por tipo
|
||||
- [x] Implementar `restore.sh` con confirmación, parada de servicios y resumen post-restauración
|
||||
- [x] Configurar crontab en el host del VPS
|
||||
- [x] Verificar backup completo: ejecutar `backup.sh supabase`, comprobar fichero generado, ejecutar `restore.sh` en un entorno de prueba
|
||||
- [x] Verificar purga: crear backups de prueba con fechas antiguas, ejecutar `backup-cron.sh`, confirmar que se eliminan los que exceden la retención
|
||||
|
||||
**Criterio de aceptación:** `just dev` levanta todo el stack en < 3 minutos. Los 5 usuarios de prueba pueden hacer login con Keycloak y llegar a la app. Deploy a producción funciona con un `git push`. Un backup manual de supabase y keycloak genera ficheros válidos que se restauran correctamente.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user