13 KiB
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
voidni 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_tabsrespondióabout:blank. Curl ahttp://localhost:5173/falló;ss -ltnpno 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
sourcesvalidados contra sus schemas Zod existentes. Comprobados miembros, referencias, reserva exclusiva, unicidad de perfiles activos, coherencia de historial y contadores conworkstationRelations/buildEnvironment.projectAccessreproduce 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-ddddesde 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.