What a script can reach
A script reaches atoms through namespaces — shell.execute(), db.query(),
s3.download(). Which namespaces exist is decided by the host, and at the CLI the default grant is
everything.
To see the grant for yourself:
function main() { const names = []; for (const k in globalThis) names.push(k); return names.sort();}kis script run globals.js --debugThat is worth running once in whatever context you care about, because the answer differs between
the CLI, a flow’s script: task, and a script embedded in a service.
The base set
Section titled “The base set”Some names are present no matter what, including under --namespaces none:
| Namespace | For |
|---|---|
log | Log lines |
json | Parse and serialise |
string, array, math | Value helpers |
time, now, tsnano | Clock and timestamps |
uuid, ulid, nanoid | Identifier generation |
hash | Digests |
template, interpolate | String templating |
cpet | The tenancy coordinate this script is running under |
The unifying property: nothing here reaches outside the process. No filesystem, no network, no subprocess. They are language services, and removing them would leave a script unable to compute or report at all.
That is why --namespaces none is meaningful rather than absolute — it removes every namespace
that can reach something.
The full grant
Section titled “The full grant”With the default --namespaces all, roughly eighty names are bound. By what they touch:
| Group | Namespaces |
|---|---|
| Local execution | shell, supershell |
| Remote execution | ssh, scp, rsync |
| Files | file, fs, glob, archive, extract |
| Structured text | yaml, jq, liquid |
| Network | http, rest, dns |
| Databases | db |
| Object storage | s3, azureblob |
| Secrets | vault, secret, crypt, letsencrypt |
| Source control | git |
| Containers and clusters | docker, podman, k8s, kubectl |
| Host and process | port, cron, osuser, lock, wait |
| Identifiers | id |
| AI | llm, embed, rag, vector, milvus, intent, guard, reason, scrape, text, validate, pipeline |
| Data pipeline | csv, excel, parquet, entity, morph, aggregate, compute, stdout |
| Documents | ocr |
| Authorization | user, rbac, abac, ambient, ownership, fields, rls |
| Platform | config, vars |
Each is documented in the atom reference, alongside the flow task that reaches the same atom.
Two of these groups deserve a note. Authorization namespaces answer who is asking — they return zero values at the CLI, where there is no request identity, and are populated when a script runs inside a service. Data pipeline namespaces are most useful inside a pipeline, where the record stream is the point.
Narrowing the grant
Section titled “Narrowing the grant”--namespaces takes all, none, or a list:
kis script run transform.js --namespaces nonekis script run fetch.js --namespaces http,jsonkis script run deploy.js --namespaces shell,ssh,vaultThe list is added to the base set, not substituted for it. --namespaces http gives a script
http plus everything in the base set — so it can still compute, log and return, which is what
makes the narrow grant usable at all.
$ kis script run globals.js --namespaces none --debugResult: ["array","cpet","hash","interpolate","json","log","math","nanoid", "now","string","template","time","tsnano","ulid","uuid", ...]
$ kis script run globals.js --namespaces shell --debugResult: [... the same, plus "shell"]A flow’s script: task takes the same parameter:
- name: transform script: language: javascript file: ./transform.js namespaces: json,string setvar: cleanedChoosing a grant
Section titled “Choosing a grant”Name what the script needs. The list is short for most scripts, and writing it down is a one-line statement of intent that survives the script being edited later:
| The script | Grant |
|---|---|
| Transforms data it was handed | none |
| Calls one API and reshapes the answer | http |
| Reads a database and reports | db |
| Deploys to hosts | shell,ssh,vault |
| Is generated by a model, or came from outside | none, and add only what it demonstrably needs |
The last row is the one that matters. Code you did not write and cannot fully review should start
at none and earn each addition. Pairing that with a language that contributes no authority of its
own — Starlark — means the script’s reach is exactly
the list you wrote, and nothing has to be audited to know it.
Restricting a grant is a design decision, so make it where the script is configured rather than at
the point of running it. A flow that carries namespaces: in its definition keeps the constraint;
a --namespaces flag typed at a terminal does not survive the next invocation.
See also
Section titled “See also”- Atom reference — what each namespace offers
- Languages — pairing a grant with a constrained language
- Calling convention — getting data in and out