Skip to content

Sandbox environment ​

A CoCoCo script only has what the platform grants it. Nothing is "removed" from a full Lua installation: the standard library is a closed set, and everything else comes through ctx, scoped to the tenant and the identity the script runs as.

What is available ​

  • Language and standard library: assert, error, pcall, type, tostring, tonumber, inspect, setmetatable/getmetatable, rawget/rawset, and the math, string, table and set libraries, plus default, coalesce, pipe, assertf and typecheck.
  • bit32 for bitwise work, because the dialect has no bitwise operators.
  • time value objects and uuid helpers. See Time.
  • exports, the table a dispatched script puts its entry functions on.
  • ctx, the platform API for the script's role. See the overview.

What is not available ​

There is no file system, no process access and no way to build code from a string: os, io, debug, package, require, load, loadstring, dofile, coroutine, collectgarbage, _G, getfenv/setfenv, select, next, xpcall, math.random and string.gmatch do not exist.

Instead ofUse
requirectx.script.load(name)
printctx.log.info/warn/error
os.time, os.datectx.time.now(), ctx.time.nowIso(), time.*
math.randomuuid.v4() for identifiers, or a seeded generator built with bit32
an HTTP clientctx.device.http for a configured device, or the workflow http_call node
a database driverctx.sql.query (reporting, read-only) or ctx.device.sql
JSON librariesctx.json

The print function may exist at run time, but its output is not shown anywhere and the type checker flags it. Use ctx.log.

Permissions and tenant scope ​

Service calls run with the identity of whoever or whatever started the script: the user in the playground, or the workflow, app or integration that runs it. ctx.graphql enforces that identity's permissions, and every ctx call is limited to the script's tenant. Integrations are further limited to the devices, templates and scripts their manifest declares and the instance binds.

Determinism ​

The language itself has no clock and no randomness. Roles that run with services (SCRIPT, CUSTOM_APP, INTEGRATION) are granted a clock and a random source, so time.now(), ctx.time.now() and uuid.v4() work there. Product-template resolver scripts get neither grant: time.now(), uuid.v4() and uuid.v7() do not exist. They can still call ctx.time.now() and ctx.time.nowIso(), which read the wall clock, so a resolver that must always resolve the same template and configuration the same way should not use them. pairs iteration order is fixed, so a script given the same input and the same service responses behaves the same every time.

Network access ​

A script cannot open arbitrary connections. The only outbound paths are through ctx functions:

  • ctx.device.http and ctx.device.sql go through a device connection configured in CoCoCo. The base URL and stored credentials come from the device configuration, not from the script.
  • ctx.graphql, ctx.sql, ctx.cache, ctx.notify and the other namespaces talk to platform services.

To call an arbitrary URL, use the http_call node in a workflow rather than a script.

Limits ​

Each run has a wall-clock, memory, instruction, call-depth and module-load budget. The defaults are listed on the overview. Exceeding one stops the script; pcall cannot catch it.

Connect machines, automate workflows, and build custom apps for print production.