metis-desk/docs/auditorias/resources-global-scope/06-software-configuraciones.md
2026-10-25 01:19:17 +02:00

14 KiB
Raw Blame History

06 — Software, configuraciones y licencias

Relaciones reales

CONFIRMADO: SoftwareInstallation vive en Companies, aunque la interfaz se abre desde un activo o puesto. ApplicationConfiguration también vive en Companies. Asset pertenece a Assets y WorkProfile a Companies. Las relaciones operativas conservan companyId obligatorio; Resource es un agregado separado. softwareRead: sequelize-software-installation.repository.ts:27 applicationRead: sequelize-application-configuration.repository.ts:34.

erDiagram
  COMPANY ||--o{ ASSET : posee
  COMPANY ||--o{ RESOURCE : posee_hoy
  COMPANY ||--o{ WORK_PROFILE : posee
  ASSET ||--o{ SOFTWARE_INSTALLATION : documenta
  RESOURCE ||--o{ SOFTWARE_INSTALLATION : software_resourceId
  RESOURCE o|--o{ SOFTWARE_INSTALLATION : licencia_opcional
  ASSET ||--o{ WORK_PROFILE : dispositivo
  WORK_PROFILE ||--o{ APPLICATION_CONFIGURATION : configura
  RESOURCE ||--o{ APPLICATION_CONFIGURATION : aplicacion_resourceId
  SOFTWARE_INSTALLATION ||--|{ SOFTWARE_INSTALLATION_REVISION : historial
  APPLICATION_CONFIGURATION ||--|{ APPLICATION_CONFIGURATION_REVISION : historial

No existe un FK de ApplicationConfiguration a «activo principal» del puesto: el perfil referencia un activo; el dashboard puede usar el ordenador de un puesto como contexto de presentación. No existe FK instalación–configuración ni obligación de crear una al dar de alta la otra. Un recurso puede aparecer en muchos equipos y perfiles. La misma pareja activo/recurso o perfil/recurso admite varios periodos cerrados, pero solo uno abierto mediante currentKey nullable unique. softwareSQL: software-installation-migration.ts:6 applicationSQL: application-configuration-migration.ts:6.

Contratos y persistencia

Propiedad SoftwareInstallation ApplicationConfiguration
Raíz UUID, companyId, values, history UUID, companyId, values, history
Destino fijo assetId + resourceId profileId + resourceId
Uso aceptado application u os application
Versión string trim ≤100 o null string trim ≤100 o null; solo delivery installed
Forma de uso No delivery installed o web
Licencia licenseResourceId UUID o null No campo de licencia
Estado pending/configured/removal_pending/removed/never_configured Mismo conjunto, evolución independiente
Notas string trim ≤4000 o null Igual
Historia ID, actor, fecha, snapshot de valores Igual; incluye delivery
Derivado needsReview needsReview

Schemas fuente, sin interfaces DTO duplicadas: softwareInput: software-installation-values.ts:5 softwareDTO: software-installations.ts:19 applicationInput: application-configuration-values.ts:5 applicationDTO: application-configurations.ts:20. Persistencia: software_installations, software_installation_revisions, application_configurations, application_configuration_revisions; snapshots definen FK a assets/work_profiles/resources y licencia. Los hijos históricos conservan FKs a Resource, incluso cuando ya no está vigente en la raíz. softwareFK: software-installation-snapshot.ts:7 applicationFK: configuration-snapshots.ts:57.

Lectura y escritura backend

  1. GET carga relaciones de compañía y revisiones, actores y contextos de activos/perfiles/personas/recursos. Comprueba referencias actuales; inconsistencias persistidas causan error, no omisión silenciosa.
  2. POST valida schema en route, actor de sesión y UUID de compañía/id en UseCases. Mappers aplican políticas de pertenencia y elegibilidad; repositorio escribe raíz y solo revisiones nuevas bajo bloqueo de compañía.
  3. Alta/reconfiguración pending/configured exige activo no retirado, recurso activo y tipo compatible; perfil/persona activos para configuración. Licencia nueva requiere activa y no caducada.
  4. Edición mantiene la pareja; sameTarget rechaza cambiar producto o destino. Notas/retirada pueden seguir registrándose con referencias inactivas según reglas del mapper. Estados terminales se validan en dominio.
  5. Igualdad semántica evita nueva revisión. needsReview se calcula al responder, no se almacena en Resource.
  6. Eliminación de registro operativo elimina sus propias revisiones mediante acción explícita; eliminar Resource queda protegido por referencias actuales/históricas.

Evidencia: profileInput: work-profile-values.ts:3 softwareMapper: software-installation-input.mapper.ts:15 applicationMapper: application-configuration-input.mapper.ts:11 softwareResponse: software-installation-response.builder.ts:7 softwareRead: sequelize-software-installation.repository.ts:27 applicationRead: sequelize-application-configuration.repository.ts:34 remove: remove-resource.ts:37. Las reglas actuales no comprueban que una licencia concreta corresponda al producto seleccionado: no existe relación canónica licencia→aplicación que lo acredite.

Flujo completo de selección actual

Paso Instalación Configuración por perfil
Apertura SoftwareInstallationsPanel abre SoftwareInstallationEditorDialog Página de configuraciones abre editor; perfil puede estar fijado
Carga softwareApi + inventoryApi + catalogApi por compañía profiles + inventoryApi + catalogApi; controlador del formulario
Candidatos Recurso activo application/os o valor actual al editar applicationOptions: plantillas builtin application o usage application; activo o seleccionado
Búsqueda Opciones de SelectWithAction; la búsqueda del listado filtra instalaciones, no catálogo remoto SelectWithAction con array local; no endpoint de búsqueda conjunta
Selección resourceId; edición bloquea destino resourceId y profileId; edición fija ambos
Alta rápida SoftwareResourceCreateDialog con ResourceEditor initialKind os/application ApplicationQuickEditor con ResourceEditor o editor de perfil
Validación React Hook Form + Zod; backend política software React Hook Form + Zod; backend política application
Guardado softwareApi.save; invalida softwareKeys.company applicationApi.save; invalida applicationKeys.company
Lectura posterior Nombre por lookup en resources y enlace /companies/C/resources/ID Nombre por lookup del inventario; ficha/historial
Historial SoftwareHistoryDialog resuelve software y licencia por IDs ApplicationHistoryDialog conserva versión, estado y delivery

softwareUI: software-installations-panel.tsx:26 softwareForm: software-installation-form.tsx:19 softwareQuick: software-resource-create-dialog.tsx:5 applicationForm: use-application-configuration-form-controller.ts:28 applicationOptions: application-configuration-form-values.ts:8 applicationQuick: application-quick-editor.tsx:8 select: select-with-action.tsx:19.

CONFIRMADO: SelectWithAction compone Select de shadcn/Base UI y una acción adjunta; no hay input de búsqueda remota ni API asíncrona de candidatos en ese contrato. No afirmar que buscar Chrome ya esté implementado en este selector. Los listados operativos sí tienen filtros/búsqueda locales. El requerimiento de búsqueda conjunta necesitará adaptar la interacción, reutilizando primitivas existentes. La opción seleccionada debe seguir resolviéndose aunque no esté en la página de candidatos o haya quedado inactiva.

Incorporar un Resource global

DERIVABLE: la FK por UUID simple puede apuntar al mismo global desde instalaciones/configuraciones de compañías distintas sin cambiar sus IDs. Deben cambiar la resolución pública de candidatos/referencias, políticas, mappers de Resource y nombres/enlaces frontend. No necesitan nullable en software_installations.companyId ni application_configurations.companyId, ni una columna scope en estos agregados. No duplicar producto por compañía.

Para conservar historia: no modificar revisiones antiguas ni recalcular sus versiones; los snapshots operativos contienen resourceId/version, no snapshot del nombre del producto. Renombrar Resource cambia el nombre resuelto en el historial operativo; su nombre anterior se consulta en historial de Resource. PROPUESTO: mantener esa semántica existente inicialmente; cualquier requisito de nombre de producto inmutable en cada revisión requeriría contrato adicional.

Inactivo global: mantener resolución por ID, bloquear nuevas asociaciones/reconfiguraciones que exijan activo, permitir notas y retirada, calcular revisión en cada compañía y excluirlo solo de candidatos nuevos. No retirar instalaciones, revocar acceso ni invalidar licencias automáticamente. El listado local de gestión no debe perder acceso a usados globales en ficha/historial.

Licencias

CONFIRMADO: son Resource con stockKey='template:software_license' o usage='license', no una entidad License agregada aparte. Seed incluye producto, edición, proveedor, modalidad, criterio, cantidad, referencia, caducidad, renovación, autorrenovación y descripción. La instalación referencia opcionalmente ese Resource; configuración de perfil no lo hace. seed: resource-catalog-seed.ts:140 usage: resource-inventory.service.ts:54 softwareFK: software-installation-snapshot.ts:7.

softwareLicenseAvailable comprueba active y expiresOn con fecha UTC inclusiva; expiresOn se resuelve por field:expires. No hay consumo de plazas, asignación a personas/cuentas ni asignación directa a la aplicación por FK. Cantidad y nombre de producto son datos documentales; no acreditan cobertura. No compartir licencia de A con B porque ambas usen Chrome global. Mantener licencia local y validarla por separado del resourceId global. softwarePolicy: software-installation-policy.ts:5 service: resource-inventory.service.ts:7.

Duplicados y adopción

Estrategia Evaluación
Coexistencia temporal global/local Recomendación inicial: mismo nombre visible, IDs/origen distintos
Aviso de coincidencias normalizadas Ayuda documental; no prueba identidad semántica ni licencia equivalente
Priorizar global en resultados Posible orden por coincidencia y origen, decisión UX explícita; nunca reemplazar ID seleccionado
Relación local→canónico Solo si aparece necesidad real de mapeo/adopción; entidad relacional y auditoría propia
Migrar referencias Requiere comando específico: destinos son fijos, unicidad abierta puede colisionar; no sirve update ordinario
Reescribir historia o borrar locales Rechazado como automatismo; preservar referencias históricas y FK

No deducir identidad de mayúsculas, idioma, edición o nombre de fabricante. Una consolidación debe mostrar previamente referencias afectadas, conflictos de parejas abiertas, reversibilidad, responsables y resultado auditable. Véase R2.6 y decisiones D07/D08 en 10.

Pruebas localizadas y ejecutadas

Dominio: Resource, SoftwareInstallation y ApplicationConfiguration; HTTP: resources.integration, software-installations.integration y applications.integration; web: resources.test.tsx, software.test.tsx y application.test.tsx. unitResource: resource.test.ts:38 unitSoftware: software-installation.test.ts:52 unitApplication: application-configuration.test.ts:75 integrationSoftware: software-installations.integration.ts:17 integrationApplication: applications.integration.ts:18.

En esta auditoría pasaron el comando de test de Resources (11 archivos reportados por Node) y los dos archivos de dominio de software/aplicación. No se ejecutó HTTP/SQL, navegador ni datos masivos. Inspeccionar un test no equivale a ejecutarlo ni acredita soporte global, aún inexistente.