Saltar a contenido

PostgreSQL Sandbox Multi-Tenant

Estado: SANDBOX VALIDADO EN VPS
Scope: global
tenant_id: global
Owner: OpenClaw Platform Governance
Fuente de verdad: docs/governance/operations/POSTGRESQL-SANDBOX-MULTI-TENANT.md

Proposito

Definir y dejar preparado un primer PostgreSQL sandbox multi-tenant, estrictamente no productivo, para validar separacion de datos entre alpuntodeventa y ladirecta con datos ficticios y sin tocar integraciones reales.

Que valida

  • uso de PostgreSQL como primera base sandbox multi-tenant
  • estrategia inicial de tablas compartidas con tenant_id
  • estructura minima para tenants, clientes, productos y ventas
  • datos demo separados por tenant
  • Row Level Security de lectura por tenant
  • lectura global controlada para un rol autorizado
  • no exposicion publica directa de la base
  • uso de red Docker interna y volumen persistente

Que no valida

  • uso productivo
  • rendimiento real
  • alta disponibilidad
  • backup automatico
  • integracion con WooCommerce
  • integracion con SGC / ERP
  • PostgREST
  • Scalar
  • APIs publicas
  • acceso externo por Nginx Proxy Manager
  • cargas de datos sensibles

Tenants iniciales

  • alpuntodeventa
  • ladirecta

Alcance

  • carpeta runtime: infra/data-foundation/postgres-sandbox/
  • compose privado con postgres:16-alpine
  • scripts SQL de bootstrap y RLS
  • documentacion operativa y de validacion
  • validacion prevista solo con datos ficticios

Restricciones

  • no usar contrasenas reales en repo
  • no publicar 5432
  • no conectar el contenedor a proxy-network
  • no usar datos reales de clientes, productos o ventas
  • no usar esta base como fuente productiva
  • no mezclar este sandbox con observabilidad tecnica actual

No uso productivo

Este sandbox existe solo para validar aislamiento multi-tenant y contrato de datos. Cualquier consumo real de negocio, dashboards, agentes o APIs sigue pendiente de etapas posteriores.

Diagnostico previo al 2026-06-02

Safe point inicial

  • git status -sb -> ## main...origin/main
  • git rev-parse HEAD -> 7d52b384638c226b656514a459a36e120da915df

Hallazgos del VPS

Relevamiento remoto de solo lectura ejecutado por ssh openclaw-vps.

  • docker disponible en VPS: /usr/bin/docker
  • psql no aparece instalado en host
  • no existe contenedor PostgreSQL activo al momento del relevamiento
  • contenedores activos observados:
  • knowledge-portal
  • portainer
  • obs-grafana
  • obs-alertmanager
  • obs-thanos-query
  • obs-prometheus
  • obs-thanos-compactor
  • obs-thanos-storegateway
  • obs-thanos-sidecar
  • obs-node-exporter
  • obs-cadvisor
  • obs-blackbox-exporter
  • openclaw-openclaw-gateway-1
  • nginx-proxy-manager
  • redes Docker existentes:
  • proxy-network
  • obs-observability-internal
  • openclaw_openclaw_internal
  • knowledge-portal_default
  • nginx-proxy-manager_default
  • portainer2_default
  • volumenes Docker existentes:
  • obs_alertmanager_data
  • obs_grafana_data
  • obs_prometheus_data
  • obs_thanos_compactor_data
  • obs_thanos_objectstore_data
  • obs_thanos_storegateway_data
  • portainer_data
  • portainer_data_new
  • puertos publicos escuchando en VPS:
  • 22
  • 80
  • 81
  • 443
  • puertos privados observados:
  • 127.0.0.1:8085 para knowledge-portal
  • 127.0.0.1:3000 para obs-grafana
  • no hay evidencia de 5432 publicado en el VPS al momento del relevamiento

Validacion runtime al 2026-06-02

Validacion ejecutada en openclaw-vps desplegando el sandbox desde una copia temporal controlada en /tmp/openclawai-sandbox-deploy/.

Evidencia confirmada:

  • docker compose up -d ejecutado sin tocar stacks productivos existentes
  • contenedor openclaw-postgres-sandbox en estado healthy
  • docker compose ps muestra solo 5432/tcp interno, sin publicacion host
  • docker inspect ... HostConfig.PortBindings devuelve {}
  • red efectiva del contenedor:
  • pg-sandbox-internal
  • consulta de tenants:
  • alpuntodeventa
  • ladirecta
  • lectura como app_alpuntodeventa_reader:
  • solo alpuntodeventa | Venta Demo APV
  • lectura como app_ladirecta_reader:
  • solo ladirecta | Venta Demo La Directa
  • lectura como app_global_reader:
  • ve ambos tenants
  • intento de acceso cruzado de app_alpuntodeventa_reader sobre tenant_id=ladirecta:
  • sin filas devueltas

Convencion previa en DATA-FOUNDATION.md

La convencion ya aprobada y respetada por este sandbox es:

  • tenant_id obligatorio
  • tablas compartidas con tenant_id como recomendacion inicial
  • source_system, auditoria y record_status obligatorios
  • tenants iniciales aprobados:
  • alpuntodeventa
  • ladirecta
  • RLS como mecanismo recomendado antes de exponer APIs o dashboards

Diseno sandbox aprobado

Red Docker sugerida

  • nombre: pg-sandbox-internal
  • driver: bridge
  • propiedad: internal: true
  • objetivo: aislar el contenedor del plano publico y evitar publicacion accidental

Volumen sugerido

  • nombre: pg_sandbox_data
  • objetivo: persistir el cluster de datos del sandbox entre reinicios

Credenciales

  • archivo esperado: infra/data-foundation/postgres-sandbox/.env
  • versionado permitido: solo .env.example
  • politica: password solo de sandbox, nunca credenciales productivas

Politica futura de backup

En esta etapa no se activa backup automatico, pero queda recomendada la siguiente politica minima futura:

  • pg_dump logico de sandbox antes de cambios estructurales
  • snapshot o copia del volumen pg_sandbox_data antes de resets
  • almacenamiento separado de artefactos y SHA256SUMS
  • retencion corta, porque es un entorno de prueba

Rollback

Rollback sugerido si el sandbox debe descartarse por completo:

  1. docker compose down
  2. docker volume rm pg_sandbox_data
  3. docker network rm pg-sandbox-internal

No aplicar rollback destructivo si existe evidencia o seeds que se quieran preservar para comparacion.

Implementacion entregada

  • compose: infra/data-foundation/postgres-sandbox/docker-compose.yml
  • runtime notes: infra/data-foundation/postgres-sandbox/README.md
  • bootstrap SQL:
  • init/001_create_schema.sql
  • init/002_seed_tenants.sql
  • init/003_seed_sample_data.sql
  • init/004_rls_policies.sql

Modelo minimo incluido

  • sandbox_mt.tenants
  • sandbox_mt.clientes
  • sandbox_mt.productos
  • sandbox_mt.ventas

Todas las tablas incluyen los campos obligatorios definidos por Data Foundation:

  • tenant_id
  • source_system
  • created_at
  • updated_at
  • created_by
  • updated_by
  • record_status
  • external_id si aplica
  • sync_batch_id si aplica

Seguridad inicial

  • RLS activado en las cuatro tablas
  • roles de lectura creados:
  • app_global_reader
  • app_alpuntodeventa_reader
  • app_ladirecta_reader
  • politica esperada:
  • app_global_reader puede leer ambos tenants
  • app_alpuntodeventa_reader solo puede leer alpuntodeventa
  • app_ladirecta_reader solo puede leer ladirecta

Validacion operativa

Los comandos de validacion quedaron documentados en:

Regla final

Este sandbox no habilita de forma automatica ninguna API, dashboard, agente o integracion productiva. Solo abre una base controlada y privada para validar aislamiento multi-tenant con datos de prueba.