Saltar al contenido principal

Identidad vs Membresía

OmniBuy separa quién eres (identidad) de dónde trabajas (membresía). Un mismo email puede pertenecer a múltiples tiendas.

El problema que resuelve

En el modelo original, merchant_users tenía un UNIQUE(email) — cada email solo podía existir en una tienda. Si un merchant tenía 2 tiendas, necesitaba 2 cuentas con 2 emails.

El modelo nuevo

merchant_identities (identidad global)
├── id (UUID PK)
├── email (UNIQUE) ← una sola vez
├── password_hash ← una sola vez
├── verified
├── name
└── is_internal ← @omnibuy.net

merchant_users (membresía por tenant)
├── identity_id (FK → merchant_identities)
├── tenant_id
├── role ← owner, admin, staff, viewer
├── email (denormalizado) ← para compat con tenant.go
├── name (denormalizado)
└── UNIQUE(identity_id, tenant_id) ← una membresía por tenant por identidad

Ejemplo

[email protected] → merchant_identities
├── membresía en "Tienda Lima" (role: owner)
├── membresía en "Tienda Cusco" (role: admin)
└── membresía en "Tienda Arequipa" (role: viewer)

María inicia sesión una vez y elige en qué tienda trabajar.

Migración

La migración 000209 es no-destructiva (Opción C):

  • Crea merchant_identities y backfilla desde merchant_users
  • Agrega identity_id a merchant_users
  • NO dropea password_hash ni UNIQUE(email) de merchant_users todavía
  • Se mantiene dual-write para compatibilidad

Diagrama

┌─────────────────────┐
│ merchant_identities │ ← Identidad global
│ (login) │
│ │
│ email │
│ password_hash │
│ verified │
└─────────┬───────────┘
│ 1:N
┌─────────┴───────────┐
│ merchant_users │ ← Membresía por tenant
│ │
│ identity_id (FK) │
│ tenant_id │
│ role │
└──────────────────────┘