Semántica de ejecución, restricciones y seguridad
Última actualización: 21 de julio de 2026
Esta página resume cómo se comporta un Script en tiempo de ejecución (orden, transacciones, errores, bloqueo), a qué restricciones estáticas está sujeto al guardarse y su modelo de seguridad. Para la sintaxis, consulte el Catálogo de statements y las Expresiones de valor; para combinaciones prácticas, consulte el Cookbook.
Orden y modo de ejecución
- Los
statementsse ejecutan secuencialmente de arriba abajo. Cuando la ejecución alcanza unReturn, termina en ese punto. - Sync se ejecuta en la ruta que atiende la solicitud; Async se ejecuta en segundo plano. Es solo una distinción de dónde ocurre la ejecución; en ambos casos el resultado es el valor de
Return(para la forma de la respuesta de la llamada, consulte Solicitud y respuesta en la descripción general de Script y Modos de ejecución). - De la capacidad (capability) al modo: si el árbol de statements contiene alguno de
ExternalIo(una llamada externaHttp),MediaIngest(ingesta de archivo de Media;{ source, encoding }bajofields.file; común a url y base64) oLongRunning(un Loop grande, etc.), entoncesexecutionModese fuerza aAsync. Estas tres son capacidades distintas y, en Restricciones estáticas más abajo, cuentan para límites diferentes.
Semántica de ejecución
Guard (condiciones previas)
No existe un statement guard dedicado. Se expresa con If y then:[Return]. Cuando se incumple la condición, devuelve un resultado y no ejecuta los statements siguientes (por supuesto, también es posible un Script sin guard).
{ "type": "If", "condition": { "<": [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] },
"then": [ { "type": "Return", "value": { "ok": false, "reason": "insufficient credit" }, "statusCode": 402 } ] }Sin transacciones y compensación best-effort
Un Script no es una transacción. Ante un fallo, el motor intenta compensar el trabajo realizado hasta ese momento y devuelve la causa del error, pero con las siguientes limitaciones (asumidas por diseño).
- Deshacer un borrado crea un nuevo
sys.id, por lo que las referencias que apuntaban a él se rompen (revertir una creación es fácil; una actualización necesita una before-image). - Los efectos externos (
Http) son irreversibles (una llamada que ya ha salido, y su cobro, no se pueden deshacer). - En caso de caída del proceso, puede quedar un estado no compensado (un orphan).
Si necesita atomicidad real, escriba la compensación en el Script usted mismo o coloque las operaciones irreversibles (como las llamadas externas) al final. El orden más peligroso es el que «encadena hasta el final pero no puede revertirse, y aun así parece seguro».
Bloqueo optimista
La contención de update/patch se acota con version en ResourceUpdate y ResourcePatch. Si se proporciona version (una expresión de valor, Int), la actualización se realiza solo cuando coincide con el sys.version actual del destino; una discrepancia aborta con un error de conflicto de versión (que se puede manejar localmente con Try/catch). Si se omite, es last-write-wins sin comprobación. Normalmente se lee primero con ResourceRead o ResourcePageRead y se pasa ese sys.version (véase CAS de bloqueo optimista en el Cookbook).
Escrituras en origin
Las escrituras siempre se aplican en origin (draft), y la exposición en delivery (CDA/ACDA) se controla con publish (el publish de ResourceCreate/ResourceUpdate/ResourcePatch, o ResourcePublish/ResourceUnpublish).
Qué se considera un fallo
- Un fallo real es un error de tiempo de ejecución de un statement: un status final de
Httpde 400 o superior (4xx·5xx; no es un fallo cuandoignoreStatusCode: true) o un tiempo de espera agotado, un cuerpo de respuesta que supera los 10MiB, o una operación de recurso fallida (destino inexistente, conflicto de versión, operación no admitida, etc.). Ante tales fallos, el motor aborta y compensa, y se pueden manejar localmente conTry/catch/finally. - Un
Returnno es un error, sino una salida anticipada normal. No es un objetivo decatch(no existe el concepto de throw de usuario). - Dentro de un
catch, se referencia{ message, statement }mediante/error.
Sin agregación en el servidor
No hay operaciones de servidor dedicadas a count, sum o group-by. El cálculo se hace iterando con ResourcePageRead y usando SetVar/JsonLogic, por lo que se está limitado por el tamaño de fetch y maxIterations (no es adecuado para agregar millones de registros).
Sin espera ni retardo
Un Script no tiene el statement Delay. Un Script se ejecuta una sola vez y termina, en la ruta de la solicitud (Sync) o en segundo plano (Async), y no espera ni sondea internamente a que termine un job externo (el resultado Async es aparte: el llamante sondea con el requestId recibido en el 202 para obtener el valor de Return).
Restricciones estáticas (validadas al guardar)
Lo siguiente se comprueba cuando se guarda un Script (al crear/actualizar). Si algo se incumple, se rechaza el guardado (falla en el momento de la autoría, no en tiempo de ejecución).
| Restricción | Predeterminado |
|---|---|
Si hay I/O externa, executionMode debe ser Async | No aplica |
Dentro del body de un Loop, las llamadas externas Http y la ingesta de archivo de Media están prohibidas | No aplica |
Máximo de llamadas externas Http por definición | 3 (maxExternalIo) |
Máximo de SetVar por definición (anidados incluidos) | 5 (maxSetVar) |
| Máximo total de statements por definición (anidados incluidos) | 15 (maxStatements) |
Límite de Http.retry | 2 (maxHttpRetry) |
Estos límites se pueden ajustar mediante la configuración del servidor (weegloo.core.script.*); los valores anteriores son los predeterminados.
La ingesta de archivo de Media es la capacidad
MediaIngesty, a diferencia de una llamada externaHttp(ExternalIo), no cuenta para el límite demaxExternalIo(3). En cambio, el requisito deAsyncy la prohibición del body deLoopse le aplican igual que aHttp.
Presupuesto de tiempo (en tiempo de ejecución)
| Modo | Presupuesto predeterminado |
|---|---|
| Sync | 10 segundos (syncTimeoutMs) |
| Async | 60 segundos (asyncTimeoutMs) |
Límites de cantidad por plan
Script es un recurso Billable y su número por Organization está limitado por plan.
| Plan | Número de Script |
|---|---|
| Free | 3 |
| Basic | 10 |
| Pro | 50 |
| Enterprise | Ilimitado |
Cuando se alcanza el límite, se rechaza la creación de un nuevo Script (por la misma vía que otros recursos Billable).
Modelo de seguridad
Cabeceras secret
Un elemento de Http.headers con secret:true es exclusivo de CMA (administrador): no se expone al usuario final (ServiceUser) y solo se descifra justo antes de la transmisión. Coloque aquí secretos como una clave de API de LLM (incluso al empaquetarse en un App Bundle, el valor secret se enmascara y nunca sale del Space de origen).
Identidad de ejecución y autorización
- Identidad de ejecución: durante la ejecución, toda operación de recurso se realiza bajo la identidad del usuario que llamó a
/execute. ElcreatedBy/updatedByde cualquier recurso que se cree o actualice es el llamante, y un ámbitocreatedBy: ":self"también se resuelve respecto al llamante. - Hay dos límites de autorización y en tiempo de ejecución el motor no vuelve a comprobar los permisos de recurso en cada statement.
- En el momento de la autoría (guardado): al guardar un Script, se comprueba si el autor posee realmente los permisos de recurso y de acción que usan sus statements. Si falta aunque sea uno, se rechaza el guardado (
WGL403015). Es decir, un Script que contiene una operación no autorizada no se guarda en primer lugar. - En el momento de la llamada (
/execute): solo se comprueba el permiso Execute de Script del llamante. Sin él, el resultado es403. Una vez que pasa, los permisos de recurso por statement no se vuelven a comprobar en tiempo de ejecución; la ejecución continúa. Funciona como el permiso de ejecución de una función en programación. Si se tiene permiso para ejecutar la función, no se vuelve a preguntar por el permiso de cada operación individual dentro de ella.
- En el momento de la autoría (guardado): al guardar un Script, se comprueba si el autor posee realmente los permisos de recurso y de acción que usan sus statements. Si falta aunque sea uno, se rechaza el guardado (
- Ámbito de propiedad:
createdBy: ":self"en un filtrowheresignifica «solo lo que ha creado el llamante actual» (por ejemplo, consultar solo la propia cartera). - Permisos delegados (atención al autor): al combinar los dos límites anteriores, ejecutar un Script equivale a actuar con los permisos del autor delegados. El llamante solo necesita Execute, y los statements dentro del Script se ejecutan exactamente dentro del ámbito para el que se autorizó al autor al guardar. En consecuencia, una operación de recurso que el llamante no podría realizar por sí mismo puede ocurrir igualmente a través del Script. Dado que los permisos concedidos al autor son el alcance efectivo de ese Script, decida con cuidado qué operaciones incluye en un Script.
Lista de comprobación resumida
Antes de guardar, compruebe lo siguiente.
- Si hay una llamada externa (
Http) o ingesta de archivo de Media,executionModees"Async". - No hay ninguna llamada externa dentro del body de un
Loop. - Las llamadas externas son 3 o menos,
SetVar5 o menos y los statements totales 15 o menos. - Los valores secret se han colocado únicamente mediante
secret:trueenHttp.headers. - Las operaciones irreversibles (llamadas externas) se han colocado lo más tarde posible.
- Si preocupa la contención de update/patch, se usa
versionenResourceUpdateoResourcePatch. - Para devolver un resultado, se ha especificado
Return.value.
Documentos relacionados
- Expresiones de valor: reglas de valores y condiciones.
- Catálogo de statements: los campos y resultados de cada statement.
- Cookbook: una colección de ejemplos completos.
- Recurso Script y endpoints: la estructura del recurso
Scripty endpoints HTTP como/execute. - Descripción general de Script: la estructura de nivel superior y los modos de ejecución.
