metis-desk/docs/integracion-visual-de-recursos-compartidos-smb.md

20 KiB
Raw Blame History

Integración visual de recursos compartidos SMB — Paso 3.5

Alcance y composición

La integración utiliza las fichas actuales de Resources y Assets, AccessWorkspace y las configuraciones de WorkProfile. La especialización se reconoce por networkShare.capability === "network:smb-share"; ni el nombre de la plantilla, ni el hostname de la UNC, ni un campo documental sustituyen una publicación.

  • CompanyResourceRelatedContent compone NetworkSharePublications con ancla Resource y la navegación contextual a accesos. Los recursos ordinarios, buzones y dominios mantienen su composición anterior.
  • AssetDetail incorpora el mismo bloque con ancla Asset, tanto en ficha como en panel lateral. La sección de pertenencia a dominios sigue siendo independiente.
  • PublicationList, PublicationRow y PublicationPeriod separan consulta paginada, presentación y datos auditados. El historial se carga cuando se despliega y conserva las publicaciones finalizadas.
  • PublicationEditor representa operaciones explícitas: publicar, trasladar o finalizar. Captura el UUID del periodo al abrirse.
  • AssetRelatedInformation, propiedad de Companies, incorpora AssetLocalIdentities. Assets no importa Companies. LocalIdentityEditor sirve para crear, vincular y retirar mediante el propietario de los comandos.
  • FolderAccessAccountField amplía el formulario oficial del mapeo. El listado, la línea temporal de revisiones y el entorno de trabajo presentan la cuenta utilizada.

Se reutilizan DetailPanel, DetailSection, EmptyState, EntityTable, EntityStatus, CursorPagination, FormDialog, FormBody, FormHelp, FormActions, FormLabel, SelectWithAction, TimeLine y BrowserLink. Las primitivas nuevas se componen con las APIs instaladas de Button, Input, Field, Table y RadioGroup de shadcn/Base UI. Los iconos proceden del catálogo Tabler del proyecto.

Selectores reutilizables

@repo/rdx-ui/components/remote-option-picker encapsula selección provisional, confirmación, búsqueda controlada, altura estable y foco inicial en búsqueda. remote-option-list representa una página con selección compacta al principio, radios accesibles y selección al pulsar una zona no interactiva de la fila.

Sus props son datos presentacionales, textos y callbacks. No conocen compañías, DTOs de negocio, endpoints ni TanStack Query. El consumidor aporta la paginación como composición. No filtran, ordenan ni vuelven a paginar la página recibida. El patrón local de OptionPickerList utiliza EntityTable con búsqueda y paginación locales; por eso no se utiliza para fingir un inventario remoto completo.

PublicationPicker aporta consulta y cursores para elegir activos y carpetas. El selector de activos también tiene un consumidor real en los diálogos de entornos locales. Se admite sobrescribir el título para no llamar «publicador» al propietario de un entorno local.

Contratos HTTP

Se conservan los comandos propietarios:

  • POST /api/asset-network-share-publications/:companyId: publish, transfer, end del paso 3.3. El traslado se ejecuta con una sola petición atómica.
  • GET /api/asset-network-share-publications/:companyId: lectura especializada de los periodos, disponible para otros consumidores.
  • GET/POST /api/local-identity-environments/:companyId: lectura paginada y comandos create, associate, retire del paso 3.4.
  • Lectura y edición oficiales de AccessWorkspace, Resources y FolderMapping.

Ampliaciones de lectura necesarias para la UI:

Endpoint o respuesta Finalidad
GET /api/asset-network-share-publications/:companyId/relationships Typed Relationships con page, summaries y publications: periodos de esa página resueltos en una única consulta adicional por lote.
GET /api/asset-network-share-publications/:companyId/asset-options?search=&cursor= Activos operativos de cualquier plantilla, máximo 20 por página.
GET /api/asset-network-share-publications/:companyId/share-options?search=&cursor= Recursos SMB activos, máximo 20 por página, con UNC original.
Respuesta de AccessWorkspace: localEnvironments Proyección por compañía de entorno, UUID/nombre del activo propietario y retirada. Una consulta por lote, sin peticiones por fila.
Respuesta de AccessWorkspace: directoryEnvironmentIds Clasificación estructurada para distinguir dominios de entornos locales al ofrecer asociaciones.

Las lecturas de opciones tienen búsqueda SQL y keyset por UUID. Los cursores se conservan como valores opacos en el cliente. Las lecturas de relaciones mantienen los cursores firmados del proveedor y sus filtros originales. No se añade metadato libre a RelationshipView, ni se descargan todos los recursos o sus revisiones para seleccionar una carpeta. Los resúmenes SMB presentan la UNC original mediante una proyección por lote.

Precondición de revisión de FolderMapping

Se detectó una incompatibilidad con el requisito de concurrencia: el contrato anterior de guardado no permitía indicar qué revisión había leído el operador. Se añade expectedRevisionId opcional fuera de values a SaveFolderMappingRequestSchema.

El formulario de edición siempre envía la revisión capturada al abrirse. Bajo el bloqueo transaccional existente de la compañía, el caso de uso comprueba la última revisión antes de actualizar. Si difiere, devuelve FOLDER_MAPPING_CONFLICT (HTTP 409) sin escritura. La identidad y los campos del formulario abierto no se sustituyen por una actualización de caché. La UI ofrece refrescar el listado y explica que hay que cerrar y volver a abrir para revisar los cambios. Los consumidores internos anteriores que no envían la precondición conservan su contrato; no cambia la semántica de cuenta omitida, UUID o null del paso 3.4.

Publicaciones, historial y navegación

El recurso muestra su publicador vigente, plantilla, estado y enlace a Asset. Asset muestra sus carpetas, UNC, estados y enlaces a Resource. Los estados vacíos distinguen la ausencia de relación de un error de lectura.

Las acciones trasladar y finalizar conservan el UUID iniciado. Un conflicto muestra el error funcional y permite actualizar sin transformar silenciosamente el comando en otro sobre el nuevo periodo. No se presenta una escritura como confirmada antes de recibir respuesta.

El historial diferencia vigente/finalizada y presenta fechas y UUID de actores proporcionados por Assets. No inventa nombres de actores. La UNC es seleccionable y copiable en su característica habitual; no se duplica en otro bloque. Los fallos de Clipboard muestran una alternativa manual.

AccessWorkspace contextual e identidades locales

Las rutas de carpeta incluyen resourceId UUID. El parser solo lo admite en el espacio de accesos de una compañía; rechaza valores inválidos, parámetros repetidos y otros destinos. El filtro se mantiene al buscar y cambiar de sección, muestra el recurso y permite retirarlo.

accessResourceIds recorre referencias de necesidades, concesiones, permisos, coberturas, grupos, pertenencias, asociaciones persona/cuenta y sus sistemas/entornos. No compara nombres o UNC ni impone coincidencia entre el sistema de la identidad y el publicador. Necesidades y concesiones de otro recurso quedan fuera del resultado. El alta contextual de una necesidad o concesión utiliza el editor existente y fija el UUID del recurso.

La columna de activo propietario aparece en cuentas, grupos y entornos. Utiliza la asociación estructurada, permite navegar al activo y distingue propietarios de entornos retirados. Crear/vincular utiliza el diálogo local oficial de esta integración. Un entorno ya propietario no ofrece reasignación; dominios y entornos globales no se ofrecen como entornos locales asociables. El backend conserva la validación definitiva.

El bloque del activo consulta entornos locales por páginas de 20, incluidos retirados, con enlaces al filtro de cuentas del entorno. No sustituye al catálogo de cuentas ni a la relación de dominio.

Cuenta y cobertura de FolderMapping

La selección permite no indicar cuenta, elegir explícitamente la cuenta del perfil, seleccionar otra cuenta válida de la persona y retirar mediante null. Una edición que no toca la cuenta conserva el valor anterior; los campos omitidos siguen omitiéndose. Un cambio explícito de persona/perfil limpia la selección incompatible. Una cuenta histórica no disponible no se reemplaza silenciosamente.

Las opciones respetan asociación persona/cuenta vigente, estado de cuenta, caducidad y catálogos activos; el backend vuelve a validar al guardar. La cuenta del perfil y la utilizada por el mapeo pueden ser distintas. No se solicitan credenciales.

accessAccountCoverage se muestra con tres etiquetas: cuenta no indicada, cobertura documentada y sin cobertura documentada. La explicación visible aclara su carácter documental. permissionsCovered continúa describiendo la cobertura general de la necesidad, por separado. No se atribuye la cobertura de otra cuenta de la persona a la cuenta elegida.

Se conservan ruta registrada, letra, estados, discrepancias de UNC y adopción explícita de la ruta actual. Las revisiones muestran la cuenta de cada revisión, sin recalcular una cobertura histórica que el contrato no proporciona.

Caché y seguridad

TanStack Query centraliza claves por compañía, ancla, filtros y cursor. Las consultas independientes del activo y del espacio de accesos se inician en paralelo y comparten caché. No se utiliza un efecto para derivar la selección, la cobertura o los resultados filtrados.

Publicar, finalizar y trasladar invalidan los extremos afectados, incluidos activo anterior y nuevo. Los cambios de Access invalidan los mapeos cuya cobertura puede haber cambiado; un cambio de catálogo global invalida los espacios dependientes. Los comandos de entornos locales invalidan su lectura, Access y los mapeos de la compañía.

La sesión aporta el operador. Las escrituras usan CSRF. Los endpoints nuevos reutilizan el contexto de lectura autenticado de Typed Relationships y validan compañía y entrada. Las proyecciones SQL limitan por compañía, usan parámetros y no cambian datos. No se añade ACL universal, credenciales, nuevas entidades, migraciones ni verificación técnica de acceso.

Skills UI/UX aplicadas

Skill y referencias locales consultadas Aplicación y adaptación
shadcn/SKILL.md; rules/forms.md, composition.md, styling.md, icons.md, base-vs-radix.md, customization.md, design-system.md y secciones pertinentes de design-system-page.md FormDialog y FormHelp conservan el patrón normativo local. Nuevos campos con Field/FormLabel, descripciones asociadas, botones deshabilitados en pendiente, radios etiquetados, EmptyState y estados textuales. Tokens semánticos y composición Base UI/Vega; se mantiene el catálogo Tabler y no se modifica vendor.
vercel-composition-patterns/SKILL.md; reglas de evitar booleanos, variantes explícitas, composición por children y separación del estado Operaciones discriminadas de publicación, listas/filas/periodos separados, composición mediante relatedContent, selectores genéricos independientes de consultas y diálogos en sus propios ficheros. No se crean providers globales.
vercel-react-best-practices/SKILL.md; async-parallel.md, rerender-derived-state-no-effect.md, rerender-move-effect-to-event.md, bundle-barrel-imports.md y criterios de memoización consultados Consultas independientes en paralelo, caché e invalidaciones de TanStack Query, paginación SQL y lotes; estado derivado durante render, acciones en handlers, sin memoización preventiva. Se mantienen las fronteras públicas ./client del monorepo y las importaciones por componente de RDX; no se introduce configuración Next.js, RSC o SWR.

Las convenciones de Metis prevalecen sobre ejemplos genéricos. Se reutiliza FormLabel en los formularios existentes y no se rediseñan sus grupos ajenos a esta entrega. La invocación de documentación de shadcn por CLI falló por resolución de red (EAI_AGAIN); las integraciones se contrastaron con las APIs locales instaladas y las referencias de la skill.

Verificación y revisión manual

Las pruebas específicas cubren enlaces por UUID, traducciones es/en, UNC Unicode, estados vacío/error, periodos auditados, transferencia con una petición y CSRF, cursores opacos, filtro estructurado, cuentas elegibles y semántica omitido/null. Los tests de RDX comprueban radios etiquetados, orden de la página, selección compacta y separación de error/carga/vacío mediante renderizado estático.

Las pruebas MariaDB/HTTP usan exclusivamente metis_desk_test, fixtures temporales y limpieza. Cubren aislamiento de compañía, búsqueda y paginación SQL, metadatos de periodos, propietarios locales por lote, rechazo de revisiones obsoletas y regresiones de los pasos 3.1–3.4 y dominios Windows.

No se dispone de navegador ni herramienta de automatización de navegador en esta sesión. No se afirma validación interactiva. Pendiente comprobar manualmente en claro/oscuro, ficha y panel lateral, móvil y escritorio:

  1. Alta SMB, asignación, consulta desde Asset, traslado y finalización.
  2. Historial y navegación a necesidades/concesiones, búsqueda y retirada del filtro.
  3. Crear/vincular/retirar entorno local, navegar al propietario y a sus cuentas.
  4. Elegir cuenta del perfil/alternativa, retirar, guardar otros campos y revisar coberturas.
  5. Concurrencia con dos operadores y conservación del formulario abierto.
  6. Foco inicial en búsqueda, radios por teclado, cancelación y restitución del foco, ayuda junto al pie, scroll y UNC extensas.

Incidencias previas indicadas por el encargo: dos expectativas de texto de Companies y TS2375 del calendario vendor. No se modifican esas pruebas ni vendor para ocultarlas. Los resultados concretos de esta ejecución se recogen en la entrega; una incidencia previa que no se reproduzca no se presenta como fallo actual.

Resultados de la ejecución (21 de octubre de 2026)

Comprobación ejecutada Resultado
pnpm --filter … typecheck: Assets, Resources, Companies, RDX UI, servidor y web Correcto. TS2375 del calendario vendor no se reproduce en estas comprobaciones.
pnpm exec biome check sobre los TS/TSX/JSON modificados y nuevos; pnpm exec eslint sobre TS/TSX afectados Correcto, sin supresiones.
Scripts de test de Assets y Resources, con --test-isolation=none 136/136 y 80/80.
Script de test de Companies, con --test-isolation=none 187/189. Persisten únicamente las dos expectativas de texto previas de companies-page.test.tsx (ficha de compañía y formulario de persona).
Script de test de RDX UI, con --test-isolation=none 54/54.
pnpm test de Typed Relationships Contracts 13/13.
Tests HTTP sin persistencia: app, infraestructura, diagnóstico, entorno y contexto de lectura 8/8. Fue necesario permitir el puerto local temporal en el entorno restringido.
MariaDB: network-shares, smb-access, network-share-publications, local-identities-folder-mapping, typed-relationships y windows-domains-ui 56/56, exclusivamente metis_desk_test.
Repetición dirigida tras la última mejora de presentación de UNC y cuenta Publicaciones MariaDB 11/11; entorno de trabajo e identidades locales UI 10/10; accesos y filtro de recurso 8/8.
Builds de servidor y web Correctos. Vite mantiene un aviso de tamaño de chunk superior a 500 kB; no se modifica la estrategia global de bundles en esta entrega.
pnpm exec turbo run build --dry=json y comprobación de sus dependencias Grafo sin ciclos, 13 tareas.
git diff --check Correcto.

Los comandos PNPM se ejecutaron con --config.verify-deps-before-run=false para utilizar las dependencias instaladas. No se instalaron librerías ni se cambiaron lockfiles. La última adaptación de los editores de Access fija su altura y coloca EntityHelp mediante FormHelp junto al pie; conserva los mismos textos y la variante original de ayuda para los demás consumidores.

Continuación del alta hacia el activo publicador

Al guardar una carpeta SMB nueva y activa desde Recursos de la compañía, se cierra el alta y se abre el editor de publicación existente, con el UUID del recurso ya confirmado. El operador selecciona expresamente un activo de esa compañía; no se infiere a partir del host UNC ni del campo documental Servidor.

La carpeta y su publicación son dos operaciones explícitas. El editor explica que la carpeta ya está guardada, conserva la selección ante errores y permite reintentar solo la publicación. «Vincular más tarde», Escape o el cierre conservan la carpeta sin publicador; la ficha mantiene la acción de vincularlo después. Las carpetas inactivas, los demás recursos y las ediciones no abren esta continuación.

La composición pertenece a CompanyResources. Resources entrega el resultado del alta mediante onCreated y abre la ficha cuando el consumidor completa el flujo; Assets conserva el editor, la selección remota, los comandos y la invalidación de publicaciones. No se añaden tablas, endpoints, migraciones ni conversiones de carpetas históricas.

Regresión reproducible con datos sintéticos y el MCP Docker fijado:

python3 scripts/visual-audit.py --network-share-publisher --check

El preparador utiliza exclusivamente una instalación desechable de metis_desk_test, con 15 compañías y una principal con 50 personas, 51 activos, 50 perfiles, 50 puestos y 66 recursos antes del recorrido. La prueba verifica alta, selección, reintento sin duplicados, aplazamiento, edición, recursos inactivos y ordinarios y aislamiento de publicaciones; genera capturas a 1440, 390 y 320 px. Los resultados de cada ejecución se guardan en publisher-report.json dentro del directorio local de evidencias.

Validación de la continuación del alta (26 de octubre de 2026)

  • python3 scripts/visual-audit.py --network-share-publisher --check: 18 comprobaciones correctas; 15 compañías, 50 personas, 51 activos, 50 perfiles, 50 puestos y 70 recursos finales en la principal. Teclado, retorno de foco, búsqueda, paginación, búsqueda vacía, error simulado de publicación, reintento con persistencia real, aplazamiento, edición, altas inactivas/ordinarias y aislamiento. Capturas inspeccionadas a 1440 y 320 px; también se generó y comprobó ausencia de desbordamiento a 390 px. Entorno retirado.
  • pnpm --filter @metis/resources --filter @metis/assets --filter @metis/companies --filter @metis/web typecheck: correcto. pnpm build: correcto.
  • Suites completas con --test-isolation=none: Resources 124/124; Assets 150/150; Companies 310/312. Persisten las expectativas de «Personas (1)» y del texto de acceso de personas en companies-page.test.tsx, ajenas a este cambio.
  • pnpm test, repetido con acceso a loopback: termina con esos dos fallos de Companies. La primera ejecución de Resources dentro del sandbox falló al abrir un puerto local; su suite completa pasó al repetir con acceso a loopback.
  • pnpm typecheck: falla en packages/shadcn-ui/src/components/calendar.tsx:165 (TS2375), fuera del cambio y sin modificar vendor. pnpm lint y pnpm check globales fallan en archivos ajenos, incluidos ejemplos de skills y código de fotos de personas.
  • Biome y ESLint dirigidos a todos los archivos TS/TSX/JSON del cambio: correctos; sintaxis de los dos scripts Python y git diff --check: correctos. python3 scripts/visual-audit.test.py: 10/10.

Skills consultadas: rdx-solid para reutilizar ownership y contratos; ux-inputs-and-forms para explicar el guardado y el aplazamiento; shadcn para componer el editor existente; vercel-react-best-practices para coordinar el avance desde el callback sin efectos ni copias de estado remoto. Los auditores especializados referidos por la skill de formularios no están instalados; las comprobaciones citadas son directas mediante Playwright MCP, no una certificación de accesibilidad. No se han ejecutado suites MariaDB adicionales: los comandos existentes se han ejercitado a través de HTTP en el entorno desechable.