Threads open a fresh Lua state with a full standard library, so they
stayed blocked wholesale. PotatoVoxel's prebuilder wants to run its
pure geometry phase on worker threads; the mod declares the new
"compute" permission and the sandbox hands out love.thread only
then. The worker runs the mod's own source (source-only, like every
mod file) and receives data only through channels.
DENIED_PREFIX blocked love.* and ffi.* submodule requires but had no
entry for jit, so require("jit.util") walked straight through to the
real module. jit.util is LuaJIT's own equivalent of the debug library
this file already denies by name: funcbc, funck and the rest read the
bytecode and constants of any function a chunk can reach, which is
enough to recover upvalues -- the real _G, love, io -- that the sandbox
exists to keep out of a mod's hands.
Adding "jit" to DENIED_PREFIX blocks jit.* submodule requires the same
way love.* and ffi.* already are, while leaving the bare jit global
(env.jit, handed over directly for jit.on/off/flush) and a bare
require("jit") untouched -- jit.util is not a field of that table
without its own require, so neither route was ever a way to reach it.
The sandbox blocks love.system and love.filesystem, which orphans the
native step bridge (#452, #489): its one consumer can no longer call
syncHealthSteps or read steps_pending.json (#1186).
Adds a "steps" manifest permission (shown to the player like the
others) gating a mod.steps facade: available() probes the bridge
quietly, sync() forwards the async refresh, poll() hands the mod its
copy of a delivery. The engine owns the pending file -- mods never name
a path and receive only { steps, from, to }. Without the permission the
acting calls name it, following the network gate. No new events, hooks
or registries; nothing removed.
RFC 0009. Tests: tests/modkit/cases/steps_bridge.lua (no-mod cold
bridge, permissioned sync/poll, per-mod copies, contract-field
filtering, malformed-delivery drop, unpermissioned refusal, bridgeless
build).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>