### Fase 4 — Búsqueda y Pulido Final **Estado: ⏳ Pendiente** **Duración estimada: 1 semana** **Objetivo: completar el MVP con calidad de producción.** Esta fase sigue TDD: **primero los tests, al final la verificación.** Ninguna tarea de implementación se da por hecha hasta que todos los tests pasan (`just test-all`). #### 4.0 Tests primero — escribir antes de implementar **Vitest (`packages/test-utils/tests/`):** - [ ] `search.test.ts` — S-series: - S-01: `search_in_collective(col, 'mil')` devuelve ítems con "milk" del colectivo - S-02: respeta aislamiento cross-collective (Eva no ve nada del colectivo de Ana) - S-03: excluye papelera (RN-08) — crear ítem, enviarlo a trash (o el contenedor correspondiente), verificar que no aparece en búsqueda - S-04: filtros por tipo (lista/tarea/nota), por creador, por rango de fechas **pgTAP (`supabase/tests/`):** - [ ] `007_search_tsvector.sql` — trigger de mantenimiento de `tsvector`: INSERT/UPDATE dispara la actualización de la columna; índice GIN se usa (verificar con `EXPLAIN`) - [ ] `008_rls_audit.sql` — tests exhaustivos por cada tabla y rol (admin/member/guest/non-member) × (SELECT/INSERT/UPDATE/DELETE) para todas las tablas de dominio **Playwright (`apps/web/tests/e2e/`):** - [ ] `search.test.ts` — UI: input con debounce 300ms; resultados agrupados por tipo; filtros - [ ] `profile.test.ts` — abandonar colectivo, eliminar cuenta (con confirmación) - [ ] `pwa.test.ts` — manifest.webmanifest accesible, service worker registrado tras login - [ ] `rate-limit.test.ts` — disparar más peticiones de auth que el rate limit configurado en Kong; verificar 429 **Manual / herramientas externas:** - [ ] Lighthouse PWA score ≥ 90 en mobile (ejecutar en un build de producción) - [ ] Instalable en iOS (Safari → Añadir a pantalla de inicio) y Android (Chrome → Instalar app) - [ ] Notificaciones push configuradas para iOS 16.4+ (requiere PWA instalada) - [ ] Offline completo verificado: desconectar red, operar en todos los módulos, reconectar y verificar sync #### 4.1 Búsqueda global - [ ] Función PostgreSQL `search_in_collective(collective_id, query, filters)` usando `tsvector` + `tsquery` - [ ] Columnas `tsvector` en `shopping_items`, `tasks`, `notes` con índice GIN - [ ] Trigger para mantener los vectores actualizados en cada INSERT/UPDATE - [ ] Pantalla `/search`: - Input de búsqueda con debounce 300ms - Resultados agrupados por tipo (listas, tareas, notas) - Filtros: tipo de contenido, miembro creador, rango de fechas, estado - La búsqueda no opera sobre papelera (RN-08) #### 4.2 Perfil de usuario - [ ] Pantalla `/profile`: - Editar nombre y avatar (Supabase Storage) - Lista de colectivos a los que pertenece con rol - Opción de abandonar colectivo - Eliminar cuenta (con aviso sobre promoción de admin si aplica) #### 4.3 PWA — Validación final Implementación que necesitan los tests manuales de la sección 4.0: - [ ] Configurar `manifest.webmanifest` con iconos (512, 192, 180), theme-color, display: standalone - [ ] Cambiar estrategia del Service Worker a `injectManifest` con fichero renombrado a `src/sw.ts` (ver gotcha #10 en CLAUDE.md) - [ ] Implementar notificaciones push con suscripción en el perfil #### 4.4 Seguridad y hardening - [ ] Auditoría de políticas RLS: verificar aislamiento total entre colectivos con tests de integración (test `008_rls_audit.sql` de 4.0) - [ ] Rate limiting en Kong para endpoints de auth y invitaciones - [ ] Headers de seguridad en nginx: CSP, HSTS, X-Frame-Options — gestionados externamente en la config de nginx del VPS - [ ] Rotación de `JWT_SECRET` y `ANON_KEY` para producción (no usar los valores por defecto de Supabase) - [ ] **Recordatorio:** al rotar `JWT_SECRET` hay que actualizar `root/.env` Y `apps/web/.env.development` a la vez, luego `docker compose up -d --force-recreate` + reiniciar Vite (ver `project_env_keys_trap` en la memoria) #### 4.Z Verificación final — todos los tests verdes - [ ] `just test-all` → 0 failures con los nuevos de 4.0 - [ ] Lighthouse PWA score ≥ 90 (manual) - [ ] Prueba de instalación PWA en un iPhone y un Android reales - [ ] Prueba de aislamiento RLS manual: login como Eva, intentar leer datos de otros colectivos vía curl con token — 0 filas **Criterio de aceptación:** búsqueda global por UI en < 300ms, PWA instalable y funcional offline, aislamiento RLS auditado, `just test-all` verde.