# Auditoría arquitectónica — Catálogo global de sistemas operativos Fecha: 25 de octubre de 2026. Estado: **auditoría y propuesta pendiente de aprobación**. No autoriza implementación, cambios de catálogo, activación de gates, consolidación ni migraciones. ## 1. Resumen ejecutivo La plantilla real es `template:os`, denominada inicialmente «Sistema operativo», con uso explícito `os`. Sus características de serie son **proveedor, edición o plan y descripción**, todas opcionales. El nombre comercial es `Resource.name`, no una característica de esa plantilla. No hay campos propios de familia o versión principal ni un catálogo normalizado de fabricantes [E01–E04]. El catálogo global continúa limitado a aplicaciones de la plantilla stock `template:application`. La limitación aparece en captura de especificación, elegibilidad, DTO, lectores, administración y navegación. El agregado `Resource` y el esquema scoped son más generales que esa política: no basta con que una fila admita `scope: global` para que el sistema soporte un SO global [E05–E12]. `SoftwareInstallation` ya referencia el producto por UUID, mantiene compañía, activo, versión, estado y licencia particular y puede incorporar referencias globales mediante el servicio público de Resources. **Es razonable reutilizar su contrato persistido y DTO operativo sin añadir otro identificador de producto**, siempre que se amplíen las referencias públicas y todos los consumidores pertinentes. No puede hacerse hoy cambiando solo un gate o una allowlist [E13–E17]. Recomendación preliminar por ejes: 1. **Identidad: A + E.** Un Resource por producto completo —familia, versión principal y edición cuando distingue producto—, con UUID como identidad y características declarativas estructuradas. E complementa la granularidad de A; no exige entidades jerárquicas. 2. **Alcance: opción 1 acotada.** Reutilizar Resources y su infraestructura global, admitiendo específicamente `template:os` además de aplicaciones, con consultas/contratos discriminados por tipo. Conservar los contratos de aplicaciones y la exclusión del SO en perfiles. No crear un catálogo persistido paralelo ni generalizar todos los recursos. 3. **Convivencia: preservar particulares.** Incorporar globales para selecciones nuevas, con procedencia visible; no reemplazar referencias ni deducir equivalencia por texto. Una posible preferencia visual es una decisión aparte. La adopción/sucesión D08.2 **sigue sin ratificar ni implementar** en las fuentes examinadas [E18–E20]. Confianza alta en el diagnóstico de código y en reutilizar Resource/SoftwareInstallation; media en las reglas semánticas de identidad, que necesitan aprobación funcional. No se conocen los datos ni los gates efectivos de una instalación real. ## 2. Estado actual y método Base inspeccionada: HEAD `91f1d07e975e25723fe28358f6fa7b6b2dde07cc`, con cambios locales previos y trabajo concurrente principalmente de ayuda contextual y diálogos. La evidencia corresponde al **árbol de trabajo**. No se modifican sus archivos; la entrega propia es este informe. Se contrastaron dominio, casos de uso, validación, servicios públicos, DTO, HTTP, consultas, migraciones existentes, frontend y pruebas. Se consultaron los antecedentes de [SO en activos/puestos](auditoria-sistemas-operativos-activos-y-puestos.md), la [decisión del resumen actual](decision-so-actual-en-activos-y-puestos.md), [software del ordenador](../software-del-ordenador.md), normativa modular, documentación R2.0–R2.6 y el acta de D08.2. No se reabre la propiedad del SO instalado. Clasificación de afirmaciones: | Marca | Significado | | --- | --- | | **V** | Verificado estáticamente en el código o documentación vigente citados. | | **T** | Probado en esta auditoría mediante los tests de §19. | | **I** | Inferencia arquitectónica sustentada en los contratos; no funcionalidad instalada. | | **P** | Propuesta pendiente de aprobación y desarrollo. | Salvo indicación P/I, las descripciones del estado actual son V. Las pruebas no convierten los modelos propuestos en funcionalidad disponible. Una migración leída no demuestra que una BD desplegada la tenga aplicada. Node `v24.20.0` y PNPM `11.25.0` concuerdan con `package.json`; herramientas ejecutadas en WSL/bash. No se leen `.env` ni credenciales, no se consulta BD real ni se crean datos maestros. Se revisan UX y contratos por código, DESIGN, patrón de diálogos y matriz de skills, sin mockups ni navegador. ## 3. Auditoría de la plantilla SO ### 3.1. Definición y significado real `template:os` es un **stockKey estable de definición**, expuesto como `builtinKey` en DTO. No es el UUID de un producto ni un UUID universal fijo de plantilla. Los registros y definiciones tienen identidades UUID propias. La plantilla tiene nombre editable, descripción inicial vacía, icono de serie y `usage: os`. Las copias y plantillas propias con uso explícito también pueden servir para SO particulares; ese uso no las convierte en globales [E01–E04]. La tabla siguiente describe la definición de serie del código; no certifica los bindings efectivos de una plantilla que haya sido editada en una instalación. El seed crea definiciones, no productos Windows, Ubuntu u otros. En esta auditoría no se leen inventarios persistidos: no se verifica cuántos SO particulares existen ni cómo están cumplimentados. Los nombres de pruebas son datos sintéticos. | Campo real | Tipo actual | Obligatorio | Utilidad | Problemas | Recomendación P | | --- | --- | --- | --- | --- | --- | | `Resource.name` | Texto, 1–100; Name normaliza su valor | Sí | Nombre comercial y selección | Puede contener fabricante, versión, edición o arquitectura sin estructura | Conservar nombre legible; proponer etiqueta coherente, sin renombrar registros automáticamente | | `field:provider` | Característica `text`, hasta 10 000 | No | Proveedor/fabricante/distribuidor documental | Texto compartido con otras plantillas; no FK ni fabricante canónico | Reutilizar con semántica SO definida; no renombrar globalmente el campo | | `field:software_edition` | Característica `text`, hasta 10 000 | No | Edición/plan | Ayuda orientada también a licencias; ausencia ambigua | Conservar; definir significado de edición e incompleto/no aplicable antes de publicar globales | | `field:description` | Característica `text`, hasta 10 000 | No | Descripción del producto | No sustituye campos de identidad; no está en el índice de búsqueda actual | Mantener descriptiva, sin extraer automáticamente identidad | | `Resource.notes` | Texto general, hasta 10 000 | Propiedad exigida por DTO; admite vacío | Notas administrativas | No es el campo description ni metadato público de identidad | Conservar notas; no usarlas para claves o atributos estructurados | | `Resource.active` | Boolean | Sí | Disponibilidad para nuevas asociaciones | No significa soporte vigente, licencia válida o instalación efectiva | Conservar su semántica actual | | `templateId` | UUID, fijo al editar | Sí | Referencia a definición/especificación | Una copia tiene identidad distinta | Global SO solo con plantilla stock real, salvo futura decisión expresa | No hay valores de producto predeterminados en la plantilla. Las descripciones de campos son ayuda, no datos que rellenar automáticamente. Las referencias de los tres campos de SO tienen `required: false`; no tienen listas de opciones ni relaciones de fabricante/familia [E01–E04]. ### 3.2. Validación, persistencia, historia e idioma Los contratos Zod son estrictos; `characteristics` identifica campos mediante UUID y admite valores escalares. `ResourceValues.create` comprueba pertenencia a la especificación, tipo, opciones exactas de `choice`, fecha ISO y obligatoriedad; recorta texto y omite valores vacíos. `reconstruct` permite reconstruir registros anteriores incompletos. No hay validación semántica fabricante–familia–versión–edición [E02–E04]. Se guardan columnas tradicionales en `resources`, `resource_characteristics`, especificaciones y tablas de revisiones. `resource_characteristics` tiene clave por recurso/campo y columnas `textValue`, `numberValue`, `booleanValue`, `dateValue`. No se persiste una ficha SO como JSON. `ResourceRevision` conserva valores, especificación, actor y fecha; UUID, ámbito y plantilla no se reasignan al editar [E03, E11]. Añadir un campo al seed **no garantiza incorporarlo a una plantilla ya existente**. `ResourceCatalog.seed` conserva la definición previa mediante su enriquecimiento permitido; no sustituye sus bindings por los nuevos. La modificación explícita de plantilla tiene propagación transaccional que conserva estructura histórica y trata campos retirados con valor. Exigir nuevos datos globalmente puede dejar particulares incompletos o bloquear futuras ediciones; necesita plan específico, no modificación ciega del seed [E04]. Los formularios particulares y globales reutilizan React Hook Form, Zod y controles declarativos. Los tipos de catálogo disponibles son text/number/date/boolean/choice; no hay aquí una relación tipada entre valores de dos características ni listas dependientes. Las opciones choice son valores textuales compartidos; el tipo del campo y las opciones anteriores tienen restricciones de edición [E02, E04, E23]. Hay traducciones es/en de interfaz, uso `os`, acciones y estados. Sin embargo, `ResourceIdentityFields` y `ResourceCharacteristicControl` muestran nombres de plantilla/campo recibidos en datos: el seed los crea en castellano y esos componentes no traducen automáticamente `field.name`. La existencia de `usage.os = Operating system` no prueba traducción completa de los metadatos del catálogo. Es una limitación a resolver expresamente en nuevos campos, sin sobrescribir nombres personalizados [E23, E24]. ## 4. Modelo de identidad del SO **V:** la identidad real es el UUID de Resource; no nombre, provider, edición ni combinación dinámica. El producto particular pertenece a compañía; el global tiene dueño NULL. Crear de nuevo con otro UUID puede representar otro producto con descripción equivalente. La idempotencia por `creationId` evita repetir una misma solicitud, no garantiza unicidad comercial [E03, E05–E08]. **P — A + E:** un Resource representa un producto seleccionable completo. Una tupla candidata para revisar identidad semántica es: `tipo SO + proveedor/fabricante canónico + familia + versión principal del producto + edición aplicable` No es una nueva PK ni un identificador compuesto que sustituya UUID. Arquitectura, canal o SKU solo entrarían en la identidad si el negocio confirma que distinguen productos que deben seleccionarse por separado. La composición no es una jerarquía universal ni obliga a crear entidades para cada nivel. Ejemplos conceptuales aportados por la solicitud: Windows 10 y Windows 11 serían recursos distintos; Windows 11 Home y Pro también. Windows Server 2022 Standard y Datacenter serían productos distintos. Para Ubuntu 24.04 LTS Desktop/Server debe aprobarse si esa distinción representa el producto que Metis necesita inventariar o solo la configuración de instalación. No se crea un catálogo maestro con estos ejemplos ni se presupone equivalencia comercial de sus etiquetas. La edición es **opcional en el modelo conceptual**, porque no todos los productos la tienen; una edición desconocida no equivale a «no aplica». La publicación de globales activos debe requerir identidad suficiente y revisión de esa diferencia. Antes de implementar se decide cómo expresarla: regla de admisión y revisión del catálogo, o característica declarativa de aplicabilidad si se necesita persistir la distinción. No inventar «Standard» o «Sin edición» como valor de relleno. ## 5. Familia, versión, edición y campos candidatos La relación fabricante → familia → versión → edición ayuda a describir y buscar, pero no es obligatoriamente una cadena de entidades. Debe admitir productos sin edición, distribuciones/proveedores distintos, nombres no numéricos y productos con varias arquitecturas. No asumir que proveedor, fabricante y distribuidor son sinónimos universales. | Concepto evaluado | Equivalente actual | Propietario conceptual | Admisión recomendada P | Lista controlada | Declarativo existente / valor para esta fase | | --- | --- | --- | --- | --- | --- | | Fabricante/proveedor | `provider` texto | Producto; puede diferir del vendedor de la licencia | Exigir dato revisado para nuevos globales activos; no exigirlo retroactivamente a particulares | Vocabulario curado útil; no nueva entidad ahora | Sí, campo existente; definir rol y normalización | | Familia | Sin campo específico | Producto | Añadir `os_family` como clave propuesta, obligatoria para nuevos globales activos | Texto curado inicialmente; choice solo con gobernanza/lista aprobada | Sí; aporta búsqueda, comparación y claridad | | Nombre comercial | `Resource.name` | Producto | Obligatorio y legible; sugerencia/validación, edición consciente | No enum | Sí, raíz existente; no requiere otro campo nombre | | Versión principal | Solo implícita en nombre/notas | Producto | Añadir `os_product_version` propuesto, texto obligatorio para nuevos globales activos | No numérica ni enum universal | Sí; distingue 10/11, XP o releases completos según producto | | Edición | `software_edition` | Producto cuando diferencia producto | Completa cuando aplica; decidir no aplica/desconocida | Vocabularios por familia, sin imponer lista universal | Sí; conservar campo y revisar ayuda específica | | Arquitectura | Sin campo SO de serie | Instalación efectiva; también puede restringir producto/SKU | Diferir salvo necesidad real; no parte de clave por defecto | Choice acotado solo si se aprueba | Un campo de producto documenta compatibilidad, no arquitectura efectiva de cada instalación | | Canal de distribución | Sin equivalente SO | Producto/paquete o instalación, según significado | Diferir; separar canal de actualizaciones de adquisición | Solo tras definir semántica | Sí si es dato documental; no mezclar retail/OEM con canal técnico | | Modalidad de licencia | `license_model` en plantilla licencia | Recurso licencia/contrato particular | Mantener allí; no duplicarla por cada SO | Ya hay Suscripción/Perpetua/OEM/Otra | No necesita ampliación del SO global | | SKU | MPN/referencia de licencia no equivalen a SKU SO universal | Producto comercial/paquete | Opcional futuro con emisor definido | No enum | Texto posible; varios SKU no deben forzar una identidad por cadena sin criterio | | Fecha de lanzamiento | Sin campo SO de serie | Release del producto al nivel que describa | Diferir salvo consumidor real; opcional con fuente | No | `date` posible; no necesaria para compartir productos | | Fin de soporte | Sin campo SO propio | Producto/release/edición/canal según fuente | Diferir y definir alcance exacto antes de usarlo | No | `date` posible; una fecha de producto mayor puede ser engañosa para distintas versiones instaladas | | Fin de soporte extendido | Sin campo propio | Política de soporte aplicable, no derecho adquirido | Diferir; fecha opcional si se conoce y se contextualiza | No | No acredita contratación ni licencia; no retirar instalaciones automáticamente | | Descripción | `description` | Producto | Opcional | No | Reutilizar | | URL oficial | `field:url` existe, pero no está enlazado a la plantilla SO stock | Producto | Ampliación opcional útil para documentación | No | Reutilizar definición si se aprueba el binding; no inventar otro campo URL | | Identificadores externos | Sin contrato específico | Producto con emisor/namespace y tipo | Diferir hasta tener integración | No universal | Un ID textual puede bastar para un consumidor; múltiples IDs exigirían diseño relacional, no JSON por defecto | **Alcance mínimo recomendado:** reutilizar provider/edición/descripción/nombre, proponer familia y versión principal y valorar URL. No añadir automáticamente el resto. Las claves nuevas de esta tabla son propuestas, no definiciones instaladas ni datos maestros aprobados. El campo URL existente es texto; no hay validación semántica de URL en la validación genérica de características. Las policies propuestas deben identificar campos por sus identidades/stockKey reales, no por nombres visibles o traducidos. No reutilizar `field:expires` como «fin de soporte del SO»: hoy participa en vigencia documental de recursos/licencias. Caducidad contractual y fin de soporte tienen significados distintos. No derivar estado `active`, `needsReview` o derechos de uso a partir de fechas nuevas sin una decisión adicional [E01, E13]. ## 6. Versión del producto frente a versión instalada **V:** `SoftwareInstallation.version` es un texto nullable de hasta 100 caracteres, sin gramática de fabricante, edición ni build separados. El dominio registra revisiones al cambiarlo y no añade revisión si los valores son semánticamente iguales. La pareja activo/producto es inmutable [E14–E16]. | Pregunta | Respuesta preliminar P y límite V | | --- | --- | | 1. ¿Windows 10 y 11 son recursos distintos? | Sí bajo A + E: cambia la versión principal del producto. No reclasificar automáticamente referencias actuales a partir del nombre. | | 2. ¿Windows 11 Home y Pro son distintos? | Sí si representan productos/ediciones distintas que el técnico debe seleccionar. La licencia sigue siendo una relación independiente. | | 3. ¿Actualización sin cambiar producto? | Actualizar `version` en la instalación actual; crea revisión conservando UUID, activo, producto y licencia. La disponibilidad se vuelve a comprobar cuando corresponda. | | 4. ¿Cambio de edición? | Si cambia el producto según la identidad aprobada, elegir otro Resource. El contrato actual no permite cambiar `resourceId` de una instalación; requiere otra raíz y un cierre correcto de la anterior. | | 5. ¿Actualización mayor: raíz o revisión? | Depende de si cambia el producto. Bajo A + E, cambiar Windows 10 por 11 implica producto y raíz nuevos; una actualización de mantenimiento del mismo producto implica revisión. Hoy no hay operación atómica de upgrade que cierre/cree ambas raíces. | | 6. ¿Qué conserva `version`? | Texto de versión/release efectivamente declarado para esa instalación. Puede contener datos históricos más amplios: no se debe convertir silenciosamente a una nueva semántica restringida ni parsear valores automáticamente. | | 7. ¿Hace falta build? | No para admitir productos SO globales. Diferir un campo `build` hasta tener consumidor y contrato. Si se aprueba, sería dato de instalación y de cada revisión; nullable para anteriores, con DTO/VO/mapper/migración y validación propia. | | 8. ¿Nombre completo? | Nombre de producto identificable —ejemplo conceptual Windows 11 Pro— más `version` de instalación —por ejemplo 24H2—; build solo si posteriormente existe. No convertir 24H2 o 26100.x en edición ni sustituir la versión principal del producto. | Ubuntu, Debian, Fedora, macOS, Windows Server y otros productos pueden usar convenciones distintas. Conservar texto permite números, puntos, nombres y sufijos; no imponer un único orden ni una conversión numérica. Para cada familia se deberá confirmar qué release distingue producto y qué detalle pertenece a la instalación. Los ejemplos no fijan reglas comerciales universales ni fechas de soporte. El resumen actual de SO evita repetir una versión literal ya incluida en el nombre, con límites alfanuméricos; es una regla de presentación, no un normalizador ni una prueba de identidad. El producto/edición se resuelve del Resource actual, mientras el historial de instalación guarda su UUID, no una revisión fijada del producto. Congelar o reconstruir la descripción comercial histórica es una decisión distinta [E17]. ## 7. Infraestructura global existente ### 7.1. Modelo actual verificado ```mermaid flowchart LR Definitions["Resources: definiciones globales\ntemplate:application y template:os"] --> App["Resource global application\nscope=global; companyId=NULL"] Definitions --> LocalOS["Resource SO particular\nscope=company; companyId=C"] App --> Resolver["Resolver por propósito\nallowlist global solo application"] LocalOS --> Resolver Resolver --> Installation["Companies: SoftwareInstallation\ncompanyId, assetId, resourceId, versión"] License["Licencia particular de C"] --> Installation Asset["Assets: activo de C\ncaracterísticas de fábrica"] --> Installation Installation --> View["SO actual derivado\nficha del activo y puesto principal"] App --> Profile["ApplicationConfiguration\nsolo application"] ``` La plantilla global define estructura reutilizable; un recurso basado en ella puede seguir siendo particular. El diagrama no afirma que exista un SO Resource global. Los atributos de fábrica son independientes de la instalación y no son entrada de esta propuesta. ### 7.2. Dónde está restringido el SO global | Capa | Restricción V | Adaptación necesaria P | | --- | --- | --- | | Dominio Resource | Scope/owner estrictos, UUID v7 para global nuevo, plantilla fija e integración prohibida. `createGlobal` no decide por sí solo `template:application` | Conservar invariantes; aplicar elegibilidad coherente en todas las fronteras | | Captura de especificación | `captureGlobalResourceSpecification` exige plantilla stock application, global y campos globales | Admitir exclusivamente stock os en su camino aprobado, sin elevar copias ni campos locales | | Política de elegibilidad | `globalApplicationTemplateEligible` allowlist application exacta | Centralizar la decisión específica por tipo sin aflojar checks de aplicaciones | | DTO de referencias | `SoftwareReference` admite application global/company y os **solo company** | Rama global os explícita; mantener el SO fuera de ApplicationConfiguration | | DTO de listado/detalle | `GlobalApplicationSummary/Detail` y catálogo particular de aplicaciones fijan `kind: application` | Consultas/DTO por tipo; no devolver SO a un contrato cerrado de aplicaciones | | Persistencia | Scoped permite global/NULL y prohíbe integración; FK UUID no impone familia application | Reutilizable en principio, sin DDL de raíz/instalación si scoped está instalado; validar sus writers y lectores | | Lectura de metadatos | Carga globales, valida allowlist y parsea unión cerrada | Extender validación y proyección conjuntamente; un SO global insertado fuera del flujo hoy provoca inconsistencia | | Administración | `repository.template()` busca application; create/update/propagación recapturan su especificación | Elección de tipo aprobada y plantilla os real; historial/capabilities y validación de identidad coherentes | | HTTP | Schemas create/update genéricos sin integración, pero rutas, respuestas y permisos orientados a global applications | Extender contrato de lectura/admin y negociación; no confiar en un `kind` enviado por navegador para autorizar plantilla | | Gates | Catálogo, selección mixta, asociación software y perfiles separados | Decidir habilitación específica del SO; no inferirla de los flags existentes | | Frontend | Catálogo/rutas/formulario global de aplicaciones; candidatos sin edición/familia estructuradas | Reutilizar primitivas con contexto de tipo, enlaces y etiquetas correctos | La ampliación no es un ajuste de SQL aislado. Si se permite `os` en la policy pero no se amplía `SoftwareReferenceSchema`, fallará la lectura. Si se amplía esa unión pero el listado global sigue parseando todos los globales con `GlobalApplicationSummarySchema`, un SO puede romper una consulta de aplicaciones. Deben filtrarse tipos **antes** de construir sus DTO específicos [E05–E12]. ### Superficies HTTP y de navegador verificadas | Superficie actual | Contrato y límite | | --- | --- | | `/api/resource-global-applications` | GET listado; POST alta administrada. `/capabilities`, `/template`, `/:id`, `/:id/admin`, `/:id/history`, POST `/:id/update` y `/:id/status`. No se localiza DELETE global público; desactivar conserva el registro. | | `/api/resource-application-candidates/:companyId` | GET candidatos por propósito; `/capabilities` negocia capacidades; `/catalog` lista aplicaciones globales/particulares y continúa excluyendo os. | | `/api/resource-application-references/:companyId/resolve` | POST de resolución por lote de UUID y propósito; lectura mínima de referencias, incluso inactivas. | | `/api/resource-application-coincidences/:companyId/:id` | GET de coincidencias de aplicación particular; no SO ni comando de fusión. | | `/catalogs/global-applications/:id` | Destino web global de aplicaciones; los enlaces de panel/mapa actuales se apoyan en él. No es una ficha SO global confirmada. | Estas rutas no se reinterpretan ni amplían en esta entrega. Su evolución por tipo debe mantener administración, proyección pública y operación particular separadas [E08, E10, E17, E18]. ### 7.3. Gates y seguridad La capability de creación actual se calcula sobre la única plantilla application servida por `repository.template()`. Con dos tipos deberá distinguir disponibilidad/autorización de cada uno; una capability de aplicación no autoriza por omisión crear SO. Los defaults declarados son catálogo false, selección mixta false, asociación software false y perfil false; administration es una capacidad interna distinta y no habilita acceso por sí sola. Los valores de entorno efectivos no se leen. El comentario de configuración sobre perfiles cerrados no sustituye al código: R2.5 soporta su gate configurable. El arranque de catálogo exige esquema scoped y CHECK/FKs activos; la migración scope existente es explícita y no se ejecuta por esta auditoría [E09–E12]. La administración global pasa por Identity y su guard público, inicialmente ligado al administrador inicial. La lectura pública y la operación contextual por compañía tienen superficies distintas; no se exponen notas/actores administrativos en metadatos. El espacio de soporte compartido no es una ACL granular operador–compañía: validar pertenencia dentro de C no significa que ese operador nunca pueda abrir B. Esta extensión no autoriza cambiar ese modelo [E12, E25]. ## 8. Integración con SoftwareInstallation ### 8.1. Reutilización e impacto **I:** en una instalación scoped preparada, A y B pueden conservar instalaciones distintas con el mismo `resourceId` de SO global, sin alterar los campos actuales de SoftwareInstallation. Su `companyId` sigue siendo A/B; el activo y `licenseResourceId` se validan en su contexto. Compartir producto no comparte instalación, versión, licencia ni historial. El repositorio ya recibe lectores públicos de Resources/Assets ligados a la misma transacción; carga las referencias globales por propósito y las incorpora al contexto mínimo como `{ id, active, usage }`. Las políticas de software aceptan `application` u `os`. Las FKs a `resources.id` no necesitan otro `globalResourceId`; la licencia continúa local. Esta estructura es reutilizable, pero el resolver actual nunca devuelve un SO global válido [E13–E16]. | Componente | Contrato conservable | Extensión necesaria | | --- | --- | --- | | Root, revisiones, tablas y DTO de SoftwareInstallation | UUID, compañía, activo, resourceId, licencia, versión, estado, notas | Ninguna para el objetivo básico, bajo la inferencia anterior | | Resolver y tipos comunes Resources | Sesión transaccional, scope y validación por propósito | Global os, su elegibilidad y DTO público, con pruebas de no ampliación de perfiles | | Referencias particulares | Pertenencia y lectura local | Conservar templates/copies usage os locales; no promoverlas automáticamente | | Selectores | Selección por UUID y badges de procedencia, recuperación y paginación | Identificación clara del tipo SO y de ediciones; contratos capaces de leer global os | | `needsReview` | Producto/activo/licencia no disponibles o retirada pendiente | Debe seguir utilizando disponibilidad del producto global; sin añadir inferencia de soporte/licencia | | Historia | Pareja fija y revisiones propias, referencias históricas conservadas | Leer global os inactivo también con gates de altas cerrados; no filtrar historia por elegibilidad de nueva asociación | | Resumen de SO actual | Mismo selector por activo + configured + kind os | Transportar scope/destino resuelto: el enlace actual está fijado a recurso de compañía y sería incorrecto para global os | | Panel, mapa y puesto | Consulta derivada del activo, gestión existente | Revisar rutas global-applications y nombre/origen; no copiar SO al puesto | **V:** el propósito vigente es `software-installation`; **no existe un propósito literal `os`**. El tipo os se determina a partir de plantilla/referencia dentro de ese propósito. `application-configuration` debe seguir aceptando solo application. No ampliar la policy de perfiles ni el inventario particular genérico para resolver esta necesidad [E10, E13–E17]. ### 8.2. Compatibilidad y concurrencia El header de contrato de Resources actual es `2`; sus clientes validan una unión que excluye global os. **P:** aprobar negociación/capacidad versionada para lectores preparados antes de permitir escrituras. Añadir una rama a un schema del servidor no actualiza los navegadores antiguos. El número del contrato y los errores de upgrade requieren decisión explícita, no se dan por implementados. Conservar la coordinación catálogo compartido → compañía → referencias/raíces y la validación de disponibilidad dentro de la transacción. La creación/edición de catálogo mantiene su bloqueo exclusivo. Desactivar global os no debe dejar carreras con nuevas instalaciones, borrar datos ni impedir notas/retirada de las existentes. Los tests MariaDB actuales contienen esas carreras para aplicaciones, pero no se han ejecutado aquí ni prueban automáticamente el caso SO [E13–E16, E26]. Cerrar gates de escritura después de crear referencias no elimina los globales ni permite que lectores antiguos las ignoren. Rollout y rollback deben preservar la lectura de todo UUID ya usado. Tampoco se habilitan licencias globales como efecto colateral. ## 9. Convivencia con SO particulares Resource utiliza el booleano `active`; «retirado» en los escenarios de recursos se interpreta aquí como inactivo, no como un estado `Resource.retired`. El estado retirado de un activo y el de una instalación son conceptos diferentes. | Escenario | Estado/riesgo V | Tratamiento recomendado P | | --- | --- | --- | | Windows 11 Pro global y particular | UUID distintos; el global SO aún no es elegible | Mantener ambos cuando se habilite; mostrar procedencia, no sustituir particular | | Dos compañías con nombres iguales | La similitud no crea identidad compartida | Crear/curar un global para nuevas selecciones; conservar referencias anteriores | | Particular con instalaciones abiertas | `assetId/resourceId` fijos y pareja abierta única | No UPDATE directo de target; conservar raíz y revisiones | | Particular que mezcla ediciones | No hay semántica estructurada que lo separe | Revisión manual; no dividir instalaciones ni inventar su edición | | Denominación incorrecta | Renombrar registra ResourceRevision; consumidores resuelven nombre actual | Corregir presentación si sigue siendo el mismo producto; si cambia identidad, crear otro producto | | Particular inactivo/retirado | No es candidato de alta; historia y notas/retirada conservan sus caminos | Mantenerlo y sus referencias; no usar global para ocultar su historia | | Falta edición | No implica ausencia de edición | Mantener incompleto hasta revisión; no equiparar con global sin edición | | Versión solo en nombre | Texto no separable de forma segura por gramática universal | Conservar original y completar características por revisión consciente | | Equivalente aparente a global | R2.6 no autoriza consolidar | Señal/revisión futura, sin reemplazar UUID; adopción requiere ratificación aparte | ### Estrategia de transición 1. **Coexistencia indefinida:** viable con el esquema conceptual actual; opción inicial de menor riesgo. 2. **Preferencia visual por globales:** puede facilitar nuevas selecciones si se aprueba, manteniendo visibles los particulares y el valor seleccionado. El orden actual es por nombre, sin una preferencia global semántica. 3. **Detección de equivalencias:** R2.6 aporta infraestructura de lectura y señales por nombre/proveedor, pero excluye explícitamente SO. Extenderla exige criterios de identidad de SO y contrato propio; no habilita fusión. 4. **Vinculación documental:** hoy no existe una relación SO particular → SO global de equivalencia. Una futura relación sería otro contrato, con autor, evidencia y semántica; no usar notas como FK encubierta. 5. **Sustitución controlada:** `resourceId` es inmutable. No reutilizar un update ordinario ni simular retirada física para cambiar solo la referencia documental. 6. **Adopción individual y migración administrativa:** D08.2 propone sucesión, planes y confirmación atómica, pero conserva acta pendiente; no hay `superseded`, `closeForSuccession`, permisos ni writers de adopción instalados en los módulos examinados. Aun ratificado para aplicaciones, su alcance SO necesitaría aprobación específica. 7. **Revisión de recursos heredados:** solo tras inventario autorizado y aislado; nunca convertir todos los textos que contengan «Windows» en un mismo producto [E18–E20]. ## 10. Duplicados e identidad semántica ### 10.1. Qué garantiza hoy el sistema - UUID distingue recursos; `creationId` y la comparación con el primer registro/actor permiten reintentar un alta global. No es una clave semántica comercial. - `ResourceUseCases` particular impide ciertos nombres repetidos en la misma plantilla/contexto, además de la regla de buzón. Esa regla textual local no es una unicidad global fabricante/familia/versión/edición. - El catálogo de **definiciones** también protege nombres dentro de su ámbito; no confundirlo con unicidad de productos Resource. - No se localizó una restricción de unicidad semántica de productos globales por características. Las claves de `resource_characteristics` impiden dos valores para el mismo campo/recurso, no dos recursos con la misma combinación de atributos [E04, E06, E11, E21]. R2.6 compara NFC, trim, espacios y minúsculas, conservando tildes, puntuación, números y ediciones. Es una señal de revisión. La búsqueda usa otra normalización, que pliega ciertos acentos vocálicos pero conserva ñ y otras escrituras, y una coincidencia por substring. Ninguna convierte Professional/Pro/Profesional ni elimina «64-bit» para fusionar [E19, E22]. ### 10.2. Qué puede conseguir E sin nuevas entidades **I/P:** características declarativas más una policy de aplicación pueden calcular/comparar una tupla normalizada y exigir consistencia de nuevos SO globales. Se pueden revisar duplicados bajo el lock de catálogo existente, siempre que todos los writers relevantes —alta, edición y propagación de campos/plantillas— apliquen la misma regla. No basta un check del formulario. **Límite:** una UNIQUE ordinaria sobre filas EAV no impone directamente una combinación repartida entre provider/familia/versión/edición. Si se exige garantía física por esa combinación, estudiar columnas relacionales o una proyección/tabla de identidad normalizada y su migración explícita. No se propone índice ni tabla en esta auditoría; no persistir una clave en JSON como sustituto del diseño. Nombre canónico, aliases, fabricante normalizado, identificadores externos y señales de duplicado tienen funciones distintas. La recomendación mínima es nombre legible coherente y metadatos curados, sin alias automáticos ni motor de equivalencias. Un identificador externo solo puede ser decisivo con namespace, unicidad y fuente fiables definidos. **P:** fijar los atributos que determinan producto al hacerlo utilizable; una corrección ortográfica puede conservar identidad si no cambia su significado, pero cambiar familia/release/edición comercial requiere otro UUID. Si se permite edición semántica de un producto ya usado, se corre el riesgo de reinterpretar instalaciones históricas. El nombre visible puede evolucionar con revisión sin renombrados masivos automáticos. ## 11. Licencias **V:** `licenseResourceId` apunta opcionalmente a un Resource particular de la misma compañía, de uso license, con FK en instalación y revisiones. La policy valida actividad/vigencia en nuevas dependencias, permite desvincular y documentar retirada y conserva historia. No existe cálculo de derechos, plazas consumidas ni compatibilidad automática producto–licencia [E13–E16]. La plantilla licencia incluye producto licenciado, edición/plan, provider, modalidad, métrica, cantidad, referencia, caducidad y renovación. Modalidad de serie: Suscripción/Perpetua/OEM/Otra. **Retail y Volumen no son opciones propias de serie**. La métrica puede documentar usuario, dispositivo, servidor, concurrente, corporativa u otro. Esto no acredita un vínculo efectivo a dispositivo/persona, transferencia permitida o cobertura de una edición. OEM, Retail, Volumen o Suscripción deben evaluarse como condiciones/documentación del recurso licencia o paquete contratado; no convertirlas automáticamente en familias/ediciones del SO. Un producto global compartido puede tener instalaciones con licencias particulares diferentes o sin referencia de licencia. La identidad de edición facilita al técnico distinguir productos, pero no demuestra derechos de uso. **Cambio imprescindible para SO global:** conservar la separación de producto global y licencia local en políticas/resolvers/selectores. No hace falta cambiar la cardinalidad ni añadir campos de licencia por este objetivo. Añadir opciones de modalidad o reglas de cobertura sería otro alcance aprobado, no una condición implícita de habilitar SO global. ## 12. UX de búsqueda, edición y selección ### 12.1. Recorrido actual y limitaciones | Tarea | Comportamiento verificado por código | Adaptación propuesta, sin nuevo diseño | | --- | --- | --- | | Crear SO global | La administración ofrece la especificación de application; os se rechaza | Entrada de tipo explícita con plantilla os stock y permisos existentes | | Buscar SO | Candidatos de software pueden incluir SO particulares; no SO globales | Consulta capaz por tipo y etiquetas de producto suficientes | | Seleccionar para activo | `SoftwareApplicationSelect` usa propósito software-installation; alta rápida SO crea particular | Mantener destino particular del alta rápida salvo acción global autorizada explícita | | Consultar características | Particular tiene ficha/especificación; global público tiene proyección application de nombre/provider/url/description | Definir proyección pública SO para identidad; no exponer notes, actores o usos de compañías | | Distinguir procedencia | Picker muestra global/company y provider; deshabilita global sin gate de asociación | Conservar badges y selección original; no presentar un particular como copia global | | Diferenciar versiones/ediciones | Etiqueta del picker es nombre; no columnas de familia/release/edición | Nombre canónico breve y metadatos secundarios; decidir filtros solo cuando el catálogo lo justifique | | Evitar ambigüedad | Revisión de coincidencias por nombre en formulario global y detección R2.6 para aplicaciones | Comparar identidad SO propuesta; cambiar campos semánticos debe invalidar la revisión previa de duplicados | El selector remoto tiene búsqueda con debounce de 200 ms, cursor/paginación, carga, error/reintento y selección inicial. El listado global admite search, provider, active y orden name/id. **Los candidatos no admiten filtros de familia, edición, versión ni provider separado:** su schema solo permite search/purpose/paginación. El paginador compara substring en nombre **o** provider; no consulta cualquier característica dinámica. Las descripciones o campos añadidos no pasan a ser buscables por existir en EAV [E10, E22–E24]. Por tanto, «Windows 11» puede distinguir Home/Pro/Enterprise/Education si esos términos están en nombres de productos correctamente curados; «Windows Server 2022» puede distinguir Standard/Datacenter de igual modo. No se puede garantizar ese resultado con nombres genéricos y edición escondida en una característica que el resolver no proyecta. Son ejemplos de UX, no datos aprobados ni resultados observados en una BD. La nueva discriminación por tipo debe reflejarse en filtros, query keys y contexto de cursores; también se revisa la invalidación por UUID de referencias, fichas e instalaciones. El helper actual de invalidación ya identifica instalaciones/configuraciones que usan el producto: se reutiliza esa estrategia explícita, sin introducir otro estado remoto ni invalidar toda la caché indiscriminadamente. Una etiqueta canónica basada en metadatos puede bastar inicialmente para selección conocida. No sustituye una búsqueda estructurada si se necesitan filtros; esa extensión exigiría query/DTO, proyección, cursor y tests. La etiqueta debe respetar el límite actual de 100 del nombre; el fabricante puede ir en información secundaria. No forzar un nombre interminable ni introducir filtros, recientes o sugerencias sin una necesidad real. ### 12.2. Edición e historia Conviene separar proveedor/familia/versión principal/edición para nuevos SO globales curados. El nombre puede proponerse y validarse respecto a esos atributos, pero hoy se introduce manualmente y crea historial. No sobrescribirlo cada vez que cambia un campo ni regenerar los existentes. Decidir si se permiten alias/localizaciones y cómo preservar la identidad al corregir texto. La característica description usa hoy el control genérico Input de tipo texto; las notas generales disponen de Textarea. El límite de 10 000 caracteres no acredita una experiencia cómoda de edición de descripciones largas. No se cambia ese control en esta auditoría. El formulario global actual exige revisar el nombre en altas y consulta posibles coincidencias por texto; la confirmación se vincula al nombre revisado, no a una huella completa de campos. Es insuficiente como prevención de duplicado de SO si cambian familia, versión o edición sin cambiar el nombre. No es una garantía de servidor de unicidad comercial [E23]. ### 12.3. UI, accesibilidad y límites de esta revisión La UI usa shadcn/Base UI y componentes propios RemoteOptionPicker, CursorPagination, SelectWithAction, FormDialog, FieldSections y ayuda contextual. Reutilizarlos, manteniendo estados diferenciados, labels, foco, cancelación y es/en. Los campos dinámicos se muestran con su nombre almacenado y necesitan política de traducción explícita. Las fichas y resúmenes también requieren enlaces que distingan destinos globales y particulares [E17, E23, E24]. DESIGN y el patrón de diálogos son normativos; ayuda contextual está cambiando concurrentemente en el árbol. No se da por terminada su nueva implementación ni se convierte una desviación en estándar. No se han probado tema claro/oscuro, responsive, teclado, foco o contraste en navegador durante esta auditoría. Las capturas de la implementación previa del resumen no validan un selector global SO futuro. No se crean mockups ni componentes. ## 13. Alternativas arquitectónicas y alcance de cambios ### Identidad - **A — Producto completo:** comprensible en selección y consistente con un target de instalación fijo. Sin metadatos adicionales no permite revisar identidad ni filtrar bien. - **B — Familia + versión, edición en instalación:** exige modificar instalación, revisiones, schemas, migración y presentación; debilita la distinción de ediciones en catálogo/licencia. - **C — Familia, versión/edición en instalación:** reduce entradas, pero traslada gran parte de identidad a cada compañía; cambia el significado operativo y el coste de migración. - **D — Entidades jerárquicas:** útil si hay consumidores reales de taxonomía, releases y edición, pero introduce relaciones, contratos y administración que hoy no se justifican. - **E — Resources declarativo:** reutiliza UUID y EAV relacional con campos estructurados/policies. No obtiene unicidad física multicampo ni equivalencia comercial solo por añadir campos. Se recomienda combinado con A. ### Globalidad - **O1 — Ampliación puntual por tipos admitidos:** incorpora os sobre Resource, con políticas específicas de tipo y propósito y contratos compatibles; menor impacto suficiente. - **O2 — Catálogo global de productos software generalizado:** puede ser una evolución de vocabulario/API si aparecen más consumidores; no requiere por sí mismo otra entidad, pero hoy implicaría renombrar/generalizar mucho más de lo necesario. - **O3 — Catálogo independiente SO:** duplicaría autoridad de producto, referencias, admin, seguridad e historial y necesitaría nuevas relaciones/migraciones; no recomendado con los requisitos actuales. ### Clasificación del impacto P/I | Cambio potencial | Reutilización / extensión / migración | | --- | --- | | Global SO con metadatos actuales en una instalación scoped | Reutilizar tablas Resource y SoftwareInstallation; extender policies, DTO, resolver, administración, consumidores y negociación. No se identifica DDL nuevo imprescindible para la relación básica. | | Familia/versión principal/URL declarativas | Evolución explícita de definiciones y bindings, con revisión de plantillas ya editadas, propagación y registros incompletos. Es cambio de datos/contrato, aunque no exija DDL de columnas. | | Entorno legacy sin scope | Requiere el procedimiento existente R2.1b previamente autorizado; no se presume aplicado ni se ejecuta ahora. | | Build/arquitectura efectiva en instalación | Extensión del agregado/DTO/revisiones y migración relacional; diferida. | | Unicidad física semántica multicampo | Diseño de columnas/proyección relacional e índices, con migración expresa; pendiente de necesidad y aprobación. | | Jerarquía de fabricantes/familias/releases/ediciones | Nuevas entidades y contratos; diferida por falta de consumidores que justifiquen el coste. | | Adopción/sucesión | Requiere ratificación D08 y alcance SO, implementación coordinada y probablemente persistencia operativa nueva; fuera de esta entrega. | | Licencias globales/compliance/perfiles con requisitos SO | No necesarias para el objetivo; pospuestas y no habilitadas por O1. | ## 14. Matrices comparativas Valoraciones cualitativas de **adecuación al objetivo actual**: A=alta, M=media/condicionada, B=baja. En migración/mantenimiento, A significa menor coste/riesgo, no más migración. Son juicios arquitectónicos, no mediciones ni una decisión aprobada. ### 14.1. Identidad | Criterio | A: producto completo | B: familia+versión | C: familia | D: jerarquía | E: declarativo con granularidad A | | --- | --- | --- | --- | --- | --- | | Coherencia de dominio | A: producto distinguible | M: edición dispersa | B: versión dispersa | A: niveles explícitos | A: producto y atributos | | Simplicidad | A: una raíz | M: campos en I | M: menos recursos, I más compleja | B: varias entidades | A: Resource existente | | Reutilización Resources | A | M | M | B | A | | Integridad/duplicidad | M: texto insuficiente | M: clave parcial | B: producto ambiguo | A si reglas aprobadas | M: policy necesaria; EAV sin UNIQUE de tupla | | Compatibilidad instalación | A: target UUID actual | B: mover edición | B: mover versión/edición | M: requiere adaptadores | A: mismo target | | Flexibilidad entre fabricantes | M: curación | M: edición no universal | M: detalle disperso | M: jerarquía no universal | A: campos opcionales/policy | | Migración heredada | A: conservar UUID | B: reinterpretar ediciones | B: reagrupar y mover valores | B: reconstruir relaciones | M: enriquecer sin inventar | | Mantenimiento | A | M | M | B | M: gobernar atributos/policies | | Evolución/inventario automático | M: nombre poco estructurado | M | M | A con coste alto | A: atributos estructurados | | UX/claridad/búsqueda | A si nombre preciso | M: edición fuera del selector | B: selección demasiado genérica | M: navegación más compleja | A: etiqueta y metadatos | | Versiones de producto | A: recursos distintos | A | B: solo en I | A | A: campo explícito | | Ediciones | A: recursos distintos | B: en I | B: en I | A | A: atributo identitario | | Compartir globalmente | A | M: global incompleto | M: global muy amplio | A | A | | Licencias documentales | A: producto reconocible | M: depende de I | B: familia demasiado amplia | A | A: edición visible sin inferir derechos | | Actualizaciones e historial | M: cambio producto exige nueva I | M: parte cambia en I | B: mezcla identidad y mantenimiento | M: muchos niveles | M: conserva I; semántica por aprobar | A + E reutiliza la separación vigente producto/instalación [E01–E17]. B/C exigen modificaciones y reinterpretaciones de instalación. D solo compensa su coste si surgen consumidores de esa taxonomía. E no justifica por sí sola crear un framework de schemas de identidad. ### 14.2. Globalidad | Criterio | O1: ampliación puntual | O2: generalización software | O3: catálogo SO separado | | --- | --- | --- | --- | | Coherencia | A: producto Resource | A si conserva políticas por tipo | M: autoridad paralela | | Simplicidad | A: extensión acotada | M: refactor de superficies | B: nueva infraestructura | | Reutilización | A | A | B | | Integridad | M: actualizar todas las barreras | M: evitar permisividad genérica | M: mantener referencias cruzadas nuevas | | Compatibilidad | M: DTO/versionado explícitos | M/B: más consumidores | B: otro tipo de destino | | Flexibilidad | M: dos tipos concretos | A | M | | Migración | A: sin mover UUID | M: posible coste de contratos | B: traslado/vínculos nuevos | | Mantenimiento | A | M: abstracción mayor | B: duplicación | | Evolución | A para SO | A para necesidades adicionales | M: silo | | UX | A: tipo y etiquetas claros | M: requiere reorganizar vocabulario | M: selección entre catálogos | O1 incluye contratos por tipo; no significa tocar una constante y aceptar SO en todos los endpoints. Se mantiene el propósito de perfiles cerrado a application [E05–E12]. ### 14.3. Convivencia | Criterio | Coexistencia visible | Preferencia por globales en altas | Adopción/sucesión controlada | | --- | --- | --- | --- | | Coherencia | A: UUID y dueño conservados | A si no cambia referencias | A si se aprueba semántica | | Simplicidad | A | M: criterios de orden/recomendación | B: coordinador/operaciones | | Reutilización | A | A: candidatos existentes ampliados | M: D08 aún propuesta | | Integridad | A: sin reescritura | A si elegido es explícito | M: atomicidad y evidencia nuevas | | Compatibilidad | A tras ampliar lectura global os | M: clientes/capabilities | B: nuevos estados/lectores si se adopta D08 | | Flexibilidad | A | A si particulares permanecen | A: selección explícita | | Migración | A: no obligatoria | A: solo futuras altas | B: operación administrativa por diseñar | | Mantenimiento | M: duplicados permanecen | M: duplicados previos permanecen | B: trazabilidad/compensación | | Evolución | M: limpieza manual diferida | A: reduce nuevas copias si se usa | A con coste y ratificación | | UX | M: procedencia evita confusión | A: facilitar selección, sin ocultar | M: flujo especializado y riesgos claros | Se recomienda coexistencia primero; preferencia visual sujeta a decisión y adopción diferida. No convertir ese orden en una migración automática [E18–E20]. ## 15. Recomendación preliminar concreta **P, sin aprobación efectiva:** 1. Cerrar la granularidad A + E: producto completo con UUID; provider/familia/versión principal y edición aplicable estructurados. Aprobar primero las excepciones de edición, arquitectura, canales y familias que no siguen la jerarquía. 2. Autorizar O1 como ampliación de la allowlist global exacta a stock os, manteniendo application y sus garantías. No promover plantillas particulares/copiadas ni campos locales a globales por declarar usage os. 3. Preparar todos los lectores, contratos versionados y destinos de navegación antes de permitir altas globales SO. Mantener aplicaciones globales y perfiles con sus contratos específicos. 4. Reutilizar SoftwareInstallation y sus licencias particulares sin nuevos campos para enlazar producto global. Conservar estados, historial, locks, validación y unicidad de pareja abierta. 5. Empezar con coexistencia y elecciones nuevas explícitas. Cualquier detección específica SO requiere revisión; adopción/sucesión queda pendiente de D08 y aprobación SO aparte. 6. Diferir build, compliance, integración automática, entidades jerárquicas y unicidad física hasta contar con requisitos/consumidores que justifiquen sus migraciones. No basta con cambiar el nombre del catálogo. La recomendación conserva Resource como autoridad y la instalación como fuente única del SO operativo. No implementa ninguna de estas fases. ### Modelo propuesto, no implementado ```mermaid flowchart LR Template["Resources: template:os stock\ncampos de identidad aprobados"] --> GlobalOS["Resource global SO\nUUID P; scope=global; owner=NULL"] Identity["Características declarativas\nproveedor, familia, release, edición aplicable"] --> GlobalOS Local["SO particulares existentes\nUUID y compañía conservados"] --> Resolver["Resources: referencias por tipo y propósito\ncontrato preparado para global os"] GlobalOS --> Resolver Resolver --> IA["SoftwareInstallation A\nactivo A, versión A, historia A"] Resolver --> IB["SoftwareInstallation B\nactivo B, versión B, historia B"] LA["Licencia particular A"] --> IA LB["Licencia particular B"] --> IB IA --> VA["Activo A / puesto principal\nvista derivada"] IB --> VB["Activo B / puesto principal\nvista derivada"] Pending["Adopción/sucesión\ndiferida y no ratificada"] -.-> Local ``` Los SO particulares se resuelven exclusivamente en su propia compañía; solo el producto global P se comparte entre A y B. Las cajas describen una propuesta de colaboración, no nuevas entidades del fabricante/familia ni tablas creadas. IA/IB siguen siendo el agregado existente y no heredan el dueño NULL del producto. ## 16. Riesgos prioritarios | Riesgo | Consecuencia | Condición antes de desarrollar/desplegar | | --- | --- | --- | | Abrir solo la policy/flag | Lecturas fallan por DTO cerrados o plantilla no admitida | Revisar captura, metadata, listado/detalle, admin, consumers y compatibilidad como unidad | | SO global contaminando listados application | Error de consulta o SO seleccionable en perfiles | Filtro por tipo antes del schema; negativos explícitos de perfiles/SMB/Access/licencias | | Clientes v2 antiguos | Parseo fallido de referencias/candidatos nuevos | Negociación/capacidad y despliegue de lectores antes de writers | | Identidad de producto mutable | Instalaciones pasadas cambian de significado | Regla de atributos identitarios y correcciones, con historia preservada | | Particular desconocido equiparado a global | Pérdida semántica al consolidar | No fusionar por texto, versión ausente o alias supuesto | | Seed sustituido o campos obligatorios masivos | Personalizaciones y ediciones bloqueadas | Evolución explícita, particular incompleto preservado, tests de propagación | | Unicidad comercial supuesta en EAV | Duplicados concurrentes o falsa garantía SQL | Policy común y locks; decidir si hace falta soporte físico relacional | | Fechas soporte mezcladas con caducidad/licencia | Retiradas o alertas incorrectas | Definir significado y no reutilizar expires silenciosamente | | Licencia global o de otra compañía aceptada | Mezcla de ámbitos y pérdida de control | Mantener license local; negativos HTTP/SQL futuros | | D08 tratado como aprobado | Cambio de targets/estados sin autorización | Ratificación expresa y alcance SO antes de sucesión | | Navegación actual de resumen | Enlace global os apuntaría a ficha particular | Scope/destino resuelto en todas las vistas e historial | | Activación real no conocida | Diagnóstico documental tomado como despliegue certificado | Verificar entorno aislado autorizado y aceptación global en una futura implementación | ## 17. Decisiones pendientes de aprobación | ID | Decisión que debe cerrar el propietario funcional/arquitectónico | Recomendación preliminar | | --- | --- | --- | | D-SO-01 | Granularidad de producto, ejemplos por familia y qué cambio supone otro UUID | A + E; principal+edición cuando distingue producto | | D-SO-02 | Rol de provider: fabricante/distribuidor y vocabulario canónico | Reutilizar campo, definir valores curados sin entidad nueva | | D-SO-03 | Obligatoriedad de familia/release y tratamiento de locales incompletos | Exigir suficiencia a nuevos globales activos; no backfill inferido | | D-SO-04 | Edición no aplica/desconocida | No equivaler ausencia; aprobar regla de publicación y, si se necesita, atributo de aplicabilidad | | D-SO-05 | Arquitectura/canal/SKU como identidad o detalle | Fuera de clave inicial salvo caso funcional demostrado | | D-SO-06 | Mutabilidad semántica de productos ya usados y revisión histórica | Nueva identidad para cambio comercial; corrección documentada sin reescritura silenciosa | | D-SO-07 | Alcance global, plantillas admitidas y contratos/rutas por tipo | O1, solo stock os; aplicaciones/perfiles mantienen restricciones | | D-SO-08 | Compatibilidad, negociación y gates específicos | Lectores preparados primero; no asumir header 2 compatible | | D-SO-09 | Detección de duplicados frente a garantía física de unicidad | Curación/policy inicial; aprobar DDL aparte si se exige garantía física | | D-SO-10 | Presentación/nombre canónico, alias y traducciones de campos | Nombre legible revisable; no generación obligatoria/renombrado masivo | | D-SO-11 | Preferencia de globales y alcance de posibles coincidencias SO | Visibilidad de ambos; priorización explícita sin sustitución | | D-SO-12 | Adopción/sucesión de particulares | Diferir; D08.2 sigue pendiente y no concede alcance SO | | D-SO-13 | Necesidad de build, soporte y fuentes externas | Posponer hasta consumidor definido; conservar version actual | | D-SO-14 | Aceptación, seguridad y plan de despliegue/rollback | Ensayos aislados por tipo, concurrencia, clientes antiguos y preservación histórica | ## 18. Evidencias de código y documentación Los enlaces señalan líneas del árbol inspeccionado. Los símbolos y rutas son la referencia estable si el trabajo concurrente desplaza líneas. La lectura de DDL no se presenta como inspección de una base instalada. | ID | Hallazgo / símbolos | Rutas y líneas | | --- | --- | --- | | E01 | Plantilla SO stock, campos compartidos y licencia; seed no crea productos | [resource-catalog-seed.ts:149](../../modules/resources/src/api/domain/resource-catalog-seed.ts#L149); [resource-catalog-seed.ts:90](../../modules/resources/src/api/domain/resource-catalog-seed.ts#L90); [resource-catalog-seed.ts:96](../../modules/resources/src/api/domain/resource-catalog-seed.ts#L96); [resource-catalog-seed.ts:229](../../modules/resources/src/api/domain/resource-catalog-seed.ts#L229) | | E02 | Tipos declarativos y contratos; uso os | [resource-definition.ts:9](../../modules/resources/src/api/domain/resource-definition.ts#L9); [resource-definition.ts:40](../../modules/resources/src/api/domain/resource-definition.ts#L40); [resource-values.ts:40](../../modules/resources/src/api/domain/resource-values.ts#L40) | | E03 | UUID/scope/owner, createGlobal y plantilla fija; revisión de Resource | [resource.aggregate.ts:63](../../modules/resources/src/api/domain/resource.aggregate.ts#L63); [resource.aggregate.ts:219](../../modules/resources/src/api/domain/resource.aggregate.ts#L219); [resource-scope.ts:5](../../modules/resources/src/api/domain/resource-scope.ts#L5); [resource-revision.entity.ts:13](../../modules/resources/src/api/domain/resource-revision.entity.ts#L13) | | E04 | Validación de valores; seed conservador, definiciones y propagación | [resource-values.vo.ts:212](../../modules/resources/src/api/domain/value-objects/resource-values.vo.ts#L212); [resource-catalog.aggregate.ts:174](../../modules/resources/src/api/domain/resource-catalog.aggregate.ts#L174); [resource-definition.entity.ts:86](../../modules/resources/src/api/domain/resource-definition.entity.ts#L86); [prepare-resource-template-updates.ts:128](../../modules/resources/src/api/infrastructure/persistence/prepare-resource-template-updates.ts#L128) | | E05 | Dos barreras globales de plantilla y campos reales | [global-application-template-policy.ts:2](../../modules/resources/src/api/application/global-application-template-policy.ts#L2); [global-resource-specification.ts:8](../../modules/resources/src/api/application/global-resource-specification.ts#L8) | | E06 | Idempotencia por UUID, alta/edición global y writer transaccional | [global-resource.use-cases.ts:22](../../modules/resources/src/api/application/global-resource.use-cases.ts#L22); [global-resource.use-cases.ts:69](../../modules/resources/src/api/application/global-resource.use-cases.ts#L69); [sequelize-global-resource.repository.ts:59](../../modules/resources/src/api/infrastructure/persistence/sequelize-global-resource.repository.ts#L59); [sequelize-global-resource.repository.ts:197](../../modules/resources/src/api/infrastructure/persistence/sequelize-global-resource.repository.ts#L197) | | E07 | Unión de referencias cerrada: os solo particular; proyecciones application | [application-reference.dto.ts:29](../../modules/resources/src/common/dto/shared/application-reference.dto.ts#L29); [application-reference.dto.ts:64](../../modules/resources/src/common/dto/shared/application-reference.dto.ts#L64); [resource-application.request.dto.ts:46](../../modules/resources/src/common/dto/request/resource-application.request.dto.ts#L46) | | E08 | Metadata, allowlist y lectores globales | [resource-reference-metadata.ts:29](../../modules/resources/src/api/infrastructure/persistence/resource-reference-metadata.ts#L29); [resource-reference-metadata.ts:89](../../modules/resources/src/api/infrastructure/persistence/resource-reference-metadata.ts#L89); [resource-reference-reader.ts:250](../../modules/resources/src/api/infrastructure/persistence/resource-reference-reader.ts#L250); [resource-reference-reader.ts:273](../../modules/resources/src/api/infrastructure/persistence/resource-reference-reader.ts#L273) | | E09 | Scope relacional y migración explícita existente | [resource-scope-schema.ts:15](../../modules/resources/src/api/infrastructure/persistence/resource-scope-schema.ts#L15); [resource-scope-schema.ts:18](../../modules/resources/src/api/infrastructure/persistence/resource-scope-schema.ts#L18); [resource-scope-migration.ts:51](../../modules/resources/src/api/infrastructure/persistence/resource-scope-migration.ts#L51) | | E10 | Propósitos, candidatos, administración y servicios públicos | [application-reference.dto.ts:5](../../modules/resources/src/common/dto/shared/application-reference.dto.ts#L5); [resource-reference-reader.ts:166](../../modules/resources/src/api/infrastructure/persistence/resource-reference-reader.ts#L166); [resource-reference-service.ts:33](../../modules/resources/src/api/application/resource-reference-service.ts#L33); [global-resource.routes.ts:71](../../modules/resources/src/api/infrastructure/http/global-resource.routes.ts#L71); [resource-application.routes.ts:26](../../modules/resources/src/api/infrastructure/http/resource-application.routes.ts#L26) | | E11 | Persistencia relacional y mapper global | [resource-relational-schema.ts:107](../../modules/resources/src/api/infrastructure/persistence/resource-relational-schema.ts#L107); [resource.model.ts:19](../../modules/resources/src/api/infrastructure/persistence/resource.model.ts#L19); [resource-persistence.mapper.ts:155](../../modules/resources/src/api/infrastructure/persistence/resource-persistence.mapper.ts#L155) | | E12 | Gates declarados, preflight y guard de administración | [resource-global-gates.ts:14](../../modules/resources/src/api/application/resource-global-gates.ts#L14); [database.ts:14](../../apps/server/src/config/database.ts#L14); [module.ts:75](../../modules/resources/src/api/module.ts#L75); [require-global-resource-manager.ts:6](../../modules/identity/src/api/infrastructure/http/require-global-resource-manager.ts#L6) | | E13 | Producto, licencia particular, vigencia y proyección pública global | [software-installation-policy.ts:6](../../modules/companies/src/api/application/software-installation-policy.ts#L6); [software-installation-policy.ts:20](../../modules/companies/src/api/application/software-installation-policy.ts#L20); [resource-inventory.service.ts:22](../../modules/resources/src/api/application/resource-inventory.service.ts#L22); [configuration-resource-references.ts:6](../../modules/companies/src/api/infrastructure/persistence/configuration-resource-references.ts#L6) | | E14 | Campos y estados de instalación; target inmutable y revisiones | [software-installation-values.ts:5](../../modules/companies/src/api/domain/software-installation-values.ts#L5); [software-installation.aggregate.ts:64](../../modules/companies/src/api/domain/software-installation.aggregate.ts#L64); [software-installation-values.vo.ts:56](../../modules/companies/src/api/domain/value-objects/software-installation-values.vo.ts#L56) | | E15 | FK e índice de instalación actual; reconstrucción histórica | [software-installation-snapshot.ts:9](../../modules/companies/src/api/infrastructure/persistence/software-installation-snapshot.ts#L9); [software-installation-migration.ts:6](../../modules/companies/src/api/infrastructure/persistence/software-installation-migration.ts#L6); [software-installation-persistence.mapper.ts:43](../../modules/companies/src/api/infrastructure/persistence/software-installation-persistence.mapper.ts#L43) | | E16 | Unidad transaccional y composición intermodular | [sequelize-software-installation.repository.ts:32](../../modules/companies/src/api/infrastructure/persistence/sequelize-software-installation.repository.ts#L32); [sequelize-software-installation.repository.ts:220](../../modules/companies/src/api/infrastructure/persistence/sequelize-software-installation.repository.ts#L220); [resource-configuration-dependencies.ts:13](../../modules/companies/src/api/infrastructure/persistence/resource-configuration-dependencies.ts#L13); [identity-runtime.ts:60](../../apps/server/src/infrastructure/http/identity-runtime.ts#L60) | | E17 | SO derivado actual, pérdida de scope en salida y destinos de navegación | [current-operating-systems.ts:20](../../modules/companies/src/web/software-installations/shared/helpers/current-operating-systems.ts#L20); [current-operating-systems.tsx:64](../../modules/companies/src/web/software-installations/detail/ui/current-operating-systems.tsx#L64); [software-installations-panel.tsx:125](../../modules/companies/src/web/software-installations/list/ui/software-installations-panel.tsx#L125); [use-workplace-map-model.ts:36](../../modules/companies/src/web/workstations/detail/controllers/use-workplace-map-model.ts#L36); [use-asset-software.ts:11](../../modules/companies/src/web/software-installations/shared/queries/use-asset-software.ts#L11) | | E18 | R2.6 excluye SO y no consolida recursos | [17-r2-6-coexistencia-duplicados.md:46](../../docs/architecture/resources-global-scope/17-r2-6-coexistencia-duplicados.md#L46); [application-coincidence-reader.ts:111](../../modules/resources/src/api/infrastructure/persistence/application-coincidence-reader.ts#L111) | | E19 | Normalización de identidad y comparación como señal | [application-coincidence.ts:4](../../modules/resources/src/api/application/application-coincidence.ts#L4); [application-coincidence.ts:9](../../modules/resources/src/api/application/application-coincidence.ts#L9); [application-coincidence.test.ts:20](../../modules/resources/src/api/application/application-coincidence.test.ts#L20) | | E20 | D08.2 sigue pendiente; estados reales de instalación sin superseded | [19-d08-2-resolucion-ratificacion.md:3](../../docs/architecture/resources-global-scope/19-d08-2-resolucion-ratificacion.md#L3); [19-d08-2-resolucion-ratificacion.md:716](../../docs/architecture/resources-global-scope/19-d08-2-resolucion-ratificacion.md#L716); [software-installation-values.ts:22](../../modules/companies/src/api/domain/software-installation-values.ts#L22) | | E21 | Unicidad textual particular y de definiciones, no unicidad semántica global EAV | [resource.use-cases.ts:128](../../modules/resources/src/api/application/resource.use-cases.ts#L128); [resource-catalog.aggregate.ts:93](../../modules/resources/src/api/domain/resource-catalog.aggregate.ts#L93); [sequelize-global-resource.repository.ts:197](../../modules/resources/src/api/infrastructure/persistence/sequelize-global-resource.repository.ts#L197); [resource-relational-schema.ts:98](../../modules/resources/src/api/infrastructure/persistence/resource-relational-schema.ts#L98) | | E22 | Búsqueda concreta: substring name/provider, provider opcional, sin características arbitrarias | [resource-reference-pagination.ts:13](../../modules/resources/src/api/application/resource-reference-pagination.ts#L13); [resource-application.request.dto.ts:16](../../modules/resources/src/common/dto/request/resource-application.request.dto.ts#L16); [resource-application.request.dto.ts:30](../../modules/resources/src/common/dto/request/resource-application.request.dto.ts#L30); [text-search.ts:2](../../packages/rdx-utils/src/text-search.ts#L2) | | E23 | Formularios, selección y proyecciones públicas/administrativas | [global-application-form.tsx:64](../../modules/resources/src/web/global-applications/shared/ui/global-application-form.tsx#L64); [global-application-coincidences.tsx:12](../../modules/resources/src/web/global-applications/shared/ui/global-application-coincidences.tsx#L12); [resource-application-picker.tsx:44](../../modules/resources/src/web/application-references/select/ui/resource-application-picker.tsx#L44); [resource-characteristic-control.tsx:29](../../modules/resources/src/web/resources/shared/ui/resource-characteristic-control.tsx#L29); [global-application-detail.tsx:48](../../modules/resources/src/web/global-applications/detail/ui/global-application-detail.tsx#L48); [global-applications-keys.ts:35](../../modules/resources/src/web/global-applications/shared/queries/global-applications-keys.ts#L35) | | E24 | Internacionalización de interfaz frente a nombres de campos; catálogo de compañía application-only | [en.json:96](../../modules/resources/src/common/locales/en.json#L96); [resource-identity-fields.tsx:36](../../modules/resources/src/web/resources/shared/ui/resource-identity-fields.tsx#L36); [resource-catalog-response.builder.ts:16](../../modules/resources/src/api/application/resource-catalog-response.builder.ts#L16); [resource-reference-reader.ts:218](../../modules/resources/src/api/infrastructure/persistence/resource-reference-reader.ts#L218); [use-company-applications-controller.ts:11](../../modules/resources/src/web/resources/list/controllers/use-company-applications-controller.ts#L11) | | E25 | Normativa, seguridad y propiedad del SO instalado | [composicion-de-modulos.md:1](../../docs/arquitectura/composicion-de-modulos.md#L1); [03-contrato-seguridad.md:7](../../docs/architecture/resources-global-scope/03-contrato-seguridad.md#L7); [decision-so-actual-en-activos-y-puestos.md:5](../../docs/architecture/decision-so-actual-en-activos-y-puestos.md#L5); [DESIGN.md:23](../../DESIGN.md#L23); [patron-de-dialogos.md:1](../../docs/patron-de-dialogos.md#L1) | | E26 | Pruebas existentes y límites de lo verificado | [resource-reference-contracts.test.ts:22](../../modules/resources/src/api/application/resource-reference-contracts.test.ts#L22); [global-resource.test.ts:14](../../modules/resources/src/api/domain/global-resource.test.ts#L14); [resource-catalog.test.ts:349](../../modules/resources/src/api/domain/resource-catalog.test.ts#L349); [resource-scope.test.ts:93](../../modules/resources/src/api/application/resource-scope.test.ts#L93); [global-software.integration.test.ts:363](../../apps/server/src/global-software.integration.test.ts#L363); [global-applications.integration.test.ts:71](../../apps/server/src/global-applications.integration.test.ts#L71); [application-coincidences.integration.test.ts:152](../../apps/server/src/application-coincidences.integration.test.ts#L152) | ## 19. Validaciones ejecutadas y límites Se ejecutaron diez archivos existentes, con aislamiento desactivado para obtener casos individuales: **44 tests, 44 correctos, cero fallos/cancelados/omitidos**. Incluyen catálogo/plantillas SO, UUID/scope, creación global, allowlist exacta, DTO/propósitos, búsqueda/paginación/gates, coincidencias, ciclo de recursos, readers/mappers y software/licencias/perfiles. No prueban un camino de éxito de SO global; comprueban, entre otras cosas, su exclusión actual. ```bash node --import tsx --test --test-isolation=none \ modules/resources/src/api/domain/resource-catalog.test.ts \ modules/resources/src/api/domain/resource-scope.test.ts \ modules/resources/src/api/domain/global-resource.test.ts \ modules/resources/src/api/application/resource-reference-contracts.test.ts \ modules/resources/src/api/application/resource-scope.test.ts \ modules/resources/src/api/application/application-coincidence.test.ts \ modules/resources/src/api/application/resource-lifecycle.test.ts \ modules/resources/src/api/infrastructure/persistence/resource-scope-reader.test.ts \ modules/companies/src/api/domain/software-installation.test.ts \ modules/companies/src/api/domain/application-configuration.test.ts ``` El primer intento bajo sandbox obtuvo 43/44: el caso HTTP de `resource-scope.test.ts` falló con `listen EPERM` al abrir loopback. Se repitió el mismo comando con autorización de ejecución para ese servidor temporal y pasaron 44/44. No se corrigió código ni se desactivó el caso. Su fixture HTTP usa repositorios en memoria con 15 compañías y 50 recursos locales; **no es MariaDB** ni una instalación poblada con 50 personas/activos. Los tests de readers/persistencia usan dobles o mappers, no certifican FKs/locks reales. Se inspeccionaron además integraciones existentes de global applications, software, coincidencias y autorización, incluidas sus negativas para SO y carreras. **No se ejecutaron SQL/MariaDB, migraciones, fixtures persistentes ni navegador** en esta auditoría. Tampoco se accedió al catálogo de un entorno real ni se verificaron sus flags efectivos. Los resultados anteriores de R2.4–R2.6 o del resumen SO no se cuentan como pruebas nuevas. No se ejecutan typecheck/lint/build globales ni una suite general que pudiera usar configuración habitual: la única escritura propia es este documento Markdown. Se comprueban referencias locales, símbolos/líneas y whitespace del informe; los diagramas Mermaid se entregan como fuente, sin renderizado validado. El diff del trabajo concurrente se conserva y no se atribuye a esta auditoría. Skills consultadas: `rdx-solid` —referencias de arquitectura/decisiones ya consultadas en esta sesión— para separar dato, identidad, contratos e inferencias; `ux-search` para búsqueda de producto conocido, etiquetas, filtros y recuperación sin sobrecargar la UI. Se contrastan APIs locales de shadcn/RDX, DESIGN y patrón de diálogos; no se generan componentes ni se requiere CLI/descarga de vendor. Los auditores `ux-*-audit` citados por ux-search no están disponibles y no se invocan ni instalan; la revisión UX es estática y no se presenta como auditoría visual o de accesibilidad completa. **Entrega: este informe. No se modifica Resources, SoftwareInstallation, Assets, Workstation, esquema, gates ni datos maestros. La recomendación necesita aprobación antes de cualquier implementación.**