Skip to main content
Una sola aplicación atiende a todas las instituciones. Cuál es la de esta petición se decide por el host.

La cadena de resolución

1

El middleware de Next lee el host

apps/web/src/middleware.ts extrae el slug del subdominio (o resuelve el dominio propio) y lo inyecta como header x-tenant-slug en la petición.
2

El middleware de Hono carga el tenant

apps/web/src/server/middleware/tenant.ts lee ese header, busca la institución y la deja en el contexto: c.get('tenant') trae { id, slug, name, ... }.
3

Se valida el acceso

tenantAccessMiddleware comprueba que el usuario de la sesión pertenezca a ese tenant. Sin eso, la petición no llega al handler.
4

Cada consulta filtra por tenantId

El aislamiento es responsabilidad del código de acceso a datos. Una consulta sin eq(tabla.tenantId, tenant.id) es una fuga entre instituciones.
En el Client API el tenant no se manda por parámetro: sale del token. Un token de servicio pertenece a una institución y no puede leer otra. No hay forma de cambiar de tenant con el mismo token.

Probar en local

El ruteo por subdominio funciona igual en desarrollo:

Source of Record: quién manda sobre cada dato

Cuando una institución ya tiene un SIS, EdTools no asume que es el dueño de la verdad. Cada tenant declara, por dominio de datos, quién es el maestro: Y para cada uno, uno de tres modos:

edtools_master

EdTools es el dueño. Es el valor por defecto en instituciones nuevas, en los cuatro dominios.

external_master

Manda un sistema externo. Solo escribe el token que figura como ese maestro.

orchestrate_only

EdTools no es dueño ni acepta ser escrito: solo orquesta procesos sobre datos ajenos.
Esto no es decorativo: el Client API lo aplica en cada escritura, y la regla es exactamente esta: Cuando no pasa, la respuesta es 403 SOR_WRITE_FORBIDDEN con el dominio en el detalle. GET /v1/me te devuelve las dos mitades de la ecuación: sorByDomain (lo que declaró la institución) y masterDomains (lo que reconoce tu token).
Los dominios de SoR son cuatro, pero el Client API solo puede declarar maestro sobre tres: students, enrollment y payments. grades se configura por SoR pero no se escribe por esta API.
Antes de escribir una sola línea de integración, llama a GET /api/client/v1/me. Ahí está todo lo que decide si tus escrituras van a pasar: scopes, módulos habilitados, SoR del tenant y dominios maestros del token.