metis-desk/docs/dominios-windows.md
2026-10-20 13:20:22 +02:00

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 normalizedDns en minúsculas. Empresa.Local. y empresa.local comparten 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 environmentId impide 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 opcionales directory ú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/companies y @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.ts pasan también de forma dirigida.
  • test:directory-domains: integración real en metis_desk_test aprobada, incluidos rollback y concurrencia; datos propios eliminados al finalizar.
  • Las 11 pruebas de @metis/relationship-contracts siguen 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/server y git 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.