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

30 KiB
Raw Blame History

R2.0 — Resumen para aprobación

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

Estado: contrato completo propuesto, pendiente de ratificación. No aprobado automáticamente. R2.0 termina con diez documentos; no implementa ni autoriza R2.1–R2.6. Los principios expresos del usuario se marcan aprobados como restricciones, no como aprobación del diseño técnico completo.

1. Decisiones recomendadas

Decisión Recomendación para ratificar Consecuencia principal
D01 Resource único con scope explícito global/company y owner NULL/UUID, CHECK, propiedad/plantilla inmutables Cambia raíz/persistencia y nuevos DTO; legacy local queda intacto
D02 Solo serie Aplicación stockKey template:application, campos globales, sin integración Regla inicial ya establecida por el usuario; otras plantillas excluidas
D03 Capacidad conceptual resources.global.manage solo para administrador inicial, comprobada desde Identity en cada operación Restricción nueva para producto e igualmente para mutaciones globales de plantillas/campos Resources; sin grants delegables
D04 Mantener explícitamente el modelo de soporte compartido actual, sin simular ACL operador–compañía Contexto de operación A nunca acepta local B, aunque el operador pueda abrir B por separado
D04-R Mantener list/CRUD locales y añadir lecturas por propósito para catálogo/candidatos/referencias Separación ya requerida; firmas y proyecciones concretas recomendadas
D05 Producto mínimo para soporte, notes/especificación completa/historia de actores solo para manager No exponer compañías usuarias, instalaciones, perfiles, licencias o datos operativos ajenos
D06 Solo active existente; inactivo resoluble, fuera de nuevas asociaciones; plantilla inactiva solo bloquea alta Resource needsReview derivado en instalación/perfil abiertos, sin campo universal ni DML masivo
D07 UUID como identidad, homónimos permitidos global/local, avisos de coincidencia sin equivalencia; replay por creationId UUIDv7 No unique global por nombre; reglas locales legacy intactas; sin tabla extra de idempotencia
D09 Routers/DTO nuevos del mismo módulo; legacy exacto; proyección mínima/lotes; negociación explícita de cliente y keys por contexto Paths, schemas, header y límites detallados en 04 son propuestas, no funcionalidades existentes
D10 Lectores duales antes de DDL, expansión ensayada y gates por catálogo/software/perfil No primer global con backend incompatible ni downgrade tras uso

Convivencia/no fusión automática, licencias locales, UUID estable, validación en servidor, no compañía ficticia y preservación de referencias históricas son decisiones de partida aprobadas por el usuario. Los detalles técnicos de esta tabla siguen pendientes de ratificación salvo los alcances expresamente marcados. No se pregunta a mitad del trabajo por estas opciones: el contrato revisable permite decidirlas después.

2. Decisiones bloqueadas y condiciones de bloqueo

No se ha encontrado una incompatibilidad que impida proponer Resources global sobre el modelo actual. Quedan bloqueadas las siguientes ejecuciones, sin ocultarlas como «detalle de implementación»:

  • Inicio R2.1: falta ratificación explícita de D01 y autorización del trabajo de implementación; antes de R2.1b además falta ensayo del esquema efectivo/version patch de MariaDB 11.8, FKs y CHECK. La preferencia por scope explícito no es aprobación.
  • Activación global: no existe hoy permiso manage ni está aprobada su asignación. D03/D04/D05 deben ratificarse e implementarse/probarse antes de G3b.
  • Variante con administradores delegables: BLOQUEADA si se exige desde primera versión, porque Identity no dispone de contrato de grant/revoke ni persistencia de permisos. La propuesta admin-inicial-only evita añadir ese alcance; no lo simula.
  • Variante de ACL estricta operador–compañía: BLOQUEADA para activación si ese es el requisito de negocio. La aplicación documenta soporte compartido, no esa ACL; debe diseñarse por separado antes de afirmar aislamiento de operador.
  • Consolidación que modifique vínculos: BLOQUEADA hasta ADR de sucesión y auditoría/reversión. El destino operativo fijo impide usar update actual para sustituir resourceId.

La política admin inicial, el modelo compartido y la privacidad son decisiones humanas de negocio. Las condiciones de SQL y pruebas son evidencias técnicas futuras que no se sustituyen por aprobación documental.

3. Decisiones diferidas

D08 consolidación con mutación; grants/revokes delegables; ocultación de un producto global por compañía; otras plantillas globales; campos de categoría/familia/identificador externo; historial público de producto; borrado físico global; vista transversal de uso de compañías. Se puede completar primera versión y R2.6 de coexistencia sin estas extensiones. No son funcionalidades prometidas ni migraciones ocultas de R2.1.

4. Riesgos críticos

  • Ensanchar indiscriminadamente IResourceInventoryService.list permitiría destinos globales en remoto y afectaría consumidores operativos que no deben compartirlos. La matriz 06 fija cada propósito, incluido los que siguen solo locales.
  • Crítico condicionado: confundir autenticación del espacio compartido con ACL por compañía. Si el despliegue requiere operadores aislados, el contrato de soporte compartido no satisface ese requisito.
  • Autorizar al administrador global como bypass de pertenencia rompería integridad: incluso manager no puede vincular local B a instalación/perfil de A.

5. Riesgos altos

Mutaciones globales de plantillas hoy no restringidas; DTO/mapper no nullable y strict legacy; FKs compuestas/DDL con commit implícito; propagación que presupone companyId; actividad validada en otra transacción; exposición de notas/actores; clientes/caché desactualizados; vuelta a lectores que no entienden globales. Se exige serialización común conservadora, proyecciones distintas y activación controlada; no se atribuye probabilidad numérica ni se afirma vulnerabilidad explotada.

6. Dependencias y orden

R2.1a prepara lectores sin DDL → R2.1b expande esquema/backfill → R2.2 aporta seguridad/contratos/resolución en transacción → R2.3 catálogo → R2.4 software y R2.5 perfiles con lectores secundarios → R2.6 coexistencia/avisos. Activación de software y perfil puede separarse; compartir composición/contratos no fusiona agregados. El registro de relaciones tipadas y consumidores SMB/directorio/Access no adquiere ámbito global.

7. Condiciones para comenzar R2.1

Ratificar D01 y constatar D02 restringida, aceptar subetapas de lectores/DDL y alcance excluido, autorizar expresamente la implementación posterior y preparar baseline/test aislado. R2.1a puede prepararse sin cerrar grants ni UI; R2.1b necesita preflight SQL documentado y recuperación ensayada. No se necesita poblar producción ni tener catálogo global abierto.

8. Condiciones para habilitar globales

Todos los lectores/propagaciones/backend compatibles; esquema completo con CHECK/FKs ON y backfill íntegro; autorización global y política operador/contexto aprobadas; proyecciones/paths y privacidad aceptadas; pruebas de seguridad, serialización, idempotencia y recuperación pasadas; catálogo y UI con estados/teclado comprobados. Para asociaciones, además lectores operativos/históricos y clientes compatibles y flags específicos. El primer global ya impide downgrade trivial; las referencias globales obligan a mantener resolución aunque se apaguen flags.

9. Fuera del alcance de R2.0

Cualquier código funcional, schema/DTO existente modificado, migración/DDL, permiso concedido, componente/hook/i18n/dependencia/configuración de despliegue alterada, pruebas HTTP/BD, siembra, catálogo implementado, transferencia de recursos, licencias globales o consolidación ejecutada. Tampoco se ejecuta el plan de pruebas futuro ni se valida una UI inexistente en Playwright.

10. Ratificación humana necesaria

Ratificar los detalles de D01, D03, D04, D05, D06, D07, D09 y D10 según registro 02; D02 inicial y vetos de integridad ya están establecidos. D08 no requiere aprobar mutaciones para lanzar coexistencia: permanece diferida. Una aprobación posterior debe identificar versión del contrato, decisiones aceptadas y variantes rechazadas. No se registra aprobación por silencio, por tiempo transcurrido ni porque el asistente recomiende una opción.

Índice de los diez entregables

  1. Contrato arquitectónico e invariantes.
  2. Decisiones D01–D10 y correspondencia D04.
  3. Seguridad, privacidad y escenarios S01–S12.
  4. API, DTO, errores, búsqueda y UX.
  5. Persistencia, MariaDB y unidad de consistencia.
  6. Matrices completas de consumidores.
  7. Despliegue, compatibilidad y rollback.
  8. Pruebas e invariantes/riesgos trazados.
  9. Implementación R2.1–R2.6, alcance y aceptación.
  10. Este resumen para revisar/ratificar.

Evidencia y comprobación R2.0

Se leyeron íntegramente los doce documentos de auditoría y se contrastaron las decisiones con código actual. HEAD fa9d95fa9e227a66a45e278d98e2895d8a9995ad; Node v24.20.0 y PNPM 11.25.0 coinciden con package.json. Las 99 huellas de fuentes citadas por auditoría 12 coincidían al inicio; durante el trabajo se detectaron cambios concurrentes, con 97 iguales y dos fuentes web modificadas en la revisión de cierre. Estas dos modificaciones afectan búsqueda local (createTextMatcher), no ámbito/permisos/backend. Se releyeron y las anclas se recalcularon sobre el contenido actual; discrepancia C09 y contrato de búsqueda revisado en 01/04. No se atribuyen esos cambios a R2.0 ni se modifican. Se ampliaron lecturas de Identity/User/module, ambos builders/mappers, SQL/constraints, proyecciones y componentes/patrones compactos. Los conflictos documentales y diferencias temporales C01–C09 están resueltos expresamente en 01; no se sobrescribió la auditoría histórica.

Esta tarea solo escribe diez Markdown nuevos bajo esta carpeta y conserva íntegros los doce de auditoría. Otros cambios de código/documentación aparecidos en el árbol compartido son concurrentes y ajenos a esta entrega; se inspeccionan cuando afectan evidencia, sin editarlos ni revertirlos. Scripts de comprobación temporales en /tmp. No se ejecutaron pnpm typecheck/lint/test/check/build ni suites funcionales: no hay código cambiado y los resultados anteriores no se reutilizan como validación actual. No se conectó BD ni se ejecutaron migraciones, datos sintéticos o Playwright. Diseño/UI se apoya en normas y skills ya consultadas, sin auditores especializados ni certificación visual.

La comprobación documental debe validar enlaces/archivo/ancla de fuente, D01–D10, INV-01–INV-26 y T01–T26, escenarios y propósitos de matrices, operaciones de API, gates y alcance permitido de cada fase. Se conservan evidencias de símbolos en el apéndice siguiente para repetir la comprobación contra el árbol actual. Las referencias futuras de tipos/paths propuestas no se confunden con símbolos/rutas ya existentes.

Evidencias de código contrastadas

Todas las entradas son código existente; los nombres propuestos en 04 no se añaden a esta lista.

Clave Archivo/línea Expresión anclada
E-accessFK modules/companies/src/api/infrastructure/persistence/access-relational.ts export const accessColumns
E-admin modules/identity/src/api/application/identity.use-cases.ts private async administrator
E-appResponse modules/companies/src/api/application/application-configuration-response.builder.ts export function buildApplicationResponse
E-applicationDTO modules/companies/src/common/application-configurations.ts export const ApplicationConfigurationSchema
E-applicationFK modules/companies/src/api/infrastructure/persistence/configuration-snapshots.ts export const applicationSnapshot
E-applicationMapper modules/companies/src/api/application/application-configuration-input.mapper.ts export function mapApplicationInput
E-applicationPolicy modules/companies/src/api/application/application-configuration-policy.ts export function applicationReferences
E-applicationRead modules/companies/src/api/infrastructure/persistence/sequelize-application-configuration.repository.ts private async load
E-auth modules/identity/src/api/infrastructure/http/require-authenticated.ts export function requireAuthenticated
E-capture modules/resources/src/api/application/resource-input.mapper.ts export function captureResourceSpecification
E-catalogDTO modules/resources/src/common/index.ts export const CatalogItemSchema
E-catalogRoutes modules/resources/src/api/infrastructure/http/resource-catalog.routes.ts export function registerResourceCatalogRoutes
E-catalogSQL modules/resources/src/api/infrastructure/persistence/resource-catalog.model.ts export async function migrateResourceCatalog
E-certificateFK modules/companies/src/api/infrastructure/persistence/configuration-snapshots.ts export const certificateSnapshot
E-compact packages/rdx-ui/src/components/compact-table.tsx export function CompactTable
E-config apps/server/src/config/database.ts export function readDatabaseEnvironment
E-csrf modules/identity/src/api/infrastructure/http/identity.routes.ts request.get("origin") !== origin
E-dbVersion compose.yaml image: mariadb:11.8
E-directoryRead modules/resources/src/api/infrastructure/persistence/directory-domain-reader.ts export class DirectoryDomainReader
E-directorySQL modules/resources/src/api/infrastructure/persistence/directory-domain-migration.ts export async function migrateDirectoryDomains
E-dto modules/resources/src/common/inventory.ts export const ResourceSchema
E-folderPolicy modules/companies/src/api/application/folder-mapping-policy.ts export function folderReferences
E-history modules/resources/src/api/infrastructure/persistence/resource-revision-specifications.ts export async function migrateResourceRevisionSpecifications
E-identityModule modules/identity/src/api/module.ts export async function createIdentityModule
E-integrationApplication apps/server/src/applications.integration.ts export async function
E-integrationResource apps/server/src/resources.integration.ts export async function
E-integrationSoftware apps/server/src/software-installations.integration.ts export async function
E-invalidation modules/resources/src/web/resources/shared/api/resource-related-query-keys.ts export function resourceRelatedQueryKeys
E-inventoryAPI modules/resources/src/web/resources/shared/api/inventory-api.ts export const inventoryKeys
E-mapper modules/resources/src/api/infrastructure/persistence/resource-persistence.mapper.ts export class ResourcePersistenceMapper
E-module modules/resources/src/api/module.ts export async function createResourceModule
E-name packages/rdx-ddd/src/value-objects/name.vo.ts export class Name
E-owner modules/resources/src/api/domain/resource.aggregate.ts companyId: UniqueID;
E-picker packages/rdx-ui/src/components/option-picker-list.tsx export function OptionPickerList
E-preview packages/rdx-ui/src/components/collection-preview.tsx export function CollectionPreview
E-processRead modules/companies/src/api/infrastructure/persistence/sequelize-process.repository.ts await this.resources.list(company)
E-projection modules/resources/src/api/infrastructure/persistence/resource-compatibility.ts export async function projectResource
E-propagation modules/resources/src/api/infrastructure/persistence/prepare-resource-template-updates.ts export async function prepareResourceTemplateUpdates
E-read modules/resources/src/api/infrastructure/persistence/resource-inventory-relational.ts export async function readInventory
E-relationshipAuth apps/server/src/infrastructure/http/relationship-read-access.ts export class SessionRelationshipReadAccess
E-remoteFK modules/companies/src/api/infrastructure/persistence/mail-remote-snapshots.ts export const remoteSnapshot
E-remotePolicy modules/companies/src/api/application/remote-connection-policy.ts export function remoteReferences
E-resourceDetail modules/resources/src/web/resources/detail/ui/resource-detail.tsx export function ResourceDetail
E-routes modules/resources/src/api/infrastructure/http/resource.routes.ts export function registerResourceRoutes
E-runtime apps/server/src/infrastructure/http/identity-runtime.ts export async function createIdentityRuntime
E-save modules/resources/src/api/application/resource.use-cases.ts save(
E-seed modules/resources/src/api/domain/resource-catalog-seed.ts const TEMPLATES
E-select packages/rdx-ui/src/components/select-with-action.tsx export function SelectWithAction
E-service modules/resources/src/api/application/resource-inventory.service.ts export interface IResourceInventoryService
E-shareRead modules/resources/src/api/infrastructure/persistence/network-share-reader.ts export class NetworkShareReader
E-shareSQL modules/resources/src/api/infrastructure/persistence/network-share-migration.ts export async function migrateNetworkShares
E-softwareDTO modules/companies/src/common/software-installations.ts export const SoftwareInstallationSchema
E-softwareFK modules/companies/src/api/infrastructure/persistence/software-installation-snapshot.ts export const softwareSnapshot
E-softwareInput modules/companies/src/api/domain/software-installation-values.ts export const SoftwareInstallationInputSchema
E-softwareMapper modules/companies/src/api/application/software-installation-input.mapper.ts export function mapSoftwareInput
E-softwarePolicy modules/companies/src/api/application/software-installation-policy.ts export function softwareReferences
E-softwareRead modules/companies/src/api/infrastructure/persistence/sequelize-software-installation.repository.ts private async load
E-softwareResponse modules/companies/src/api/application/software-installation-response.builder.ts export function buildSoftwareResponse
E-sql modules/resources/src/api/infrastructure/persistence/resource.model.ts export async function migrateInventory
E-supportRead modules/assets/src/api/infrastructure/persistence/sequelize-support.repository.ts SELECT r.id,r.name
E-supportSQL modules/assets/src/api/infrastructure/persistence/support-migration.ts support_resource_company
E-templateStatus modules/resources/src/api/domain/resource-catalog.aggregate.ts active(
E-textSearch packages/rdx-ui/src/lib/text-search.ts export function normalizeSearchText
E-unitApplication modules/companies/src/api/domain/application-configuration.test.ts test(
E-unitLifecycle modules/resources/src/api/application/resource-lifecycle.test.ts test(
E-unitResource modules/resources/src/api/domain/resource.test.ts test(
E-unitSoftware modules/companies/src/api/domain/software-installation.test.ts test(
E-usage modules/resources/src/api/application/resource-inventory.service.ts function resourceUsage
E-user modules/identity/src/api/domain/user.aggregate.ts export type UserProps

Fuentes documentales completas de la auditoría

Fuente SHA-256 al formalizar
01-modelo-resource.md d8dda2ac4e22351eb3be203da7331c9e1ade5f0975bd51ea94bc10b983b6f78b
02-plantillas-aplicacion.md 4be8cb2dba0fa8e54fdda7bff0ac83027b98f6d29aef5eadf27208eeb54d4e1c
03-sequelize-mariadb.md 2805772bc224be908cf82df775d93c907926573ca7d1d7cbd67b82cc70fb15f9
04-aislamiento-autorizacion.md 562771079ce0fa35e798a93e43e7f6189381e12cd10b03ccbfd889a8f68f6053
05-consumidores-resource.md 9deba084c334c2cbb79584a3f083bce313284641a9a737c6b42a952ebf3531be
06-software-configuraciones.md a900e206f30827829731973b427770019ad411e26afa19013386b39d76b3efe3
07-contratos-api.md 5148d7494bee890ed519c07947d28533778e098a1cf65679c65a95537707df5d
08-propuesta-ui-ux.md d4162d5c2ceef6183658a901a31018e4070ea712df650de60ad05ef83f9ec5a9
09-alternativas-arquitectonicas.md cf29fc96d801d658b31189b6379bca22afbaff610d528e09aaec7ec9ff09c11c
10-plan-implementacion.md 532387597f375c5daec91ffec4e4badb6b57c78b2e2eb4ae74327d390734a93d
11-resumen-ejecutivo.md 7df1095dd62e65ce654f685a924796cca0baaa4ef786e34ec0d34b27291f0bdc
12-matriz-trazabilidad.md 6030853b658bc9cf404e59f4e3e3471eb8bd6ffbd5678814b11e8a3597efae70

Resultado de comprobación documental

Correctos: 10 entregables, 224 enlaces locales (181 con línea), 69 anclas de símbolos, D01–D10 y los 26 invariantes con sus T01–T26. Los doce documentos de auditoría conservan sus huellas. Se ejecutaron comprobadores Python de existencia/anclas/cobertura y whitespace individual con git diff --no-index --check; git diff --check no reporta errores. La comparación con el baseline detectó cambios concurrentes en 27 archivos ya existentes y otros nuevos ajenos a esta tarea, conservados sin editarlos ni revertirlos. Esa comparación no se presenta como ausencia de cambios del resto del repositorio.

El siguiente comprobador es reproducible desde la raíz, solo lectura; no sustituye la revisión semántica de matrices/decisiones ni ejecuta tests futuros:

python3 - <<'PY'
from pathlib import Path
import hashlib
import re
import subprocess

base = Path('docs/architecture/resources-global-scope')
files = sorted(base.glob('*.md'))
assert len(files) == 10
links = 0
for file in files:
    body = file.read_text()
    assert chr(123) * 2 not in body and chr(125) * 2 not in body
    assert body.count(chr(96) * 3) % 2 == 0
    for target in re.findall(r'\]\(([^)]+)\)', body):
        if target.startswith(('https://', 'http://')):
            continue
        name, _, anchor = target.partition('#')
        source = (file.parent / name).resolve()
        assert source.is_file(), target
        if anchor.startswith('L'):
            assert 1 <= int(anchor[1:]) <= len(source.read_text().splitlines())
        links += 1
    result = subprocess.run(['git', 'diff', '--no-index', '--check', '/dev/null', str(file)], capture_output=True, text=True)
    assert result.returncode in (0, 1) and not result.stdout and not result.stderr
contract = (base / '01-contrato-arquitectonico.md').read_text()
tests = (base / '08-plan-pruebas.md').read_text()
decisions = (base / '02-decisiones-d01-d10.md').read_text()
for number in range(1, 27):
    assert f'| INV-{number:02} |' in contract
    assert f'| T{number:02} / INV-{number:02} |' in tests
for number in range(1, 11):
    assert f'| D{number:02} |' in decisions
summary = (base / '10-resumen-para-aprobacion.md').read_text()
anchors = re.findall(r'^\| E-([^| ]+) \| \[([^]]+)\]\([^#]+#L(\d+)\) \| `([^`]+)` \|$', summary, re.M)
for key, name, line, token in anchors:
    assert token.replace(' / ', '|') in Path(name).read_text().splitlines()[int(line)-1], key
sources = re.findall(r'^\| \[([^]]+\.md)\]\(../../auditorias/resources-global-scope/[^)]+\) \| `([a-f0-9]{64})` \|$', summary, re.M)
assert len(sources) == 12
for name, digest in sources:
    assert hashlib.sha256((Path('docs/auditorias/resources-global-scope') / name).read_bytes()).hexdigest() == digest
print(f'OK: {len(files)} documentos, {links} enlaces, {len(anchors)} símbolos, 26 invariantes con pruebas y 12 fuentes intactas.')
PY