Ambas funciones deployadas al proyecto inq-roi-desa (xgqbkxcliyjzisoccsur).
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled

This commit is contained in:
2026-07-07 11:02:27 -03:00
parent 6be9f6267f
commit 074f726d62
12 changed files with 142 additions and 29 deletions

View File

@@ -323,3 +323,66 @@ Sprint orientado a "client-readiness": cerrar los dos gaps que impedían usar In
**Sprint 7 abierto:** multi-usuario y acceso de clientes. Modelo de 4 roles (`platform_admin`, `member`, `client_editor`, `client_viewer`). Patrón de InQ Sizing (documento de referencia: `cowork/InQ ROI - Simulador de procesos/autenticacion-y-usuarios.md`). InQuality como organización administradora de la plataforma.
**Cerrado:** 2026-06-24.
---
## Reflexiones del cierre de Sprint 7
> Agregado el 2026-07-06 al cerrar formalmente el sprint.
### Decisión estratégica
Sprint de mayor escala arquitectónica desde Sprint 4 (refactorización Dexie→Supabase). Sprint 7 abrió el producto a usuarios externos con control de acceso real: tabla `organizations`, 4 roles de plataforma, Edge Functions de invitación, panel de administración de InQuality, y ajustes de UX para cada rol. La fundación de multi-tenancy está operativa.
### Resultado
**Etapa 1 (DB):** migración 014 — tabla `organizations`, `org_id` en `users` y `processes`, constraint de roles ampliado (platform_admin, member, client_editor, client_viewer, guest). Migración 015 — SECURITY DEFINER helpers (`current_org()`, `is_inquality()`, `current_platform_role()`), trigger `handle_new_user`, RLS completa con 4 roles en 7 tablas.
**Etapa 2 (Edge Functions):** `invite-user` (invita via Supabase Auth Admin API + UPSERT en public.users) y `revoke-user` (baja a 'guest', suspensión suave). Diseño simplificado respecto al BRIEF: 2 funciones en lugar de 3 separadas (create/suspend/delete). Limitación documentada: "eliminar" es soft (baja a guest), hard delete queda para sprint futuro.
**Etapa 3 (Auth layer):** fix crítico — `syncProfileFromDB` ahora lee `platform_role` y `org_id` desde DB en lugar de inferir del email. `AuthUser` extendido con `orgId`. Login email/password. Página `/reset-password` para flujo de invite. Guard `TOKEN_REFRESHED` en `onAuthStateChange`. 558 tests.
**Etapa 4 (Admin UI):** panel `/admin` con guard `platform_admin`, páginas de Organizations y Users con CRUD completo, invitación de usuarios via Edge Function, suspensión/reactivación, badges de rol, skeletons, alertdialogs para acciones destructivas, ícono Shield en AppHeader. 558 tests.
**Etapa 5 (Client UX):** routing por rol — `client_viewer` redirigido desde workspace al reporte, `client_editor` bloqueado de importar BPMNs. Library con lista plana para clientes (sin panel de grupos). Reporte abre en tab ROI para `client_viewer`. Fix bug: `normalizeGroupLabel()` limpia artículos iniciales del label de grupos (dato corrupto en Supabase). 578 tests.
### Decisiones arquitectónicas tomadas en el sprint
| Decisión | Estado al cierre |
|---|---|
| Estrategia de migración: Opción A (auto-crear orgs desde `processes.client`) | Definitiva — migración 014 aplicada |
| Trigger `handle_new_user`: rol `member` por defecto (no `platform_admin`) | Definitiva — confirmada por director |
| UPSERT en Edge Function invite-user (race condition handle_new_user) | Definitiva — patrón de InQ Sizing |
| "Eliminar" usuario como soft delete (baja a 'guest') | Provisional — hard delete en sprint futuro |
| "Reactivar" restaura a 'client_editor' por defecto | Provisional — limitación documentada |
### Patrón recurrente identificado: guards de rol via `useEffect`
En tres etapas (AdminLayout, WorkspacePage, ImportPage), Claude Code implementó guards de rol como efectos de componente en lugar de `beforeLoad` de TanStack Router. El patrón es funcional (RLS garantiza seguridad de datos) pero subóptimo para TanStack Router, que provee `beforeLoad` precisamente para evitar que rutas protegidas monten. Este patrón surgió como heurística del agente cuando el guard se especificó en la descripción del comportamiento en lugar de en la spec de la ruta. **Aprendizaje para Sprint 8+:** especificar guards siempre en la sección de router con el código exacto de `beforeLoad`.
### Lo que funcionó bien
**La auditoría previa de policy names por parte de Claude Code (Etapa 1).** Antes de escribir los DROP POLICY, Claude Code leyó las migraciones 001-013 y reportó los nombres exactos con discrepancias respecto al brief. Sin esta auditoría, `"all_activity_resource_assignments"` habría dejado la policy permisiva original activa. Este comportamiento proactivo de verificación debería solicitarse explícitamente en futuros prompts de migración RLS.
**El flujo de validación con cambio temporal de rol en Supabase Studio.** El director pudo validar el comportamiento de `client_editor` y `client_viewer` sin necesidad de crear usuarios reales de prueba, editando su propio `platform_role` temporalmente. Técnica útil para validación rápida pre-onboarding de clientes reales.
**La normalización de datos en capa de repositorio.** `normalizeGroupLabel()` en `settings-repo.ts` resolvió un dato corrupto en Supabase sin migración ni intervención manual — limpieza transparente al leer/escribir. Patrón replicable para otros datos con formato variable en la DB.
### Estado del producto al cierre de Sprint 7
- Auth completo con 4 roles, organizaciones, y panel de administración operativo
- Primer acceso de cliente posible: invitación → magic link → set password → library filtrada por org → workspace (editor) o reporte (viewer)
- Datos: 578 tests Vitest, build limpio
- Deuda técnica identificada: 2 ítems (guards via useEffect × 3 componentes, doble suscripción onAuthStateChange)
- Backlog identificado: 1 ítem (Settings accesible para roles de cliente)
### Próxima revisión — Sprint 8
**Prioridades candidatas (sin decisión tomada aún):**
- Primer onboarding real de cliente (Banco Solar) — smoke test end-to-end del flujo de invite
- Hard delete de usuarios (Edge Function `delete-user`)
- Migrar guards de rol a `beforeLoad` de TanStack Router
- Email visible en panel admin (requiere join con `auth.users` via service_role)
- Historial de simulaciones (diferido desde Sprint 3)
**Cerrado:** 2026-07-06.