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

142 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# R2.0 — Decisiones D01–D10
> **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](11-r2-1a-lectores-compatibles.md). 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.
## Registro y aprobación
La fuente exacta de IDs es «Decisiones que requieren aprobación» en [auditoría 09](../../auditorias/resources-global-scope/09-alternativas-arquitectonicas.md). Se preservan literalmente sus materias: D01 «A frente a B y representación de ámbito»; D02 «allowlist inicial y futuras plantillas elegibles»; D03 «permiso global y quién lo recibe»; D04 «modelo de acceso operador–compañía»; D05 «proyección pública/administrativa de historial y notas»; D06 «disponibilidad local de globales y plantilla»; D07 «política de duplicados/ediciones»; D08 «consolidación y conservación histórica»; D09 «URLs/endpoints/versionado»; D10 «activación, rollback y despliegue mixto».
La resolución por propósito del apartado D04 de la solicitud se trata como **D04-R**, subordinada al modelo contextual y a D02/D05/D09; no sustituye D04. El registro no renumera decisiones previas.
Estados: **APROBADA PARA IMPLEMENTACIÓN** solo significa regla expresamente establecida por el usuario; **RECOMENDADA** necesita ratificación; **BLOQUEADA** indica información/incompatibilidad imprescindible no resuelta; **DIFERIDA** puede posponerse. Ningún estado autoriza escribir código en R2.0. La aprobación del conjunto permanece pendiente.
| ID | Decisión | Alternativas | Recomendación | Evidencia | Estado |
| --- | --- | --- | --- | --- | --- |
| D01 | Modelo de ámbito | A explícito; B derivado NULL; C catálogo+copia; D adopción | A, Resource único con CHECK de par | [resource.aggregate.ts:11](../../../modules/resources/src/api/domain/resource.aggregate.ts#L11) [resource.model.ts:19](../../../modules/resources/src/api/infrastructure/persistence/resource.model.ts#L19) [inventory.ts:35](../../../modules/resources/src/common/inventory.ts#L35) | RECOMENDADA |
| D02 | Elegibilidad inicial | Serie Aplicación; todo usage application; plantillas genéricas | Solo stockKey template:application global, campos globales, sin integración | [resource-catalog-seed.ts:140](../../../modules/resources/src/api/domain/resource-catalog-seed.ts#L140) [resource-inventory.service.ts:54](../../../modules/resources/src/api/application/resource-inventory.service.ts#L54) [resource-catalog.model.ts:48](../../../modules/resources/src/api/infrastructure/persistence/resource-catalog.model.ts#L48) | APROBADA PARA IMPLEMENTACIÓN en alcance inicial expreso; ampliación DIFERIDA |
| D03 | Administración global | Todos los operadores; admin inicial; concesión delegable | Capacidad conceptual mapeada solo a admin inicial para v2 inicial | [identity.use-cases.ts:75](../../../modules/identity/src/api/application/identity.use-cases.ts#L75) [user.aggregate.ts:8](../../../modules/identity/src/api/domain/user.aggregate.ts#L8) [module.ts:19](../../../modules/identity/src/api/module.ts#L19) | RECOMENDADA; delegación DIFERIDA |
| D04 | Modelo operador–compañía | Soporte compartido actual; ACL nueva | Conservar soporte compartido y validar compañía operativa, sin prometer ACL | [require-authenticated.ts:6](../../../modules/identity/src/api/infrastructure/http/require-authenticated.ts#L6) [relationship-read-access.ts:7](../../../apps/server/src/infrastructure/http/relationship-read-access.ts#L7) | RECOMENDADA; política de negocio a ratificar |
| D04-R | Lecturas por propósito | Ampliar list; nuevos puertos explícitos | Gestión local separada, catálogo global y candidatos/referencias tipados por propósito | [resource-inventory.service.ts:7](../../../modules/resources/src/api/application/resource-inventory.service.ts#L7) [remote-connection-policy.ts:6](../../../modules/companies/src/api/application/remote-connection-policy.ts#L6) | APROBADA PARA IMPLEMENTACIÓN en separación exigida; forma de contratos RECOMENDADA |
| D05 | Privacidad de datos e historial | DTO único; proyecciones mínimas/admin | Producto mínimo para soporte, root/historial administrativo para manager | [resource-detail.tsx:11](../../../modules/resources/src/web/resources/detail/ui/resource-detail.tsx#L11) [inventory.ts:35](../../../modules/resources/src/common/inventory.ts#L35) | RECOMENDADA; no exponer operaciones ajenas APROBADA PARA IMPLEMENTACIÓN |
| D06 | Disponibilidad/ciclo | active existente; publicación nueva; overrides de producto | active, sin publicación; desactivar preserva relaciones; overrides diferidos | [software-installation-response.builder.ts:7](../../../modules/companies/src/api/application/software-installation-response.builder.ts#L7) [application-configuration-response.builder.ts:7](../../../modules/companies/src/api/application/application-configuration-response.builder.ts#L7) [resource-catalog.aggregate.ts:49](../../../modules/resources/src/api/domain/resource-catalog.aggregate.ts#L49) | RECOMENDADA; preservación al desactivar APROBADA PARA IMPLEMENTACIÓN |
| D07 | Identidad/duplicados/ediciones | UUID; nombre único; canónico externo | UUID, coexistencia, avisos no vinculantes; versión instalada separada | [name.vo.ts:5](../../../packages/rdx-ddd/src/value-objects/name.vo.ts#L5) [resource.use-cases.ts:64](../../../modules/resources/src/api/application/resource.use-cases.ts#L64) [software-installation-values.ts:5](../../../modules/companies/src/api/domain/software-installation-values.ts#L5) | RECOMENDADA en política técnica; coexistencia/no fusión APROBADA PARA IMPLEMENTACIÓN |
| D08 | Consolidación/historia | Reescribir; cerrar/crear sucesoras; solo coexistir | R2.6 inicial coexistencia/avisos; futura operación de sucesión explícita | [software-installation-input.mapper.ts:15](../../../modules/companies/src/api/application/software-installation-input.mapper.ts#L15) [application-configuration-input.mapper.ts:11](../../../modules/companies/src/api/application/application-configuration-input.mapper.ts#L11) | DIFERIDA; prohibición de conversión/reescritura APROBADA PARA IMPLEMENTACIÓN |
| D09 | API/URLs/versionado | Ensanchar legacy; nuevas superficies | Routers propios Resources, DTO separados y señal de versión para consumidores | [resource.routes.ts:54](../../../modules/resources/src/api/infrastructure/http/resource.routes.ts#L54) [resource-catalog.routes.ts:65](../../../modules/resources/src/api/infrastructure/http/resource-catalog.routes.ts#L65) [inventory-api.ts:11](../../../modules/resources/src/web/resources/shared/api/inventory-api.ts#L11) | RECOMENDADA |
| D10 | Activación/rollback | Big bang; expandir/lectores/gates | R2.1a lectores → R2.1b DDL → seguridad → catálogo → consumidores | [module.ts:39](../../../modules/resources/src/api/module.ts#L39) [prepare-resource-template-updates.ts:15](../../../modules/resources/src/api/infrastructure/persistence/prepare-resource-template-updates.ts#L15) [support-migration.ts:86](../../../modules/assets/src/api/infrastructure/persistence/support-migration.ts#L86) | RECOMENDADA; no downgrade incompatible APROBADA PARA IMPLEMENTACIÓN |
## D01 — Scope explícito
**Contexto/problema:** raíz, mapper y DTO requieren compañía; las definiciones ya interpretan NULL como global. Añadir NULL sin contrato no delimita comandos ni evita aceptar ámbitos contradictorios.
**Opciones:** A añade discriminador más CHECK; B ahorra columna y usa Maybe como las definiciones, pero exige las mismas policies y adaptación de lectores; C conserva locales a costa de duplicación y deja el producto global fuera de Resource; D añade adopción por compañía innecesaria para la primera versión.
**Recomendación/justificación:** A declara intención explícita en raíz, schemas y SQL, con companyId NULL como ausencia real de dueño. El discriminador no otorga permiso ni hace insegura a B por sí mismo. Coste aceptado: redundancia validada en CHECK/dominio. La tabla comparativa amplia permanece en auditoría 09.
**Compatibilidad/consecuencias:** backfill company para todos los existentes, DTO legacy intacto; raíz cambia, snapshots heredados conservan semántica por ámbito inmutable. No nueva compañía ni tabla de productos.
**Riesgo/aceptación:** migración FKs, strict DTO, lectores mixtos; pares inválidos y ámbitos desconocidos deben fallar y las FKs locales seguir activas (T01/T02/T19/T20). D01 es prerrequisito de R2.1, pendiente de ratificación explícita.
## D02 — Serie Aplicación exclusivamente
**Contexto/problema:** stockKey identifica serie, usage permite aplicaciones propias; confundirlos abre globales operativos o particulares. La regla restrictiva está establecida por la petición actual, no por aceptación de una respuesta previa.
**Opciones/recomendación:** serie Aplicación frente a cualquier plantilla application o habilitación genérica. Elegir serie global con campos globales y sin integration. Resolver UUID en catálogo, no constante universal ni nombre.
**Consecuencias/compatibilidad:** los locales de plantillas propias application continúan; no reclasificar copias ni extender resourceTemplateCapability. Editar valida plantilla fija y ámbito, aun con formulario manipulado; desactivar plantilla no oculta productos existentes.
**Riesgo/aceptación:** catálogo editado en ejecución; T03/T13/T21 demuestran renombrado/local copy/stockKey y rechazo de licencias/OS/SMB/support/certificados. R2.1/R2.2/R2.3 adoptan esta regla. Otras plantillas requieren decisión nueva, sin campo editable que permita autoelevarse.
## D03 — Capacidad administrativa no delegable inicialmente
**Contexto/problema:** authenticate comprueba sesión, Identity solo tiene isInitialAdmin y authVersion. No existe resources.global.manage ni API para conceder privilegios. Un admin de compañía no existe como rol acreditado.
**Opciones/recomendación:** permitir toda sesión reproduciría la carencia; RBAC persistente añade alcance; se recomienda una capacidad conceptual evaluada por Identity como sesión válida y actor.isInitialAdmin. No se añade un permiso en la cookie ni tabla de roles.
**Consecuencias:** administrador inicial la recibe por la política aprobada, sin modificar usuarios ni sembrar un grant. Nadie puede concederla/revocarla a otro en esta versión. La retirada de sesión invalida el acceso; cambio futuro de política es despliegue validado, no un formulario oculto. El administrador inicial protegido no puede desactivarse: no prometer revocación individual que el código impide. Delegación/revocación independiente exige diseño Identity y se difiere.
**Compatibilidad/riesgo:** restringir mutaciones de plantilla/campos globales que propaguen a productos afecta a operadores que hoy pueden editarlas. Debe aprobarse esa reducción; no basta proteger el producto mientras una plantilla global queda editable por todos.
**Aceptación:** T10/T11 y S01–S06 prueban actor, por ID, historial, plantilla compartida, sesión invalidada y ausencia de bypass. Gate de R2.2/R2.3 pendiente de aprobación de quién administra. Si se exige delegación desde el inicio, esta variante queda **BLOQUEADA** hasta diseñar concesión/revocación real; no se simula con isInitialAdmin.
## D04 y D04-R — Contexto y propósito
**Contexto/problema:** pertenencia de registro no implica ACL de operador. El espacio de soporte actual permite en general operar sobre compañías atendidas; cambiar el path cambia la operación autorizada bajo ese modelo, pero jamás legitima mezclar local B con activo A.
**Opciones/recomendación:** conservar el modelo documentado y validar sesión/existencia/contexto por operación; una ACL granular es un proyecto separado, no un requisito implícito de scope. Lecturas específicas por propósito protegen los tipos, incluso al administrador. Gestión local/list permanecen locales.
**Consecuencias:** modo catálogo sin compañía solo contiene definiciones; candidatos/resolución siempre reciben C. No usar isInitialAdmin como bypass para referencias de B en A. Nuevos propósitos no se aceptan como strings libres.
**Compatibilidad/riesgo:** remoto admite hoy cualquier Resource local del contexto; ensanchar list permitiría productos globales sin regla. A03 se evita con nuevas superficies; A02 es crítico solo si el producto presume ACL que no tiene.
**Aceptación:** T05–T08/T14/T26 y matriz completa 06. Ratificar soporte compartido antes de activar R2.2; si se requiere aislamiento por operador, queda **BLOQUEADA la activación** hasta definir esa ACL y probarla. No bloquea redactar el contrato ni investigar DDL.
## D05 — Proyecciones y privacidad
**Contexto/problema:** ResourceDTO completo contiene notas, estructura e historial/actorName; no debe viajar entero en un selector ni permitir inferir clientes consumidores.
**Opciones/recomendación:** producto público al espacio autenticado con whitelist de campos comerciales; detalle administrativo completo y endpoint separado de historial paginado; referencias mínimas según propósito. No agregar compañías/instalaciones, ni siquiera para managers, sin autorización de contexto distinta.
**Consecuencias/compatibilidad:** provider/url/description son características; otros campos que añada un administrador a la plantilla no se publican automáticamente. Notes e identidad del operador solo en administración. El historial operativo permanece en su compañía y puede resolver nombre actual sin acceder a historial global.
**Riesgo/aceptación:** datos internos en campos libres; T11/T12/S06 verifican exactamente claves ausentes, incluido con campos extra en plantilla. R2.2 determina schemas; R2.3 implementa vistas. Se requiere ratificar qué datos se muestran a soporte; el veto a operaciones ajenas ya es requisito aprobado.
## D06 — Actividad, plantilla y recuperación
**Contexto/problema:** active del producto, disponibilidad de plantilla y estado de instalación son tres conceptos. Solo dos agregados tienen needsReview derivado.
**Opciones/recomendación:** active existente basta; no draft/published. Plantilla inactiva impide crear Resource, sin anular referencias a un producto ya activo. Inactivo sale de candidatos nuevos, sigue legible y permite notas/retirada. Política de ocultación por compañía diferida; no reutilizar resource_availability para un Resource, pues referencia definiciones.
**Consecuencias:** reactivación no instala/configura nada. No borrar globales en primera versión. Revisión calculada al GET/refetch; no persistir ni crear revisiones masivas. UI no puede prometer actualización instantánea en otros navegadores.
**Compatibilidad/riesgo/aceptación:** preservar reconfiguring de mappers y estados terminales (T09/T12/T16/T22). R2.3–R2.5 deben resolver usados aunque inactive; overrides futuros requerirán su propia semántica/tabla y no ocultarán historia. Las extensiones de disponibilidad quedan DIFERIDAS.
## D07 — Identidad y duplicados
**Contexto/problema:** UUID identifica Resource, name está normalizado pero no identifica producto. No hay fabricante relacionado, familia, ID externo único ni versión de producto canónico. provider es texto libre opcional.
**Opciones/recomendación:** conservar UUID como identidad, permitir homónimos globales/locales y avisar de coincidencia textual fiable. No unique por nombre global. Los locales conservan NAME_EXISTS actual por plantilla/contexto: esta petición no obliga a eliminar esa validación histórica. Microsoft 365 Apps, Office 2021, Edge, Chrome y ESET NOD32 representan productos diferentes si el administrador los registra como tales; número en el nombre comercial no se convierte automáticamente en versión instalada.
**Regla de alta:** el administrador determina producto distinto según nombre comercial, proveedor y edición comercial que lo distinga, aunque familia sea similar. La edición/familia no se inventa como nueva columna: puede expresarse en nombre/descripcion existente. Una equivalencia de producto **confirmada** debe reutilizar el UUID global existente: no se crea una segunda definición por compañía ni una segunda definición global conocida del mismo producto. Dos productos distintos pueden tener igual nombre; dos UUID con nombres iguales solo son candidatos a duplicado, nunca equivalentes por similitud. Sin identificador canónico externo no se promete unicidad semántica automática: el administrador revisa coincidencias y elige explícitamente usar el existente o declarar un producto distinto antes de crear. Este control humano no se sustituye por NAME_EXISTS global ni por una fusión automática. Aviso fuerte solo si nombre normalizado y provider presente normalizado coinciden; si falta provider, coincidencia de nombre es débil. Normalización propuesta: Unicode NFC, trim, colapso de espacios y minúsculas; conservar tildes, números y signos. No usar coincidencia difusa para equivalencia.
**Reintentos:** nueva alta global acepta creationId UUID v7 generado una vez con el generador ya disponible de rdx-ddd; será el ID de Resource. Reutilizar creationId tras timeout retorna la raíz actual solo si la primera revisión corresponde al mismo actor y a los valores de alta normalizados. Cambiar payload/actor, o colisionar con un local, devuelve RESOURCE_CREATION_CONFLICT sin datos ajenos. No usar rehydrate como create ni modificar otros UUID; añadir parámetro de identidad validada al contrato de create futuro. Sin tabla de idempotencia ni nueva dependencia; no hay borrado global que permita reutilizar el ID. No se promete igualdad byte a byte de la respuesta de reintento si el producto se editó después.
**Consecuencias/riesgo/aceptación:** revisa recomendación de unicidad global de auditoría 09 por la instrucción actual; pruebas T17/T18 de homónimos, cifras, diacríticos, concurrencia del mismo creationId y recuperación tras reinicio. R2.3/R2.6 implementan avisos; la forma creationId y política de normalización necesitan ratificación con D09.
## D08 — Adopción y consolidación
**Contexto/problema:** software y perfil fijan destino y prohíben cambiar resourceId; reescribir raíz e historia no es compatible. También puede existir pareja abierta con el global.
**Opciones/recomendación:** R2.6 inicial ofrece coexistencia y avisos, con nuevas asociaciones elegidas explícitamente; consolidación destructiva descartada. Contrato futuro recomendado de sucesión: seleccionar local C y global, comprobar equivalencia expresamente, inventariar referencias y planificar cada relación por separado.
**Contrato futuro, no habilitado:** previsualización incluye instalaciones/configuraciones abiertas/cerradas, conflictos con global ya abierto, versiones/delivery/estado/licencia/notas y referencias no soportadas. Historial cerrado nunca se reescribe. Una transferencia futura cierra una relación antigua mediante comando auditable específico (sin falsear una retirada técnica) y crea sucesora con otro UUID, manteniendo resourceId antiguo en historia. No puede implementarse hoy con update ni estados de retirada simulados: necesita aprobar semántica de evento/razón de sucesión, vínculo old/new y persistencia relacional con identidad. El global y el local conservan sus UUID y dueño.
**Licencia/reversión:** conservar licencia local si usuario lo confirma y sigue válida; no inferir equivalencia de productos desde licencia. Un rollback solo genera operaciones compensatorias sobre sucesoras no modificadas; si hubo cambios posteriores, no existe reversión automática segura y requiere plan manual. No borrar sucesoras para fingir que nunca existieron. Revalidar plan frente a estado vigente, serializar conflictos y registrar actor/fecha/motivo/identidades e idempotencia antes/después.
**Consecuencias/aceptación:** estas decisiones y cualquier tabla/comando de sucesión son DIFERIDAS, no requisitos ocultos de R2.1. T25 valida coexistencia inicial y que no existe conversión por owner/scope. La consolidación posterior queda BLOQUEADA para ejecución hasta ADR adicional y pruebas específicas; no se inventan aquí tablas existentes.
## D09 — API y navegación
**Contexto/problema:** no hay detalle Resource por ID ni búsqueda remota de productos; strictObject legacy rechaza añadir scope. `/resource-catalog/global` administra plantillas.
**Opciones/recomendación:** routers propios del mismo módulo para producto global y candidatos/referencias por compañía, con GET/POST y sufijos update/status existentes. Propuesta completa 04: paths y schemas nuevos expresamente conceptuales, headers de contrato e idempotencia de creationId; no modificar shapes legacy ni crear módulo paralelo.
**Consecuencias/compatibilidad:** búsqueda conjunta paginada en servidor, UUID+procedencia, snapshots mínimos; gestión particular sigue usando inventoryApi y ResourceDTO actuales. Cliente compatible se identifica antes de usar relaciones globales, nunca mediante permisos de la UI. Fichas globales tienen URL propia y retorno a contexto local. Caché por compañía/propósito y global según proyección; sin compartir admin DTO con consultas públicas.
**Riesgo/aceptación:** T19/T22/T23, paginación con homónimos y denegación uniforme, ausencia de waterfall/N+1 por fila. R2.2 define schemas y compatibilidad; R2.3–R2.5 adoptan los routers. Paths y señal de versión requieren aprobación del contrato, no se afirman ya instalados.
## D10 — Evolución segura
**Contexto/problema:** migraciones se invocan desde composition root, lectores actuales fallan con NULL, propagación recorre compañías y hay FKs compuestas. Cambiar scope no autoriza a ejecutar automáticamente DDL al desplegar cualquier versión.
**Opciones/recomendación:** expansión controlada con lectores tolerantes al esquema anterior, gates separadas para catálogo/software/perfil y ensayo DDL; no big bang ni flag que cambie significado del listado legacy.
**Consecuencias/compatibilidad:** 07 fija estados de despliegue y matriz de versiones. Reversión deja de ser trivial desde el primer global persistido, aun sin instalaciones; desde primera relación global ningún lector antiguo puede volver a atender consumidores. Flags off detienen nuevas escrituras, no ocultan referencias usadas ni desactivan resolución.
**Riesgos/aceptación:** T15/T20/T21/T24. Ensayo de MariaDB 11.8 y constraints efectivo obligatorio, sin foreign_key_checks=0 ni rollback DDL ficticio. R2.1 no abre globales; R2.2 resuelve autorización y serialización; activación R2.3–R2.5 requiere gates verificadas.
## Bloqueos, diferimientos y alcance aprobado
No falta evidencia para proponer un diseño coherente sobre el modelo actual. Sí permanecen bloqueadas **las ejecuciones** siguientes: R2.1 hasta ratificar D01 y preflight SQL; activación de catálogo hasta D03/D04/D05 y pruebas de seguridad; adopción con mutación hasta contrato de sucesión. Si se exige permiso delegable o ACL estricta en la primera versión, faltan esos contratos Identity y la variante queda BLOQUEADA, no cubierta por la recomendación admin-only/soporte compartido.
Decisiones no técnicas que no puede suplir el asistente: quién administra, quién accede al espacio de soporte y qué privacidad se acepta. Sus recomendaciones no equivalen a consentimiento. No se solicita confirmar estas decisiones a mitad de la elaboración: el documento [10](10-resumen-para-aprobacion.md) las presenta como resultado revisable, sin implementar nada.