Saltar al contenido
Studeia Docs
AI-assisted translation — last updated 2026-06-03. For original (pt-BR or en-US), use the language switcher.

Multi-tenancy y aislamiento de datos

Arquitectura multi-tenant de Studeia: cada institución tiene aislamiento completo a nivel de base de datos con filtro por tenantId, RLS Supabase, API keys por tenant, white-label total y SSO independiente.

2026-06-03 7 min
Resposta curta

Multi-tenancy en Studeia significa que cada institución (Tenant) tiene datos completamente aislados a nivel de base de datos. Filtro obligatorio por tenantId en todas las queries Prisma, RLS Supabase como safety net, API keys por tenant, configuración de IA independiente (puede usar sus propias claves Anthropic/OpenAI) y white-label total (dominio, branding, tema, email).

Modelo conceptual

Tenant (Institución)
  ├── Users (alumnos, profesores, coordinadores, admin institucional)
  ├── Courses → Modules → Lessons
  ├── ClassGroups (grupos de clase)
  ├── MediaAssets (biblioteca de medios)
  ├── Automations
  ├── EmailTemplates
  ├── VideoProviderConfig (BBB/Zoom/Teams/Meet)
  ├── TenantApiKey (claves propias de IA)
  ├── TenantSubscription (billing)
  ├── ...todas las demás entidades

Los usuarios sin tenantId son B2C (plataforma directa). Los usuarios con tenantId pertenecen a una institución.

Aislamiento de datos — 3 capas

Capa 1: Filtro obligatorio en queries

Toda query Prisma en el código de la aplicación filtra por tenantId:

const { tenantId } = requireTenant(user);
const courses = await prisma.course.findMany({
  where: { tenantId }, // OBLIGATORIO
});

requireTenant() en apps/web/lib/tenant.ts devuelve NextResponse 403 si el usuario no tiene tenant. Sin esta llamada, es imposible acceder a datos B2B.

Capa 2: RLS en Supabase

Como safety net frente a bugs, las políticas RLS en Supabase refuerzan el aislamiento incluso en queries directas. Si un código olvida el filtro tenantId, la base de datos lo rechaza.

Capa 3: Auditoría de admin global

Cuando un admin global necesita acceder a los datos de un tenant (soporte, depuración), utiliza impersonación mediante cookie HMAC con:

  • TTL fijo de 1h (no prorrogable)
  • Firma HMAC-SHA256 con IMPERSONATION_SECRET
  • Auditoría en AdminAuditLog (acción impersonate.start, IP, user-agent)
  • getUserProfile() devuelve isImpersonating: true + overlay en memoria
  • Supabase auth NUNCA modificado (solo overlay)
  • Banner fijo en /institution/ alerta al admin durante la sesión

El panel admin SaaS global incluye impersonacion para soporte.

API keys por tenant

Por defecto, todas las llamadas LLM usan las claves globales (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.) de Studeia. Los costos se imputan al tenant mediante metering.

Sin embargo, las instituciones que ya tienen cuentas en Anthropic/OpenAI/Google pueden usar sus propias claves (TenantApiKey, cifrada AES-256-GCM en la base de datos):

  1. Los costos van DIRECTAMENTE a la cuenta del tenant en Anthropic/OpenAI
  2. Studeia no cobra margen de IA — solo la suscripción mensual
  3. Resolución automática: TenantApiKeyProviderApiKey global → process.env (cascada en apps/web/lib/api-key-resolver.ts)

NUNCA se asigna process.env en runtime (generaría conflictos entre tenants) — la key se pasa mediante las opciones del SDK.

White-label completo

Cada tenant puede personalizar:

AspectoCómo
Logo, faviconSubida en ajustes
Colores (primary, accent, background)Editor con vista previa
Fuente (Google Fonts)Desplegable
Tema visual (de 9 opciones)Toggle por usuario o predeterminado del tenant
CSS personalizadoSaneado, máx. 10KB
Dominio personalizadoDNS CNAME + TXT _studeia-verify + TLS automático Caddy (on-demand)
Logo en emailPor plantilla
Email de envío (SMTP/Resend/SendGrid)TenantEmailConfig
Ocultar marca StudeiaSí (plan enterprise)

Roles y permisos

RolÁmbitoPuede hacer
studentPropio progresoChat tutor, cursos, simulacros, gamificación
parentHijos vinculadosVer progreso, alertas, informes
teacherPropios grupos/cursosCrear cursos, subir material, ver alumnos de los grupos
coordinatorTodos los grupos del tenantGestionar grupos, ver todos los alumnos
pedagogueTodos los alumnos del tenantOrientación educativa, informes
institution_adminTodo el tenantConfig IA, API keys, white-label, usuarios
adminGlobal (plataforma)Todo + gestionar tenants

Límites por plan

Límites aplicados mediante checkTenantResourceLimit(tenantId, resource) en apps/web/lib/plan-limits.ts:

PlanAlumnos máx.ProfesoresCursosIA
Demo111Solo Haiku, 10 msgs/día
Mini10IlimitadoIlimitadoTodos los proveedores
Crescimento50IlimitadoIlimitadoTodos los proveedores
Escala100IlimitadoIlimitadoTodos los proveedores
EnterpriseCustom (maxStudentsOverride)IlimitadoIlimitadoTodos los proveedores

7 puntos de aplicación (todos auditados el 2026-04-11):

  1. POST /api/courses/[courseId]/enroll — auto-inscripción del alumno
  2. POST /api/institution/courses/[id]/clone — clonación de curso
  3. POST /api/institution/courses/import — importación IMS CC
  4. executeEnrollUser() en automatización
  5. POST /api/scim/v2/Users — aprovisionamiento SCIM
  6. POST /api/institution/users — vincular usuario existente
  7. PATCH /api/institution/users/[id] — ascender rol

Cómo solicitar override enterprise

Los tenants enterprise pueden tener Tenant.maxStudentsOverride: Int? ajustado por el admin global. Sin override (null), enterprise = ilimitado. Contacto comercial mediante contact@studeia.com.

Limitaciones

  • Un User pertenece a UN tenant. Para profesores que atienden múltiples escuelas, crear usuarios separados.
  • El intercambio de cursos entre tenants no es nativo (cada tenant tiene su CMS aislado). Roadmap: marketplace de cursos con licenciamiento.
  • La migración de un tenant a otro plan es instantánea, pero el downgrade que viola los límites actuales queda bloqueado hasta que el tenant ajuste los recursos.

Ver también

FAQ

¿Los datos de los tenants están realmente aislados?

Sí. Tres capas: (1) toda query Prisma filtra por tenantId obligatoriamente (regla crítica 30 del proyecto); (2) políticas RLS en Supabase como safety net; (3) auditoría automatizada de queries cross-tenant mediante tests. La impersonación de admin global está auditada (AdminAuditLog) y usa cookie HMAC con TTL fijo de 1h.

¿Puedo tener dominio propio (white-label completo)?

Sí. Configure Tenant.customDomain en los ajustes + apunte el CNAME al dominio de Studeia. TLS automático mediante Let's Encrypt en Caddy (on-demand TLS, tras verificación del dominio por registro TXT). Logo, favicon, colores, fuentes, 9 temas visuales e incluso mensajes de email personalizables. Puede eliminar la marca Studeia completamente.

¿Los costos de IA son por tenant?

Sí. Cada llamada LLM se registra en AiUsageLog con tenantId. El admin global puede ver el desglose de costos por tenant en /admin/finance/ai-cost (con cálculo de margen vs MRR). Los tenants pueden usar sus propias API keys (TenantApiKey) — en ese caso los costos van al tenant, no a Studeia.

¿Cómo se gestionan los usuarios cross-tenant?

Por diseño, un User pertenece a UN tenant (User.tenantId). Para casos B2B donde un pedagogo atiende múltiples escuelas, recomendamos crear usuarios separados por institución. El admin global puede reasignar usuarios mediante /admin/tenants (auditado).

Veja tambem

Multi-tenancy y aislamiento de datos