Sistema de Registro del producto
El Sistema de Registro del producto (SoR) es la capa de datos de cara al cliente — datos del
tenant, modelados en @tedos/domain (Drizzle/Postgres) en un esquema Postgres product dedicado.
Es separado del grafo del Plan Engine del flujo de trabajo: los dos nunca
comparten tablas (ver la separación de las dos bases de datos en
Mapa de la plataforma).
Se entregó en el esfuerzo E1 (la "MVP slice 1 de Comprender"), centrado en identidad: una persona única y unificada deduplicada entre los canales de un cliente, con datos fiscales, sobre infra real con tenancy + roles del lado del servidor. Comprender es el tenant #1 — ver Comprender.
Qué entregó E1
- Un paquete SoR del producto —
@tedos/domain— en un esquema Postgresproductdedicado. - Un contrato compartido congelado en
@tedos/shared(zod-como-fuente + tipos TypeScript inferidos) paraproject/person/person_identitymás las formas de los endpoints. Tanto la API como el admin lo importan — consistencia por construcción. - Auth + tenancy en
apps/api(Clerk): una guardiarequireProjectmapea una org de Clerk →projectId+ rol; el operador es superadmin. Cada ruta/p/:id/*se autoriza del lado del servidor. - Un shell de admin de dos niveles (plataforma + contexto de proyecto) — ver admin.
- Dedupe por clave de coincidencia (email / teléfono / RFC): la misma persona desde dos canales se unifica en un registro, con una auditoría de fusión append-only.
Modelo de datos (@tedos/domain, esquema product)
| Tabla | Propósito |
|---|---|
project | El tenant (= una org de Clerk = un cliente) — clerk_org_id, name, status, domain |
person | Una persona unificada dentro de un proyecto — full_name, email, phone, rfc (PII fiscal, enmascarada en presentación) |
person_identity | Un registro de fuente/canal para una persona — channel, external_ref, raw (jsonb) |
person_merge | Log de auditoría de fusión append-only |
Claves de coincidencia — casi-únicas en (project_id, email), (project_id, phone),
(project_id, rfc); el servicio de fusión/dedupe enlaza con ellas. El alcance por tenant
(project_id) es obligatorio en cada fila de producto.
Superficie API (apps/api, Fastify v5)
Todas las rutas detrás de la guardia de auth/tenancy (org de Clerk + rol; superadmin = cualquier proyecto). El alcance por tenant es del lado del servidor, nunca confiado del cliente.
| Método | Ruta | Qué |
|---|---|---|
GET / POST | /projects | Lista / crea los proyectos del operador |
GET | /projects/:id | Un proyecto |
GET | /p/:id/students | Lista + busca las personas del proyecto |
GET | /p/:id/students/:sid | Una persona (vista única) |
POST / PATCH | /p/:id/students | Crea / actualiza una persona |
POST | /p/:id/students/merge | Fusiona dos personas (dedupe) |
GET | /p/:id/summary | Resumen del proyecto |
El admin alcanza estas a través de un proxy del lado del servidor, de modo que la sesión de Clerk + el contexto de tenant se inyectan en el servidor — ver admin.
Roles
Una membresía de org de Clerk mapea a un rol de proyecto: Owner · Sales · Finanzas · Soporte ·
Alumno. El operador es superadmin (cualquier proyecto). El rol restringe la navegación de Nivel 2
(admin) y la autorización en cada ruta /p/:id/* (API).
Aislamiento: esquema-por-cliente
E1 entregó un único esquema product. El siguiente paso de arquitectura (ADR-007) mueve a
aislamiento esquema-por-cliente — un clúster Postgres, un esquema por proyecto, un esquema de
control/registro para la lista de proyectos, y un accesor de BD con alcance por tenant que
selecciona el esquema. Esto hace trivial una exportación limpia por cliente ("los clientes son
dueños de sus datos y pueden exportarlos"). Ver
Datos, memoria y asistente.
La regla dura
Según ADR-006, los datos de tenant/cliente nunca entran al grafo del flujo de trabajo. El SoR
del producto (esquema product) y el grafo del Plan Engine (esquema plan) nunca comparten tablas.
Tal como está construido, ambos esquemas viven hoy en el mismo clúster Fly Managed Postgres — un
compromiso documentado (aún no hay datos reales de tenant) con una ruta de actualización registrada
hacia un clúster dedicado antes de volumen real de PII de tenant. Ver Decisiones
(ADR-006/007).