Verified against the v0.65+ source (workbench/module_sandbox.py) — answers to all three, plus one naming trap that bites everyone:
⚠️ There are TWO requires fields with different meanings:
- Top-level
module.json:requires (next to commands) → the sandbox capability block. This is the one you want.
- Per-command
commands[].requires → a list of credential names the command needs. Unrelated to sandboxing.
1. Valid keys and values (top-level requires):
{
"requires": {
"network": ["api.linear.app"],
"subprocess": false,
"filesystem_writes": []
}
}
network — hostname allowlist for outbound connections. Wildcards work ("*.stripe.com"). Since v0.56 the check validates the resolved IP against the hostname allowlist (Dave's report), so real HTTPS to an allowed host just works. Anything not listed raises SandboxViolation with the exact host in the message.
subprocess — boolean. false makes any subprocess.* call raise.
filesystem_writes — glob list of writable paths (e.g. ["/tmp/**"]). Empty list = no writes. Reads are not restricted — only writes.
For Linear Guard, the block above is exactly right: outbound to api.linear.app only, no shell, no writes. The Studio badge flips from SANDBOX · UNRESTRICTED to the declared-capabilities view.
Honest scope note (it's in the module's own docstring): this is language-level enforcement — "fail loud on undeclared capability", designed to catch drift and AI-drafted mistakes, not to contain a determined adversary. The publisher signature + trust allowlist remain the primary defense. Also note allowed_destinations (which you already set) is a different knob — it governs the egress-broker checks, not handler socket calls; keep both.
2. Re-sign needed? Yes. requires lives in module.json, and the bundle signature covers the canonical manifest — an edited manifest without a re-sign fails the loader's signature check. So: edit → railcall market module sign <dir> → railcall market publish (bump the version). The station reads the block at module load; installers get it with the update.
3. Docs: you're right, it was missing. The requires block wasn't documented on the marketplace-developer pages — that's a gap you've just fixed for everyone; docs update is landing today. Credit awarded for the catch.