15 KiB
Dominios Windows · Modelo e identidad (paso 2.1)
Un dominio Windows se registra como Resource. Conserva el UUID, nombre, compañía,
estado, notas, características e historial nativos. No existe una nueva raíz
WindowsDomain, ni depende de un activo, servidor o controlador.
Catálogo y capacidad
La semilla añade la plantilla Dominio Windows al final del catálogo, sin cambiar la selección inicial ni el orden de las plantillas anteriores. Contiene Nombre DNS (texto obligatorio) y Nombre NetBIOS (texto opcional). No duplica el nombre o estado del recurso. La inicialización es idempotente y no repone los nombres personalizados.
La clave persistida e inmutable stockKey = template:windows_domain se traduce
explícitamente a directory:domain mediante resourceTemplateCapability. Se
reutiliza la clasificación ya existente: stockKey no forma parte del contrato
editable del catálogo. No se deduce por nombre visible, idioma, UUID o presencia de
campos. Las claves de campo field:domain_dns y field:domain_netbios identifican
los campos semánticos cuyos UUID se generan mediante UniqueID, como los demás.
No hay un motor universal ni un catálogo de capacidades independiente. La función
podrá ampliarse con otra correspondencia explícita cuando exista un consumidor de
network:smb-share. Una plantilla creada por el usuario con los mismos nombres
no adquiere la capacidad. Renombrar o reordenar la plantilla conserva su semántica.
Se impide retirar DNS/NetBIOS y hacer opcional DNS; el tipo texto de los campos se
protege con las reglas existentes de edición del catálogo.
Identidad y validación
DirectoryDomainValues valida los datos documentales, sin consultar DNS o AD:
- Elimina espacios exteriores y un único punto final DNS. Conserva las mayúsculas
del nombre introducido y obtiene
normalizedDnsen minúsculas.Empresa.Local.yempresa.localcomparten clave de negocio. - Rechaza vacío, espacios interiores, protocolos, direcciones numéricas, etiquetas vacías, guiones en extremos y caracteres fuera de letras ASCII, números y guiones.
- Admite etiquetas de hasta 63 caracteres y un nombre AD de 2 a 64 caracteres. Se aceptan etiquetas únicas heredadas; registrarlas no es una recomendación para desplegar nuevos dominios de etiqueta única.
- Política IDN v1: se introduce el A-label ASCII (punycode), por ejemplo
xn--espaa-rta.local. No se convierte silenciosamente Unicode ni se utilizan bibliotecas nuevas o resoluciones de red. - NetBIOS es opcional, se recorta y normaliza a mayúsculas, con máximo 15 caracteres, sin caracteres de control, separadores reservados ni nombres exclusivamente numéricos. No se impone que coincida con la primera etiqueta DNS.
La política ASCII y los límites de AD se apoyan en las convenciones de nombres de Microsoft. La elección de A-label explícito y el registro de etiquetas únicas heredadas son políticas documentales de Metis; no certifican que exista o sea desplegable el dominio.
El mapper de entrada normaliza las características antes de crear o actualizar
ResourceValues. El repositorio vuelve a obtener la identidad semántica antes de
proyectarla. Actualizar el DNS cambia características y proyección en la misma
transacción y conserva el UUID. También los cambios de estado pasan por esa
comprobación. La propagación de plantillas conserva los campos semánticos y sus
valores; no puede retirar el DNS obligatorio de la plantilla de dominio.
Contexto de accesos y responsabilidad modular
Se elige creación automática de un contexto dedicado. Al crear el primer dominio
de una compañía, Companies crea un AccessItem(system) clasificado como AD. Cada
dominio obtiene un AccessItem(environment) propio dentro de ese sistema. Un
segundo dominio reutiliza el sistema clasificado y obtiene otro entorno. Los nombres
visibles no clasifican sistemas: un sistema anterior llamado «Active Directory» no
se adopta automáticamente. Si su nombre impide crear el sistema dedicado, se devuelve
un conflicto de contexto y se revierte el alta; no se reasignan cuentas existentes.
La vinculación o adopción explícita de entornos anteriores queda fuera de este paso.
Resources es propietario de la identidad DNS y del vínculo con el entorno.
Companies conserva sistemas, entornos, cuentas, grupos y pertenencias. Se reutilizan
sus agregados, políticas, validaciones, persistencia e historial; no se crean cuentas
ni grupos en Resources. Identity sigue reservado a usuarios de autenticación Metis.
El contrato público nuevo es IDirectoryContextWriter, exportado por
@metis/resources/services. No contiene ORM, HTTP ni operaciones genéricas. Companies,
que ya depende de Resources, lo implementa. Su composition root devuelve
directoryContexts(transaction): IDirectoryContextWriter. El servidor inyecta esa
factoría en createResourceModule. La transacción solo aparece en composición e
Infrastructure; Application consume el puerto ya vinculado a ella. No hay import
Resources → Companies, dependencias nuevas, imports privados entre módulos ni
cambios en @metis/relationship-contracts.
SequelizeResourceRepository.save coordina un único commit. Resource, su historial,
el sistema/entorno, sus revisiones, referencias y la asociación se guardan con la
misma conexión y transacción Sequelize. Un Result de fallo posterior a escribir se
convierte en excepción interna para provocar rollback y se traduce de nuevo a
Result fuera del callback gestionado. No se coordinan peticiones HTTP separadas.
Orden de bloqueos al guardar con el participante configurado: catálogo de recursos, catálogo global de accesos, compañía y workspace. Mantiene el orden usado por los repositorios de catálogo y accesos, y serializa altas concurrentes. Las restricciones SQL siguen protegiendo frente a escrituras ajenas a esa coordinación.
Persistencia relacional
Las migraciones explícitas siguen el mecanismo de arranque existente, con tablas,
índices y restricciones completables al repetirse. Solo se han ejecutado contra
metis_desk_test durante este trabajo, nunca contra datos de desarrollo o producción.
| Tabla | Responsabilidad y restricciones |
|---|---|
access_directory_systems |
Clasifica un sistema AD por workspace de compañía. PK systemId, unicidad de workspace, FK a (id, workspaceId, kind) de access_items, CHECK kind=system y FK de compañía al workspace. |
access_directory_environments |
Clasifica los entornos de ese sistema. PK environmentId, FK al AccessItem de tipo environment, FK al sistema clasificado del mismo workspace y compañía, clave compuesta para referencias desde Resources. |
resource_directory_domains |
Proyección mínima: PK/FK resourceId, compañía, plantilla, DNS normalizado, entorno y actor/fecha de asociación. No copia nombre, estado, notas, NetBIOS ni historial del recurso. |
En la proyección de dominios:
- UNIQUE
(companyId, normalizedDns)incluye dominios desactivados. Un mismo DNS se admite en compañías distintas. - UNIQUE
environmentIdimpide asociar dos dominios al mismo entorno. - FK compuesta a
(id, companyId, templateId)de Resources garantiza compañía y plantilla; otra a(id, stockKey)del catálogo y un CHECK restringen la semántica a la plantilla de dominio, sin codificar su UUID. - FK
(environmentId, companyId)exige un entorno AD clasificado de esa compañía. - FK al actor y fecha inmutables trazan la creación de la asociación. El historial Resource audita nombres, DNS, NetBIOS y estado; AccessRevision audita el contexto.
- DNS se almacena en columna ASCII con comparación binaria, CHECK de no vacío y representación canónica sin mayúsculas, espacios exteriores ni punto final.
- Los índices compuestos auxiliares de las tablas raíz permiten las FK de tipo, compañía y plantilla. No son identidades de negocio adicionales.
Las identidades auxiliares son las de Resource y AccessItem, no UUID sustitutos de
esas entidades. No se usa JSON. Ninguna FK nueva apunta a
access_environment_values o access_system_values: esas tablas se borran y
reinsertan al editar. El sistema de un entorno ya es inmutable por el dominio
AccessItem; se protege además la desactivación lateral de contextos clasificados.
Las escrituras válidas siguen pasando por los agregados de Companies.
Operaciones e interfaz
Se mantienen los endpoints existentes de Resources:
POST /api/resources/:companyId: alta mediante la plantilla de dominio.POST /api/resources/:companyId/:id/update: nombre, notas y características, incluidos DNS y NetBIOS.GET /api/resources/:companyId: consulta con metadatos opcionalesdirectoryúnicamente cuando existe una asociación real confirmada.GET /api/resources/:companyId?environmentId=<uuid>: consulta inversa, filtrada por compañía. Valida query estricta y no crea un endpoint transversal nuevo.POST /api/resources/:companyId/:id/status: activa o desactiva el Resource sin desactivar el entorno ni sus cuentas/grupos.
directory contiene capacidad, DNS normalizado y UUID de sistema y entorno; los
nombres editables DNS/NetBIOS siguen en las características. No se aceptan estos
metadatos de salida como privilegios o asociación de entrada. Se conserva la
protección de autenticación/sesión del router y el ámbito de compañía existente.
No se añade una ACL nueva ni se confunden grupos externos con permisos Metis.
El formulario actual muestra DNS/NetBIOS y ayuda contextual inferior es/en. Antes de guardar indica que el contexto se creará, sin simular que ya existe. En edición presenta los nombres del sistema y entorno realmente asociados. Se reutilizan selector, campos, estados, historial y diálogo existentes; no hay pantallas nuevas.
El contexto es fijo: no hay sustitución, traslado ni desvinculación en este paso. Cambiar DNS tampoco renombra silenciosamente el entorno existente: el vínculo sigue siendo su UUID, aunque su etiqueta documental conserve el nombre inicial o sea editada desde accesos. Las cuentas y grupos mantienen sus referencias.
El borrado definitivo continúa usando la protección por referencias de Resources: la asociación estructural impide eliminar un dominio vinculado, incluso sin cuentas. La operación soportada para retirarlo es desactivarlo; se reserva el DNS y se conserva trazabilidad. Liberar o eliminar contextos requerirá una política explícita posterior, sin borrar cuentas/grupos silenciosamente.
Pruebas y alcance restante
Las pruebas nuevas cubren clasificación, renombrado, plantilla protegida, normalización y límites DNS/NetBIOS, contexto dedicado, referencias incompatibles, compañía, conservación de UUID/historial e idempotencia de semillas. El formulario se verifica en es/en para estados pendiente y confirmado.
La integración dedicada pnpm --filter @metis/server test:directory-domains exige
NODE_ENV=test y DB_NAME=metis_desk_test. Usa UUID de fixture, no limpia datos
ajenos y cierra conexiones. Comprueba repetición de migraciones, dos altas concurrentes,
unicidad y FK reales, compañía, lectura directa/inversa por HTTP, edición legítima de
valores de entorno, cuentas/grupos conservados, archivo, borrado protegido y rollback
tras crear contexto. El script usa el runner nativo con tsx y sin aislamiento por
subprocesos para ejecutar y enumerar los casos en este entorno.
No se implementan LDAP, descubrimiento, sincronización, controladores, equipos unidos, relaciones con activos, SMB, FolderMapping, paneles de cuentas/grupos ni navegación mediante Typed Relationships. No se modifica Asset, Workstation o WorkProfile.
Verificación de esta entrega
- Typecheck de
@metis/resources,@metis/companiesy@metis/server: correcto. - Biome check y ESLint de los 38 ficheros de código/configuración afectados: correctos.
- Suite Resources, ejecutada con el script del paquete y
--test-isolation=none: 53/53 pruebas aprobadas. - Suite Companies con el mismo modo del runner: 169/171 aprobadas. Fallan dos
expectativas de textos en
companies-page.test.tsx(líneas 180 y 210), sobre «Personas (1)» y «Esta persona no tiene acceso a Metis Desk». Sus pruebas y componentes de pantalla no se han modificado. No se han eliminado ni omitido para presentar un resultado global satisfactorio. - Las cuatro pruebas nuevas de
directory-context-plan.test.tspasan también de forma dirigida. test:directory-domains: integración real enmetis_desk_testaprobada, incluidos rollback y concurrencia; datos propios eliminados al finalizar.- Las 11 pruebas de
@metis/relationship-contractssiguen aprobadas, sin cambios en el paquete durante el paso 2.1. - Grafo de los 13 paquetes del workspace sin ciclos; se conserva la dirección Companies → Resources.
- Build de
@metis/serverygit diff --check: correctos.
No se ejecuta la suite global de persistencia ni se aplica ninguna migración a
bases de desarrollo o producción. En este entorno PNPM requiere
--config.verify-deps-before-run=false para ejecutar los comandos con las
dependencias ya instaladas; no se añade esa opción a la configuración del proyecto.
Archivos principales
| Ámbito | Archivos |
|---|---|
| Semántica y transporte | modules/resources/src/common/resource-capabilities.ts, directory-domains.ts, inventory.ts, index.ts, resource-template-icons.ts y traducciones locales/es.json, locales/en.json. |
| Dominio y catálogo | modules/resources/src/api/domain/value-objects/directory-domain-values.vo.ts, resource-catalog-seed.ts, resource-catalog.aggregate.ts y pruebas de dominio/catálogo. |
| Aplicación Resources | modules/resources/src/api/application/directory-context-writer.ts, directory-domain-input.ts, resource-input.mapper.ts, resource.repository.ts, resource-response.builder.ts. |
| Persistencia y API Resources | modules/resources/src/api/infrastructure/persistence/directory-domain-migration.ts, directory-domain-projection.ts, sequelize-resource.repository.ts; infrastructure/http/resource.routes.ts, api/module.ts y api/services.ts. |
| Contexto Companies | modules/companies/src/api/application/directory-context-plan.ts y su prueba; infrastructure/persistence/directory-context-migration.ts, directory-context-writer.ts, access-persistence.ts y api/module.ts. |
| Formulario existente | modules/resources/src/web/resources/shared/controllers/use-resource-form-controller.ts, ui/resource-form.tsx, ui/resource-fields.tsx y resources.test.tsx. |
| Composición y ejecución | apps/server/src/infrastructure/http/identity-runtime.ts, apps/server/src/directory-domains.integration.test.ts y scripts en los package.json de servidor, Resources y Companies. |
Integración visual · Paso 2.4
La ficha de recurso compone ahora las pertenencias y la navegación contextual a cuentas/grupos. La ficha de activo permite consultar, asociar, cambiar rol, trasladar y finalizar pertenencias con los comandos existentes. Véase integración visual de dominios Windows para rutas, paginación, componentes, pruebas y límites.