sandbox: a script fetched through a Storage (URI gap 13) #69
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
The
std/fshalf of gap 13 is built; theSandboxhalf is not: a script fetched through aStoragehas no member to hand it to.Source
Acceptance criteria
Sandboxloads a script from aStorageDependencies
None known.
Moved from the planning lists of the docs; the design record stays the specification.
[loop:torbscript] intake: in scope (author orion, label loop), source URI.md gap 13, not a duplicate, no collision with a design record. A
Sandboxmember in the std, likely no seed impact; sonnet/medium. next: refine, waiting (ready buffer full: #4, #163, #164, #223 are ready) until 2026-10-10T04:00:00Z[loop:torbscript] claim refine by session:loop-torbscript-20261023 until 2026-10-23T10:16:00Z
[loop:torbscript] release refine: the worker failed to start (all CLI live sessions busy); no work done, back to the backlog. next: refine
[loop:torbscript] claim refine by session:loop-torbscript-20261023 until 2026-10-23T10:32:00Z
[loop:torbscript] decided by the loop:
Sandbox.loadText<Value>(text: String, name: String, capabilities);std/sandboxdoes not learnStorage.Why:
Resource,Sandboxand the manifest's sources sit" keepsSandboxoff theStorageregistry on purpose (it stays onPath/Resource/EmbeddedText), and gap 13 only asks for a member a script fetched through aStoragecan be handed to. The smallest such member takes the text: the caller doesstorage.readText(uri).await()?and passes the result. Nostd/sandbox->std/storagedependency, and the grant story (RESOURCES.md section 5:std/fs/std/storagestay the imports that mean "this program reads what the user named") is untouched.loadScript/load.script,host.trb:tree.withFile absolute, text, then check, lower, continuation; "a file loaded again with the same text is the script loaded before"). The new member is the same path with the text handed in instead of read from disk; there is no write-to-file detour (the gap's complaint).Sandbox.load/Storage.readText. RESOURCES.md section 5's planned rename (load->read,embedded,load(Resource)) is not built; if it lands, this member follows the verb for "a run-time source" (readText) in that PR.nameis the script's display name inSandboxErrormessages and the module identity (not a path, not resolved against anything); it is not part of the cache key, the text is.7aef9a54(loadScriptnative +load.scriptinstruction + std change in onefeatcommit, no seed refresh), and the compiler's own code does not call the new member. The implementer confirms in CI bootstrap; if the published seed cannot compile the newnative fndeclaration, fall back to the two-commit rule (teach, then migrate) and the PR waits on Torben's seed refresh.hostLoadScriptreads a file in the host; a text variant passes the text instead (the host already works ontree.withFile path, text). If that turns out to exceed one PR, the implementer lands the VM half, makes the native-binary call answer a documentedSandboxError(as slice 7 did before slice 8) and says so in the PR; the rest is then a follow-up issue (~1 h+) filed at that point, not before.[loop:torbscript] refined spec (supersedes the two bullets of the issue body; the body is left as filed).
Goal. A program that fetched a script through a
Storagehands it to the sandbox without writing it to a file first (URI.md gap 13,Sandboxhalf; thestd/fshalf is done).Design point.
docs/design/URI.mdsection 13 gap 13 and the section "WhereResource,Sandboxand the manifest's sources sit";docs/design/RESOURCES.mdsection 5 (Sandboxverbs) anddocs/design/SCRIPTS.mdslices 7 and 8. Decision: previous comment.Acceptance criteria.
Sandbox.loadText<Value>(text, name, capabilities): Result<Script<Value>, SandboxError>instd/sandbox, same checks, grants, limits and error shape asSandbox.load;SandboxError.linecounts lines oftext; the message namesnamewhereloadnames the path.torb run), and in a native binary through the script host (or, per the fallback in the decision, answers a documentedSandboxErrorthere).std/sandboxtakes no dependency onstd/storage; the doc example fetches withMemoryStorage.readText(...).await()?and loads the result.tests/conformance/vm-only/sandbox-storage.trb(+.expected) that stores scripts in aMemoryStorage, reads them back and loads them: a configuration applied to a receiver; the same text twice (one script); a type error with its line; an ungranted and a granted import; a panic with its line; a text that is not UTF-8 stays aStorageFailure.NotTextof the caller (never reaches the sandbox). If the native binary is covered, a case intests/conformance/sandbox-crossing.trbfor both back ends.Sandboxsection of RESOURCES.md gains the member (URI.md section 14 "The prose" asks for exactly this),docs/standard-library/sandbox.mdanddocs/language/configuration/the-sandbox.md; skills regenerated (torb docs skill docs skills,--checkclean).Seed. Not touching it by design (no syntax change, no driver flag, no std name the compiler looks up by string); a new native (
loadScriptTextnext toloadScriptincompiler/src/backend/c/natives.trb) is covered by the seed note in the decision comment. Never touchseed/.Size. One PR, one
feat(sandbox): ...commit (two only if the seed fallback applies:feat(vm): teach ...thenfeat(sandbox): ...). Touchesstd/sandbox/src/lib.trb,compiler/src/vm/{interpret,run,host}.trb,compiler/src/backend/{c/natives,bytecode/emit,bytecode/format}.trb,compiler/src/ir/lower/call.trb, docs, tests. Implementer: sonnet/high (compiler/src,std/). Gates a and b (it touchescompiler/src/ir/lower, bytecode backend); forge CI only.[loop:torbscript] refine: checked against URI.md gap 13, RESOURCES.md section 5, SCRIPTS.md slices 7/8, CONCEPT and CLAUDE.md; sharpened goal and acceptance criteria, decided the API (
Sandbox.loadText, nostd/storagedependency), seed impact (none expected, fallback stated) and size (one PR, one commit), labelreadyset. Worker usage ~75k tokens. next: implement[loop:torbscript] claim implement by session:loop-torbscript-20261023 until 2026-10-23T14:44:00Z