Volver a la wiki

Base de datos CreaRack Pro · explicación coloquial

Base de datos CreaRack Pro · explicación coloquial

Resumen para alguien que entra al proyecto y quiere entender qué se guarda, dónde y por qué sin enterarse de cada columna. Si buscas el schema completo con FKs e índices, ve a [[crearack-tech—bd—tecnico]].


En una frase

CreaRack Pro guarda todo en una sola base de datos PostgreSQL 18. No hay Mongo, no hay Redis para datos persistentes, no hay servicios separados. Una BD, ~55 tablas, todas viviendo bajo el paraguas de una entidad raíz: la Organization (el cliente SaaS).


Por qué PostgreSQL y no otra cosa

RazónDetalle
MadurezEl estándar para SaaS serios. 30 años de batalla.
Multi-tenancy nativoRow-Level Security (RLS) sin librerías raras. Te lo explico abajo.
JSONBCampos JSON con índices = lo mejor de SQL + NoSQL. Lo usamos en model_data, management_config, encrypted_data.
Sin proveedor únicoSi mañana hay que mudarse, PG corre en cualquier sitio (Hetzner, AWS, on-prem).
Equipo lo conoceLo que dominas es siempre mejor que lo nuevo de moda.

La idea clave: multi-tenancy con RLS

CreaRack Pro es SaaS: un cliente NO puede ver los datos de otro cliente. Punto. Pero implementarlo bien tiene truco.

Hacemos dos capas de aislamiento que trabajan juntas:

Capa 1 · Django ORM (programador)

Cada vez que escribimos código que consulta la BD, filtramos por organización:

device = get_object_or_404(Device, id=device_id, rack__organization=org)
#                                                ^^^^^^^^^^^^^^^^^^^^^^
#                                                esto es OBLIGATORIO

Capa 2 · PostgreSQL RLS (la red de seguridad)

Si un programador se olvida del filtro (humanos somos humanos), PostgreSQL bloquea la consulta igualmente. Magia: cada request HTTP setea una variable de sesión (SET app.current_org_id = '123') y PG aplica políticas RLS automáticamente a 35 tablas:

USING (organization_id = current_setting('app.current_org_id')::int)

Es como tener un guardia de seguridad en la BD: aunque el programador deje la puerta abierta, el guardia mira el carnet de la organización antes de entregar la fila.

Implementado en v1.0.50 tras una auditoría de seguridad. Detalle técnico en [[crearack-tech—bd—tecnico]] § RLS.


Mapa mental: las 7 apps

CreaRack Pro tiene 7 apps Django, cada una con sus modelos. Esta es la jerarquía conceptual:

erDiagram
    Organization ||--o{ User : "tiene"
    Organization ||--o{ Rack : "es dueña de"
    Organization ||--o{ Blueprint : "es dueña de"
    Organization ||--o{ MonitoringTarget : "monitoriza"
    Organization ||--o{ SignagePlayer : "controla"
    Organization }o--|| Plan : "está suscrita a"
    Plan }o--o{ SaaSModule : "incluye"
    Rack ||--o{ Device : "contiene"
    Rack }o--o{ RackGroup : "agrupado en"
    Blueprint ||--o{ BlueprintPlacement : "ubica"
    BlueprintPlacement }o--|| Rack : "muestra"
    MonitoringTarget ||--o{ AIInsight : "genera"
    AIInsight }o--o{ IncidentGroup : "agrupado en"

Y aquí qué hace cada app:

AppPara qué sirveModelos clave
coreMulti-tenancy, usuarios, permisos, auditoríaOrganization, User, Plan, SaaSModule, SystemLog, StoredCredential
racksDiseñador visual de racks (Konva.js)Rack, Device, RackGroup, Stencil, BoxCategory, ConfigBackup
blueprintsMapas de infraestructura (Auto-Plan AI)Blueprint, BlueprintPlacement, MapAnnotation, AIPrompt
monitoringObservatorio de red + ITSM + CNS (Network Sentinel AI)MonitoringTarget, AIInsight, IncidentGroup, SLAPolicy, Runbook, MaintenanceWindow
networkInteligencia de vendors, MIBs, conexiones de puertosVendorProfile, CustomMib, DeviceProfile, PortConnection
terminalScripts SSH + Local Agent (failover Sentinel)Script, AgentInstance
signageDigital Signage CMS (cartelería)SignagePlayer, MediaAsset, Playlist, Schedule, ClientProject

Qué tablas son “globales” (no por organización)

La regla general es todo lleva organization_id NOT NULL. Pero hay excepciones — datos del sistema que comparten todos:

TablaPor qué es global
core_systemlogLogs del sistema (visibles por todos)
core_scripttemplateTemplates de scripts pre-instalados
racks_boxcategoryCategorías base de cajas (Server, Switch, etc.)
racks_stencilStencils de fabricantes (Cisco, HP, Dell…) compartidos
monitoring_monitoringalertAlertas globales
network_vendorprofileCatálogo de vendors (Cisco, Juniper, Aruba…)
network_signagevendoradapterAdapters de vendors signage (Samsung MDC, LG, PJLink)

En estas tablas, organization_id puede ser NULL (= global). El ORM hace un OR para que cada tenant vea lo suyo + lo global:

stencil = Stencil.objects.get(
    Q(organization=org) | Q(organization__isnull=True),
    id=stencil_id,
)

Tips para el día a día

Si quieres añadir un campo nuevo a un modelo

  1. Editar <app>/models.py
  2. docker compose exec web python manage.py makemigrations
  3. docker compose exec web python manage.py migrate
  4. Verificar que el campo respeta RLS (si la tabla está protegida, ver lista en [[crearack-tech—bd—tecnico]])
  5. Commit (el hook bib_report_change se quejará si te lo saltas)

Si necesitas consultar la BD a pelo (debug)

Hay un usuario dani_readonly con SELECT en todas las tablas. Cuando conectas por psql directo, RLS se bypasea (no hay app.current_org_id seteado), así que ves la data de todos los tenants. Es intencional, para diagnóstico.

psql postgres://dani_readonly:PASS@crearack-prod:5432/crearack

Si quieres mirar lo de UN tenant específico

SET app.current_org_id = '123';  -- el ID del tenant
SELECT * FROM racks_rack;        -- ahora solo ves los suyos
SET app.current_org_id = '0';    -- vuelves a ver todo

Backups · cómo funcionan

Dos niveles:

NivelQué cubreCuándo
pg_dump diarioToda la BD entera (dump físico)Cron servidor PROD, 3:00 AM
Backup per-tenantZIP con backup_data.json (14 entity types) + media uploads por organizaciónHuey task run_org_backups, 3:30 AM

El segundo permite descargar el backup de UN solo cliente sin tener que hacer un restore completo. Útil para exportar/migrar.


¿Y Valkey, qué pinta?

Valkey (compatible Redis) NO guarda datos persistentes. Solo:

Si Valkey se cae, perdemos la cola y los WebSockets pero la BD sigue intacta. Por eso no entra en backups.


Para el otro lado: la BD del workspace

CreaRack Pro y workspace tienen BDs distintas y filosofías distintas:

AspectoCreaRack ProWorkspace
MotorPostgreSQL 18Cloudflare D1 (SQLite distribuido)
UbicaciónHetzner CCX (1 nodo)Cloudflare edge (replicado global)
Modelos55 (Django ORM)~25 tablas (SQL plano)
Multi-tenantSí (RLS)No (uso interno equipo de 3)
Backupspg_dump + per-tenantWrangler export (CF)

Si quieres entender el workspace, ve a [[workspace-tech—bd—coloquial]] (versión coloquial) o [[workspace-tech—bd—tecnico]] (técnico).


Véase también

Subir