This commit is contained in:
205
sprints/sprint-8/ETAPA_1_PROMPT.md
Normal file
205
sprints/sprint-8/ETAPA_1_PROMPT.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# Sprint 8 — Etapa 1: Migración DB (aditiva)
|
||||
|
||||
> **Tipo:** Base de datos — migración aditiva
|
||||
> **Rama:** main
|
||||
> **Estimación:** 1-2 horas
|
||||
> **Dependencias:** Etapa 0 completada ✅
|
||||
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Crear la infraestructura de datos para el modelo `organizations → areas → processes` sin romper nada de lo que ya funciona. Esta migración es **completamente aditiva**: crea lo nuevo, no elimina lo viejo. Las columnas `client` y `group_id` de `processes`, y la tabla `process_groups`, se eliminan en una migration de limpieza posterior (después de que Etapas 3-4 migren la UI).
|
||||
|
||||
---
|
||||
|
||||
## Contexto del schema actual
|
||||
|
||||
Leer las migraciones en `supabase/migrations/` antes de escribir cualquier SQL. Schema relevante al momento de esta etapa:
|
||||
|
||||
**`processes` — columnas existentes relevantes:**
|
||||
- `client text NOT NULL DEFAULT ''` — el campo libre "clientName" (se elimina más adelante)
|
||||
- `group_id uuid REFERENCES public.process_groups(id) ON DELETE SET NULL` — agrupador viejo (se elimina más adelante)
|
||||
- `org_id uuid REFERENCES public.organizations(id) ON DELETE SET NULL` — ← este es el correcto, agregado en migración 014
|
||||
|
||||
**`process_groups` — tabla existente:**
|
||||
- `id, name, created_by, created_at, updated_at` — no tiene FKs entrantes salvo `processes.group_id`
|
||||
|
||||
**`organizations` — tabla existente desde migración 014:**
|
||||
- InQuality existe con `is_provider = true`
|
||||
- Otras orgs creadas automáticamente desde `processes.client` en la migración 014
|
||||
|
||||
**Funciones SECURITY DEFINER disponibles (migración 015):**
|
||||
- `public.is_inquality()` → true si el usuario pertenece a InQuality
|
||||
- `public.current_org()` → org_id del usuario actual
|
||||
- `public.current_platform_role()` → rol del usuario actual
|
||||
- `public.is_platform_admin()` → true si es platform_admin
|
||||
|
||||
---
|
||||
|
||||
## Alcance estricto — Migration 017
|
||||
|
||||
Crear el archivo `supabase/migrations/017_create_areas.sql`.
|
||||
|
||||
### Paso 1: Crear tabla `areas`
|
||||
|
||||
```sql
|
||||
-- Nueva tabla areas: reemplazará process_groups como agrupador normalizado por org
|
||||
CREATE TABLE IF NOT EXISTS public.areas (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
org_id uuid NOT NULL REFERENCES public.organizations(id) ON DELETE CASCADE,
|
||||
name text NOT NULL,
|
||||
description text,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
ALTER TABLE public.areas ENABLE ROW LEVEL SECURITY;
|
||||
```
|
||||
|
||||
### Paso 2: Agregar `area_id` a `processes`
|
||||
|
||||
```sql
|
||||
-- area_id reemplazará group_id como agrupador normalizado dentro de una org
|
||||
-- Nullable: procesos sin área asignada son válidos ("Sin área")
|
||||
ALTER TABLE public.processes
|
||||
ADD COLUMN IF NOT EXISTS area_id uuid REFERENCES public.areas(id) ON DELETE SET NULL;
|
||||
```
|
||||
|
||||
### Paso 3: RLS para `areas`
|
||||
|
||||
```sql
|
||||
-- SELECT: InQuality ve todas las áreas; cliente ve solo las de su org
|
||||
CREATE POLICY "areas_select" ON public.areas
|
||||
FOR SELECT USING (
|
||||
public.is_inquality()
|
||||
OR org_id = public.current_org()
|
||||
);
|
||||
|
||||
-- INSERT / UPDATE / DELETE: solo platform_admin
|
||||
CREATE POLICY "areas_insert" ON public.areas
|
||||
FOR INSERT WITH CHECK (
|
||||
public.current_platform_role() = 'platform_admin'
|
||||
);
|
||||
|
||||
CREATE POLICY "areas_update" ON public.areas
|
||||
FOR UPDATE USING (
|
||||
public.current_platform_role() = 'platform_admin'
|
||||
);
|
||||
|
||||
CREATE POLICY "areas_delete" ON public.areas
|
||||
FOR DELETE USING (
|
||||
public.current_platform_role() = 'platform_admin'
|
||||
);
|
||||
```
|
||||
|
||||
### Paso 4: Migración de datos — asignar procesos sin org a InQuality
|
||||
|
||||
```sql
|
||||
-- Procesos sin org_id son datos de prueba de InQuality.
|
||||
-- Asignarlos a la org de InQuality (is_provider = true) para limpiar los NULLs.
|
||||
UPDATE public.processes
|
||||
SET org_id = (
|
||||
SELECT id FROM public.organizations WHERE is_provider = true LIMIT 1
|
||||
)
|
||||
WHERE org_id IS NULL;
|
||||
```
|
||||
|
||||
### Lo que esta migración NO hace (intencional)
|
||||
|
||||
```
|
||||
❌ NO dropea la columna `client` de processes
|
||||
❌ NO dropea la columna `group_id` de processes
|
||||
❌ NO dropea la tabla `process_groups`
|
||||
❌ NO modifica ninguna política RLS existente
|
||||
```
|
||||
|
||||
Estas eliminaciones ocurren en una migration posterior, después de que la UI deje de usar esas columnas.
|
||||
|
||||
---
|
||||
|
||||
## Verificación post-migración
|
||||
|
||||
Después de aplicar la migración en Supabase (SQL Editor o `supabase db push`), verificar con estas queries:
|
||||
|
||||
```sql
|
||||
-- 1. Verificar que la tabla areas existe con RLS activa
|
||||
SELECT schemaname, tablename, rowsecurity
|
||||
FROM pg_tables
|
||||
WHERE schemaname = 'public' AND tablename = 'areas';
|
||||
-- Esperado: rowsecurity = true
|
||||
|
||||
-- 2. Verificar columna area_id en processes
|
||||
SELECT column_name, data_type, is_nullable
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'processes'
|
||||
AND column_name = 'area_id';
|
||||
-- Esperado: una fila, data_type = 'uuid', is_nullable = 'YES'
|
||||
|
||||
-- 3. Verificar que no quedan procesos sin org_id
|
||||
SELECT COUNT(*) as sin_org FROM public.processes WHERE org_id IS NULL;
|
||||
-- Esperado: 0
|
||||
|
||||
-- 4. Verificar políticas de areas
|
||||
SELECT policyname, cmd FROM pg_policies
|
||||
WHERE schemaname = 'public' AND tablename = 'areas';
|
||||
-- Esperado: 4 políticas (areas_select, areas_insert, areas_update, areas_delete)
|
||||
|
||||
-- 5. Verificar que process_groups sigue existiendo (no se eliminó)
|
||||
SELECT table_name FROM information_schema.tables
|
||||
WHERE table_schema = 'public' AND table_name = 'process_groups';
|
||||
-- Esperado: 1 fila (la tabla sigue ahí — se elimina más adelante)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Criterios de validación
|
||||
|
||||
- [ ] Archivo `supabase/migrations/017_create_areas.sql` creado
|
||||
- [ ] Migración aplicada en Supabase (reportar resultado del SQL Editor o `supabase db push`)
|
||||
- [ ] Las 5 queries de verificación retornan los valores esperados
|
||||
- [ ] `npm run build` sin errores (no hay cambios en TypeScript — build debe ser idéntico al de Etapa 0)
|
||||
- [ ] `npm run test` sin regresiones (592 tests, sin cambios)
|
||||
- [ ] `process_groups` sigue existiendo en la DB (verificar con query 5)
|
||||
|
||||
---
|
||||
|
||||
## Restricciones explícitas
|
||||
|
||||
- **NO** modificar ningún archivo TypeScript en esta etapa — solo SQL
|
||||
- **NO** dropear `process_groups`, `client`, ni `group_id` — eso viene después
|
||||
- **NO** tocar las políticas RLS existentes en `processes`, `organizations`, ni otras tablas
|
||||
- **NO** crear datos de prueba en `areas` — la tabla arranca vacía
|
||||
|
||||
---
|
||||
|
||||
## Archivos autorizados a modificar/crear
|
||||
|
||||
```
|
||||
simulador-web/
|
||||
└── supabase/
|
||||
└── migrations/
|
||||
└── 017_create_areas.sql ← único archivo a crear
|
||||
```
|
||||
|
||||
Ningún archivo TypeScript debe cambiar en esta etapa.
|
||||
|
||||
---
|
||||
|
||||
## Commit esperado
|
||||
|
||||
```
|
||||
feat(db): migración 017 — tabla areas, area_id en processes, RLS, bulk-assign org
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Reporte esperado
|
||||
|
||||
Al finalizar, reportar:
|
||||
1. Contenido exacto del archivo `017_create_areas.sql`
|
||||
2. Resultado de aplicar la migración (output de Supabase)
|
||||
3. Resultado de las 5 queries de verificación (con los valores reales)
|
||||
4. Resultado de `npm run build` y `npm run test`
|
||||
5. Confirmar que `process_groups` sigue existiendo (query 5)
|
||||
Reference in New Issue
Block a user