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

80 KiB
Raw Blame History

D08.1 — Contrato arquitectónico de adopción controlada particular → global

1. Estado del documento

Propuesta, 25 de octubre de 2026. Dictamen: APTA CON CONDICIONES. No ratifica D08 ni autoriza implementación, R2.7 o despliegue. Las condiciones y decisiones pendientes están en §§23–25. Los nombres nuevos de tablas, permisos, operaciones, DTO, estados y flags son propuestas, no capacidades existentes.

Entrega exclusivamente documental: este es el único archivo nuevo autorizado. No se ejecutan DDL, DML, fixtures, servicios ni pruebas de una adopción inexistente. No se cambian código, modelos, schemas, APIs, permisos, flags, dependencias, tests ni documentos históricos. Se conserva el árbol previo no confirmado.

Base principal leída completa: R2.6, especialmente §29. Se contrastan R2.0, D01–D10, seguridad, HTTP/DTO, consumidores e informes R2.2, R2.3, R2.4 y R2.5, consultados en esta misma secuencia de trabajo. No se reinterpretan sus evidencias históricas como nuevas pruebas.

Se consultan AGENTS.md, DESIGN.md, capas, composición, DDD, HTTP, software, aplicaciones del perfil y auditoría central. Se aplica rdx-solid y sus referencias de arquitectura/backend/decisiones para evaluar alternativas, agregados y transacciones. No se diseña una pantalla ni se realiza auditoría visual nueva.

Leyenda: V verificado; P propuesta fundamentada; A pendiente de aprobación; T dependencia técnica; R riesgo residual; F fuera de alcance. Una propuesta detallada no equivale a una decisión ratificada.

2. Resumen ejecutivo

D08.1-A/P: recomendar A2, sucesión de asociaciones seleccionadas de una compañía, con revisión humana de producto, preflight persistido e inmutable, confirmación atómica e idempotente y procedencia relacional. No se adopta el Resource como entidad: se documentan nuevas asociaciones al global y se cierran las anteriores por una causa explícita. Particular y global mantienen identidad, ámbito, propietario e historial. El particular sigue disponible en selectores.

Hallazgo V: ambos agregados tienen removed, pero significa retirada técnica. No tienen cierre por sucesión documental. Simular configured → removal_pending → removed para cambiar una referencia falsearía su historia. Se propone aprobación separada D08.1-B1 de un terminal documental superseded, exclusivo de estos agregados, con revisión causal y negociación de consumidores. No existe hoy; sin aprobarlo o una alternativa equivalente, la confirmación sigue bloqueada.

Los permisos explícitos de adopción, la auditoría central y el escritor transaccional conjunto tampoco existen. Los repositorios actuales abren transacciones propias y usan upsert: no se pueden encadenar sin adaptación. Estas son dependencias delimitadas, no garantías actuales.

Mantener A0/R2.6 mientras falte aprobación. Una futura primera fase puede preparar autorización, auditoría, lectores compatibles y preflight; confirmación y compensación requieren autorización y gates separados. No se cierra la aceptación global pendiente del programa.

3. Problema y justificación

R2.6 descubre candidatos; no acredita equivalencia ni mueve asociaciones. resourceId y asset/profile son targets inmutables de las raíces operativas. Actualizar solo la raíz rompería su coherencia con revisiones anteriores; reescribir también esas revisiones destruiría la evidencia histórica.

Adoptar tiene sentido cuando un operador autorizado decide documentar asociaciones concretas bajo un producto global ya verificado. Puede no convenir por edición, licencia, ambigüedad o consumidores solo locales. Mantener coexistencia es una decisión legítima, no un defecto que corregir automáticamente.

La operación no instala, desinstala, concede acceso ni consume licencias. Una sucesora configurada exige verificación expresa de disponibilidad. Versión instalada, licencia y forma de uso siguen siendo datos locales de cada asociación.

4. Contratos actuales verificados

Los enlaces apuntan a código vigente; los métodos futuros propuestos no se consideran implementados.

Evidencia Contrato V e implicación
Resource, ownership Raíz company/UniqueID o global/null; create/createGlobal separados; owner/scope/plantilla fijos.
Modelo inicial, migración scoped MariaDB, expansión explícita, CHECK scope/owner y FK; no catálogo de aplicaciones paralelo.
SoftwareInstallation, valores Raíz UUID, compañía, asset/resource fijos; create solo pending/configured; update no cambia target; terminales inmutables.
ApplicationConfiguration, valores Raíz UUID, compañía, profile/resource fijos; versión solo installed; historial de revisiones propias.
Transiciones Software, Profile pending→configured o never_configured; configured→removal_pending→removed. No existe superseded ni closeForAdoption.
WorkProfile, Workstation Agregados locales independientes. No se reasignan por adoptar una aplicación; el perfil controla configuraciones al comprobar borrado.
Mapper Software, Profile Validan target fijo, disponibilidad y pareja abierta única; no equivalencia comercial.
Migración Software, Profile QueryInterface crea raíces/revisiones, currentKey nullable UNIQUE y UNIQUE(configurationId,position). No hay dos Model Sequelize con hooks de adopción ya instalados.
Snapshots Software, Profile FK RESTRICT a recursos, activo/perfil, licencia nullable y actor en revisiones. state STRING(20) no autoriza estados desconocidos al dominio.
Repo Software, Profile get/save/remove abren transacción propia; persist privado usa ON DUPLICATE KEY UPDATE; remove elimina raíz y revisiones. Eliminar no es cerrar.
Sesión Resources, puerto forTransaction recibe Transaction: catálogo compartido y compañía FOR UPDATE; resolve recupera inactivos; validateNewAssociation comprueba actividad/gate por propósito.
Dependencias Companies Lectores Resources/Assets ligados a transacción; no hay escritor público de sucesión. ORM permanece en Infrastructure.
Guard global, Identity Sesión y administrador inicial comprobados en servidor. No hay resources.adoption.confirm ni ACL granular operador–compañía.
DTO Software, Profile Zod estricto, cinco estados, historial completo, sin procedencia de sucesión. Referencias globales negocian Resources-Contract: 2.
Software API/keys, Profile API/keys Familias por compañía, timeout y validación de respuesta. No queries de planes/operaciones.

currentKey es assetUUID:resourceUUID o profileUUID:resourceUUID, NULL si removed/never_configured. Las cerradas no bloquean otro registro con UUID nuevo del mismo par. No existe versión numérica general del agregado: hay UUID/posición de revisiones, fecha y valores reconstruidos. La última revisión detecta incluso un cambio que después vuelve al valor anterior; la fecha sola no basta.

La búsqueda de FK en migraciones encuentra revisiones como hijos directos de ambas raíces. No se consultó una BD real ni se garantiza ausencia de dependencias externas/futuras. Procesos, entorno, puesto y paneles son consumidores indirectos que también deben revisarse.

El prefijo actual de escritura operativa es catálogo compartido → compañía exclusiva, conforme al código y R2.4/R2.5. R2.2 describe una etapa anterior con lock exclusivo de catálogo; no se copia como comportamiento actual. CRUD Resource/propagación usa catálogo exclusivo y puede coordinar Access antes de compañía. Adopción no escribe esos recursos ni necesita locks Access.

La auditoría central está acordada como diseño futuro, todavía no implementado. Revisiones con actor/fecha y requestId no son por sí solas journal transversal ni idempotencia de adopción.

5. Invariantes

ID Regla futura obligatoria Verificación exigida
I01 UUID particular/global distintos y conservados; no cambiar owner/scope/plantilla. Dominio, HTTP estricto y snapshots SQL.
I02 Raíz anterior conserva UUID, target y todas sus revisiones; solo añade cierre aprobado. Mapper, FK y comparación de revisiones previas.
I03 Sucesora UUID v7 nueva, misma C y asset/profile, destino elegible. create y procedencia tipada.
I04 Cerradas históricas no se reabren ni reescriben. Dominio y ausencia de UPDATE histórico.
I05 Estado, versión, licencia, delivery y notas de sucesora son decisiones explícitas revisadas. Plan y aceptación de huella; sin inferencia textual.
I06 No fusionar, descartar ni actualizar asociaciones de destino por colisión. Conflicto de par, UNIQUE y carreras.
I07 Todas las seleccionadas o ninguna; no omitir conflictos al confirmar. Una transacción y fallos por punto de escritura.
I08 Solo referencias locales C y globales por propósito; permiso efectivo en servidor. Puertos/policies y pruebas negativas.
I09 Éxito requiere procedencia, revisiones y auditoría en el mismo commit. Fallo de auditoría provoca rollback.
I10 Repetición idéntica conserva resultado sin duplicar sucesoras/eventos efectivos. Idempotencia durable y UNIQUE.
I11 Gates off no ocultan historia ni revierten operaciones. Lectores y despliegue compatibles.
I12 Particular sigue disponible según sus reglas; sin archivo automático ni alias de identidad. Recursos y selectores sin sustitución.

Son compatibles con D01–D10. Cierre documental y negociación nuevos requieren aprobación adicional, no se consideran ya ratificados.

6. Alternativas

D08.1-A/P, comparación sin puntuaciones arbitrarias:

Alternativa Integridad, compatibilidad y reversibilidad Coste, operación y pruebas Recomendación
A0: mantener R2.6 Conserva todo; no precisa compensación. Menor riesgo/coste; el operador elige globales en altas nuevas. Válida permanentemente y mientras falte aprobación.
A1: reasignar resourceId Contradice sameTarget, I02 y D08; raíz e historial divergen o se destruye historia. Simplicidad SQL aparente; exige rehacer dominio y consumidores. Descartada bajo estas invariantes; requeriría modificar decisiones ratificadas.
A2: cierre y sucesión Conserva recursos y raíces anteriores; nueva identidad y causa. Falta cierre documental. Compensar es otra sucesión. Más coste en permisos, lectores, procedencia, transacción e idempotencia; pruebas de carreras/fallos. Preferida condicionalmente, sin retirada ficticia.
A3: equivalencia documental No mueve asociaciones; no sustituye validación por propósito ni prueba identidad universal. Menor riesgo operativo, pero añade aprobación/corrección/auditoría de relación. Funcionalidad independiente diferida, no prerrequisito oculto de A2.
Híbrida A2 + R2.6 Solo seleccionadas pasan al global; demás consumidores siguen locales. Lotes delimitados, obligación de explicar parcialidad. Forma recomendada; sin alias ni A3 persistida implícita.

7. Semántica de adopción

Una propuesta descubre un candidato. Un plan contiene fotografía, selección y evidencia revisable. Una decisión autorizada confirma expresamente ese plan vigente. Una operación confirmada existe únicamente después del commit y su auditoría.

Propuesta funcional sujeta a P02:

  • Un plan tiene una compañía, una fuente particular y un destino global; nunca varias compañías/destinos.
  • Selección individual explícita de raíces Software, Profile o ambas. Permitir adopción parcial respecto al inventario total.
  • Confirmación atómica de todas las seleccionadas. Conflictos seleccionados bloquean el conjunto; no existe «seguir con las válidas».
  • No seleccionadas, cerradas y otros consumidores se enumeran intactos. No hay marca de Resource «adoptado» que redirija usos futuros.
  • Selección vacía produce ADOPTION_NO_EFFECT, sin operación ficticia equivalente a A3.
  • Plan conservable sin ejecutar; cambiar selección/valores/evidencia crea otro plan inmutable. No se encadenan lotes automáticamente.
flowchart TD
    R[Coincidencia R2.6 o destino elegido] --> E[Revisión comercial y operativa]
    E --> P[Preflight persistido en una compañía]
    P --> B{Completo y sin bloqueos seleccionados}
    B -->|No| N[Nuevo plan o coexistencia]
    B -->|Sí| C[Confirmación explícita e idempotente]
    C --> V{Datos y permisos vigentes bajo locks}
    V -->|No| F[Conflicto sin efectos operativos]
    V -->|Sí| T[Cierre aprobado, sucesoras y auditoría]
    T --> M[Commit único]
    M --> H[Resultado e historia consultables]
    H --> K[Compensación independiente si se aprueba]

8. Agregados afectados

D08.1-B/P y B1/A:

Dimensión SoftwareInstallation V ApplicationConfiguration V Sucesión P
Identidad/propietario UUID y companyId obligatorio. Igual. Anterior conservada; sucesora UUID v7 nueva y misma C.
Target assetId/resourceId fijos. profileId/resourceId fijos. Mismo asset/profile, nuevo Resource en otra raíz.
Cierre disponible update pending→never_configured o removal_pending→removed; no closeForAdoption. Igual. Comando causal B1 condicionado; no remove/delete.
Alta create(company,values,actor,time), solo pending/configured. Igual. create real, no rehydrate; estado revisado, nunca configured por defecto.
Campos obligatorios/nullable assetId, resourceId, licencia nullable, versión nullable ≤100, state, notas nullable ≤4.000. profileId, resourceId, delivery installed/web, versión nullable ≤100, state, notas nullable ≤4.000. Todos explícitos; copiar/cambiar/vaciar requiere decisión del plan.
Versión/licencia/entrega Licencia local válida al asociar; no prueba cobertura de fabricante. Web exige versión null; no campo licencia. No trasladar automáticamente ni introducir licencia en Profile.
Unicidad currentKey UNIQUE par abierto; cerradas NULL. Igual por profile/resource. Liberar par anterior al cerrar; destino abierto debe estar libre. Destino histórico cerrado no bloquea por sí solo.
Historial UUID/posición/actor/fecha y valores con target fijo. Igual. Nueva revisión de cierre y primera de sucesora; no modificar previas.
Elegibilidad Activo no retirado, referencia disponible y licencia activa/vigente. Perfil/persona activos, activo no retirado, aplicación disponible y forma de uso válida. Policies actuales más validación Resources de nueva asociación por propósito.
Dependencias Revisiones y vistas de equipo/puesto. Revisiones, perfiles, entorno/procesos. Procedencia añade FK; dependencias incompatibles bloquean, no se reasignan.

B1: decisión separada de cierre documental

Se recomienda someter a aprobación superseded, terminal solo de estos dos agregados: pending/configured→superseded, conservando versión/licencia/delivery/notas/target anteriores. Se añade revisión causal vinculada a la operación. No afirma retirada técnica. removal_pending seleccionado bloquea: hay que resolver la retirada real fuera y repetir preflight. removed/never_configured quedan intactos y no se seleccionan.

No ampliar sin más ConfigurationSchema compartido con Access: introduciría el estado en familias sin sucesión. Se necesitan unions específicas de Software/Profile, transiciones, closed, currentKey, mappers, builders, historial, filtros, contadores, traducciones y negociación. Que STRING(20) admita el texto no resuelve nada de ello.

Sin B1: mantener A0. Puede evaluarse por separado un piloto solo pending→never_configured con sucesora pending, si expresa cancelación real de una necesidad; no cubre configuradas ni está autorizado implícitamente. Un indicador lateral que deje la anterior como configured tampoco resuelve closed/currentKey ni representación legacy sin otro contrato.

Ambos agregados están en Companies/MariaDB y pueden compartir una unidad tras adaptar sus puertos. Hoy no la comparten. No requieren transacción distribuida ni commits separados para cerrar y crear.

9. Modelo relacional propuesto

D08.1-C/P. Conceptual, sin migración ni SQL ejecutable. Companies posee planes y operaciones; Resources aporta referencias públicas ligadas a transacción, Identity autoriza y auditoría común registra. No se crea un framework ni dependencia Resources→Companies.

Todas las entidades e internas, incluidos items, evidencias, conflictos e intentos, tienen UniqueID/UUID v7. Fechas UTC. No hay notas ni JSON que sustituyan relaciones.

Tabla conceptual Datos y relaciones esenciales
resource_adoption_plans id PK; companyId FK; sourceResourceId/targetResourceId FK; createdBy FK y nombre seguro conservado; createdAt/expiresAt; kind adoption/compensation; originalOperationId FK nullable para compensación; status ready/blocked; schemaVersion/policyVersion; fingerprint BINARY(32) y creationRequestFingerprint separado; nombres/proveedor/active/template/scope/owner observados y revisión Resource mediante FK. Inmutable.
resource_adoption_plan_evidence id, planId FK, kind vendor-document/product-reference/operator-verification, referenceText/explanation acotados sin secretos, actorId/fecha. Evidencia humana, no permiso.
resource_adoption_plan_software_items id, planId, sourceInstallationId FK, sourceRevisionId FK/posición, assetId FK, role source/destination, selected, observedState, action keep/succeed, proposedState/version/licenseResourceId/notes, decisiones explícitas de versión/licencia y evidencia de compatibilidad. Observación histórica mediante revisión conservada y columnas necesarias.
resource_adoption_plan_application_items Variante tipada: sourceConfigurationId/revisionId, profileId, role source/destination, selected, observedState, acción y proposedState/delivery/version/notes, decisión de aplicabilidad; sin licencia.
resource_adoption_plan_dependencies id, planId, dependencyKind/Id, revisión o huella observada, disposition keep/block. FK tipadas cuando exista tabla estable; referencias diagnósticas sin FK se reconocen como tales, no se inventa FK polimórfica.
resource_adoption_plan_conflicts id, planId, code, severity, blocksConfirmation; FK nullable a item software o perfil, o ninguna para conflicto de plan, CHECK como máximo una. Detalle público acotado, no SQL.
resource_adoption_commands id PK solicitado v7, companyId/actorId FK, action confirm/compensate, idempotencyKey UUID, planId FK, requestFingerprint, state pending/committed/rejected, fecha, resultCode, resultOperationId FK nullable. Reserva durable, no adopción confirmada.
resource_adoption_operations id PK v7 servidor; commandId FK UNIQUE, planId FK UNIQUE; compañía/origen/destino/actor/FK; nombres históricos mínimos, authorizedAt/committedAt, kind; originalOperationId FK UNIQUE nullable para compensación completa. Solo resultados confirmados, sin estado parcial.
resource_adoption_software_items id, operationId FK, planItemId FK UNIQUE, predecessorId/successorId FK software_installations, predecessorClosureRevisionId/successorInitialRevisionId FK; UNIQUE predecessorId, UNIQUE successorId, CHECK anterior≠sucesora. Solo ejecutadas.
resource_adoption_application_items Mismas relaciones tipadas hacia application_configurations/revisiones. No entityId genérico en lugar de FK.
Auditoría común: operaciones/eventos/cambios tipados Modelo futuro ya acordado: actor, petición, resultado, efectos y causalidad; vínculo único con operación de adopción. No journal paralelo sustitutorio.
Intentos comunes ID, commandId opcional, requestId, actor autenticado cuando exista, acción, código seguro y fecha, referencia al resultado original. Rechazo/transitorio se distingue de efecto confirmado. Integración futura con auditoría común.
erDiagram
    COMPANY ||--o{ ADOPTION_PLAN : delimita
    COMPANY ||--o{ ADOPTION_OPERATION : delimita
    RESOURCE ||--o{ ADOPTION_PLAN : fuente_particular
    RESOURCE ||--o{ ADOPTION_PLAN : destino_global
    ACTOR ||--o{ ADOPTION_COMMAND : solicita
    ADOPTION_PLAN ||--o{ PLAN_SOFTWARE_ITEM : observa
    ADOPTION_PLAN ||--o{ PLAN_PROFILE_ITEM : observa
    ADOPTION_PLAN ||--o{ PLAN_EVIDENCE : fundamenta
    ADOPTION_PLAN ||--o{ PLAN_CONFLICT : explica
    ADOPTION_PLAN ||--o{ PLAN_DEPENDENCY : conserva
    ADOPTION_COMMAND ||--o{ AUDIT_ATTEMPT : diagnostica
    ADOPTION_PLAN ||--o{ ADOPTION_COMMAND : solicita
    ADOPTION_COMMAND ||--o| ADOPTION_OPERATION : confirma
    ADOPTION_OPERATION ||--o{ SOFTWARE_SUCCESSION : produce
    ADOPTION_OPERATION ||--o{ PROFILE_SUCCESSION : produce
    SOFTWARE_INSTALLATION ||--o| SOFTWARE_SUCCESSION : predecesora
    SOFTWARE_INSTALLATION ||--o| SOFTWARE_SUCCESSION : sucesora
    APPLICATION_CONFIGURATION ||--o| PROFILE_SUCCESSION : predecesora
    APPLICATION_CONFIGURATION ||--o| PROFILE_SUCCESSION : sucesora
    ADOPTION_OPERATION ||--|| AUDIT_OPERATION : registra
    ADOPTION_OPERATION o|--o| ADOPTION_OPERATION : compensada_por

Las filas destination del plan son observaciones keep, nunca seleccionables; conservan testigos de parejas abiertas/cerradas además del inventario source. Cada operación tiene al menos un item en total; cada colección tipada puede estar vacía. Una sucesora puede ser predecesora de compensación: son roles diferentes. Los fallos pertenecen a planes/intentos, no a líneas fingidas de una ejecución parcial.

Restricciones y límites del motor

Propuesta: RESTRICT al borrar/actualizar identidades, sin cascadas hacia procedencia, raíces, revisiones o auditoría. UNIQUE(companyId,actorId,action,idempotencyKey) reserva petición; commandId también es único global. CHECK asegura coherencia state/resultOperationId/resultCode y referencias locales de cada fila.

FK compuestas para misma C: claves candidatas UNIQUE(id,companyId), incluidas en raíces operativas si se necesitan, y columnas correspondientes en elementos. Para revisión de raíz: UNIQUE(id,configurationId) y FK compuesta desde elemento; en revisión Resource, (id,resourceId). Son índices futuros explícitos, no ya existentes. Tipos/longitudes/collation deben coincidir con las columnas vigentes; UniqueID no impone un formato físico UUID distinto al actual.

FK simple garantiza existencia, no owner/scope, permiso, vigencia, plantilla o equivalencia. Estas condiciones requieren servicios bajo transacción. No proponer CHECK con consultas a otras tablas. CHECK local puede asegurar IDs distintos, campos por estado y referencias exclusivas; que haya items, no ciclos de compensación, mismo asset/profile y target correcto requiere validación transaccional.

currentKey UNIQUE nullable permite varios históricos cerrados; no es un índice parcial WHERE. El mapper verifica su correspondencia con estado/target y B1 debe mantenerla. MariaDB FK admite ausencia de padre si un componente es NULL: no usar owner global nulo en una FK compuesta para fingir comprobación de pertenencia.

Índices iniciales propuestos: planes/operaciones (companyId,fecha,id), operaciones (sourceResourceId,id)/(targetResourceId,id), comandos por clave única y (companyId,state,id), items por plan/operación y referencias de navegación, conflictos por (planId,id). Requieren EXPLAIN/volumen en R2.7. Constraints con nombres únicos en la BD 11.8 ensayada, sin asumir reglas de MariaDB 12.1; documentación oficial.

Sin purga inicial. Consecuencia funcional pendiente de P07: las FK RESTRICT de observaciones de planes también retienen raíces/revisiones no seleccionadas o de planes abandonados. Crear un preflight no altera su estado operativo, pero sí puede impedir su borrado posterior. Este coste no se oculta como compatibilidad aditiva: requiere aprobación antes de habilitar planes persistidos. Si no se acepta, rediseñar previamente observaciones históricas normalizadas con identidad conservada y referencias vivas opcionales, sin borrar evidencia ni fingir FK polimórficas.

Endpoints delete actuales deben rechazar explícitamente toda raíz/revisión retenida por plan o procedencia antes de borrar revisiones; FK RESTRICT como defensa final. Igual protección para Resource, compañía y revisiones/actores referenciados. No cambiar a SET NULL para facilitar borrado. Se conservan nombres seguros históricos además de referencias vivas, según auditoría central. Retención/anonimización definitiva es decisión funcional pendiente, no recomendación jurídica; una purga futura no puede permitir reutilizar una clave confirmada y necesita tombstone relacional suficiente.

10. Preflight

D08.1-D/P. Solo crea metadatos de plan y auditoría; no cambia Resources ni asociaciones. Una lectura efímera no es confirmable. Observación coherente y guardado dentro de una transacción breve según §12; al responder libera locks, sin snapshot entre peticiones.

Entrada: compañía del path, fuente/destino, selección tipada UUID, valores deseados por sucesora y evidencia; creationId v7 para reintento del mismo plan. Todos los nullable explícitos. Actor/owner/scope/capacidades no proceden del body.

Bloque del plan Datos revisables
Identidad C, UUID/ámbito/owner de ambos, nombres/proveedor observados, descripción/URL pública para distinguir edición, active y plantilla real.
Elegibilidad Resultado separado software-installation/application-configuration, razones y gate efectivo. Solo propósitos seleccionados bloquean confirmación.
Inventario Abiertas/cerradas de la fuente, UUID, asset/profile y contexto propio autorizado, última revisión/posición, estado; seleccionadas frente a intactas.
Valores Software: versión/licencia/estado; Profile: delivery/versión/estado; antes/propuesto y decisión explícita conservar/cambiar/vaciar, sin secretos de licencia.
Conflictos Bloqueos de plan/seleccionadas, avisos de no seleccionadas, asociaciones destino abiertas/cerradas, dependencias y revisión humana necesaria.
Efectos Cierre B1 exacto si aprobado, nueva raíz por item, conservación del resto, resultado esperado; ninguna instalación/desinstalación física.
Control planId, versión de schema/policy, fingerprint, createdAt/expiresAt, ready/blocked, cobertura y conteos exactos de la fotografía, permisos requeridos.

Colecciones paginadas en servidor sobre filas persistidas del plan, cursor ligado a plan/tipo, orden UUID, pageSize 1..100 (20 por defecto). No consultar inventario vivo en cada página fingiendo que es el plan original. Solo inventario completo produce ready; el complete de una página R2.6 no acredita cobertura de dependencias.

Presupuestos propuestos sujetos a P04: 100 seleccionadas, 10.000 observadas, vigencia 30 minutos. No son benchmarks. Exceso/fallo de fuente produce blocked y ADOPTION_PLAN_TOO_LARGE/ADOPTION_PLAN_INCOMPLETE, nunca truncamiento silencioso confirmable. Expirar no borra el registro. Validar límites con volumen antes de ratificar producción.

Repetir creationId exige mismo actor/C y misma huella de entrada canónica creationRequestFingerprint; devuelve el plan original, aunque haya quedado obsoleto, sin volver a observar y generar otra fotografía bajo ese ID. La huella de entrada excluye fechas/observaciones generadas por servidor y se distingue de fingerprint del plan.

R2.6 localiza destinos; ni name-provider ni name-only otorgan conformidad. Evidencia: referencia identificada del proveedor, ficha comercial/edición, inventario con identificador comercial o verificación explícita de lo instalado/disponible. Debe explicar aplicabilidad de versión, licencia y forma de uso. Si falta proveedor o hay ambigüedad, exigir evidencia adicional concreta y explicación; un checkbox o repetir el nombre no basta. Edición incompatible bloquea la pareja: otro destino o coexistencia, sin «forzar» ni inventar provider.

Regla propuesta de evidencia confirmable: una operator-verification y al menos una product-reference o vendor-document identificable, especialmente si falta provider; explanation debe distinguir producto/edición y no repetir solo el nombre. Una product-reference puede remitir al inventario técnico autorizado, sin exigir documentación pública inexistente.

Zod puede validar estructura/presencia, no demostrar veracidad comercial. La comprobación comercial sigue siendo responsabilidad humana auditable. No se copian notas administrativas globales; notas operativas antiguas quedan en la raíz anterior, y cualquier nota sucesora se revisa explícitamente sin credenciales.

11. Conflictos

D08.1-E/P. B = bloqueante; H = bloqueante con revisión humana; W = advertencia no seleccionada; I = repetición informativa. H no permite bypass. Excluir una asociación exige otro plan y explica parcialidad. Detalles solo sobre información ya autorizada.

Condición verificable Severidad / bloquea Revisión y alternativa Código propuesto / efecto
Destino global inactivo B / sí Otro destino o reactivación autorizada fuera, luego preflight. ADOPTION_TARGET_UNAVAILABLE; blocked/stale.
No elegible Software B / sí si software seleccionado Corregir destino; no OS global. ADOPTION_SOFTWARE_INELIGIBLE; blocked.
No elegible Profile B / sí si perfil seleccionado Otra aplicación; no seleccionada solo W. ADOPTION_PROFILE_INELIGIBLE.
Fuente de B/scope incorrecto; referencia o raíz inexistente B / sí Respuesta uniforme sin datos de B; nueva selección. ADOPTION_REFERENCE_NOT_FOUND; 404.
Instalación seleccionada cerrada B / sí Conservar intacta; seleccionar otra abierta en nuevo plan. ADOPTION_SOFTWARE_CLOSED.
Configuración seleccionada cerrada B / sí Igual para perfil. ADOPTION_PROFILE_CLOSED.
Cerrada observada, no seleccionada W / no Conservar target/historial. ADOPTION_HISTORY_PRESERVED; keep.
removal_pending seleccionada H / sí Resolver retirada real fuera; preflight nuevo. ADOPTION_WITHDRAWAL_IN_PROGRESS.
Asociación destino ya abierta en mismo asset/profile H / sí No merge. Excluir o resolver fuera y nuevo plan. ADOPTION_DESTINATION_ALREADY_OPEN.
Carrera de currentKey asset/global B / sí Rollback; regenerar plan, sin upsert a raíz ajena. ADOPTION_SOFTWARE_PAIR_CONFLICT.
Carrera de currentKey profile/global B / sí Igual para perfil. ADOPTION_PROFILE_PAIR_CONFLICT.
Licencia ajena, tipo inválido, inactiva/caducada B / sí Otra local válida o null explícito admisible. ADOPTION_LICENSE_UNAVAILABLE.
Cobertura comercial de licencia sin acreditar H / sí Evidencia o null revisado sin afirmar cobertura. ADOPTION_LICENSE_COMPATIBILITY_UNCONFIRMED.
Versión de otra edición o no revisada H / sí Verificar/proponer valor o null; no inferir del nombre. ADOPTION_VERSION_UNCONFIRMED.
delivery web con versión no nula B / sí Corregir null o installed en otro plan. ADOPTION_DELIVERY_CONFLICT; 400 si DTO inválido.
Activo retirado, perfil/persona inactivos B / sí Conservar anterior; resolver legítimamente fuera. ADOPTION_CONTEXT_UNAVAILABLE.
Cambio de revisión/estado/licencia/contexto/inventario B / sí Nuevo preflight aunque valores vuelvan al anterior. ADOPTION_PLAN_STALE; cero efectos.
Plan expirado/incompleto/huella distinta B / sí Nuevo plan revisado. ADOPTION_PLAN_EXPIRED/INCOMPLETE/STALE.
Permiso insuficiente B / sí Sujeto habilitado; sin elevar rol por body. FORBIDDEN; 403 antes de datos protegidos.
Flags necesarios off B / sí para ejecución nueva Procedimiento de activación, no botón que los cambie. ADOPTION_FEATURE_DISABLED; 409.
Misma clave/contenido finalizado I / no ejecuta Resultado original tras autorizar consulta. Mismo resultado, sin efectos nuevos.
Misma clave/contenido diferente o contexto inválido B / sí No reutilizar ni revelar resultado ajeno. ADOPTION_IDEMPOTENCY_CONFLICT o 404 seguro.
Dependencia incompatible sobre raíz a cerrar H / sí Resolver fuera o excluir en nuevo plan; no mover su FK. ADOPTION_DEPENDENCY_CONFLICT.
Nueva dependencia/consumidor no preparado B / sí Contrato/soporte antes de confirmar. ADOPTION_DEPENDENCY_CHANGED.
B1, auditoría o escritor unitario no disponibles B / sí Mantener A0 y gate de confirmación off. ADOPTION_NOT_READY.
Fallo intermedio B / sí Rollback total, recuperar por clave. INTERNAL_ERROR/ADOPTION_RETRY_REQUIRED.
Selección vacía B / sí Coexistencia; A3 aparte. ADOPTION_NO_EFFECT.

Pertenencia/tipo inaccesible no se convierte en 409 detallado que revele datos. La vigencia de licencia se vuelve a comprobar al cruzar medianoche UTC aunque sus revisiones no cambien. Todos los conflictos seleccionados se resuelven antes de confirmar; no hay confirmación parcialmente exitosa.

12. Concurrencia

D08.1-F/P. Huella detecta cambio; locks y transacción protegen validación/escritura. Ninguna sustituye a la otra.

Huella canónica

SHA-256 d081-plan-v1: secuencia de campos tipados, UTF-8, longitudes y marcadores diferentes para ausente/null/texto/bool/entero; colecciones ordenadas por tipo/UUID; UUID minúscula, fechas ISO UTC, posiciones enteras. Strings validadas preservan semántica: no aplicar normalizador de coincidencias a valores operativos. No depender de orden de propiedades ni JSON.stringify para igualdad de dominio. HTTP representa 64 caracteres hex; persistencia 32 bytes.

Incluye versión de schema/policy, C/plan/tipo, fuente/destino con scope/owner/template/active y revisión/posición, datos públicos comerciales observados; selección/acciones/evidencia/valores sucesores; revisión/posición/valores de todas las raíces observadas; pares destino; testigos de activo/perfil/persona/licencia con actividad/vigencia y revisiones disponibles; dependencias; gates relevantes; createdAt/expiresAt. En tablas sin revisión, incluir columnas relevantes validadas o su huella; no inventar rowVersion existente. El día UTC de vigencia de licencia se revalida además.

Servidor recupera plan persistido y reconstruye observaciones bajo locks; separa intención inmutable y datos vigentes. Nueva revisión invalida aunque el valor vuelva al anterior. Nueva raíz incluso no seleccionada invalida conservadoramente inventario; propagación de plantilla puede invalidar revisión Resource. Permiso se comprueba aparte: un booleano hasheado no acredita autorización.

Token propuesto (planId,fingerprint,expiresAt) comprobado contra filas del servidor; no credencial portadora ni permiso para saltar lecturas. Hash diferente→conflicto, nunca aprobación de un hash nuevo enviado por navegador. No hay snapshot entre peticiones.

Orden de locks

  1. Autorizar petición sin retener locks de usuario mientras se espera compañía; política vigente al inicio como R2.2, sin revocación retroactiva prometida.
  2. Abrir unidad; primera operación, puerto Resources de escritura: catálogo LOCK IN SHARE MODE y compañía C FOR UPDATE.
  3. Bloquear comando reservado y plan, por ese orden. Reserva previa breve confirma solo metadatos, sin retener locks operativos (§14).
  4. Current reads compartidas de fuente/destino/licencias por UUID ordenado mediante puertos propietarios; definiciones protegidas por catálogo. No invocar CRUD Resource ni elevar lock compartido a exclusivo.
  5. Leer/proteger contexto/dependencias mediante APIs ligadas; raíces Software por UUID y después Profile por UUID, orden fijo. Comprobar que todos los escritores del contexto respetan mutex de compañía.
  6. Revalidar conjunto/huella/parejas/testigos. Mutex cubre pares destino sin fila aún; UNIQUE es defensa final. No SKIP LOCKED que omita seleccionadas.
  7. Persistir cierre, sucesoras, procedencia y auditoría; commit libera locks.

No asumir que snapshot ordinario REPEATABLE READ tomado antes de esperar es lectura actual; revalidación requiere current reads y conjunto coherente bajo mutex. No imponer SERIALIZABLE global. Escrituras SQL externas sin protocolo quedan fuera de esa garantía y exigen controles operativos.

Catálogo exclusivo de desactivación serializa con asociación: si desactivación commit primero, rechazo; si adopción primero, sucesoras se conservan y una desactivación posterior puede causar needsReview. No se promete impedir desactivación legítima posterior. Deadlock/timeout→rollback y error reintentable; reintentos internos, si existen, acotados sobre unidad completa con revalidación, no continuación de un item.

13. Atomicidad

D08.1-G/P. Un caso de uso Companies coordina; puerto Application describe unidad de negocio, Infrastructure abre una Transaction y liga escritores/lectores propietarios. Sin ORM en Domain/Application. Reutilizar policies/create y añadir comando B1 si aprobado. No encadenar endpoints ni save actuales suponiendo que heredan una transacción externa: no la admiten.

Dependencias T: escritores internos ligados para ambas raíces, lectura actual de contexto/dependencias, B1, resultado/procedencia y auditoría. Composición explícita, sin exportar modelos de Resources ni crear DI framework.

Upsert actual no es alta segura de sucesora: ON DUPLICATE KEY UPDATE puede colisionar con currentKey de otra raíz y actualizar sus valores. Exigir INSERT estricto, nuevo UUID y conflicto UNIQUE saneado. Para predecesoras: UPDATE por identidad/testigo y append de revisión; comprobar filas afectadas e IDs, nunca reinterpretar colisión de pareja como actualización idempotente.

sequenceDiagram
    participant U as Operador
    participant H as HTTP Companies
    participant C as Coordinador Infrastructure
    participant R as Resources público
    participant DB as MariaDB
    U->>H: Plan, huella, clave y confirmación
    H->>H: Sesión, permiso, CSRF y DTO
    H->>C: Reserva durable autorizada
    C->>DB: Reserva y auditoría; commit breve
    C->>DB: BEGIN unidad operativa
    C->>R: Sesión ligada a Transaction
    R->>DB: Catálogo S y compañía X
    C->>DB: Comando, plan, referencias, contexto y raíces
    C->>C: Revalidar huella, policies y conflictos
    alt Plan válido
        C->>DB: Cierres y revisiones, INSERT sucesoras
        C->>DB: Procedencia, auditoría, comando committed
        C->>DB: COMMIT
        H-->>U: Resultado original persistido
    else Rechazo previo a escrituras operativas
        C->>DB: Comando rejected y auditoría
        C->>DB: COMMIT solo metadatos
        H-->>U: Conflicto original almacenado
    else Error durante escritura
        C->>DB: ROLLBACK unidad operativa
        C->>DB: Intento fallido en otra transacción
        H-->>U: Error seguro; consultar misma clave
    end

Reserva no crea/cierra asociaciones y puede quedar pending tras caída. La promesa atómica abarca todos los efectos operativos, resultado y auditoría de éxito, no borrar la existencia de intentos. Preparar y validar todos los candidatos antes de escribir; fallo posterior aborta todo.

En Sequelize v6, devolver Result.fail normalmente resuelto en managed transaction no provoca rollback. Después de la primera escritura operativa hay que abortar controladamente en Infrastructure, esperar rollback y convertir al resultado apropiado fuera. Antes de efectos sí se puede persistir deliberadamente rechazo/auditoría. Es una condición que debe probarse; documentación v6.

Fallo Resultado
Antes de iniciar, sin permiso/DTO inválido Sin datos privados ni efectos operativos; intento seguro según política.
Reserva/auditoría de solicitud no persiste No iniciar adopción.
Validación final Rechazo auditable, cero cierres/sucesoras; nuevo plan si stale.
Tras cerrar una raíz, al crear sucesora/revisión Rollback de todas las raíces, claves, revisiones y procedencia. Reserva pending recuperable.
Auditoría de éxito o antes de commit Rollback total; no éxito sin evidencia.
Conexión perdida durante commit Estado incierto para cliente: recuperar por clave, no declarar rollback ni crear otra clave.
Después de commit / respuesta perdida Éxito durable y resultado original al reintentar autorizado.
Presentación o invalidación de caché No revierte éxito. Mostrar resultado conocido y actualizar queries afectadas.
También falla registrar intento tras rollback Diagnóstico técnico seguro con requestId; no prometer persistencia con BD caída.

No hay acción externa contra equipos/licencias en esta unidad, ni necesidad demostrada de transacción distribuida/outbox. Automatización remota futura sería otro contrato.

14. Idempotencia

D08.1-H/P. Separar planId (fotografía/intención), commandId UUID v7 cliente y operationId UUID v7 servidor (resultado). Idempotency-Key UUID v7 generado una vez por confirmación y reutilizado tras timeout; no por click/nombre. Scope UNIQUE(companyId,actorId,action,key). Consultar exige permiso vigente; conocer una clave no entrega resultados de otro sujeto.

Huella de solicitud: versión, acción, C, actor autenticado, commandId, planId/fingerprint revisada, originalOperationId al compensar y aceptación explícita. No requestId de transporte. Valores por item están en plan cubierto por hash.

  1. Reserva breve mediante INSERT estricto y auditoría; UNIQUE arbitra simultáneas. Existente→comparar huella/autorizar. No upsert que cambie payload ni lock retenido mientras usuario revisa.
  2. committed/rejected→resultado persistido antes de exigir vigencia del plan o gates de ejecuciones nuevas. Sí revalidar sesión/capacidad de consulta. Plan expirado/gate off no borra commit.
  3. pending→unidad §13. Compañía y comando serializan; segundo relee resultado bajo locks y no repite. Otro comando tampoco confirma dos veces un plan: UNIQUE(planId) y comprobación consumido.
  4. Rechazo determinista previo a efectos: persistir rejected/código/auditoría en esa unidad; repetición conserva rechazo. Corrección necesita nuevo plan/comando/clave.
  5. Error técnico con rollback: reserva sigue pending, sin resultado final. Intento aparte y reintento idéntico con validación completa. 500/503 transitorio no es resultado confirmado ni rechazo de negocio cacheado. Commit incierto exige leer fila, no marcar rejected.
stateDiagram-v2
    [*] --> pending: reserva autorizada durable
    pending --> committed: efectos y auditoría en commit único
    pending --> rejected: rechazo previo a efectos
    pending --> pending: rollback técnico o caída
    committed --> committed: repetir devuelve resultado
    rejected --> rejected: repetir devuelve rechazo

Estados del comando propuesto, no de Resource/Software/Profile. No durable «a medias». Espera excedida→503 ADOPTION_RETRY_REQUIRED, Retry-After acotado; no dos ejecutores. No se necesita lease/worker: reintento válido retoma pending bajo mutex.

Resultado original se reconstruye de operación/items/revisiones iniciales inmutables, nunca de valores actuales de sucesoras. Conserva UUID, hechos al commit y códigos; requestId del wrapper puede cambiar. Lectura de estado actual es distinta. No purgar claves/resultados inicialmente; retención final P07. Botón deshabilitado solo ayuda UX.

Caso Comportamiento
Misma clave/contenido finalizado Mismo resultado de negocio, sin nuevas sucesoras/revisiones/eventos efectivos.
Misma clave con otro contenido 409 ADOPTION_IDEMPOTENCY_CONFLICT, sin resultado ajeno.
Dos peticiones idénticas simultáneas UNIQUE y serialización; relectura o retry misma clave si excede espera.
Dos claves, mismo plan Una operación; otra ADOPTION_PLAN_ALREADY_CONFIRMED con referencia autorizada.
Dos planes sobre misma raíz Primera confirma; segunda stale/cerrada o UNIQUE predecessorId, sin efectos parciales.
Timeout antes/después del commit, restart Consultar pending/rechazo/resultado; recuperar misma operación, no nueva clave.

15. Auditoría

D08.1-C/H y T. Usar el diseño común acordado, hoy pendiente. Procedencia explica old/new; auditoría explica actor, solicitud y efectos. No sustituir el mecanismo común por un journal paralelo.

Éxito: actor de sesión/nombre histórico seguro, C, acción, requestId/fechas, evento causal y cierres/altas/cambios tipados con UUID y revisiones. No registrar que cambió Resource: solo se referencia. Plan/reserva son escrituras de metadatos y también se auditan en sus commits; lectura R2.6 no se convierte en evento de adopción.

Reintento puede registrar intento técnico vinculado al original, sin duplicar efectos de negocio. Rechazo no aparenta éxito. Fallo post-rollback genera intento en transacción independiente. Ningún éxito sin auditoría persistida en su propia unidad.

Nunca cuerpo HTTP íntegro, cookies, CSRF, tokens, contraseñas, seriales secretos, credenciales ni notas administrativas globales. Referencias documentales aportadas deben ser seguras. Logs técnicos conservan causa saneada/requestId; no sustituyen auditoría durable.

Dependencia mínima bloqueante: escritor/lector común ligado a transacción que cubra estos caminos y falle conjuntamente con negocio. Cubrir adopción no declara completada toda la auditoría central. No habilitar confirmación con auditoría diferida a un TODO.

16. Compensación

D08.1-I/P, sujeta a P06. No rollback ni «deshacer» automático: otra operación autorizada con plan, clave, actor y procedencia puede cerrar sucesoras documentales y crear nuevas raíces particulares. La adopción original y su resultado permanecen confirmados/inmutables; el vínculo de compensación explica el hecho posterior.

Propuesta inicial: compensación completa una sola vez, sin parcial ni recursiva. Todas las sucesoras deben seguir abiertas pending/configured y con la misma última revisión que su primera revisión al commit. Una nueva revisión, incluso notas o un cambio luego revertido, bloquea esta compensación acotada. Cualquier dependencia nueva/incompatible bloquea el conjunto.

Revalidar: no compensación previa, particular original actualmente disponible, asset/profile/persona, licencia/versión/entrega propuestas y par particular libre. Las particulares anteriores no se reabren: crear otras con UUID nuevo. Valores nuevamente revisados, sin restaurar snapshot ciegamente; ambas historias se conservan completas.

Cerrar referencia global existente no exige global activo ni reabrir gates de asociación global. Crear la particular compensatoria sí exige policies locales y gate específico de compensación. Cerrar adopción no impide consultar resultados ni debe obligar a activar globales para recuperar contexto.

flowchart LR
    A[Particular anterior cerrada] --> O[Adopción confirmada]
    O --> G[Sucesora global]
    G --> V{Sin evolución ni dependencias nuevas y contexto válido}
    V -->|No| X[Compensación bloqueada: intervención nueva]
    V -->|Sí| C[Compensación autorizada]
    C --> H[Cierre documental de sucesora global]
    C --> N[Nueva particular con UUID nuevo]
    H --> J[Adopción e historias conservadas]
    N --> J

Misma atomicidad/locks/auditoría/idempotencia; action=compensate, originalOperationId FK UNIQUE. Timeout/repetición recupera la misma compensación. Una sucesora incompatible impide modificar cualquiera. Nunca borrar sucesoras ni restaurar backup para hacer desaparecer la adopción.

Sin aprobar B1 y su cierre inverso documental tampoco hay compensación habilitada. Si hubo evolución, conservar estado y elaborar una intervención específica nueva; «manual» no es un bypass para sobrescribir trabajo posterior.

17. Seguridad

D08.1-J/P. D04 conserva soporte compartido, no tenant por cliente. Verificar pertenencia no crea ACL inexistente. A nunca usa fuente/licencia/asset/profile de B, tampoco admin. Si se exige limitar operador a compañías, es dependencia Identity antes de activar, no filtro frontend.

Operación Vigente V Propuesta P/A
Coincidencias/producto público Sesión vigente, proyección mínima; gate catálogo en detector. Sin cambios; no autoriza adopción.
Uso propio C APIs operativas actuales/contexto C. Sin cambios ni uso transversal.
Crear/consultar plan No capacidad específica. resources.adoption.plan + C; admin inicial si P03 se aprueba.
Confirmar No existe. resources.adoption.confirm + C, aceptación y revalidación de propósito/gates.
Consultar comandos/operaciones No existe. resources.adoption.history + C; leer catálogo no concede evidencia sensible.
Compensar No existe. resources.adoption.compensate + history + C y gate propio.

Son capacidades conceptuales, no grants. Recomendación inicial: política explícita Identity no delegable para admin inicial. Aunque coincida el sujeto con global.manage, no deducir permiso de adopción desde leer/gestionar catálogo. Hace falta contrato público de autorización por acción que exprese lo aprobado. Sin RBAC/ACL nuevos por omisión; si se requiere delegación o dos personas, diseñarlos antes.

Autorizar antes de datos protegidos, al inicio de cada confirmación/consulta/reintento. Actor de sesión active/authVersion, nunca body. Autorización al inicio no promete cancelación retroactiva si se revoca después, conforme R2.2; P03 debe ratificarlo.

UUID/C/scope/tipo/propósito se comprueban en servidor bajo unidad. Global stock application, campos globales válidos e integración ausente; usage/nombre de copia no bastan. Propósito derivado del item tipado, no string libre para elevar acceso. Enlaces reautorizan; planes sin notas administrativas globales.

401 sin sesión; 403 capacidad; 404 uniforme de contexto/referencia/plan/operación no accesible. 409 detallado solo sobre información autorizada. POST requiere origen/CSRF, incluso preflight que escribe metadatos. DTO/query estrictos; UUID/token/clave no son permiso.

18. HTTP/DTO

D08.1-K/P. Todas las rutas/DTO siguientes son propuestas, ninguna se introduce ahora. Superficie Companies /api/resource-adoptions/:companyId, separada del detector Resources. JSON solo transporte. Implementar posteriormente con Zod estricto e inferencia, sin interfaces duplicadas.

Contratos comunes

Params UUID, headers relevantes validados, origen/CSRF en POST. Idempotency-Key para confirmar/compensar. Query vacía salvo listados. Arrays únicos/acotados y nullable explícitos. No admitir actorId, owner/scope, capabilities, force, SQL ni destino diferente por item.

DTO conceptual Contenido
CreateAdoptionPlan creationId v7, sourceResourceId, targetResourceId; softwareItems [{installationId, proposedState pending/configured, version, licenseResourceId, notes, versionDecision, licenseDecision}]; applicationItems [{configurationId, proposedState, delivery, version, notes, versionDecision}]; evidence [{kind,referenceText,explanation}]. Nullable explícitos; preserve/replace/clear coherentes con los valores y evidencia.
AdoptionPlanSummary ID/C/kind, source/target mínimos observados, fechas/versiones/fingerprint, ready/blocked, cobertura, conteos exactos y bloqueos, efecto previsto y aceptación requerida.
AdoptionPlanItem Unión software/profile con UUID/revisión/contexto autorizado, valores observados/propuestos, keep/succeed y conflictos; licencia solo software, cerradas keep.
ConfirmAdoption commandId v7, planId, fingerprint y acceptReviewedPlan: true. Sin valores editables; modificarlos exige plan nuevo.
AdoptionResult operationId, commandId, planId, C/kind, fecha y actor autorizado, source/target observados, conteos, enlaces a elementos/auditoría. Líneas: IDs/revisiones anteriores y sucesoras, causa y valores al commit, sin historia administrativa global.
CommandStatus pending, committed con referencia a resultado, o rejected con código seguro. GET no ejecuta pendientes.
CreateCompensationPlan creationId, originalOperationId, evidencia y valores explícitos para todas las nuevas particulares.
ConfirmCompensation Mismo envelope de confirmación, action derivada de ruta/plan y permiso correspondiente.

Límites propuestos: referenceText 500, explanation 2.000, evidencia 1..20; versión/notas conservan 100/4.000; selecciones/páginas §10. Pendientes de prueba/ratificación; no valores de negocio autocompletados.

Operaciones

Método/ruta tras prefijo Auth y entrada Salida/HTTP Idempotencia/concurrencia/paginación
POST /plans plan + C + CSRF; CreateAdoptionPlan. 201 nuevo o 200 mismo creationId; 400/401/403/404/409. Plan con conflictos puede ser 201 blocked, sin éxito operativo. creationId ligado a actor/C/contenido, observación/guardado en unidad.
GET /plans/:planId plan + C, query vacía. 200 summary/fotografía; 401/403/404. Inmutable; expiración derivada, no valores vivos.
GET /plans/:planId/items y /conflicts plan + C; type si aplica, cursor/pageSize. 200 page {items,nextCursor}; 400/401/403/404. Cursor C/plan/tipo, orden UUID, 1..100.
POST /confirm confirm + C + CSRF; ConfirmAdoption e Idempotency-Key. 200 resultado tanto inicial como repetición; 400/401/403/404/409, 500 o 503 retry. Location al resultado. Reserva durable y locks §§12–14; mismo resultado de negocio.
GET /commands/:commandId history + C, query vacía. 200 estado; 401/403/404. Recuperación; private,no-store; no ejecutar.
GET /operations history + C; cursor/pageSize, sourceId/targetId/kind opcionales validados. 200 page; 400/401/403/404. committedAt/id, cursor ligado a filtros/C.
GET /operations/:operationId y /result history + C, query vacía. 200 summary o resultado original; 401/403/404. Hechos originales inmutables; estado compensatorio actual separado en consulta de operación.
GET /operations/:operationId/items history + C; type/cursor/pageSize. 200 líneas causales; 400/401/403/404. Orden estable; sin todo el historial por defecto.
POST /operations/:operationId/compensation-plans compensate/history + C + CSRF; CreateCompensationPlan. 201/200 plan o 400/401/403/404/409. creationId, observación de evolución, gate compensatorio de preflight.
POST /compensate compensate/history + C + CSRF; ConfirmCompensation y clave. 200 resultado; códigos base y conflictos §16. action compensate, UNIQUE originalOperationId, atomicidad e idempotencia.

Detalle/result pueden componerse en una sola respuesta si distingue hechos originales de estado actual; la separación funcional no obliga a viajes redundantes. No endpoint merge ni cambio de resourceId/scope.

Negociación y errores

Resources-Contract: 2 cubre globales, no estados nuevos. P05/B1: proponer X-Metis-Operational-Contract: 2 para sucesión y su representación en rutas afectadas de software/perfil/entorno/procesos, sin cambiar significado del header Resources. Desconocido→400; cliente sin soporte que recibiría B1→409 OPERATIONAL_CLIENT_UPGRADE_REQUIRED, Vary correspondiente, nunca lista parcial ni superseded traducido a removed.

Todos los lectores deben desplegarse antes del primer B1: backend antiguo tampoco rehidrata ese estado. Rutas nuevas exigen contrato propuesto. Otra representación de cierre exige revisar P05, no declarar aditiva una respuesta que rompe schemas estrictos.

Errores propuestos: §11 y ADOPTION_PLAN_ALREADY_CONFIRMED, ADOPTION_IDEMPOTENCY_CONFLICT, ADOPTION_RETRY_REQUIRED, ADOPTION_COMPENSATION_CHANGED, ADOPTION_ALREADY_COMPENSATED, ADOPTION_HISTORY_IN_USE. {code,requestId} y conflictos tipados solo autorizados; categorías HTTP explícitas, sin mapear FORBIDDEN a 409 por defecto. Rechazo almacenado sin SQL/stack/mensajes del motor.

19. Consumidores

D08.1-L/P. S sin cambios; E extensión aditiva; G requiere gate de escritura; X incompatible sin preparación; D depende de decisión.

Consumidor Impacto Contrato necesario
ResourceDetail S/E Recursos intactos; posible enlace autorizado a operación, sin convertir UUID en misma entidad.
ApplicationCoincidencesDialog S/E/G Sigue informativo; «Preparar plan» solo permiso/gate; ninguna coincidencia confirma ni selecciona raíces.
SoftwareInstallation G/X/D B1, closed/currentKey, procedencia, historial y delete protegido; target anterior fijo.
ApplicationConfiguration G/X/D Igual, delivery/versión propios; no deriva instalaciones de equipo.
WorkProfile E/X en proyección Identidad/actividad/target intactos; sucesora abierta y cerrada histórica diferenciadas; borrado respeta referencias.
Workstation y activo E/X en lectura Mantener equipo/perfiles, no contar predecesora cerrada como abierta ni copiar configuraciones entre perfiles.
Entorno/procesos D/X Clasificación/contadores revisan B1; referencias a UUID antiguo no se mueven automáticamente.
Selectores S Particular/global siguen conforme a reglas de elegibilidad, sin ocultación, alias, selección ni prioridad por adopción.
Catálogo global S Sin versiones/licencias locales ni uso transversal; Resource no cambia.
Borrado de raíces/revisiones observadas X/D RESTRICT por planes persistidos puede bloquear delete aun sin adopción; P07 debe aprobarlo o cambiar el modelo antes de activar preflight.
Inventario y consumers solo locales S Remoto, Access, SMB, dominio, certificados, soporte, buzones/carpetas conservan UUID y allowlist; se enumeran intactos.
Historiales E/X Anterior enlaza operación/sucesora; nueva señala predecesora/operación, sin fusionar arrays de revisiones.
APIs Companies E nuevas rutas; X B1 Nuevos contratos; lector antiguo recibe upgrade seguro. CRUD ordinario no adquiere permiso de sucesión.
Auditoría T/E Consulta causal autorizada, sin elevar acceso a historia administrativa global.
TanStack Query E Claves por sujeto/C/plan/operación, invalidación dirigida tras commit, sin duplicar estado remoto.

UI solo funcional: plan explicable, selección explícita, valores revisados, bloqueos visibles, confirmación y resultado enlazable. Diseño detallado se difiere; seguiría DESIGN, patrones de diálogo, i18n y organización por entidad/operación.

Tras commit: invalidar softwareKeys.company(C) si hay software, applicationKeys.company(C) si perfil, planes de fuente/C y operaciones de C/sujeto. Uso/entorno comparten queries operativas. Si hay derivadas independientes de puesto/dashboard/procesos, añadir sus claves precisas por contextos afectados al inspeccionarlas. Referencias/candidatos por propósito solo si su proyección depende de vínculos modificados; producto/actividad no cambian, por tanto no vaciar todo Resources ni catálogo global. Coincidencias R2.6 permanecen.

Fallo de invalidación se recupera con refetch dirigido; no revierte commit. Repetir resultado puede reintentar actualización local. Logout/401/403 elimina proyecciones sensibles del sujeto; caché no acredita permiso.

20. Flags y despliegue

Ningún flag se crea/cambia ahora; existentes default false. P08: gates nuevos independientes, también default false:

Gate propuesto Habilita No habilita
RESOURCE_ADOPTION_PREFLIGHT_ENABLED Crear planes de adopción autorizados. Confirmar ni compensar.
RESOURCE_ADOPTION_CONFIRM_ENABLED Nueva ejecución de plan válido y prerrequisitos completos. Propósitos cerrados, permisos ni compensación.
RESOURCE_ADOPTION_COMPENSATION_PREFLIGHT_ENABLED Preparar plan compensatorio autorizado. Ejecutarlo ni abrir adopción directa.
RESOURCE_ADOPTION_COMPENSATE_ENABLED Confirmar compensación revisada. Forzar evolucionadas, borrar historia ni asociar nuevos globales.

Lectura autorizada de resultados/operaciones previos y resolución usada no se apaga con escritura. Catálogo de lectura no concede adopción. Adopción nueva exige catálogo y gates por tipos seleccionados: software o perfiles. Gate de picker mixto no es permiso de escritura ni requisito técnico de destino elegido por UUID válido. Compensación particular aplica §16, sin reabrir asociación global.

Despliegue futuro, no ejecución:

  1. Aprobar semántica/alcance/versionado y permisos. Inventariar lectores/escritores/dependencias. Resolver o aceptar expresamente deuda/gates previos de R2.4–R2.6 sin declararlos cerrados por este documento.
  2. Diseñar/ensayar migraciones explícitas en MariaDB 11.8 desechable con CHECK/FK activos. DDL separado del DML; no rollback ficticio de ALTER TABLE ni foreign_key_checks=0. Ensayo de recuperación separado de compensación.
  3. Desplegar auditoría/autorización y lectores compatibles en todos los backends/clientes, con gates cerrados. No escribir B1 con instancias antiguas activas.
  4. Ejecutar matriz §21 y volumen. Activar solo preflight limitado, revisar cobertura/coste/permisos; lectura correcta no activa confirmación.
  5. Piloto de confirmación autorizado por compañía/selección acotada. Monitorizar latencia, consultas, contención, deadlocks, UNIQUE/auditoría, rechazos/stale, pending antiguos y recuperación por clave; sin secretos en logs.
  6. Compensación exige aprobación/prueba propia; no activarla junto al piloto.
  7. Gates off detienen comandos nuevos, no borran resultados. Validación al inicio no promete cancelar una transacción en curso: drenar escrituras si se exige parada inmediata y coordinar instancias/env; no cambio instantáneo supuesto.

Rollback de despliegue: antes de B1, volver solo a versión compatible con expansión. Desde la primera revisión nueva, lectores B1 son versión mínima obligatoria; backend previo no es downgrade seguro. Cerrar escrituras y corregir hacia delante o usar versión preparada que siga leyendo B1. Compensar tampoco elimina ese requisito histórico. Restaurar backup no es «deshacer adopción».

21. Matriz de pruebas R2.7

Diseño futuro, no ejecutado. U unidad/DTO/canonicalización; M MariaDB real; H HTTP real con sesión/CSRF; P Playwright MCP. Base desechable metis_desk_test; ≥15 compañías y principal con ≥50 personas/activos/recursos/perfiles/puestos; volumen ampliado para límites/históricos. Unitarias pequeñas. Barreras observables como las existentes, sin sleeps arbitrarios.

ID Escenario Expectativa Capas
T01 UUID diferentes, homónimos Recursos intactos; sucesora UUID nueva, target anterior conservado. U,M,H,P
T02 Proveedor ausente/name-only Sin evidencia adicional no confirmar; no asumir fabricante. U,H,P
T03 Misma marca, edición diferente Bloqueo comercial explícito, no merge heurístico. U,H,P
T04 Destino inactivo/OS/copia application inválida Sin nueva asociación; proyección segura. U,M,H
T05 Fuente/licencia/asset/profile B bajo A, también admin 404/error seguro, cero efectos. U,M,H
T06 Sin asociaciones/selección vacía Plan no-effect, no operación equivalente A3. U,H,P
T07 Solo Software, solo Profile y ambas Exactamente seleccionadas, un commit; resto intacto. U,M,H,P
T08 pending/configured/removal_pending/terminales B1 aprobado solo donde corresponda; cerradas keep y retirada bloqueada. U,M,H,P
T09 Destino abierto/cerrado histórico Abierto bloquea; cerrado no colisiona; sin upsert sobre otra raíz. U,M,H
T10 Carrera par asset/global y profile/global Un resultado válido; otro stale/conflict y sin efectos parciales. M,H
T11 Licencia ajena/inactiva/caducada/cobertura no acreditada/null revisado Policies y evidencia correctas, medianoche UTC revalidada. U,M,H
T12 Versión incompatible/web con versión Bloqueo/schema; no inferencia del nombre. U,H,P
T13 Cambio/reversión de valores, revisión/dependencia nueva tras plan stale, sin sobrescribir; revisión detectada aunque valores iguales. U,M,H,P
T14 Orden, null/ausente/vacío, UUID/Unicode/posiciones Huella determinista y diferencias significativas; no permiso por hash. U
T15 Simultáneas misma clave, distintas claves mismo plan, planes misma raíz Un efecto, resultado/conflicto explícito, auditoría sin duplicados efectivos. M,H
T16 Misma clave/body diferente/actor distinto Conflicto/denegación sin datos ajenos; reserva inmutable. U,M,H
T17 Timeout antes/después de commit y restart Pending recuperable o resultado original; no nueva clave/sucesoras. M,H,P
T18 Fallo antes de cierre, después de cierre, durante alta/revisión Rollback integral; hashes de raíces/claves/revisiones como antes. M,H
T19 Fallo procedencia/auditoría/antes de commit Sin efectos ni evento de éxito huérfano. M,H
T20 Result.fail tras escritura administrada Adaptador aborta realmente; detectar commit accidental. M
T21 Error de respuesta/cache después de commit Resultado durable; ningún rollback fingido ni reejecución distinta. M,H,P
T22 Desactivación en ambos órdenes de locks Rechazo si desactivar primero; si adopción primero, preservar sucesoras y revisión derivada. M,H
T23 Compensación sin evolución Nuevas particulares UUID nuevas, historia preservada, un vínculo inverso. U,M,H,P
T24 Sucesora modificada/nueva dependencia, incluso valor restaurado Bloqueo completo, sin sobrescribir. U,M,H,P
T25 Compensación repetida/parcialmente incompatible Resultado original; una incompatible implica cero cambios. M,H,P
T26 Compensar con global/gates off y particular activo/inactivo No reabrir globals para cerrar existente; policies locales obligatorias. U,M,H
T27 Sin sesión/permiso, origen/CSRF inválidos 401/403 y cero datos privados/efectos. H,P
T28 Cada flag off, resultado previo, proyección sin secretos Nueva ejecución bloqueada; resultado autorizado legible. U,M,H,P
T29 Cliente/backend anterior y ConfigurationSchema compartido Upgrade seguro, sin B1 en Access ni lectores viejos atendiendo B1. U,M,H,P
T30 Delete de raíz/revisión/Resource con procedencia Error de negocio y RESTRICT, sin borrar revisiones parcialmente. M,H,P
T31 Plan explicable, conflictos, selección, confirmación, recuperación Sin automático; foco/teclado y resultado auditable. H,P
T32 0/1/límite/exceso, paginación, error y contenido extenso No truncar a ready; límites/cobertura reales y responsive. U,M,H,P
T33 Regresiones R2.2–R2.6, Identity, Assets, perfiles/puestos, licencias/SMB/Access/remoto/historia Defaults off, UUID/referencias preservados, consumidores locales sin globales nuevos. U,M,H,P
T34 Caída pending, rechazo repetido, resultado tras evolucionar sucesoras Recuperación sin lease ficticio; rechazo/resultado estables; GET no ejecuta. M,H
T35 Varias instancias, deadlock/timeout/carga/lotes Reintento unitario acotado y coste/latencia medidos sin SLA inventado. M,H

MCP futuro: carga/error/vacío, selección revisable, motivos, Tab/Shift+Tab/Escape, foco inicial/retorno; anchos 1600/1440/1280/1024/768/390, capturas inspeccionadas y datos extensos según procedimiento. No se preparan fixtures ni navegador en D08.1.

22. Riesgos residuales

Tipo Riesgo y tratamiento
R Evidencia humana incorrecta: estructura/trazabilidad no demuestra identidad comercial. Mantener A0 si no se resuelve.
A/T B1 rompe estado cerrado de lectores actuales; requiere aprobación y despliegue, no basta VARCHAR.
T/R APIs actuales cargan colecciones/historial; preflight necesita proyección acotada y persistida e índices/mediciones propios. Tiempos R2.6 no estiman confirmación.
T/R Mutex exige todos los escritores cooperantes. Inventario y pruebas; SQL externo/futuro sin lock queda fuera.
T Upsert, transacciones privadas y Result.fail post-escritura necesitan adaptación probada, no se cambian aquí.
A Parcialidad, permisos/doble aprobación, retención y compensación requieren propietario de producto.
T Auditoría central no implementada; no confirmar sin capacidad común necesaria.
R Lotes largos retienen locks y serializan C; medir límites, no dividir commit de un plan.
R Primera revisión B1 impide downgrade a backend anterior aunque se compense después.
R BD caída impide prometer intento durable; nunca éxito sin auditoría atómica.
F Deduplicación automática, alias global, cambios de UUID/owner, licencias automáticas, ejecución remota, purgas y nueva ACL.

23. Decisiones pendientes

ID Clase Propuesta y cuestión a resolver Aprobación/dependencia
P01 — B1 A Cierre documental superseded específico o alternativa que no falsee retirada; pending/configured permitidos, removal_pending bloqueado. Producto/arquitectura; sin resolver no confirmar A2 configurada.
P02 — A A Selección parcial hasta 100, un commit por plan y resto explícitamente intacto, frente a exigir todas las asociaciones. Producto; si exige todas, revisar cobertura/conflictos/límites.
P03 — J A/T Permisos por acción: admin inicial no delegable recomendado, sin dos personas obligatorias. Decidir delegación, separación de funciones o ACL. Producto/seguridad e Identity; no permiso implícito desde global.manage.
P04 — D/F A/T Vigencia 30 min, 100 seleccionadas/10.000 observadas y evidencia acotada; ratificar tras medir. Producto/operación, sin rendimiento prometido.
P05 — K/L A/T Negociación Operational-Contract: 2 y schemas específicos/lectores B1. Arquitectura/consumidores; ampliación D09 explícita.
P06 — I A Compensación completa única, sin evolución, sin parcial/recursiva; se puede diferir sin anunciar reversibilidad. Producto/seguridad. Intervención posterior no significa bypass.
P07 — C/H A Retención/consulta/privacidad; sin purga inicial y protección RESTRICT también de observaciones no seleccionadas/planes abandonados, o rediseño explícito previo. Resolver anonimización por responsable competente si corresponde. Producto/privacidad; claves confirmadas no reutilizables.
P08 — despliegue A/T Gates separados, piloto y versión mínima; resolver/aceptar deuda previa antes de activar. Producto/operación. Aprobación técnica no abre flags.
T01 T Escritor/lector común de auditoría, cobertura atómica de metadatos/efectos. Implementación futura y prueba de fallos.
T02 T Puerto Companies de unidad de adopción, current reads y escritores ligados/INSERT estricto. Conforme capas, sin modificar repositorios en D08.1.
T03 T Modelo físico/FK compuestas, eliminación protegida, UNIQUE e idempotencia. Ensayos MariaDB 11.8 con restricciones activas.
T04 T Inventario de dependencias/escritores y actualización de procesos/entorno/counters. Responsables consumidores; FK no basta.
T05 T Autorización pública Identity por acción y negociación de clientes. Antes de confirmar, no solo frontend.

Locks/idempotencia están definidos como propuesta y contrastados con prefijo actual, pero garantías nuevas requieren T02/T03 y carreras. No se dan por ratificadas parcialidad, permisos, retención, estados o compensación. Una aprobación que excluya P01/P05 debe delimitar expresamente el alcance restante.

24. Recomendación

Mantener A0 y recomendar A2: selección explícita, cierre documental aprobado, nuevas raíces y procedencia relacional, sin A1 ni equivalencia automática. A3 puede evaluarse independientemente, sin obligación nueva para R2.6.

Propuesta de alcance futuro, sin autorizarlo:

  • R2.7a: autorización/auditoría, ensayo de expansión, lectores compatibles y preflight completo e inmutable. Sin confirmar asociaciones. Puede revisarse antes de aprobar toda compensación.
  • R2.7b: tras P01–P05/P08 y T01–T05, confirmación síncrona de una C/fuente/destino, selección acotada, ambas familias en una unidad, consulta/historial/idempotencia y pruebas de fallos/carreras. Sin automatismos ni lotes entre compañías.
  • Compensación posterior: P06 y pruebas propias, gate independiente. Hasta entonces no ofrecer «deshacer» ni prometer reversibilidad.

Es planificación documental: no abre ramas/tareas ejecutables, migraciones ni R2.7. Aprobar arquitectura no autoriza esas fases.

25. Condiciones de aprobación

Matriz de consistencia

Propuesta Contrato actual Compatibilidad Cambio requerido Decisión
Conservar Resources/UUID D01/D07, Resource scoped Compatible. Ningún owner/scope/plantilla cambia. I01/P.
Sucesoras UUID nuevas D08/sameTarget/revisiones Compatible como comando nuevo no existente. Procedencia/comando, sin UPDATE target. A2/P.
superseded documental Cinco estados/closed actuales Incompatible sin ampliación de lectores/schemas; no falsea retirada. Aprobar B1 y evolución explícita de contrato operativo/D09; schemas específicos/counters. P01/P05.
Piloto pending→never_configured Transición existente Solo cancelación real; no configuradas. Aprobar alcance alternativo separado. No autorizado.
Atomicidad conjunta Repositorios con transacción propia Garantía nueva no disponible. Puerto unitario y rollback real. T02.
Destino por propósito D02/D04-R/D06/sesión Resources Compatible. Puerto vigente en misma unidad. P/T.
Permiso de adopción D03/D04, admin global no implica adopción Extensión explícita. Aprobar sujetos/contrato Identity. P03/T05.
Procedencia relacional D08/normalización Compatible, tablas nuevas no existentes. Modelo físico/migración futura/ensayo. T03.
Auditoría en commit Diseño acordado aún pendiente Requisito compatible y bloqueante. Mecanismo común y cobertura. T01.
Idempotencia de comando No-op update/creationId global Aquellas capacidades no bastan. Reserva/resultados/UNIQUE/retención. H/P07/T03.
Selección de C D04/consumers locales Compatible si producto aprueba parcialidad. Cobertura/exclusiones explícitas. P02.
Compensación D08: nueva sucesión sin borrar historia Compatible condicionada; no existe. Plan inverso/evolución/gate/auditoría. P06.
Particular en picker D07/R2.6 Compatible. No ocultar ni sustituir. Sin cambio.
B1 en entorno/procesos R2.4/R2.5/DTO estrictos Incompatible sin preparación. Lectores/contadores/negociación. T04/P05.
Gates y despliegue D10/default false Compatible con gates separados; no downgrade histórico. Preflight/versión mínima, no activar ahora. P08.

No se cambia D01–D10 ni se ratifica D08 en este archivo. Ampliar estados/negociación es decisión adicional pendiente. Si la solución elegida contradice un contrato ratificado, debe aprobarse/documentarse su evolución explícita antes de implementarla, conservando documentos históricos.

Dictamen

APTA CON CONDICIONES: arquitectura viable y revisable con decisiones funcionales/dependencias delimitadas. Para ratificar el contrato de confirmación: resolver P01–P05/P08, aceptar procedencia/idempotencia/locks y asignar T01–T05. Para compensación, P06; para purga, P07 y contrato adicional. Aprobar rumbo con condiciones no permite omitirlas al programar.

P07 debe resolver además el régimen inicial de retención y su impacto en delete antes de habilitar preflight persistido; una futura purga sigue necesitando contrato adicional.

Antes de implementar: aprobación escrita de semántica/alcance, HTTP/seguridad/versionado y plan relacional. Antes de activar: constraints/migraciones ensayadas, lectores/escritores compatibles, autorización/auditoría implementadas, matriz §21 ejecutada con resultados/limitaciones, flags default off y tratamiento explícito de deuda/gates previos. G6 histórico R2.4 y aceptación global pendiente R2.5/R2.6 no se cierran aquí.

Verificación de esta entrega

Entorno WSL, Node 24.20.0, PNPM 11.25.0, estado Git y snapshot de archivos sin secretos comprobados. Inspección de dominio, Zod, persistencia, guards, locks, composición, keys y consumidores; pruebas existentes R2.4, R2.5, R2.6 y barreras consultadas como evidencia, sin ejecutarlas de nuevo. Fuentes externas primarias citadas de MariaDB/Sequelize v6, sin atribuirle APIs v7.

Cierre documental realizado: 25 apartados y enlaces locales comprobados sin destinos ausentes; cinco bloques Mermaid revisados estáticamente, sin afirmar renderizado con un motor Mermaid; fences equilibrados, ausencia de espacios finales/conflictos y comparación de hashes de los 3.168 archivos previos, sin modificaciones. Solo se añade este documento. No ejecutar typecheck/lint/test/check/build ni nuevas pruebas SQL/HTTP/MCP: no cambia código y la petición prohíbe pruebas/fixtures de una adopción inexistente. 105/105, 6/6, 50/50 y 22 comprobaciones MCP/12 capturas son resultados históricos R2.6, no nuevos de D08.1.