# ADR-007: Schemas de Base de Datos Sin Tablas **Estado:** Aceptado **Fecha:** 2025-11-10 **Autores:** Equipo Técnico GAMILIT **Decisores:** Tech Lead, Database Architect --- ## Contexto Durante la reorganización de la base de datos a arquitectura modular (13 schemas por dominio), se identificaron 3 schemas sin tablas propias: 1. **admin_dashboard** - 0 tablas, 4 vistas 2. **gamilit** - 0 tablas, 14 funciones 3. **storage** - 0 tablas, 1 enum Esta situación genera confusión sobre si son schemas "incompletos" o si hay una estrategia arquitectónica intencional. --- ## Decisión Se decide **mantener los 3 schemas sin tablas** por las siguientes razones estratégicas: ### 1. admin_dashboard **Estrategia:** Usar **vistas exclusivamente** sobre tablas de otros schemas. **Justificación:** - Evita duplicación de datos - Mantiene una capa de agregación separada - Facilita cambios en la estructura subyacente sin afectar dashboards - Performance adecuado con índices en tablas base **Implementación:** ```sql -- 4 vistas implementadas: - user_stats_summary (agrega datos de auth_management + gamification) - organization_stats_summary (agrega social_features + progress_tracking) - moderation_queue (agrega content_management + audit_logging) - recent_admin_actions (agrega audit_logging) ``` **Beneficio:** Separación de concerns - el schema admin_dashboard NO posee datos, solo los presenta. ### 2. gamilit **Estrategia:** Schema para **funciones utilitarias compartidas** (sin datos propios). **Justificación:** - Funciones de utilidad necesitan ubicación centralizada - No requieren tablas de estado - Se usan desde múltiples schemas - Evita duplicación de código SQL **Implementación:** ```sql -- 14 funciones utilitarias: - get_current_user_id() - get_current_user_role() - validate_email_format() - validate_username() - now_mexico() - is_admin() - audit_profile_changes() - update_updated_at_column() - etc. ``` **Beneficio:** Reutilización de lógica común sin acoplamiento de datos. ### 3. storage **Estrategia:** **Delegar completamente a Supabase Storage API**. **Justificación:** - Supabase Storage maneja buckets, objetos y metadatos internamente - No necesitamos tablas custom para storage - Reduce complejidad de mantenimiento - Aprovecha features optimizadas de Supabase (CDN, transformaciones, etc.) **Implementación:** - API: `supabase.storage.from('bucket').upload()` - Sin tablas custom - Metadata en `storage.objects` (tabla managed de Supabase) **Beneficio:** Menor superficie de mantenimiento, features enterprise incluidas. --- ## Alternativas Consideradas ### Alternativa 1: Crear Tablas en admin_dashboard **Pros:** Datos "propios" del dashboard **Cons:** Duplicación de datos, sincronización compleja, ETL necesario **Decisión:** ❌ Rechazado - vistas son suficientes ### Alternativa 2: Crear Schema functions/ en lugar de gamilit **Pros:** Nombre más explícito **Cons:** Breaking change, migraciones complejas **Decisión:** ❌ Rechazado - nombre gamilit es histórico y funcional ### Alternativa 3: Implementar Custom Storage en storage schema **Pros:** Control total sobre storage **Cons:** Reinventar la rueda, 100+ horas de desarrollo, bugs potenciales **Decisión:** ❌ Rechazado - Supabase Storage es superior --- ## Consecuencias ### Positivas ✅ **Claridad Arquitectónica:** Documentado que schemas sin tablas son intencionales ✅ **Menor Complejidad:** No duplicación de datos ✅ **Mejor Mantenimiento:** Cambios en un solo lugar ✅ **Performance:** Vistas optimizadas con índices en tablas base ✅ **Reutilización:** Funciones compartidas evitan código duplicado ### Negativas ⚠️ **Confusión Inicial:** Desarrolladores nuevos pueden pensar que están "incompletos" ⚠️ **Documentación Crítica:** Requiere ADR (este documento) para explicar estrategia ⚠️ **Dependencia de Supabase:** Storage depende 100% de servicio externo ### Mitigación - ✅ Este ADR documenta la estrategia claramente - ✅ Comentarios en DDL explican el propósito de cada schema - ✅ Inventario de base de datos (DATABASE_INVENTORY.yml) documenta el estado - ✅ Backups de Supabase Storage configurados --- ## Estado de Implementación | Schema | Tablas | Objetos | Estado | Documentado | |--------|--------|---------|--------|-------------| | **admin_dashboard** | 0 | 4 vistas | ✅ Completo | ✅ Sí | | **gamilit** | 0 | 14 funciones | ✅ Completo | ✅ Sí | | **storage** | 0 | 1 enum (legacy) | ✅ Completo | ✅ Sí | --- ## Referencias - **DDL:** `/apps/database/ddl/schemas/*/` - **Inventario:** `/docs/90-transversal/inventarios/DATABASE_INVENTORY.yml` - **ADR Relacionado:** ADR-002 (Arquitectura de Base de Datos) - **Epic:** EMR-001 (Migración a Schemas Modulares) --- ## Aprobaciones - [x] Tech Lead - [x] Database Architect - [x] Backend Lead - [x] DevOps Lead --- ## Changelog | Fecha | Versión | Cambio | |-------|---------|--------| | 2025-11-10 | 1.0 | ADR inicial - Decisión documentada | --- **Este ADR resuelve la confusión sobre schemas "vacíos" y establece que su estado actual es intencional y arquitectónicamente sound.**