Auth
TED OS authenticates with Clerk. Auth is centralized in a reusable @tedos/auth package
and shared across the platform's surfaces, which live on subdomains of tuempresa.digital.
This page describes the auth mechanics. No real keys, tokens, or env values appear anywhere — environment variables (Clerk keys, the GitHub token) are referred to by name only.
The reusable package
@tedos/auth centralizes the two pieces every surface needs:
- CSP — a Content-Security-Policy that allows the Clerk frontend API. The CSP is derived from the Clerk publishable key so each surface gets the right Clerk domain without hand-maintaining a hostname. (The CSP entry point is plain JavaScript, because the Next config runs in Node and cannot import TypeScript.)
- Middleware — the Clerk middleware that protects routes.
The package's React entry (@tedos/auth/react) also provides the client-side gate used by the
docs site.
The platform decision is to protect internal surfaces with Clerk via this package, not with a paid hosting-provider access wall.
Subdomain client apps share the session
The platform's surfaces — admin, console, and client apps — run on subdomains of
tuempresa.digital. They share the Clerk session for free via the root cookie, with no Clerk
satellite / Pro tier required. For a surface to log in, three things must all be true:
- The app is plain Clerk app code (not a satellite configuration).
- Its CSP allows the Clerk frontend API for
tuempresa.digital(derived from the publishable key). - The subdomain is added to the Clerk Dashboard allowlist.
How each surface authenticates
| Surface | How |
|---|---|
| admin | Clerk; a requireProject guard maps a Clerk org → project + role; every /p/:id/* route is authorized server-side |
| console | Clerk app on a subdomain, sharing the root-cookie session |
| comprender (client app) | Clerk app on a subdomain under the client's brand/URL, sharing the session |
| this docs site | A client-side Clerk gate via @tedos/auth/react — the gate renders ungated when no publishable key is configured, so local dev and the build never break |
Tenancy + roles
In the product, a Clerk organization is a tenant (= a project = a client). A user's org membership maps to a project role (Owner · Sales · Finanzas · Soporte · Alumno); the operator is superadmin. Tenant scoping is enforced server-side, never trusted from the client. See Product SoR → Roles.
The docs gate
This documentation site is itself Clerk-gated. The gate is a client module that reads the Clerk publishable key from a build-time custom field; when the key is unset (local dev or an unconfigured build) the gate renders ungated so the site always builds. The gate must stay intact when this site changes.