El Ecosistema Salud TecsaS3 es una plataforma multi-tenant. Cada operación del CLI viaja dentro de un perímetro de seguridad definido por cuatro entidades encadenadas: Tenant, TenantOrg, Plan y UserPlan. Este documento describe cómo se compone ese perímetro, qué cabeceras HTTP se inyectan automáticamente y cómo configurar el CLI para operar dentro de él.

Modelo de datos

  • Tenant — la frontera de seguridad. Define el slug que identifica al cliente y el tipo de cliente (ESE, HOSPITAL, EPS, SEDE).
  • TenantOrg — la unidad operativa dentro del tenant (un hospital con varias sedes, una EPS con varias regionales). No todos los recursos tienen tenant_org directo: la mayoría lo resuelve transitivamente vía Plan.
  • Plan (PlanGestionEcosistema) — la unidad de aislamiento de datos. Activa el PlanFilteredManager cuando PLAN_DATA_ISOLATION_ENABLED=True.
  • UserPlan — la asignación por usuario, con bandera es_principal para marcar el plan por defecto del usuario en el Workspace.
El Tenant siempre es obligatorio. TenantOrg y Plan son opcionales a nivel CLI pero requeridos por casi todos los endpoints de negocio. La middleware del backend (PlanIsolationMiddleware) rechaza con 403 tenant_context_required cualquier request a una ruta protegida si no se resolvió membresía.

Cabeceras HTTP inyectadas

El cliente HTTP del CLI (cli/src/tecsas3_cli/http_client.py:79-94) añade automáticamente tres cabeceras a cada request cuya URL cae bajo un prefijo protegido: Las cabeceras solo se inyectan en rutas cuyos path empiecen por uno de los TENANT_PROTECTED_PREFIXES definidos en http_client.py:27-40:
Si el path no está en la lista, las cabeceras se omiten y la request viaja sin contexto de tenant. Esto incluye /account/, /admin/ y rutas de plataforma.
La lista es la única fuente de verdad y vive en el código. Si añades un endpoint nuevo, actualiza TENANT_PROTECTED_PREFIXES en http_client.py para que el CLI le inyecte las cabeceras; de lo contrario el backend responderá 403 tenant_context_required.

Configurar el contexto desde el CLI

El CLI ofrece precedencia clara: flag > variable de entorno > config local > config global. Para el multi-tenant los flags relevantes son --tenant, --tenant-org y --plan-id (cli/src/tecsas3_cli/cli.py:93-95).
El modo --allow-global (escape hatch planificado para v0.4.x) desactiva el chequeo de tenant y solo está reservado para operadores con PLATFORM_SUPERADMIN que ejecutan tareas de provisioning cross-tenant. No lo uses en scripts de negocio: cualquier request que viaje sin X-Tenant-Slug contra una ruta protegida será rechazada con 403 tenant_context_required. La regla de oro: el contexto de tenant se negocia al inicio del script, no en cada comando.

Roles de membresía

TenantMembership.role controla el alcance operativo dentro del tenant. Los siete roles canónicos definidos en la plataforma son: Los roles se asignan vía platform_admin o gestion, no desde el CLI. Para inspeccionar la membresía efectiva de tu usuario:

Validación y depuración

Tres comandos útiles para auditar el contexto:
El auth whoami retorna además tenant_org_id, plan_id, roles[] y la fecha de expiración del token. En modo JSON, esa estructura es estable y apta para jq.

Referencias

  • cli/src/tecsas3_cli/http_client.py:27-40TENANT_PROTECTED_PREFIXES
  • cli/src/tecsas3_cli/http_client.py:79-94_headers() (inyección de cabeceras)
  • cli/src/tecsas3_cli/runtime.py:39-45Runtime.ensure_tenant() (validación previa)
  • cli/src/tecsas3_cli/config.py:40-49Profile (campos tenant/tenant_org/plan_id)
  • cli/src/tecsas3_cli/cli.py:93-95 — flags globales --tenant, --tenant-org