Function Permissions
SDK 0.8.0 and CLI 0.10.0 support an optional functions/<task>/permissions.json. The file declares the EVM target and function-selector pairs used by a release. It is packaged with the code, so its contents are covered by the release checksum and immutable version tag.
{
"calls": [
{
"target": { "arg": "tokenAddress" },
"function": "transfer(address,uint256)"
},
{
"target": { "11155111": "0x1111111111111111111111111111111111111111" },
"function": "0x095ea7b3"
}
]
}The fixed address above is a placeholder: replace it with the intended contract on that chain. thyme new does not create this optional file.
File contract
| Field or limit | Rule |
|---|---|
| Top level | An object with exactly calls; do not include a version field. |
calls | Array of entries with exactly target and function. |
| Argument target | { "arg": "tokenAddress" } refers to a top-level argument. The name matches ^[A-Za-z_][A-Za-z0-9_]*$. |
| Fixed target | A nonempty mapping from positive decimal chain IDs to valid EVM addresses. |
function | ABI function signature such as approve(address,uint256), or exactly four bytes as 0x plus eight hex characters. |
| File size | At most 16 KiB of UTF-8 JSON. |
| Call count | At most 50 entries after deduplication by target declaration and selector. |
Unknown fields are errors. Addresses are checksummed and selectors normalized. Argument targets cannot use nested paths, and a target cannot combine arg with chain mappings.
{ "calls": [] } explicitly declares no calls. Omitting the file means the release has no permission declaration; that is different from an empty declaration.
Resolution and enforcement
Argument targets resolve against executable args. Fixed targets resolve against the executable chain; every declared target must resolve. A returned call is matched using its address and the first four bytes of calldata. Empty calldata has no selector and cannot match a rule.
The declaration does not constrain calldata argument values. For example, declaring transfer(address,uint256) does not restrict the transfer recipient or amount. It also does not by itself grant a Safe module permission or replace a profile's on-chain authorization.
thyme upload rejects invalid manifests, including in CI and with --yes. The backend independently validates the archive. In the cloud, calls outside a declared manifest are rejected before submission. See Flow permission enforcement for profile compatibility and migration behavior.
Local verification
The local checker resolves argument targets from raw args.json, and obtains the chain ID from RPC_URL when fixed targets are present. Undeclared or unresolved calls produce warnings rather than blocking local execution. Ensure an argument used as a target is explicitly present in args.json; the checker does not apply Zod defaults or transforms to it.
For current local-run limitations, see thyme run. A successful local process exit is not proof of cloud permission compatibility.
Release changes
Changing the manifest changes the archive checksum. Upload a new immutable tag, review the new permissions, then switch a paused executable to that release. Args changes can also change resolved addresses for argument targets and may require renewed profile authorization.
The SDK's archive utilities carry the raw manifest text; they do not validate it. Archive integrators must validate the extracted text before trusting a declaration.