Permisos y límites de confianza
Intersección manifest/host, identidades revocables, roles de UI y controles distintos para plugins, IA y servidor.
Consulta las versiones, cambios y requisitos en Framework 4.0 y CLI 1.2.
Autoridad efectiva
WU calcula permisos como la intersección entre solicitudes del manifest y grants del shell. Si no hay solicitudes o no hay grants, la app no obtiene capacidades técnicas. Agregar un grant que la app no pidió tampoco la amplía.
{
"name": "cart",
"entry": "assets/cart.js",
"wu": {
"permissions": [
{ "capability": "store.read", "resource": "cart", "required": true },
{ "capability": "store.write", "resource": "cart.items", "required": true },
{ "capability": "events.emit", "resource": "cart:changed" }
]
}
}
await wu.init({
apps: [{
name: 'cart',
url: '/apps/cart',
grants: [
{ capability: 'store.read', resource: 'cart' },
{ capability: 'store.write', resource: 'cart.items' },
{ capability: 'events.emit', resource: 'cart:changed' },
],
}],
});
required: true exige cobertura completa para registrar la app. Una solicitud opcional puede quedar denegada o cubierta parcialmente; la política conserva diagnósticos. Ser opcional no significa que se autorice cuando llegue la primera llamada.
Capacidades técnicas admitidas
| Capacidad | Operación |
|---|---|
events.emit |
Emitir hechos en los recursos concedidos |
events.subscribe |
Suscribirse a eventos permitidos |
rpc.provide |
Proveer handlers del bus y contratos de métodos |
rpc.call |
Solicitar respuestas y consumir contratos |
store.read |
Leer, obtener snapshots y suscribirse a paths |
store.write |
Escribir y hacer batch sobre paths |
drag.offer |
Ofrecer datos de un tipo en un arrastre |
drag.accept |
Aceptar datos de un tipo en un destino |
store.update necesita lectura y escritura. No existen grants arbitrarios device.*, deploy.* o build.*; la lista está cerrada en wu-policy.js.
Los recursos usan strings exactos o un wildcard final. Para store, el comodín debe ocupar un segmento completo, como cart.*. wu:, system: y app: son namespaces reservados para emisión y provisión/llamadas RPC. Una solicitud events.emit:* se solapa con ellos y no es una forma válida de otorgar toda la autoridad del host.
Identidad durante el lifecycle
El core crea una lease por aplicación y entrega una facade congelada. Cada método comprueba que esa lease siga activa; las funciones añaden la identidad correcta sin aceptar que una app se convierta en otra cambiando appName.
Al desmontar se revocan facades y se limpian recursos asociados. Los contratos consumidos mediante facade también se envuelven para fallar tras revocación. Una variable global que conserva una facade antigua no recupera autoridad cuando una app con el mismo nombre vuelve a montar: se crea una identidad de lifecycle nueva.
Los hooks de eventos/store de los trece adapters respetan la facade de la app en 4.0. Eso protege las llamadas cooperativas, pero module comparte el realm y puede alcanzar el host. Shadow DOM y los sandboxes same-origin no contienen código hostil; usa una app remota en otro origen para esa frontera.
Cuatro controles diferentes
| Control | Qué decide | Qué no decide |
|---|---|---|
| Grants técnicos WU | Uso de bus, RPC y paths del store | Acceso a datos del backend |
setPrincipal / roles |
Si una app puede montarse en la UI | Autorización fiable del usuario en servidor |
| Permisos de plugins | Qué métodos ofrece su API de instalación | Contención de código que ya ejecuta en el host |
| Flags de IA | Lectura, escritura, DOM, red o ejecución de actions IA | Permisos de dominio de una operación remota |
La configuración de plugins emplea otra lista: mount, events, store, apps, config, unsafe. El host debe conceder explícitamente los permisos solicitados. Las actions IA utilizan flags como executeActions, writeStore y network. Ninguna lista puede intercambiarse con otra.
Frontera del servidor
Credenciales, acceso a recursos, idempotencia y auditoría durable pertenecen a un servicio autenticado. Un handler de action es código host y puede capturar fetch o un cliente privilegiado en un closure; la API suministrada al handler no puede contener ese closure.
Para operaciones con efectos, diseña un gateway que valide identidad, parámetros, alcance, policy y aprobación antes de ejecutar. Timeline y store no deshacen envíos, pagos, builds ni cambios de infraestructura. Si el dominio admite deshacer, se implementa una compensación explícita.
El subpath wu-framework/server ofrece createNonce, securityHeaders, buildCsp, middleware y wrappers de respuesta. Esos helpers construyen cabeceras; su instalación real corresponde al servidor que entrega la página y los assets.
Migración controlada
await wu.init({
compatibility: { profile: 'compat-v2', warnings: 'once' },
apps: [],
});
console.table(wu.compatibility.getMigrationReport());
El perfil compat-v2 habilita puentes concretos para eventPermissions, grants implícitos de plugins y ejecución implícita de actions IA. Es una migración explícita con diagnóstico; no debe convertirse en la configuración base de una app nueva. strictEvents: false también es un escape deliberado para código de confianza y reduce comprobaciones del bus.
Referencia de implementación
Política: src/core/wu-policy.js, src/core/wu-policy.js, src/core/wu-policy.js; leases: src/core/wu-core.js y src/core/wu-core.js; plugins: src/core/wu-plugin.js; defaults IA: src/ai/wu-ai-permissions.js; compatibilidad: src/core/wu-compatibility.js. Pruebas: tests/unit/capability-security-v3.test.js, tests/unit/plugin-security.test.js, tests/unit/security-regressions.test.js, tests/security/compatibility-boundaries.test.js.