Gambit Permissions Guide
Gambit Permissions Guide
This guide explains Gambit's permission contract for deck execution and how to
inspect effective permissions in traces.
Overview
Gambit models permissions with five Deno-native kinds:
readwriterunnetenv
Permissions can be declared in workspace config (gambit.toml) and in deck
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 and surfaces 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.