- Implement folder account options helper for filtering access items based on person ID and date. - Create FolderAccessAccountField component for selecting accounts with profile integration. - Develop AssetLocalIdentities component for managing local identities associated with assets. - Introduce LocalIdentityOwner component to display and manage local identity ownership. - Add LocalIdentityEditor for creating, associating, and retiring local identities. - Implement local identity API for fetching and executing local identity commands. - Create tests for local identity UI components to ensure functionality and correctness. - Add NetworkShareOptions class for structured and paginated SMB selection. - Introduce NetworkShareAddress component for displaying and copying network share addresses. - Create RemoteOptionList and RemoteOptionPicker components for remote option selection with pagination and search. - Add tests for RemoteOptionList to validate rendering and behavior under various states.
16 KiB
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.
CompanyResourceRelatedContentcomponeNetworkSharePublicationscon ancla Resource y la navegación contextual a accesos. Los recursos ordinarios, buzones y dominios mantienen su composición anterior.AssetDetailincorpora el mismo bloque con ancla Asset, tanto en ficha como en panel lateral. La sección de pertenencia a dominios sigue siendo independiente.PublicationList,PublicationRowyPublicationPeriodseparan consulta paginada, presentación y datos auditados. El historial se carga cuando se despliega y conserva las publicaciones finalizadas.PublicationEditorrepresenta operaciones explícitas: publicar, trasladar o finalizar. Captura el UUID del periodo al abrirse.AssetRelatedInformation, propiedad de Companies, incorporaAssetLocalIdentities. Assets no importa Companies.LocalIdentityEditorsirve para crear, vincular y retirar mediante el propietario de los comandos.FolderAccessAccountFieldamplí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,enddel 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 comandoscreate,associate,retiredel 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:
- Alta SMB, asignación, consulta desde Asset, traslado y finalización.
- Historial y navegación a necesidades/concesiones, búsqueda y retirada del filtro.
- Crear/vincular/retirar entorno local, navegar al propietario y a sus cuentas.
- Elegir cuenta del perfil/alternativa, retirar, guardar otros campos y revisar coberturas.
- Concurrencia con dos operadores y conservación del formulario abierto.
- 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.