Saltar a contenido

ADR-0002 · Multi-tenancy híbrida (lógico SMB default + físico enterprise opt-in)

  • Status: Accepted
  • Date: 2026-04-30
  • Deciders: Cristian Fernández (Zerviz Group)
  • Supersedes: N/A
  • Related: ADR-0003 (persistencia), ADR-0005 (auth), docs/discovery/00-phase1-prerequisites.md Anexo A-02.

Context

El sistema debe soportar N tenants con onboarding programático sin redeploy. La regla base prohíbe asumir baseline costoso. Tenants vienen en dos perfiles:

  • SMB: mayoría esperada. Requieren costo bajo, onboarding rápido, sin SLA de aislamiento físico.
  • Enterprise: minoría con requisitos regulatorios o contractuales de aislamiento (cuenta AWS dedicada, KMS propio, datos aislados a nivel infra).

IPLACEX es fixture de prueba SMB; Zerviz interno también es SMB.

Decision

Modelo de dos tiers:

Tier lógico (default — SMB)

  • Una sola cuenta AWS por env (ze-dev, ze-qa, ze-prod).
  • Cognito User Pool único compartido (ze-{env}-users) con claim custom:tenant_id en cada usuario.
  • RDS Postgres común (ver ADR-0003) con RLS sobre cada tabla que toque datos de tenant: CREATE POLICY tenant_iso ON <tabla> USING (tenant_id = current_setting('app.tenant_id')::uuid);.
  • DynamoDB compartido con PK = TENANT#<id> y SK por entidad. Item-level access via IAM con dynamodb:LeadingKeys.
  • KMS CMK por tenant (alias/ze-{env}-tenant-<id>) para datos sensibles (PII de conversaciones, transcripciones, audit). Buckets S3 y secretos del tenant cifran con esta CMK.
  • Onboarding: API POST /tenants en tenant-mgmt. Crea tenant en RDS ze_control_plane.tenants, provisiona CMK + alias, registra en Cognito (group tenant-<id>), publica TenantCreated.

Tier físico (opt-in — enterprise)

  • Cuenta AWS dedicada por tenant (ze-prod-tenant-<id>), provisionada por AWS Organizations.
  • Stack Terraform infra/tenants/<tenant>/ aplicado con var.tenant_id. Todos los recursos del tenant (Lambdas, RDS propio, DDB propio, S3, Cognito UP propio, KMS propio) viven en esa cuenta.
  • Control plane (tenant-mgmt, auth-bff, EventBridge bus de plataforma, billing) sigue en la cuenta ze-prod.
  • Cross-account roles: la cuenta-tenant asume roles del control plane sólo para publicar eventos de plataforma y emitir métricas de billing.
  • No RLS dentro del tenant (innecesario, aislamiento ya es físico).
  • Costos del tier físico se cargan al tenant.

Decisión por tenant

tenant-mgmt mantiene tenants.tier ∈ {logical, physical}. Cambio de tier = migración planificada (no automática). En V1 sólo el equipo de plataforma activa el tier físico; opt-in vía form / contrato.

Consequences

Positive

  • SMB onboardea en minutos sin Terraform.
  • Enterprise obtiene aislamiento físico verificable (auditable a nivel cuenta AWS).
  • Cumple ISO 27001 A.13.1.3 (segregación en redes) en tier físico.
  • KMS CMK por tenant facilita compliance individual (Ley 19.628 cuando aplique).

Negative

  • Doble pipeline de provisioning (lógico + físico) → más Terraform modules a mantener.
  • RLS en Postgres requiere SET app.tenant_id en cada conexión; olvido ⇒ leak entre tenants. Mitigado con middleware obligatorio en packages/tenant-context.
  • Cross-account billing del tier físico requiere AWS Organizations + tag enforcement.

Alternatives considered

  • Sólo tier lógico: rechazado — algunos prospects enterprise requieren aislamiento físico contractual.
  • Sólo tier físico: rechazado — costo prohibitivo para SMB (~ USD 50/mes/tenant baseline).
  • Database per tenant en una cuenta: rechazado — no escala a N alto y no resuelve aislamiento de compute/secrets.

Tenant-isolation impact

(Es el ADR de aislamiento. Resumen en sección Decision.) Tests de aislamiento obligatorios en cada servicio:

  • tests/integration/tenant-isolation.test.ts: dado tenant A y tenant B, una request del A no puede leer ni escribir filas del B.
  • Test de bypass: forzar tenant_id faltante / falsificado en JWT debe devolver 403.

Blast radius

  • Tier lógico: bug que rompe RLS ⇒ leak entre todos los tenants SMB del env. Crítico. Mitigado por packages/tenant-context + tests + revisión obligatoria de queries.
  • Tier físico: blast radius limitado a la cuenta del tenant.

Cost note

  • Tier lógico: incremental por tenant ≈ USD 0–2/mes (sólo CMK + entradas Cognito + filas RDS).
  • Tier físico: baseline USD 50–200/mes/tenant según engine RDS y volumen — facturado al tenant.

ISO 27001 controls touched

  • A.9.4.1 (restricción de acceso a información): RLS + IAM LeadingKeys.
  • A.10.1.1 (políticas de uso de criptografía): KMS CMK por tenant.
  • A.13.1.3 (segregación en redes): tier físico = cuenta AWS separada.
  • A.18.1.4 (privacidad y protección de datos personales): KMS + Object Lock por tenant.

Sources

  • docs/discovery/00-phase1-prerequisites.md U-04, 1.3, Anexo A-02.
  • Playbook §2 (multi-tenant model).