# DATABASE_INVENTORY.yml - ERP Core # Inventario canonico de objetos de base de datos # Ubicacion Canonica: orchestration/inventarios/ # Ultima actualizacion: 2026-01-07 version: "3.0" project: erp-core updated_at: "2026-01-07" updated_by: Backend-Agent (Sprint 6-7) # ============================================================================= # CONFIGURACION DE MOTOR # ============================================================================= engine: name: PostgreSQL version: "15+" extensions: - name: uuid-ossp purpose: Generacion de UUIDs - name: pg_trgm purpose: Busqueda fuzzy por trigram - name: btree_gist purpose: Indices GiST para exclusion - name: pgcrypto purpose: Funciones criptograficas # ============================================================================= # RESUMEN # ============================================================================= summary: total_schemas: 14 total_tables: 191 total_tables_base: 118 total_tables_extensions: 73 total_functions: 70 total_triggers: 100 total_rls_policies: 102 total_ddl_files: 20 implemented_extensions: 6 documented: 30 # ============================================================================= # POLITICA DE CARGA LIMPIA # ============================================================================= clean_load_policy: directiva: "core/orchestration/directivas/legacy/DIRECTIVA-POLITICA-CARGA-LIMPIA.md" principio: "DDL-First - Los archivos DDL son la fuente de verdad" prohibiciones: - "Ejecutar ALTER TABLE directo en BD sin actualizar DDL" - "Crear carpeta migrations/" - "Crear archivos fix-*.sql, patch-*.sql, hotfix-*.sql" - "Dejar BD y DDL desincronizados" paths: db_ddl_path: "database/ddl" db_scripts_path: "database/scripts" db_seeds_path: "database/seeds" db_name: "erp_generic" comandos: crear: "./scripts/create-database.sh" recrear: "./scripts/reset-database.sh" eliminar: "./scripts/drop-database.sh" seeds_dev: "./scripts/load-seeds.sh dev" seeds_prod: "./scripts/load-seeds.sh prod" # ============================================================================= # ARCHIVOS DDL IMPLEMENTADOS # ============================================================================= ddl_files: orden_ejecucion: 1: "00-prerequisites.sql" 2: "01-auth.sql" 3: "01-auth-extensions.sql" 4: "01-auth-mfa-email-verification.sql" 5: "02-core.sql" 6: "02-core-extensions.sql" 7: "03-analytics.sql" 8: "04-financial.sql" 9: "05-inventory.sql" 10: "05-inventory-extensions.sql" 11: "06-purchase.sql" 12: "07-sales.sql" 13: "08-projects.sql" 14: "09-system.sql" 15: "09-system-extensions.sql" 16: "10-billing.sql" 17: "11-crm.sql" 18: "12-hr.sql" 19: "13-audit.sql" 20: "14-reports.sql" extensiones_nuevas: - archivo: "01-auth-extensions.sql" fecha: "2025-12-08" estado: IMPLEMENTADO specs: - SPEC-TWO-FACTOR-AUTHENTICATION.md - SPEC-SEGURIDAD-API-KEYS-PERMISOS.md - SPEC-OAUTH2-SOCIAL-LOGIN.md tablas: 16 funciones: 6 vistas: 2 triggers: 3 detalle: groups_herencia: [auth.groups, auth.group_implied, auth.user_groups] acl: [auth.models, auth.model_access, auth.record_rules, auth.rule_groups, auth.model_fields, auth.field_permissions] api_keys: [auth.api_keys] two_factor: [auth.trusted_devices, auth.verification_codes, auth.mfa_audit_log] oauth2: [auth.oauth_providers, auth.oauth_user_links, auth.oauth_states] - archivo: "05-inventory-extensions.sql" fecha: "2025-12-08" estado: IMPLEMENTADO specs: - SPEC-VALORACION-INVENTARIO.md - SPEC-TRAZABILIDAD-LOTES-SERIES.md - SPEC-INVENTARIOS-CICLICOS.md tablas: 10 funciones: 7 vistas: 3 triggers: 4 detalle: valoracion_svl: [inventory.stock_valuation_layers, inventory.category_stock_accounts, inventory.valuation_settings] lotes_series: [inventory.lots, inventory.move_line_consume_rel, inventory.removal_strategies] conteos_ciclicos: [inventory.inventory_count_sessions, inventory.inventory_count_lines, inventory.abc_classification_rules, inventory.product_abc_classification] - archivo: "01-auth-mfa-email-verification.sql" fecha: "2026-01-07" estado: IMPLEMENTADO sprint: 5 specs: - Sprint 5: MFA Implementation - Sprint 5: Email Verification Flow tablas: 2 detalle: mfa: [auth.user_mfa_secrets] email_verification: [auth.email_verification_tokens] - archivo: "02-core-extensions.sql" fecha: "2026-01-07" estado: IMPLEMENTADO sprint: 6 specs: - BE-013: Currency Exchange Rates tablas: 1 detalle: currency: [core.currency_rates] - archivo: "09-system-extensions.sql" fecha: "2026-01-07" estado: IMPLEMENTADO sprint: 6 specs: - BE-016: Settings Service 3-Level tablas: 3 funciones: 1 triggers: 3 detalle: settings: [system.system_settings, tenants.tenant_settings, auth.user_preferences] caracteristicas: - Cascada 3 niveles (User -> Tenant -> System) - RLS Policies por tenant y usuario - Seed data con configuraciones base - archivo: "13-audit.sql" fecha: "2026-01-07" estado: IMPLEMENTADO sprint: 7 specs: - BE-017: Audit Trail - BE-018: Access Logs - BE-019: Security Events tablas: 3 funciones: 3 detalle: audit: [audit.audit_logs, audit.access_logs, audit.security_events] enums: - audit.audit_action (INSERT, UPDATE, DELETE) - audit.access_event_type (LOGIN_SUCCESS, LOGIN_FAILED, LOGOUT, etc) - audit.security_severity (LOW, MEDIUM, HIGH, CRITICAL) caracteristicas: - Funciones de limpieza automatica - Indices optimizados para consultas - Partial indexes para filtros comunes - archivo: "14-reports.sql" fecha: "2026-01-07" estado: IMPLEMENTADO sprint: 8 specs: - RF-REPORT-001: Reportes Predefinidos - RF-REPORT-002: Dashboards - RF-REPORT-003: Report Builder - RF-REPORT-004: Reportes Programados - BE-021: DashboardsService - BE-022: WidgetsService - BE-023: ExportService tablas: 12 funciones: 0 detalle: reportes: [reports.report_definitions, reports.report_executions, reports.report_schedules, reports.report_recipients, reports.schedule_executions, reports.custom_reports] dashboards: [reports.dashboards, reports.dashboard_widgets, reports.widget_queries] data_model: [reports.data_model_entities, reports.data_model_fields, reports.data_model_relationships] enums: - reports.report_type (financial, accounting, tax, management, operational, custom) - reports.execution_status (pending, running, completed, failed, cancelled) - reports.export_format (pdf, xlsx, csv, json, html) - reports.delivery_method (none, email, storage, webhook) - reports.widget_type (15 tipos) - reports.param_type (string, number, date, etc) - reports.filter_operator (eq, ne, gt, gte, lt, lte, like, in, etc) caracteristicas: - RLS policies para aislamiento multi-tenant - 15 tipos de widgets soportados - Soporte para reportes programados con cron - Data model para Report Builder visual # ============================================================================= # SCHEMAS # ============================================================================= schemas: # --------------------------------------------------------------------------- # CORE_AUTH - Autenticacion # --------------------------------------------------------------------------- - name: core_auth description: Autenticacion, sesiones y tokens module: MGN-001 rf: [RF-AUTH-001, RF-AUTH-002, RF-AUTH-003, RF-AUTH-004] status: documented ddl_file: apps/database/ddl/schemas/core_auth/ tables: - name: users_auth description: Credenciales de autenticacion rf: RF-AUTH-001 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID, fk: core_tenants.tenants.id} - {name: user_id, type: UUID, fk: core_users.users.id} - {name: email, type: VARCHAR(255), unique: true} - {name: password_hash, type: VARCHAR(255)} - {name: is_active, type: BOOLEAN, default: true} - {name: email_verified_at, type: TIMESTAMPTZ} - {name: last_login_at, type: TIMESTAMPTZ} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - {name: updated_at, type: TIMESTAMPTZ, default: NOW()} indexes: - {name: idx_users_auth_email, columns: [email], unique: true} - {name: idx_users_auth_tenant, columns: [tenant_id]} rls_policies: - {name: tenant_isolation, using: "tenant_id = current_setting('app.current_tenant_id')::uuid"} - name: sessions description: Sesiones activas rf: RF-AUTH-002 columns: - {name: id, type: UUID, pk: true} - {name: user_id, type: UUID, fk: users_auth.id} - {name: token_hash, type: VARCHAR(255)} - {name: ip_address, type: INET} - {name: user_agent, type: TEXT} - {name: expires_at, type: TIMESTAMPTZ} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} indexes: - {name: idx_sessions_user, columns: [user_id]} - {name: idx_sessions_expires, columns: [expires_at]} - name: refresh_tokens description: Tokens de refresco JWT rf: RF-AUTH-002 columns: - {name: id, type: UUID, pk: true} - {name: user_id, type: UUID, fk: users_auth.id} - {name: token_hash, type: VARCHAR(255)} - {name: expires_at, type: TIMESTAMPTZ} - {name: revoked_at, type: TIMESTAMPTZ} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} indexes: - {name: idx_refresh_tokens_user, columns: [user_id]} - name: password_resets description: Tokens de recuperacion de password rf: RF-AUTH-003 columns: - {name: id, type: UUID, pk: true} - {name: user_id, type: UUID, fk: users_auth.id} - {name: token_hash, type: VARCHAR(255)} - {name: expires_at, type: TIMESTAMPTZ} - {name: used_at, type: TIMESTAMPTZ} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - name: login_attempts description: Intentos de login fallidos (brute force protection) rf: RF-AUTH-004 columns: - {name: id, type: UUID, pk: true} - {name: email, type: VARCHAR(255)} - {name: ip_address, type: INET} - {name: attempted_at, type: TIMESTAMPTZ, default: NOW()} - {name: success, type: BOOLEAN} indexes: - {name: idx_login_attempts_email, columns: [email]} - {name: idx_login_attempts_ip, columns: [ip_address]} - name: oauth_accounts description: Cuentas OAuth vinculadas rf: RF-AUTH-005 columns: - {name: id, type: UUID, pk: true} - {name: user_id, type: UUID, fk: users_auth.id} - {name: provider, type: VARCHAR(50)} - {name: provider_user_id, type: VARCHAR(255)} - {name: access_token, type: TEXT} - {name: refresh_token, type: TEXT} - {name: expires_at, type: TIMESTAMPTZ} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} indexes: - {name: idx_oauth_provider_user, columns: [provider, provider_user_id], unique: true} functions: - name: validate_password params: [user_id UUID, password TEXT] returns: BOOLEAN rf: RF-AUTH-001 description: Valida password contra hash - name: cleanup_expired_sessions params: [] returns: INTEGER rf: RF-AUTH-002 description: Elimina sesiones expiradas triggers: - name: trg_update_users_auth_timestamp table: users_auth event: BEFORE UPDATE function: update_updated_at() # --------------------------------------------------------------------------- # CORE_USERS - Usuarios # --------------------------------------------------------------------------- - name: core_users description: Gestion de usuarios y perfiles module: MGN-002 rf: [RF-USERS-001, RF-USERS-002, RF-USERS-003] status: documented ddl_file: apps/database/ddl/schemas/core_users/ tables: - name: users description: Usuarios del sistema rf: RF-USERS-001 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID, fk: core_tenants.tenants.id} - {name: first_name, type: VARCHAR(100)} - {name: last_name, type: VARCHAR(100)} - {name: display_name, type: VARCHAR(200)} - {name: avatar_url, type: TEXT} - {name: phone, type: VARCHAR(20)} - {name: timezone, type: VARCHAR(50), default: "'UTC'"} - {name: locale, type: VARCHAR(10), default: "'es-MX'"} - {name: is_active, type: BOOLEAN, default: true} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - {name: updated_at, type: TIMESTAMPTZ, default: NOW()} - {name: deleted_at, type: TIMESTAMPTZ} indexes: - {name: idx_users_tenant, columns: [tenant_id]} - {name: idx_users_name_search, columns: [first_name, last_name], type: gin_trgm} rls_policies: - {name: tenant_isolation, using: "tenant_id = current_setting('app.current_tenant_id')::uuid"} - name: user_profiles description: Perfil extendido de usuarios rf: RF-USERS-002 columns: - {name: id, type: UUID, pk: true} - {name: user_id, type: UUID, fk: users.id, unique: true} - {name: bio, type: TEXT} - {name: company, type: VARCHAR(200)} - {name: job_title, type: VARCHAR(100)} - {name: address, type: JSONB} - {name: social_links, type: JSONB} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - {name: updated_at, type: TIMESTAMPTZ, default: NOW()} - name: user_preferences description: Preferencias de usuario rf: RF-USERS-003 columns: - {name: id, type: UUID, pk: true} - {name: user_id, type: UUID, fk: users.id, unique: true} - {name: theme, type: VARCHAR(20), default: "'light'"} - {name: notifications_email, type: BOOLEAN, default: true} - {name: notifications_push, type: BOOLEAN, default: true} - {name: language, type: VARCHAR(10), default: "'es'"} - {name: date_format, type: VARCHAR(20), default: "'DD/MM/YYYY'"} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - {name: updated_at, type: TIMESTAMPTZ, default: NOW()} # --------------------------------------------------------------------------- # CORE_RBAC - Roles y Permisos # --------------------------------------------------------------------------- - name: core_rbac description: Control de acceso basado en roles module: MGN-003 rf: [RF-RBAC-001, RF-RBAC-002, RF-RBAC-003] status: documented ddl_file: apps/database/ddl/schemas/core_rbac/ tables: - name: roles description: Definicion de roles rf: RF-RBAC-001 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID, fk: core_tenants.tenants.id} - {name: name, type: VARCHAR(100)} - {name: slug, type: VARCHAR(100)} - {name: description, type: TEXT} - {name: is_system, type: BOOLEAN, default: false} - {name: is_active, type: BOOLEAN, default: true} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - {name: updated_at, type: TIMESTAMPTZ, default: NOW()} indexes: - {name: idx_roles_tenant_slug, columns: [tenant_id, slug], unique: true} rls_policies: - {name: tenant_isolation, using: "tenant_id = current_setting('app.current_tenant_id')::uuid"} - name: permissions description: Definicion de permisos rf: RF-RBAC-002 columns: - {name: id, type: UUID, pk: true} - {name: module, type: VARCHAR(50)} - {name: action, type: VARCHAR(50)} - {name: resource, type: VARCHAR(100)} - {name: description, type: TEXT} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} indexes: - {name: idx_permissions_module_action, columns: [module, action, resource], unique: true} - name: role_permissions description: Asignacion permisos a roles rf: RF-RBAC-002 columns: - {name: role_id, type: UUID, fk: roles.id} - {name: permission_id, type: UUID, fk: permissions.id} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} constraints: - {type: pk, columns: [role_id, permission_id]} - name: user_roles description: Asignacion roles a usuarios rf: RF-RBAC-003 columns: - {name: user_id, type: UUID, fk: core_users.users.id} - {name: role_id, type: UUID, fk: roles.id} - {name: assigned_at, type: TIMESTAMPTZ, default: NOW()} - {name: assigned_by, type: UUID, fk: core_users.users.id} constraints: - {type: pk, columns: [user_id, role_id]} functions: - name: user_has_permission params: [p_user_id UUID, p_module VARCHAR, p_action VARCHAR, p_resource VARCHAR] returns: BOOLEAN rf: RF-RBAC-002 description: Verifica si usuario tiene permiso especifico - name: get_user_permissions params: [p_user_id UUID] returns: TABLE rf: RF-RBAC-002 description: Retorna todos los permisos del usuario # --------------------------------------------------------------------------- # CORE_TENANTS - Multi-tenancy # --------------------------------------------------------------------------- - name: core_tenants description: Gestion multi-tenant module: MGN-004 rf: [RF-TENANTS-001, RF-TENANTS-002, RF-TENANTS-003] status: documented ddl_file: apps/database/ddl/schemas/core_tenants/ tables: - name: tenants description: Organizaciones/empresas rf: RF-TENANTS-001 columns: - {name: id, type: UUID, pk: true} - {name: name, type: VARCHAR(200)} - {name: slug, type: VARCHAR(100), unique: true} - {name: domain, type: VARCHAR(255)} - {name: logo_url, type: TEXT} - {name: settings, type: JSONB, default: "'{}'"} - {name: is_active, type: BOOLEAN, default: true} - {name: trial_ends_at, type: TIMESTAMPTZ} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - {name: updated_at, type: TIMESTAMPTZ, default: NOW()} - {name: deleted_at, type: TIMESTAMPTZ} indexes: - {name: idx_tenants_slug, columns: [slug], unique: true} - {name: idx_tenants_domain, columns: [domain]} - name: tenant_settings description: Configuracion por tenant rf: RF-TENANTS-002 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID, fk: tenants.id, unique: true} - {name: currency, type: VARCHAR(3), default: "'MXN'"} - {name: timezone, type: VARCHAR(50), default: "'America/Mexico_City'"} - {name: date_format, type: VARCHAR(20), default: "'DD/MM/YYYY'"} - {name: fiscal_config, type: JSONB} - {name: modules_enabled, type: JSONB} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - {name: updated_at, type: TIMESTAMPTZ, default: NOW()} - name: plans description: Planes de suscripcion rf: RF-TENANTS-003 columns: - {name: id, type: UUID, pk: true} - {name: name, type: VARCHAR(100)} - {name: slug, type: VARCHAR(50), unique: true} - {name: description, type: TEXT} - {name: price_monthly, type: DECIMAL(10,2)} - {name: price_yearly, type: DECIMAL(10,2)} - {name: features, type: JSONB} - {name: limits, type: JSONB} - {name: is_active, type: BOOLEAN, default: true} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - name: subscriptions description: Suscripciones de tenants rf: RF-TENANTS-003 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID, fk: tenants.id} - {name: plan_id, type: UUID, fk: plans.id} - {name: status, type: VARCHAR(20)} - {name: starts_at, type: TIMESTAMPTZ} - {name: ends_at, type: TIMESTAMPTZ} - {name: canceled_at, type: TIMESTAMPTZ} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} indexes: - {name: idx_subscriptions_tenant, columns: [tenant_id]} - {name: idx_subscriptions_status, columns: [status]} # --------------------------------------------------------------------------- # CORE_CATALOGS - Catalogos Maestros # --------------------------------------------------------------------------- - name: core_catalogs description: Catalogos maestros compartidos module: MGN-005 rf: [RF-CATALOGS-001, RF-CATALOGS-002, RF-CATALOGS-003] status: planned ddl_file: apps/database/ddl/schemas/core_catalogs/ tables: - name: partners description: Clientes, proveedores, contactos rf: RF-CATALOGS-001 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID, fk: core_tenants.tenants.id} - {name: name, type: VARCHAR(200)} - {name: tax_id, type: VARCHAR(20)} - {name: email, type: VARCHAR(255)} - {name: phone, type: VARCHAR(20)} - {name: is_customer, type: BOOLEAN, default: false} - {name: is_supplier, type: BOOLEAN, default: false} - {name: is_contact, type: BOOLEAN, default: false} - {name: credit_limit, type: DECIMAL(15,2), default: 0} - {name: is_active, type: BOOLEAN, default: true} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - {name: updated_at, type: TIMESTAMPTZ, default: NOW()} - {name: deleted_at, type: TIMESTAMPTZ} indexes: - {name: idx_partners_tenant_tax, columns: [tenant_id, tax_id], unique: true} - {name: idx_partners_name_search, columns: [name], type: gin_trgm} rls_policies: - {name: tenant_isolation, using: "tenant_id = current_setting('app.current_tenant_id')::uuid"} - name: products description: Productos y servicios rf: RF-CATALOGS-002 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID, fk: core_tenants.tenants.id} - {name: sku, type: VARCHAR(50)} - {name: name, type: VARCHAR(200)} - {name: description, type: TEXT} - {name: category_id, type: UUID, fk: categories.id} - {name: unit_id, type: UUID, fk: units.id} - {name: price, type: DECIMAL(15,4)} - {name: cost, type: DECIMAL(15,4)} - {name: is_service, type: BOOLEAN, default: false} - {name: is_active, type: BOOLEAN, default: true} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - {name: updated_at, type: TIMESTAMPTZ, default: NOW()} indexes: - {name: idx_products_tenant_sku, columns: [tenant_id, sku], unique: true} - name: categories description: Categorias jerarquicas rf: RF-CATALOGS-002 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID, fk: core_tenants.tenants.id} - {name: parent_id, type: UUID, fk: categories.id} - {name: name, type: VARCHAR(100)} - {name: slug, type: VARCHAR(100)} - {name: path, type: LTREE} - {name: is_active, type: BOOLEAN, default: true} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - name: units description: Unidades de medida rf: RF-CATALOGS-003 columns: - {name: id, type: UUID, pk: true} - {name: code, type: VARCHAR(10)} - {name: name, type: VARCHAR(50)} - {name: category, type: VARCHAR(20)} - {name: is_base, type: BOOLEAN, default: false} - {name: conversion_factor, type: DECIMAL(15,6), default: 1} - name: currencies description: Monedas rf: RF-CATALOGS-003 columns: - {name: id, type: UUID, pk: true} - {name: code, type: VARCHAR(3)} - {name: name, type: VARCHAR(50)} - {name: symbol, type: VARCHAR(5)} - {name: decimal_places, type: INTEGER, default: 2} - {name: is_active, type: BOOLEAN, default: true} - name: countries description: Paises rf: RF-CATALOGS-003 columns: - {name: id, type: UUID, pk: true} - {name: code, type: VARCHAR(3)} - {name: name, type: VARCHAR(100)} - {name: phone_code, type: VARCHAR(5)} - {name: is_active, type: BOOLEAN, default: true} - name: states description: Estados/Provincias rf: RF-CATALOGS-003 columns: - {name: id, type: UUID, pk: true} - {name: country_id, type: UUID, fk: countries.id} - {name: code, type: VARCHAR(10)} - {name: name, type: VARCHAR(100)} - {name: is_active, type: BOOLEAN, default: true} # --------------------------------------------------------------------------- # CORE_AUDIT - Auditoria # --------------------------------------------------------------------------- - name: core_audit description: Logs de auditoria module: MGN-019 rf: [RF-AUDIT-001, RF-AUDIT-002] status: planned ddl_file: apps/database/ddl/schemas/core_audit/ tables: - name: audit_logs description: Log de cambios en entidades rf: RF-AUDIT-001 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID} - {name: user_id, type: UUID} - {name: entity_type, type: VARCHAR(100)} - {name: entity_id, type: UUID} - {name: action, type: VARCHAR(20)} - {name: old_values, type: JSONB} - {name: new_values, type: JSONB} - {name: ip_address, type: INET} - {name: user_agent, type: TEXT} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} indexes: - {name: idx_audit_tenant_entity, columns: [tenant_id, entity_type, entity_id]} - {name: idx_audit_created, columns: [created_at]} partitioning: type: RANGE column: created_at interval: MONTHLY - name: activity_logs description: Log de actividad de usuarios rf: RF-AUDIT-002 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID} - {name: user_id, type: UUID} - {name: action, type: VARCHAR(100)} - {name: resource, type: VARCHAR(100)} - {name: details, type: JSONB} - {name: ip_address, type: INET} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} # --------------------------------------------------------------------------- # CORE_NOTIFICATIONS - Notificaciones # --------------------------------------------------------------------------- - name: core_notifications description: Sistema de notificaciones module: MGN-008 rf: [RF-NOTIF-001, RF-NOTIF-002] status: planned ddl_file: apps/database/ddl/schemas/core_notifications/ tables: - name: notifications description: Notificaciones de usuarios rf: RF-NOTIF-001 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID} - {name: user_id, type: UUID} - {name: type, type: VARCHAR(50)} - {name: title, type: VARCHAR(200)} - {name: message, type: TEXT} - {name: data, type: JSONB} - {name: read_at, type: TIMESTAMPTZ} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} indexes: - {name: idx_notifications_user_read, columns: [user_id, read_at]} rls_policies: - {name: tenant_isolation, using: "tenant_id = current_setting('app.current_tenant_id')::uuid"} - name: notification_templates description: Templates de notificaciones rf: RF-NOTIF-002 columns: - {name: id, type: UUID, pk: true} - {name: tenant_id, type: UUID} - {name: code, type: VARCHAR(50)} - {name: name, type: VARCHAR(100)} - {name: subject, type: VARCHAR(200)} - {name: body, type: TEXT} - {name: channels, type: JSONB} - {name: is_active, type: BOOLEAN, default: true} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} # ============================================================================= # CONVENCIONES Y ESTANDARES # ============================================================================= conventions: naming: schemas: "core_{nombre}" tables: snake_case_plural columns: snake_case foreign_keys: "fk_{tabla_origen}_{tabla_destino}" indexes: "idx_{tabla}_{columnas}" primary_keys: "{tabla}_pkey" triggers: "trg_{tabla}_{evento}" functions: snake_case mandatory_columns: - {name: id, type: UUID, description: "Primary key"} - {name: tenant_id, type: UUID, description: "Multi-tenant isolation (si aplica)"} - {name: created_at, type: TIMESTAMPTZ, default: NOW()} - {name: updated_at, type: TIMESTAMPTZ, default: NOW()} soft_delete: column: deleted_at type: TIMESTAMPTZ rls: pattern: tenant_isolation context_variable: app.current_tenant_id mandatory_indexes: - "idx_{tabla}_tenant_id" - "idx_{tabla}_created_at" # ============================================================================= # HISTORIAL # ============================================================================= history: - date: "2026-01-07" action: "Implementacion DDL Sprint 8 - Reports & Dashboards" author: Database-Agent changes: - "Creado 14-reports.sql (12 tablas: reportes, dashboards, data model)" - "Actualizado create-database.sh con 20 DDL files" - "Validado recreacion completa de BD con --force" sprints_cubiertos: - Sprint 8: Reports & Dashboards specs_cubiertas: - RF-REPORT-001: Reportes Predefinidos - RF-REPORT-002: Dashboards - RF-REPORT-003: Report Builder - RF-REPORT-004: Reportes Programados tablas_nuevas: 12 enums_nuevos: 7 rls_policies_nuevas: 7 - date: "2026-01-07" action: "Implementacion DDL Sprint 5-7" author: Backend-Agent changes: - "Creado 01-auth-mfa-email-verification.sql (2 tablas: MFA + Email Verification)" - "Creado 02-core-extensions.sql (1 tabla: currency_rates)" - "Creado 09-system-extensions.sql (3 tablas: settings 3-level cascade)" - "Creado 13-audit.sql (3 tablas: audit_logs, access_logs, security_events)" - "Creado recreate-database.sh (wrapper para recreacion)" - "Actualizado create-database.sh con 19 DDL files" - "Validado recreacion completa de BD" sprints_cubiertos: - Sprint 5: MFA + Email Verification - Sprint 6: Catalogs & Settings - Sprint 7: Audit & Notifications tablas_nuevas: 9 funciones_nuevas: 4 triggers_nuevos: 3 - date: "2025-12-08" action: "Implementacion DDL extensiones Auth e Inventory" author: Database-Agent changes: - "Creado 01-auth-extensions.sql (16 tablas, 6 funciones, 2 vistas)" - "Creado 05-inventory-extensions.sql (10 tablas, 7 funciones, 3 vistas)" - "Actualizado create-database.sh con orden de ejecucion completo" - "Agregada seccion clean_load_policy y ddl_files" specs_cubiertas: - SPEC-TWO-FACTOR-AUTHENTICATION.md - SPEC-SEGURIDAD-API-KEYS-PERMISOS.md - SPEC-OAUTH2-SOCIAL-LOGIN.md - SPEC-VALORACION-INVENTARIO.md - SPEC-TRAZABILIDAD-LOTES-SERIES.md - SPEC-INVENTARIOS-CICLICOS.md - date: "2025-12-05" action: "Reestructuracion completa siguiendo filosofia GAMILIT" author: Requirements-Analyst changes: - "Agregada trazabilidad RF por tabla" - "Documentadas columnas con tipos" - "Agregados indices y RLS policies" - "Documentadas funciones y triggers"