142 lines
23 KiB
Markdown
142 lines
23 KiB
Markdown
# 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.
|