Saltar a contenido

PostgREST Sandbox Multi-Tenant

Fecha: 2026-06-02

Objetivo

Validar el camino PostgreSQL -> API REST -> OpenAPI sobre datos completamente ficticios, sin exponer PostgREST a Internet, sin tocar bases productivas y sin abrir un DNS nuevo.

Que valida

  • conectividad entre PostgREST y el PostgreSQL sandbox
  • exposicion REST de tenants, clientes, productos y ventas
  • autenticacion sandbox con JWT
  • validacion de claims tenant_id, role, scope, aud, iss y exp
  • aplicacion efectiva de RLS tambien via API
  • disponibilidad de OpenAPI inicial entregado por PostgREST
  • aislamiento de red sin puertos publicados al host

Que no valida

  • escritura multi-tenant
  • publicacion via Nginx Proxy Manager
  • Scalar
  • Kong
  • API keys productivas
  • consumo de datos reales

Relacion con PostgreSQL sandbox

Este sandbox depende de infra/data-foundation/postgres-sandbox/ y no crea una base paralela.

Reglas:

  • usa solo la red pg-sandbox-internal
  • usa solo la base openclaw_sandbox
  • usa solo datos ficticios ya sembrados en sandbox_mt
  • reutiliza roles lectores ya validados por RLS
  • refuerza las policies con tenant_id del claim cuando existe token

Relacion con API Platform

Esta etapa implementa la primera seguridad runtime del contrato definido en API-PLATFORM.md.

Concretamente valida:

  • que PostgREST puede ser la primera capa REST real
  • que el aislamiento por tenant no depende solo de la URL
  • que el rol SQL puede venir desde el claim role
  • que la lectura cross-tenant sigue bloqueada por RLS

Relacion con futuros OpenAPI y Scalar

PostgREST sigue entregando un OpenAPI inicial en el endpoint raiz interno.

Eso permite:

  • confirmar que existe una fuente runtime para contratos de API
  • documentar la futura integracion con Scalar
  • reservar developers.alpuntodeventa.com.ar para 15.6
  • mantener 15.4 completamente interno

Diseno 15.4 aprobado

La etapa 15.4 reemplaza los tres runtimes fijos de 15.3 por un unico runtime interno:

  • openclaw-postgrest-sandbox

Propiedades del runtime:

  • rol SQL derivado desde claim role
  • claim tenant_id disponible para reforzar RLS
  • claim scope documentado y emitido en tokens sandbox
  • enforcement granular de scope por recurso via db-pre-request
  • validacion de aud y exp por PostgREST
  • validacion de iss y consistencia role/tenant_id por db-pre-request
  • secreto JWT fuera de Git
  • solo lectura
  • sin puertos publicados al host

Restricciones de seguridad

  • no publicar puertos al host
  • no unir el stack a proxy-network
  • no crear hostnames ni DNS nuevos
  • no usar developers.alpuntodeventa.com.ar todavia
  • no instalar Scalar
  • no instalar Kong
  • no guardar passwords o secretos reales en el repo
  • no abrir escritura mientras no exista necesidad real
  • no mezclar datos reales con el sandbox

Por que no se expone publicamente

Aunque ahora existe JWT, esta etapa sigue siendo solo de validacion interna.

Se mantiene cerrada porque todavia faltan:

  • politica final de API keys
  • documentacion interactiva real
  • reglas de exposicion segura
  • auditoria de consumo mas completa

Artefactos

  • infra/data-foundation/postgrest-sandbox/docker-compose.yml
  • infra/data-foundation/postgrest-sandbox/.env.example
  • infra/data-foundation/postgrest-sandbox/README.md
  • infra/data-foundation/postgrest-sandbox/bootstrap/bootstrap-authenticator.sh
  • infra/data-foundation/postgrest-sandbox/bootstrap/reconcile-postgrest-security.sql
  • infra/data-foundation/postgrest-sandbox/tools/generate-sandbox-jwt.py

URL interna esperada

  • Runtime: http://openclaw-postgrest-sandbox:3000/

Validacion objetivo

  1. Sin token: acceso rechazado.
  2. Token APV: solo ve alpuntodeventa.
  3. Token La Directa: solo ve ladirecta.
  4. Token Global: puede ver ambos tenants.
  5. Filtro cruzado devuelve [].
  6. Token expirado: rechazo.
  7. Token invalido: rechazo.
  8. docker inspect muestra PortBindings vacio o null.
  9. No aparecen secretos en compose, docs ni logs operativos.

Scope enforcement activo

En 15.4b el sandbox ya aplica scope enforcement dentro de sandbox_private.enforce_postgrest_claims.

Contrato runtime:

  • /clientes -> read:clientes o read:all
  • /productos -> read:productos o read:all
  • /ventas -> read:ventas o read:all
  • /tenants -> read:all
  • / -> accesible con token valido para mantener OpenAPI interno
  • otros recursos -> rechazo por fuera del contrato del sandbox

La seguridad sigue apoyandose en capas:

  • PostgREST valida firma, aud y expiracion
  • db-pre-request valida iss, claims, recurso y scope
  • RLS mantiene el aislamiento real por tenant_id

Evidencia runtime final en VPS

Validacion final ejecutada el 2026-06-02:

  • openclaw-postgres-sandbox se mantuvo healthy
  • openclaw-postgrest-sandbox quedo running
  • docker inspect devolvio PortBindings {} y solo la red pg-sandbox-internal
  • apv-clientes pudo leer /clientes solo para alpuntodeventa y recibio 403 en /ventas y /productos
  • apv-ventas pudo leer /ventas solo para alpuntodeventa y recibio 403 en /clientes
  • ladirecta-productos pudo leer /productos solo para ladirecta y recibio 403 en /ventas
  • global-all pudo leer /clientes, /productos, /ventas y /tenants viendo ambos tenants ficticios
  • token sin scope y token con scope desconocido recibieron 403
  • token invalido y token expirado recibieron 401
  • token con iss invalido recibio 403
  • la raiz / respondio 200 solo con token valido
  • no se detectaron secretos ni tokens en los logs revisados