metis-desk/docs/architecture/resources-global-scope/01-contrato-arquitectonico.md
2026-10-25 01:19:17 +02:00

19 KiB
Raw Blame History

R2.0 — Contrato arquitectónico de Resources Global Scope

Ratificación posterior — 24 de octubre de 2026: D01–D10 y D04-R ratificadas en los términos recomendados de R2.0; variante A, Resource único con scope explícito. Solo se autoriza implementar R2.1a. El registro vigente de alcance y evidencias está en 11 — Lectores compatibles. Los estados «propuesto», «recomendado» y «pendiente» del cuerpo se conservan como evidencia de la versión documental inicial y quedan actualizados por este registro; ratificación conceptual no equivale a ejecución de R2.1b–R2.6.

Versión documental 1, 24 de octubre de 2026. Estado: CONTRATO PROPUESTO PARA RATIFICACIÓN, sin implementación autorizada. «Debe» especifica el contrato futuro bajo las decisiones recomendadas; no convierte una recomendación en aprobación. El registro de estados y alcance aprobado es 02; la entrada de revisión es 10.

1. Alcance y precedencia

Extender Resource para registrar una definición de aplicación compartida sin copias por compañía. Instalación, configuración, licencia, activo, perfil y permisos siguen siendo locales según sus contratos. Se conserva Resources como módulo propietario, UUID estable, persistencia relacional y composición explícita. No se crea ApplicationCatalog como modelo paralelo ni un framework de plugins.

Los doce documentos de la auditoría son evidencia histórica; esta serie formaliza sus decisiones sin modificarlos. Los requisitos expresos del usuario prevalecen. La ruta docs/architecture/resources-global-scope/ se utiliza por petición expresa; no renombra docs/arquitectura/ ni altera su normativa. Sources y discrepancias se registran al final de este documento.

Fuentes normativas de integración: capas, composición, HTTP, DDD. Application no importa Sequelize; los puertos públicos de Resources no exponen repositorios ni modelos.

2. Qué existe y qué cambia

CONFIRMADO: ResourceProps exige companyId UniqueID; resources.companyId tiene NOT NULL/FK; ResourceSchema exige UUID. El inventario público lista exclusivamente por compañía. El catálogo de definiciones ya admite companyId NULL y stockKey estable. resource.aggregate.ts:11 resource.model.ts:19 inventory.ts:35 resource-inventory.service.ts:7 resource-catalog.model.ts:48.

APROBADA PARA IMPLEMENTACIÓN por requisito expreso: una aplicación global sigue siendo Resource, puede ser usada por compañías distintas y no representa permiso/licencia/instalación. Solo la plantilla de serie template:application produce globales inicialmente. No se modifican automáticamente referencias históricas. Esto establece restricciones del futuro trabajo, no autoriza implementar R2.1 en esta tarea.

RECOMENDADA D01: un Resource raíz porta scope declarado global/company y propietario discriminado. Los valores propios del producto permanecen en ResourceValues; scope/owner pertenecen a la raíz, no a características dinámicas. El ámbito se representa una vez y se valida al construir/reconstruir; no introducir un Value Object contenedor sin comportamiento necesario.

Campo conceptual Global Compañía Contrato
id UUID v7 nuevo UUID v7 nuevo Identidad global única; IDs persistidos válidos se conservan
scope global company NOT NULL, conjunto cerrado; datos anteriores company
companyId null UUID de companies Dueño, no compañía seleccionada ni tenant del operador
values.templateId UUID resuelto por stockKey de serie UUID de plantilla visible local/global Inmutable después de alta
values.active boolean boolean Existente, sin nuevo draft/published
values/name/characteristics/notes Datos de producto Datos locales propios de plantilla Mismos límites y validación dinámica; integración prohibida en global
specification/history Capturas de estructura/valores Capturas locales Conservar IDs, actor/fecha y revisiones; scope/owner heredados de raíz inmutable

Los pares global+UUID, company+NULL, scope desconocido o ausente en un esquema ya migrado son inválidos. Dominio usa UniqueID para referencias locales, DTO UUID string/null y SQL tipo compatible con UUID existente. Backfill solo marca scope; no mueve Resource a NULL ni crea UUID nuevos. Una lectura legacy sin columna puede derivar company exclusivamente dentro del adaptador transitorio, si companyId es válido; no es la representación final B.

3. Plantillas y clasificación

Regla global: definición de kind template, stockKey exacto template:application, propietaria global, todos sus campos globales; templateId es el UUID real de esa definición. builtinKey es nombre de transporte de stockKey, no otro identificador. No usar nombre, icono, fieldId provider ni usage por sí solo para habilitar globales. La plantilla de serie puede no tener usage persistido: el clasificador actual la reconoce por stockKey. resource-inventory.service.ts:54 resource-catalog-seed.ts:140 index.ts:19.

Locales: conservar plantillas propias de uso application y la serie; software admite además OS local según sus políticas. Una copia de Aplicación no se convierte en plantilla de serie. Los usos SMB, license, certificate, directory, support, os y desconocidos no producen globales. Cambio de plantilla o scope/owner queda fuera del CRUD, incluso sin referencias.

Ampliar elegibilidad requiere nuevo ADR, revisión de consumidores/privacidad, pruebas negativas y despliegue de lectores antes de cambiar una allowlist del servidor. No añadir un booleano editable globalEligible al formulario como vía para elevar privilegios.

RECOMENDADA D06: desactivar la definición de plantilla bloquea altas de Resource bajo ella, pero no bloquea asociaciones a un Resource existente activo. El override local de plantillas controla creación local, no es una política de uso del catálogo global. Edición de un producto existente usa su specification y validación vigente; nuevas obligatoriedades propagadas se exigen en la siguiente edición. Propagación global/local transaccional y preservación de campos retirados con valor siguen la normativa existente. No hay versión numérica de plantilla ni herencia viva; no inventarlas. resource-input.mapper.ts:69 prepare-resource-template-updates.ts:15.

4. Lecturas con responsabilidad explícita

Superficie conceptual Datos Autoridad y límites
Gestión local existente Resource de C, DTO legacy sin scope añadido Sesión/modelo compartido actual; nunca global ni recurso de B
Catálogo global público al espacio de soporte Definición mínima, activos e inactivos Sesión activa, datos de producto, sin historial administrativo
Administración global Resource global completo y su historial paginado Capacidad conceptual resources.global.manage, propuesta D03
Candidatos por propósito/C Global application activa + local elegible activo; software añade OS local Filtro servidor antes de paginar; nunca licencia ni otro local B
Resolución por UUID/C/propósito Referencia mínima activa o inactiva elegible Repetir seguridad/tipo; resolver inactivos no habilita nuevas escrituras
Otros consumidores Catálogos/relaciones locales como hoy Conservan sus propios lectores/políticas; no ampliar list genérico

Resources decide alcance/tipo de Resource. Companies decide compañía, activo/perfil/persona, disponibilidad operativa y licencia; Assets conserva SMB/directorio/support. El propósito nace del caso de uso de servidor al escribir, nunca se confía en propósito/scope enviados por navegador. Ver 03, 04 y 06.

5. Ciclo de vida y relaciones

Crear requiere permiso global, plantilla elegible activa y campos válidos. Tras alta, active determina disponibilidad: no hay estado de publicación adicional. Editar conserva UUID, ámbito, propietario, plantilla y primeras revisiones. Actualización semánticamente idéntica o repetir status no añade revisión.

Desactivar conserva Resource e historial; candidatos nuevos lo excluyen; lectura por UUID lo resuelve; no elimina ni retira instalaciones/configuraciones/licencias, no reasigna a otro producto. Reactivar devuelve disponibilidad, sin modificar estados locales. Borrado físico global se difiere: la primera versión no ofrece comando ni endpoint de borrado global. El borrado local existente conserva sus controles. Un futuro borrado global exige ausencia de toda referencia actual/histórica, control de reintentos y auditoría; no se habilita por reutilizar removeResource.

needsReview no es universal: hoy lo calculan los builders de SoftwareInstallation y ApplicationConfiguration como !closed && (!available || state==='removal_pending'). Al desactivar el producto, las relaciones abiertas cumplen !available; las cerradas mantienen needsReview false. No persistir un flag en Resource, no escribir todas las compañías ni emitir revisiones operativas por una desactivación global. Reactivar puede quitar esa causa del aviso, pero no otras. software-installation-response.builder.ts:7 application-configuration-response.builder.ts:7.

Regla exacta de edición operativa preservada: nuevo registro o cambio de state/version (y delivery para perfil) que termine pending/configured requiere referencia disponible. Añadir solo notas, guardar sin cambios o avanzar retirada sigue permitido con recurso inactivo, mientras el estado y demás invariantes lo permitan. Una nueva asociación a inactivo se rechaza incluso si se pide estado terminal. Cambiar licenseResourceId exige licencia local disponible; no se deduce compatibilidad licencia-producto. software-installation-input.mapper.ts:15 application-configuration-input.mapper.ts:11.

6. Invariantes transversales

Todos son requisitos futuros. «Base» identifica principios ya establecidos por el usuario, no evidencia de implementación v2. El resto depende de ratificación según D01–D10. Errores con * son nombres conceptuales nuevos; los demás existen. Se mapearán a Result y HTTP en 04. Cada fila tiene prueba futura obligatoria en 08.

ID Descripción / validación Nivel Error esperado Prueba Fase / origen
INV-01 Local tiene companyId UUID y FK companies válida Dominio/HTTP/SQL INVALID_REQUEST / COMPANY_NOT_FOUND T01 R2.1; Base
INV-02 Global carece de propietario; par discriminado coherente Dominio/DTO/SQL CHECK INVALID_REQUEST T02 R2.1; Base + D01
INV-03 Solo serie Aplicación global y campos globales, sin integración Resources dominio/Application RESOURCE_GLOBAL_TEMPLATE_NOT_ALLOWED* T03 R2.1/R2.2; Base/D02
INV-04 Inst./config./licencia conservan compañía propia NOT NULL Dominio/SQL consumidor INVALID_REQUEST T04 R2.4/R2.5; Base
INV-05 Software: global application o local application/os de C Resources + Companies SOFTWARE_REFERENCE_NOT_FOUND/UNAVAILABLE T05 R2.4; Base
INV-06 Perfil: global application o local application de C Resources + Companies APPLICATION_REFERENCE_NOT_FOUND/UNAVAILABLE T06 R2.5; Base
INV-07 licenseResourceId solo local license de C; activo/vigencia al asociar Companies SOFTWARE_REFERENCE_NOT_FOUND/UNAVAILABLE T07 R2.4; Base
INV-08 Nunca local B en operación de A, tampoco para admin Policy por propósito NOT_FOUND o unavailable sin datos de B T08 R2.2–R2.5; Base
INV-09 Desactivar global no elimina/modifica relaciones ni historia Resource Application Sin error en desactivación válida T09 R2.3–R2.5; Base
INV-10 Escribir/historial admin global requiere autorización vigente Identity/HTTP/Application UNAUTHENTICATED/FORBIDDEN T10 R2.2; Base, asignación D03
INV-11 Candidatos/resolución no exponen operación ni notas/historial ajenos DTO/consulta FORBIDDEN o unavailable T11 R2.2; Base/D05
INV-12 UUID históricos se conservan y resuelven incluso inactivos Persistencia/lectores Corrupción interna si FK/ámbito inválido T12 R2.1/R2.4/R2.5; Base
INV-13 scope/owner/template/destinos operativos inmutables por update Dominio/HTTP estricto TEMPLATE_FIXED / *_TARGET_IMMUTABLE / INVALID_REQUEST T13 R2.1–R2.5; D01
INV-14 Gestión local y list genérico excluyen globales Repo/servicio/HTTP RESOURCE_NOT_FOUND para ID global en CRUD local T14 R2.1/R2.2; Base
INV-15 Validar elegibilidad dentro de la misma unidad de escritura Infrastructure ligada a servicio público *_REFERENCE_UNAVAILABLE T15 R2.2/R2.4/R2.5; D10
INV-16 Solo activo crea asociación nueva; existente inactivo permite recuperación Policy consumidor *_REFERENCE_UNAVAILABLE o éxito según edición T16 R2.4/R2.5; D06
INV-17 UUID identifica producto; coincidencia textual no fusiona Resources/UX Sin error solo por homónimo global T17 R2.3/R2.6; Base/D07
INV-18 Reintento de alta global conserva UUID y primera revisión Nuevo comando/persistencia RESOURCE_CREATION_CONFLICT* si cambia petición T18 R2.3; D07/D09
INV-19 DTO legacy local no recibe scope nuevo ni NULL Builders/compatibilidad RESOURCE_CLIENT_UPGRADE_REQUIRED* para operación global no soportada T19 R2.1–R2.5; Base/D09
INV-20 CHECK/FKs no se eliminan sin restaurar garantías; no datos operativos NULL Migración/SQL Constraint SQL, error interno saneado T20 R2.1; Base/D10
INV-21 Propagación procesa global y local conservando snapshots Resources repositorio Rollback total de DML si invariantes fallan T21 R2.1; D10
INV-22 Invalidar/refetch nombres/avisos con claves de contexto y propósito API web/Query Error de refetch visible, no vacío falso T22 R2.3–R2.5; D09
INV-23 Catálogo de productos no es catálogo de plantillas ni plugin nuevo Módulo/contratos No endpoint legacy reinterpretado T23 R2.2/R2.3; Base
INV-24 No global nuevo con backend/lector incompatible activo Despliegue/gates RESOURCE_GLOBAL_FEATURE_DISABLED* T24 R2.1–R2.5; Base/D10
INV-25 Adopción no convierte propietario ni reescribe historia; sin automatismo Comando futuro No operación R2.6 sin contrato adicional T25 R2.6 posterior; Base/D08
INV-26 Dashboard/procesos/fichas resuelven usados sin ampliar consumidores operativos Lectores secundarios unavailable visible, nunca identidad ajena T26 R2.4/R2.5; Base/D04

7. Discrepancias y precisiones resueltas

Se leyeron íntegramente los doce Markdown y al inicio coincidían las 99 huellas del código de la auditoría, HEAD fa9d95fa9e. Durante la formalización aparecieron cambios concurrentes de búsqueda/listados ajenos a esta tarea: en la revisión de cierre 97 huellas siguen iguales y cambian dos fuentes web auditadas (C09). No se detecta implementación nueva de ámbito, ACL o catálogo en el backend contrastado. Estos ajustes son decisiones de contrato, no bugs corregidos:

ID Tensión de la auditoría/solicitud Resolución R2.0
C01 D04 original es modelo operador–compañía; solicitud desarrolla además resolución bajo D04 Preservar D04 original, subcontrato D04-R para propósito; correspondencia exacta en 02
C02 Auditoría 02 contempla que plantilla inactiva bloquee nuevas selecciones; 06 conserva disponibilidad por Resource Bloquea altas Resource, no asociaciones de producto activo ya existente; no política local de producto en v2 inicial
C03 Auditoría 09 recomienda unicidad de nombre por ámbito; petición actual prohíbe usar nombre como clave de unicidad UUID es única identidad; homónimos globales no se rechazan solo por nombre. Reglas de nombre de locales siguen intactas; ver D07
C04 Borrado global sin uso se consideró posible Se difiere operación global de borrado; desactivación suficiente inicialmente, lectura histórica garantizada
C05 Migración/lectores aparecen en órdenes distintos R2.1a lectores tolerantes al esquema anterior → R2.1b expansión SQL → R2.2 seguridad → R2.3 catálogo → flags consumidores
C06 needsReview puede leerse como atributo genérico o tarea masiva Solo derivado en dos builders existentes, sin nuevo atributo universal ni revisión operativa automática
C07 No versión SQL exacta en auditoría compose declara mariadb:11.8; soporte CHECK documental confirmado, versión patch/modos/DDL efectivo no inspeccionados
C08 Inventario local debe conservar contrato, pero usados globales necesitan nombres en otras vistas Servicio explícito de referencias y DTO mínimo; jamás ampliar list para remoto/certificados/Access
C09 Cambios concurrentes introducen createTextMatcher en listados; software-installations-panel y use-resources-page-controller difieren de la huella de auditoría No son cambios R2.0 ni soporte global; se releen y actualizan anclas. El helper pliega acentos vocálicos sin convertir ñ en n: el contrato nuevo de búsqueda conserva esa semántica en servidor, sin asumir que una collation genérica sea equivalente

La fecha/versiones de ejecución de tests de la auditoría no se trasladan como resultados R2.0. En esta fase solo se comprueban documentos, fuentes y consistencia. Evidencia enlazada en cada contrato y resultados finales en 10; no se ejecuta código funcional ni BD.