Use the hardened execution profile
The hardened profile is opt-in. Copy the published
contracts/hardened/profile.json contract to touba.hardened-profile.json,
reference it in your project profile, then prepare and run the project.
{
"run_profiles": {
"hardened": {
"require_supply_chain_lock": true,
"supply_chain_lock": "touba.lock.json",
"hardened_profile": "touba.hardened-profile.json"
}
}
}
Declare budgets in .tb source, after imports and before declarations; the compiler produces the required AIR limits.
module examples.bounded
limits run
max_run_ms as 30000
max_steps as 100
max_tool_calls as 20
max_agent_invocations as 5
max_provider_calls as 10
Each tool binding must include
"sandbox": { "required": true }. Also supply a durable checkpoint path.
The runtime uses opaque_refs for provider data and refuses execution if the
lock, sandbox, budgets, redaction or checkpoint storage requirements are unmet.
This is defense in depth, not a guarantee against exfiltration by an authorized handler, general prompt-injection detection, or identical sandbox protection across operating systems.
With a prepared run plan and validated lock:
touba run --run-plan .touba/build/hardened/touba.run-plan.json \
--human-checkpoint-out .touba/pending-approval.json --output json
HardenedBudgetRequired identifies a missing compiled source limit; HardenedDurableCheckpointRequired identifies missing checkpoint configuration. JSON output and its admission trace retain these codes without business payloads. A pure program validates the budget/lock/checkpoint path; it does not qualify handler OS isolation.
Locate the installed contract
For an installed Touba distribution, this macOS/Linux command prints the bundled contract path without changing the installation:
node --input-type=module <<'JS'
import {execFileSync} from 'node:child_process';
import {accessSync} from 'node:fs';
import {dirname, resolve} from 'node:path';
const info = JSON.parse(execFileSync('touba', ['version', '--json'], {encoding: 'utf8'}));
if (!info.distribution.sdk_archive) throw new Error('An installed Touba distribution is required');
const profile = resolve(dirname(info.distribution.sdk_archive), '../lib/contracts/hardened/profile.json');
accessSync(profile);
console.log(profile);
JS
Copy this file into your project and preserve its checks.
In a source checkout, the path is implementation/contracts/hardened/profile.json.
Sandbox qualification
When sandbox.required: true, macOS uses sandbox-exec; Linux x64 combines
bubblewrap, seccomp and the native touba-sandbox launcher with Landlock ABI 3
or newer. Out-of-scope data, writes, descendants and network connections are
denied by default. Native Linux checks cover Ubuntu 24.04, Node and Python,
including termination of descendants on timeout.
On Linux, bubblewrap must be installed and user namespaces available. An Ubuntu
host protected by AppArmor may require an administrator profile limited to that
binary, without disabling global protections. Each write_paths entry must
already exist: use a dedicated output directory to create files. Write access
does not grant read access. Exact Unix socket scopes require Landlock ABI 9;
an unenforceable policy is refused before launch. The probe runs a command
under confinement to check prerequisites.
The Windows backend is still undergoing V1 qualification, including asynchronous
Python handlers without network authorization. It is not announced as available
in a finalized distribution. An unavailable sandbox or unsupported policy
prevents execution, with no direct-execution fallback. Without a required
sandbox, handlers remain trusted host code.
HandlerSandboxUnsupportedPolicy identifies a policy unsupported by the
selected backend.
The technical baseline permits the interpreter's native libraries and metadata,
not every JavaScript module or the user's directory. For an installed, verified
JavaScript SDK, prepare inventories its individual files in sandbox.code_paths.
Third-party dependencies require explicit paths; no whole directory is opened.
Explicit binding fragments keep their own inventory.
The code_paths selection supplements this technical inventory; [] removes
additional files, not the verified SDK files. Data paths remain separate permissions.
Enable the sandbox through host decisions:
touba prepare --mode plan --host-decisions-json '{"bindings":{"tool:orders.review/ReadOrder":{"sandbox":{"required":true}}}}'
Use your tool reference, install its SDK, review the inventory, then use
--mode write and --mode check. Relative handler file arguments are resolved
before the isolated process starts. Data access still requires a grant and
explicit read_paths or write_paths. Code paths never grant write access.
For startup failures, development-only --handler-diagnostics <file.jsonl>
records the error class and known source position, without private messages.