Manifiesto de control personalizado
Id del esquema: custom-control-manifest@1
Esquema legible por máquina: custom-control-manifest.schema.json
La descripción canónica de un control personalizado (al estilo PCF, sección 6.3): el remoto de Module Federation que el reproductor de aplicaciones basadas en modelo monta en lugar de un editor de campo nativo dentro de un formulario o una vista. Un manifiesto se valida de forma idéntica tanto si se registra a través del Centro de control de administración como si se envía mediante una llamada directa a la API, lo genera un asistente de IA o llega dentro de una importación de solución: la regla de una única vía de validación (sección 6.7).
No se escribe a mano. El registro de un control es la carga del paquete que compiló
@parsware/pack, y este manifiesto se compone a partir del propio
parsware.json de ese archivo comprimido (§28). Lo que sigue describe la forma almacenada, para
leer una solución exportada o validar una que haya generado usted.
Forma
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
logicalName | string | sí | Con el prefijo del editor, en snake_case en minúsculas (p. ej., par_signature_pad). Se enlaza a un campo de formulario mediante la propiedad control del campo. |
displayName | string | sí | Nombre legible que se muestra en la paleta de campos del diseñador de formularios. |
description | string | null | no | Descripción breve que se muestra junto al control. |
scope | string | sí | El nombre de ámbito global del contenedor de Module Federation (único por remoto), leído del mf-manifest.json de la compilación en lugar de volver a escribirse. |
module | string | sí | La ruta del módulo expuesto que carga el reproductor (p. ej., ./Control). Debe empezar por ./. También se lee de la compilación. |
entryFileName | string | no | El archivo de entrada del contenedor dentro del paquete (p. ej., remoteEntry.js). La URL de entrega se calcula a partir del entorno, el nombre lógico y este valor: no hay ninguna URL que almacenar. Vacío en el modo hospedado. |
packageHash | string | null | no | SHA-256 en hexadecimal en minúsculas del archivo comprimido del paquete a partir del cual se registró el control. Al importar se comprueba frente a los bytes que viajaron en un paquete de solución, para que lo que se sirve sea lo que se exportó. Nulo en el modo hospedado. |
remoteEntryUrl | string | null | no | Solo en el modo hospedado: una URL http(s) absoluta de un remoteEntry.js servido externamente, para la recarga en caliente durante la creación. Su registro se rechaza salvo que el nivel del entorno sea Desarrollo, y un control hospedado no viaja en un paquete de solución: su código no es algo que la plataforma deba transportar. |
substitutesFor | string[] | sí | Los tipos de control de campo a los que se puede enlazar este control: uno o varios de Text, MultilineText, Number, Boolean, DateTime, Lookup, File, Image, Custom. Debe contener al menos una entrada. La paleta de campos ofrece el control solo donde coincide el tipo de control del campo. Son las familias de tipos de datos a las que pertenece un campo, no los nombres de los controles integrados que elige una ubicación en el formulario (TextArea, Toggle, Dropdown, …), que son otro vocabulario que casualmente comparte cuatro nombres. |
Lo que ya no tiene
requestedScopes y declaredEntities han desaparecido, y additionalProperties es
false, así que un manifiesto que aún incluya cualquiera de los dos se rechaza en lugar de
ignorarse en silencio. Un control se ejecuta con los permisos de la persona que lo usa (§24): un
conjunto de ámbitos solicitados solo se intersecaba con la propia sesión del usuario, así que
podía restringir al usuario de un control pero nunca ampliarlo, y ninguna ruta de código leía la
lista de entidades declaradas. Eliminar ambos convierte la historia de seguridad en una frase en
lugar de dos ajustes.
También ha desaparecido el remoteEntryUrl obligatorio. El paquete viaja ahora como un paquete
servido desde el propio origen de la plataforma, así que la URL se calcula en lugar de
almacenarse (§28).
El contrato del control
El módulo expuesto (./Control) es un único componente de React que implementa el contrato fijo
ParswareControlProps de @parsware/runtime-sdk:
interface ParswareControlProps {
value: unknown; // the bound field's current value
onChange: (next: unknown) => void; // commit a new value back to the form
fieldMetadata: FieldMetadata; // the bound field's type/label/constraints
context: RuntimeContext; // the same auth/data/logging context apps get
}
El reproductor proporciona estas props en el momento del renderizado. Un control solo accede a la
plataforma a través de context (un ParswareRuntime), nunca mediante una llamada directa al
Gateway ni al servicio de identidad.
Dónde se valida
- Registro: la capa de aplicación valida el manifiesto con
custom-control-manifest@1y exige quelogicalNameempiece por el prefijo del editor propietario antes de registrar el control en un entorno. - Importación de solución: cada manifiesto incluido en un paquete de solución se vuelve a validar con el mismo esquema antes de registrar el control en el entorno de destino.
Notas de seguridad
Un control personalizado se ejecuta en el mismo entorno de JavaScript que el Shell (Module Federation, no un iframe; sección 6.3), así que el límite de confianza se aplica en otros puntos:
- Un control empaquetado se sirve desde el propio origen de la plataforma, así que no hay ningún origen externo que añadir a la lista de permitidos. La lista de permitidos de la CSP sigue controlando el modo hospedado, que es la única forma cuyo paquete un creador puede apuntar a cualquier sitio, y que se rechaza fuera de un entorno de desarrollo.
- El archivo comprimido se comprueba antes de almacenarse: tamaño, número de archivos, cuánto ocupa al expandirse, que ninguna entrada nombre una ruta fuera de su propia carpeta y que cada archivo sea de un tipo que la plataforma sirve.
- El control solo puede cargarse si una solución lo implementó en ese entorno, y el hash del paquete se verifica al importar y de nuevo antes de descomprimirlo en disco.
- Cada llamada de datos que realiza a través del Runtime SDK se autoriza en el servidor frente al App Context Token, que incluye los ámbitos propios del usuario. Un control puede hacer exactamente lo que puede hacer la persona que lo usa, y ningún campo de este manifiesto cambia eso.
Relacionado
- Manifiesto del paquete de artefacto: el
parsware.jsondentro del archivo comprimido a partir del cual se compone este manifiesto. - Manifiesto de aplicación personalizada: el equivalente para las aplicaciones React personalizadas, que todavía no han adoptado el empaquetado.
- Definición de formulario basado en modelo: la propiedad
controlde un campo de formulario hace referencia a un control por sulogicalName.