Gambit Permissions Guide
Gambit Permissions Guide
This guide explains Gambit's permission contract for native agent execution and
how to inspect effective permissions in traces. File names, metadata, and trace
event names still use deck where compatibility requires it.
Overview
Gambit models permissions with five Deno-native kinds:
readwriterunnetenv
Permissions can be declared in workspace config (gambit.toml) and in agent
metadata (PROMPT.md or TS deck definitions). Effective permissions are
computed by monotonic intersection: child scopes can only stay the same or get
narrower.
Where You Can Declare Permissions
Workspace Ceiling (gambit.toml)
Use workspace permissions to set a root ceiling.
[workspace]
permissions.read = ["./decks", "./shared"]
permissions.write = ["./workspace"]
permissions.net = false
permissions.env = false
[workspace.permissions.run]
commands = ["deno", "node"]
paths = ["./bin/safe-tool"]
Deck Declaration (PROMPT.md front matter)
+++
label = "my-deck"
permissions.read = ["./docs"]
permissions.write = false
[permissions.run]
commands = ["deno"]
+++
Reference Override ([[actions]], [[scenarios]], [[graders]])
+++
[[actions]]
name = "do_thing"
path = "./actions/do/PROMPT.md"
description = "Runs a child action"
actions.permissions.read = ["./shared"]
+++
Notes:
- Relative paths are resolved from the owner declaration location.
- Unspecified kinds in a declaration normalize to deny (
false) for that layer.
Run Semantics
run supports:
- boolean (
true/false) - command list (
run = ["deno", "node"]) - object form:
[permissions.run]
commands = ["deno"]
paths = ["./bin/tool"]
Path grants and command grants are intentionally separate:
pathschecks exact normalized path matches.commandschecks exact command-name matches.- No implicit basename fallback between the two modes.
- In object form,
pathsandcommandsmust be arrays. paths = true/commands = trueare invalid; userun = truefor full run
access.
Trace Observability
Gambit traces include effective permissions and layer decisions on:
run.startdeck.startaction.start
Example trace fragment:
{
"type": "run.start",
"runId": "run-...",
"permissions": {
"baseDir": "/workspace",
"effective": {
"read": ["/workspace/shared"],
"write": false,
"run": { "paths": [], "commands": ["deno"] },
"net": false,
"env": false
},
"layers": [
{
"name": "host",
"effective": {
"read": true,
"write": true,
"run": true,
"net": true,
"env": true
}
},
{
"name": "workspace",
"effective": {
"read": ["/workspace/shared"],
"write": false,
"run": { "paths": [], "commands": ["deno"] },
"net": false,
"env": false
}
}
]
}
}
Debugging Checklist
- Confirm the event has a
permissionsblock. - Check
effectivefirst (what was actually applied). - Then inspect
layersin order to see where a permission narrowed. - Validate
baseDirwhen a relative path grant looks unexpected.
Compatibility
This phase documents permission computation; it does not enforce new worker
behavior by itself. Existing deck-loading compatibility remains in place, with
warnings for deprecated metadata where applicable.