Grants
SandScript uses a grant system for capability-based security. Code
inside a grant block runs with specific capabilities
that the host provides. The host decides whether to approve or
deny each grant request. On this site, the host is the runner
page, and its policy is the set of identifiers you tick at the
consent gate.
Basic usage
grant "database" {
let result = Database.query();
Console.log("result:", result);
}
When execution reaches the grant statement, the
runtime yields to the host with a grant request. The host approves
the request and provides the capability, or denies it.
The denied block
The denied block provides structured recovery when a
grant is denied or revoked:
grant "database" {
let result = Database.query();
Console.log("result:", result);
} denied (revoked) {
Console.log("capability denied:", revoked);
}
The denied block fires in two cases:
- Request-time denial. The host rejects the grant request.
- Mid-execution revocation. The host revokes the grant while code runs inside the block.
The optional parameter receives an array of the denied or revoked identifiers.
Multiple grants
Request multiple capabilities at once with parenthesized identifiers:
grant ("database", "network") {
let data = Database.query();
Network.send(data);
} denied (revoked) {
Console.log("denied:", revoked);
}
All identifiers must be approved for the block to execute. If the
host denies any of them, the denied block fires with
the array of denied identifiers.
Block precedence
The denied block takes precedence over
try/catch for grant-related revocation. They are
independent control flow mechanisms:
grant "database" {
try {
let result = Database.query();
} catch (e) {
// Does NOT catch revocation
}
} denied (revoked) {
// Fires on revocation — takes precedence over try/catch
Console.log("revoked:", revoked);
}
Without a denied block, revocation throws a
GrantDeniedError, which propagates through
try/catch normally.
Grant identifiers are expressions
A grant identifier is an arbitrary expression, not only a string. What a program will request is therefore not knowable before it runs. A host enforces its policy at request time, as an allowlist, never as a prediction. This is why the runner on this site compares identifiers by their marshalled bytes: two structurally equal identifiers must compare equal, whatever their type.