metis-desk/docs/auditorias/workplace-dashboard/05-viabilidad-tecnica.md

13 KiB
Raw Blame History

Viabilidad técnica y validación

Fecha: 22 de octubre de 2026. Investigación estática, sin modificaciones de implementación. Referencias E: inventario.

Consultas reutilizables

Fuente / endpoint GET Cliente y claves existentes Coste y uso propuesto
/api/companies/:companyId Compañía ya recibida por la ficha; companyKeys.detail Personas, sedes, departamentos y asignaciones; evitar segunda copia de estado
/api/assets/:companyId inventoryApi.get, inventoryKeys.company de Assets Toda la compañía, activos/puestos/relaciones/historiales; fuente actual del puesto
/api/asset-catalog/:scope catalogApi, catalogKeys.scope de Assets Completa plantillas; usar specification del activo cuando proceda
/api/work-profiles/:companyId profileApi.get, profileKeys.company Todos los perfiles con revisiones; filtrar por host y compañía
/api/software-installations/:companyId softwareApi.get, softwareKeys.company Todas las instalaciones; filtrar por host, no pedir por fila
/api/resources/:companyId inventoryApi.get, inventoryKeys.company de Resources Recursos y proyecciones, datos para software/configuraciones
/api/access/:scope getAccess, accessKeys.scope Catálogo y accesos; cobertura/reviews. No hay filtro de puesto
/api/folder-mappings/:companyId folderApi, folderKeys.company Mapeos con cobertura de cuenta y revisión
/api/mail-configurations/:companyId mailApi, mailKeys.company Configuraciones nuevas y snapshots legacy; no unir las legacy por profileId inexistente
/api/mailboxes/:companyId Contratos MailboxesResponseSchema; E36 Buzones y usos temporales; validar procedencia de acceso de persona
/api/application-configurations/:companyId applicationApi, applicationKeys.company Aplicaciones de perfil, distintas de instalación en host
/api/certificate-configurations/:companyId certificateApi, certificateKeys.company Configuración, caducidad/revisión del certificado
/api/printer-configurations/:companyId printerApi, printerKeys.company Perfil e impresora; no convertirla en miembro exclusivo
/api/telework-authorizations/:companyId teleworkApi, teleworkKeys.company Contexto de persona y efectividad calculada por servidor
/api/remote-connections/:companyId remoteApi, remoteKeys.company Conexiones de personas; filtrar explícitamente por origen/destino/persona
/api/asset-support/:companyId/:assetId Cliente de soporte y supportKeys de Assets Consulta por equipo; evitar cargar cada miembro para un resumen inicial
/api/asset-infrastructure/:companyId InfrastructureResponseSchema; E35 Roles, interfaces y direcciones registradas; filtrar por assetId
/api/local-identity-environments/:companyId Contratos LocalIdentityQuerySchema Filtros por activo/entorno, paginación nextAfterId; 100 máximo por página
/api/asset-directory-memberships/:companyId y /:assetId/current Contratos DirectoryMembershipQuerySchema Paginación y pertenencia actual; contexto de directorio del host
/api/asset-network-share-publications/:companyId Contratos de publicaciones E20 assetId, resourceId, includeEnded, cursor, pageSize <=100; no total global en respuesta
/api/processes/:companyId Process API Procesos de personas; opcional, sin referencia directa al puesto

Las rutas se contrastan con registradores HTTP; los identificadores de catálogos se verifican en el cliente instalado. Los GET de configuraciones citados rechazan query desconocida; no añadir workstationId o profileId a HTTP por imitar el filtro de la UI. Las rutas de navegador contextuales de perfil no implican filtros backend equivalentes.

Reutilización y límites

Reutilización directa: datos básicos del puesto, cabecera/acciones, historial, enlaces, diálogos y panel de software.

Adaptación menor: resumen de equipo, contadores definidos, tabla de equipamiento compacta, cuenta en tabla de perfiles, vista de última revisión.

Desarrollo nuevo de composición: filtros de configuraciones por perfiles del host, procedencia visible, estados parciales, resúmenes y enlaces contextuales de remoto/soporte/directorio. Los datos existen; el agregado de pantalla no está implementado.

Funcionalidad no soportada: tickets activos, telemetría, presencia actual, puntuación de salud y comprobación real de permisos SMB. No desbloquearlas con datos inventados en el fixture.

El dashboard inicial puede construirse con consultas existentes. No hay necesidad demostrada de nuevo endpoint. Si una medición posterior detecta payload excesivo, latencia o incoherencia entre snapshots de consultas independientes, justificar una lectura agregada/paginada antes de diseñarla. Sería un contrato nuevo con autorización y pruebas propias, fuera de esta auditoría.

Composición y dependencias

La ficha vive en modules/companies/src/web/workstations/detail/; el agregado y comandos, en Assets. useEnvironmentQueries y buildEnvironment de Companies ya reúnen el contexto de perfil (E30). El primero solicita once fuentes y condiciona su data a que todas existan: no copiarlo sin revisar la recuperación parcial. El segundo es cálculo puro y conserva profileId/compañía y estados abiertos. E37 muestra el registro real de módulos en identity-runtime.ts, llamado desde el arranque; no todas las rutas se registran directamente en index.ts.

Reutilizar las APIs públicas de módulos; no importar repositorios ni modelos ORM en frontend. Componentes genéricos de @repo/rdx-ui deben recibir datos semánticos y callbacks, sin DTO específico de puesto. No modificar vendor ni extraer una plataforma genérica de widgets sin consumidores reales.

Las composition roots son explícitas. No se confirmó un sistema dinámico de plugins que deba adaptarse para esta pantalla. Sí hay proveedores/contratos tipados de relaciones (@metis/relationship-contracts) y servicios entre módulos: las publicaciones SMB y directorio se componen en sus propietarios. No introducir acceso cruzado a tablas como supuesto «plugin de dashboard».

Rendimiento y coherencia

Riesgo Evidencia / alcance Decisión recomendada
Payload por compañía Inventario/perfiles/configuraciones incluyen revisiones; no GET individual de puesto localizado Usar caché existente y carga por necesidad; medir antes de nuevo endpoint
Multiplicar queries por perfil E30 hace 11 consultas por compañía Compartir claves y cargar cada familia una vez; filtrar después. No montar un hook agregador por fila
N+1 en soporte/publicaciones APIs admiten consulta por activo; puesto hasta 200 miembros Consultar principal primero; detalle del resto bajo demanda. No fan-out masivo inicial
Coste de filtrado local E11 hace find de activos/catálogos por miembro; controller filtra perfiles Mapas/sets cuando haya recorrido repetido relevante; no useMemo preventivo sin necesidad
Conteo de página incompleta Publicaciones y entornos locales paginados Seguir cursor para total o etiquetar parcial; no confundir recuento cargado con total
Lecturas no atómicas entre APIs Queries independientes y momentos distintos Datos parciales y refetch dirigidos; no prometer fotografía transaccional global
Cambio de host Las relaciones derivan de computerAssetId actual Recalcular al cambiar dato de query; no copiar relaciones en estado ni sincronizar con efectos
Fallo secundario bloquea todo E30 retorna data: undefined si falta una fuente Estado por bloque; conservar datos previos al actualizar y reintento específico

No se midieron latencias, volumen de respuesta ni planes SQL. El lector de puestos usa consultas en lote de raíces, revisiones y miembros; no hay base para afirmar un N+1 de BD por puesto en ese lector (E07). Hay recorridos locales repetidos y varios loaders de contexto; distinguir riesgo de coste real medido.

Mutaciones e invalidación

  • Guardar el puesto invalida inventoryKeys.company(companyId) en su controller; el host y relaciones derivadas se recalculan al refrescar.
  • Renombrar relee inventario para conservar composición vigente y evita enviar valores capturados al comenzar edición; no se encontró control optimista de revisión en el contrato de puesto. No prometer resolución completa de concurrencia.
  • Ciclo de vida invalida inventario; ficha solicita refetch de perfiles tras desmantelar. Esto no desactiva perfiles en backend.
  • Software, perfiles y configuraciones conservan sus comandos y claves propias. La integración futura debe revisar cada consumidor antes de introducir contadores derivados; no invalidar toda la caché.
  • No descartar promesas con void ni ocultar errores en lógica nueva. Los .catch(() => undefined) existentes de reintento no se corrigen durante esta documentación; TanStack Query expone el error de consulta, pero no debe suponerse que todos los callbacks futuros harán lo mismo.

Autenticación, ámbito y permisos

CONFIRMADO E33: requireAuthenticated valida sesión y versión de autenticación; los routers de puesto y consultas relacionadas reciben ese middleware. El actorId se obtiene de sesión y los cuerpos/params se validan con Zod. La pertenencia de persona, sede y miembros se valida con contextos por compañía y restricciones relacionales; las escrituras de inventario usan transacciones y bloqueo de compañía.

No se localizó una ACL usuario–compañía ni un rol específico por operación de puesto en el recorrido de rutas, use cases y repositorio. El middleware autenticado no recibe companyId ni consulta membresías del operador. En relaciones tipadas, SessionRelationshipReadAccess verifica sesión y existencia de compañía, y utiliza contextos emitidos por servidor; no acredita una ACL por compañía (E34).

Por tanto, aislamiento de datos por IDs y pertenencia de entidades está confirmado en las rutas inspeccionadas; autorización granular del operador por compañía NO ESTÁ CONFIRMADA. No inferirla del filtrado frontend ni simular distintos roles como si ya existieran. El dashboard debe reutilizar el contrato efectivo y cualquier nueva lectura debe conservar comprobaciones en servidor. No exponer accesos de compañías distintas ni considerar la compañía atendida como tenant de la empresa de soporte.

No se inspeccionaron credenciales ni se generaron conexiones remotas reales. No incluir tokens, contraseñas o destinos sensibles en un mockup.

Registro de investigación y validación

  • Ejecutados desde WSL/bash: pwd, git status --short, node --version, pnpm --version; versiones correctas. El estado inicial contiene cambios previos ajenos a esta tarea.
  • Inspección con rg, rg --files, lecturas de archivos y manifests/skills. Se revisaron fuentes activas, contratos, tests existentes, DDL y documentación; no se verificó una BD desplegada.
  • MCP: browser_tabs respondió about:blank. Curl a http://localhost:5173/ falló; ss -ltnp no pudo usar netlink. No se confirmó URL Vite ni sesión sintética. No se inició servidor, no se ejecutaron migraciones ni se sembraron datos.
  • JSON: 16 bloques de sources validados contra sus schemas Zod existentes. Comprobados miembros, referencias, reserva exclusiva, unicidad de perfiles activos, coherencia de historial y contadores con workstationRelations/buildEnvironment. projectAccess reproduce exactamente las coberturas y revisiones del ejemplo. Son comprobaciones locales, no guardados de dominio ni consultas a la BD.
  • Pruebas existentes dirigidas: los tres archivos finalizaron correctamente, sin fallos. Comando reproducible desde raíz:
TSX_TSCONFIG_PATH=tsconfig.json node --import tsx --test \
  modules/assets/src/api/domain/workstation.test.ts \
  modules/companies/src/web/workstations/detail/helpers/workstation-relations.test.ts \
  modules/companies/src/web/workstations/detail/ui/workstation-detail.test.tsx
  • Una comprobación auxiliar inicial de Access falló al importar @repo/rdx-ddd desde el eval de la raíz, donde no es dependencia directa. Se corrigió la comprobación usando la ruta local del VO, sin modificar configuración; la ejecución final fue satisfactoria. No es un fallo del producto ni se ocultó alterando sus tipos.
  • Se comprobaron 108 enlaces locales y todas las rutas completas de código citadas entre backticks; sin destinos inexistentes. El catálogo contiene 37 grupos y 89 referencias a archivos/líneas verificadas. Se revisó el contenido completo de los ocho entregables y se comprobó el diff de cada fichero nuevo con git diff --no-index --check: sin diagnósticos de whitespace. En modo --no-index, el código 1 por archivo nuevo no se interpreta como un error de formato.
  • El fixture contiene 1 compañía, 2 personas, 5 activos, 7 recursos, 4 puestos y 4 perfiles. No se cargaron en persistencia. Las comprobaciones locales no cumplen ni sustituyen el volumen funcional/visual exigido por AGENTS.md.

No se ejecutan pnpm typecheck, pnpm lint, pnpm test, pnpm check ni pnpm build globales: los únicos cambios son Markdown y un fixture de diseño. Las suites de integración quedan pendientes por su persistencia y por la prohibición de migraciones/datos. No declarar una auditoría visual, de rendimiento o de accesibilidad como superada.