Somewhere safe to be wrong.
A sandbox is a scratch microtheory of one browser session's own, hung below
WellContext so it sees the whole shipped ontology and nothing shipped sees it. A
reader can therefore use every type, every relation and every rule the KB ships, and
cannot damage any of them: their content is visible only from inside, and one control
takes all of it away again.
Why that shape and not a permission system: visibility here is logical, not
administrative. genlContext already decides what a context can see, and hanging the
sandbox at the bottom of the spindle gives exactly the asymmetry wanted — everything
flows in, nothing flows out — with no new concept and nothing to enforce. A shipped
rule firing over sandbox facts places its conclusion in the sandbox, because
placement is the maximal common descendant of the rule's context and the antecedents'
(docs/contexts.md), and the sandbox is the only context below both. So the derived
content is inside the thing that gets discarded, without anything arranging for that.
Three facts about the lifecycle:
genlContext edge per idle visitor.wrap-session and validated on the way back in —
a name is being built from it, and a name built from unvalidated client input is an
injection.edit's :remove, and the genlContext edge with them. The edge is not in the
extent — genlContext is a forced-decontextualized predicate, so it is stored in
UniverseContext — which is why it is fetched by hand rather than swept up with the
rest.Promotion — moving something out of a sandbox into a context that outlives it — is deliberately not here. A sandbox is a dead end, and a dead end that cannot be half-escaped is easier to reason about than one with a door in it.
Somewhere safe to be wrong. A **sandbox** is a scratch microtheory of one browser session's own, hung below `WellContext` so it sees the whole shipped ontology and nothing shipped sees it. A reader can therefore use every type, every relation and every rule the KB ships, and cannot damage any of them: their content is visible only from inside, and one control takes all of it away again. Why that shape and not a permission system: visibility here is *logical*, not administrative. `genlContext` already decides what a context can see, and hanging the sandbox at the bottom of the spindle gives exactly the asymmetry wanted — everything flows in, nothing flows out — with no new concept and nothing to enforce. A shipped rule firing over sandbox facts places its conclusion **in the sandbox**, because placement is the maximal common descendant of the rule's context and the antecedents' (docs/contexts.md), and the sandbox is the only context below both. So the derived content is inside the thing that gets discarded, without anything arranging for that. Three facts about the lifecycle: - **The context is created on the first write, not on the first page.** A reader who only looks costs the KB nothing, and a KB full of empty sandboxes would be a KB with a `genlContext` edge per idle visitor. - **The session id is in the context name**, so two readers of one process never share one. It is minted into a cookie by `wrap-session` and validated on the way back in — a name is being built from it, and a name built from unvalidated client input is an injection. - **Reset is a real teardown**, not a flag: every sentex in the extent goes through `edit`'s `:remove`, and the `genlContext` edge with them. The edge is not in the extent — `genlContext` is a forced-decontextualized predicate, so it is stored in `UniverseContext` — which is why it is fetched by hand rather than swept up with the rest. Promotion — moving something out of a sandbox into a context that outlives it — is deliberately not here. A sandbox is a dead end, and a dead end that cannot be half-escaped is easier to reason about than one with a door in it.
(context-for token)The sandbox context named by token, or nil when the token is not one we minted.
Sandbox<token>Context satisfies the context naming invariant (CapitalCamelCase
ending in Context), so it is an ordinary context in every other respect.
The sandbox context named by `token`, or nil when the token is not one we minted. `Sandbox<token>Context` satisfies the context naming invariant (CapitalCamelCase ending in `Context`), so it is an ordinary context in every other respect.
(context-of req)The sandbox context this request belongs to, or nil when it carries no valid token.
The sandbox context this request belongs to, or nil when it carries no valid token.
(extent target ctx)Every sentex stored in the sandbox — what the reader put there and what the shipped rules concluded from it, which are in the same place by construction.
Every sentex stored in the sandbox — what the reader put there and what the shipped rules concluded from it, which are in the same place by construction.
(live? target ctx)Does this sandbox exist in the KB yet? It exists exactly when its edge does; the extent can be empty (everything in it retracted) and the sandbox still be open.
Does this sandbox exist in the KB yet? It exists exactly when its edge does; the extent can be empty (everything in it retracted) and the sandbox still be open.
(mint-token)A fresh session token — the low half of a random UUID, which is hex and needs no encoding to sit in either a cookie or a symbol.
A fresh session token — the low half of a random UUID, which is hex and needs no encoding to sit in either a cookie or a symbol.
(open target ctx)Make sure ctx exists, and answer it. Idempotent — the edge is find-or-create, so a
second call on a live sandbox writes nothing. Bare, not !: it only ever adds.
Make sure `ctx` exists, and answer it. Idempotent — the edge is find-or-create, so a second call on a live sandbox writes nothing. Bare, not `!`: it only ever adds.
(reset! target ctx)Discard the whole sandbox: every sentex in it, then the edge that made it a context.
One edit, so it is one settle, and the dependency-directed sweep does the rest — a
conclusion derived into the sandbox goes with the premises it rested on, and its
justification with it. Retracting the extent wholesale is safe even though the sweep
reaches some of it first: a handle already gone is a no-op in :remove.
Answers {:removed-sentexes n :removed-justifications n}. Irreversible, hence the
! — that is the whole point of the control.
Discard the whole sandbox: every sentex in it, then the edge that made it a context.
One `edit`, so it is one settle, and the dependency-directed sweep does the rest — a
conclusion derived into the sandbox goes with the premises it rested on, and its
justification with it. Retracting the extent wholesale is safe even though the sweep
reaches some of it first: a handle already gone is a no-op in `:remove`.
Answers `{:removed-sentexes n :removed-justifications n}`. Irreversible, hence the
`!` — that is the whole point of the control.(token-of req)This request's session token — the one wrap-session put on it, else the cookie's,
else nil.
This request's session token — the one `wrap-session` put on it, else the cookie's, else nil.
(wrap-session handler)Give every request a session token, minting one into a cookie the first time.
The token alone writes nothing — it names a sandbox that may not exist yet. Only
open creates the context, and only a write calls it.
Give every request a session token, minting one into a cookie the first time. The token alone writes nothing — it names a sandbox that may not exist yet. Only `open` creates the context, and only a write calls it.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |