Toda entidad de negocio de Metis Desk, tanto raíz de agregado como entidad interna, tiene un identificador global único UniqueID. Se genera como UUID v7, igual que en factuges-erp. Clientes, personas, departamentos, asignaciones, revisiones, sedes/ubicaciones, documentos, tickets, intervenciones, assets, contratos y las demás entidades seguirán esta regla.
La identidad no depende de nombres, correos, referencias visibles ni claves numéricas incrementales. No cambia al actualizar, activar o archivar. Las relaciones entre entidades usan el UniqueID de la entidad referenciada.
Los UUID anteriores válidos, incluidos los v4 de usuarios ya creados, se conservan al leer y escribir. No se reasignan identificadores ni se reescriben relaciones. UniqueID.create valida un identificador recibido; UniqueID.generateNewID genera uno nuevo.
Los identificadores viajan como cadenas UUID en DTOs y se validan con z.uuid. Dentro del dominio y de los puertos de repositorio se usa UniqueID, no string. Infrastructure convierte a la representación persistida. La clave primaria y las claves foráneas se declaran explícitamente en las migraciones.
El marcador técnico de configuración y el identificador opaco de cookie de express-session no representan entidades de negocio y mantienen sus contratos de infraestructura.
## Declaraciones
packages/rdx-ddd proporciona la base compartida, independiente del filesystem del ERP:
- ValueObject: valor escalar inmutable e igualdad semántica por valor y tipo. Los Value Objects no tienen identidad.
- UniqueID, Name y EmailAddress: Value Objects compartidos con create, getProps, toPrimitive, toString y equals.
- DomainEntity: identidad UniqueID y propiedades de dominio. La igualdad se basa en identidad y tipo, independientemente de los atributos.
- AggregateRoot: entidad que delimita una unidad de consistencia y es persistida por su repositorio.
La dependencia uuid 13 se usa para generar UUID v7, como en el ERP; se evita implementar un generador propio.
Se conserva la organización y los nombres del ERP, con tipos estrictos y sin copiar sus dependencias o utilidades no utilizadas. Esta base escalar no introduce comparación genérica de objetos compuestos ni un bus de eventos sin consumidores.
Las raíces se declaran en archivos *.aggregate.ts; las entidades internas en *.entity.ts. Los Value Objects específicos de un módulo viven en domain/value-objects. Domain permanece libre de Express, DTOs de transporte y Sequelize. La validación propia de los Value Objects puede usar Zod, igual que en el ERP.
## Ciclo de vida y fronteras
create valida invariantes de creación y devuelve Result. La nueva raíz genera su UniqueID cuando no recibe uno explícito. rehydrate exige el ID persistido, no genera otro y no aplica reglas de alta ni emite eventos. update aplica invariantes de actualización y compara valores con equals.
En esta entrega los agregados devuelven una instancia nueva al cambiar; una actualización semánticamente idéntica devuelve la misma instancia. Todas conservan el UniqueID original.
Application adapta DTOs a Value Objects mediante InputMapper. Los errores de entrada esperados se devuelven como Result. Los repositorios aceptan identificadores y valores de dominio.
Infrastructure reconstruye los Value Objects mediante create antes de llamar a rehydrate. Un valor persistido inválido provoca un error de consistencia sin incluir datos sensibles; no se oculta ni se reemplaza por un valor generado. toPersistence serializa primitivas. Los builders HTTP también serializan primitivas y solo exponen los campos previstos por el DTO.
## Aplicación actual y siguientes módulos
User es la raíz del agregado de identidad. Sus Value Objects son UniqueID, Name, EmailAddress y PasswordHash. Conserva las invariantes del administrador inicial, la activación y la invalidación de sesiones.
Company es la raíz del agregado de compañías clientes. Person, Department, DepartmentAssignment y Site son entidades internas con UniqueID propio y referencia UniqueID a su compañía. AssignmentRevision conserva cada versión de una asignación y tiene su propio UniqueID. Los contactos son personas con isContact=true. Name, EmailAddress, PhoneNumber, CalendarDate y SiteAddress representan sus valores; los campos opcionales usan Maybe. Las reglas de pertenencia, periodos y departamento principal se resuelven dentro de Company. El repositorio carga y guarda el agregado completo dentro de una transacción con bloqueo de la compañía.
AccessWorkspace es una raíz adicional para el catálogo global o la configuración informática de una compañía. Cada espacio conserva su propio UUID. AccessItem y AccessRevision son entidades con UUID propio. AccessValues encapsula la definición tipada e inmutable, con identificadores y fechas reconstruidos como UniqueID y CalendarDate. Las referencias relacionales preservan las dependencias y el historial conserva el actor autenticado. Consultar [Cuentas, grupos y recursos](../cuentas-grupos-y-recursos.md).
AssetCatalog es la raíz del catálogo de activos; AssetDefinition, TemplateField y CatalogAvailability son entidades con UUID propio. AssetDefinitionValues reconstruye nombres y referencias como Value Objects. Consultar [Campos y plantillas de activos](../campos-y-plantillas-de-activos.md).
Asset es la raíz de cada activo real y AssetRevision una entidad con UUID propio, instantánea de valores, actor y fecha. AssetValues y AssetSpecification son Value Objects inmutables. La especificación capturada conserva los campos y reglas de la ficha aunque cambie el catálogo. Consultar [Inventario de activos](../inventario-de-activos.md).
Los módulos de documentos y tickets todavía no existen. Se declararán como agregados o entidades al implementar sus operaciones y reglas de consistencia. La decisión de pertenencia a un agregado se toma por sus invariantes y transacciones; no convierte automáticamente cada tabla en una raíz ni fuerza todo el cliente y sus tickets dentro de un solo agregado.
Cada entidad que se incorpore deberá tener UniqueID desde su primera implementación, mapper de persistencia y pruebas de identidad, invariantes, rehidratación y actualización.