Two venues, one default
- Jail (default). Every app runs inside an iframe with
connect-src 'none', cannot reach the host page’s DOM, and cannot make network calls. This is the surface for every unreviewed or model-generated component. - In-client (approved). After a human review, an approved version of the app renders natively in the host DOM. It participates in the page’s origin, cookies, and CSP.
open(). A forged inClient field on a
stored, imported, or streamed tree is stripped before the runtime attaches its
own verdict. In-thread previews always render in the jail — the approved venue
is never used for conversation surfaces.
The approval record
An in-client approval is a small audit-trail record:vendo_inclient_approvals collection. The verdict is
simply “some stored approval pins the current version’s content hash”.
Corrupt or hand-crafted rows can never grant. Deleting an app clears its
approvals.
The version hash covers all app content, so any edit — pin change,
generated-component change, tree edit — produces a new hash and invalidates
every existing approval for that app.
Verdict states
open() attaches a payload.inClient field to the tree surface:
“Never approved” is the universal state and does not announce itself.
version-changed is loud: users see a visible notice (“…running in the
sandbox again until the new version is re-approved”) so they know an approval
was invalidated. If an approved component fails to compile or render, the
surface drops back to the jail with an error notice.
Reviewing what changed: ship-diff
Before minting an approval, a reviewer reads the ship-diff — the diff of approvable code against the last approved baseline, hash-pinned to the current version:Minting approvals
Vendo Cloud provides the human review console that mints approvals for production hosts. For local demos and development, Vendo exposes a documented injection seam that pins the app’s current version hash — you approve what is running, never a hand-crafted hash.Server-side
Development wire route
404, matching /dev/remixable-source). The request must resolve a host
principal — anonymous callers get 401.
Approvals are audited through guard.report. Read the record store with
vendo.apps.inClient.approvals(appId, { principal }).
What runs in the host page
Approved content runs in a closed module space: sucrase-compiled code with a controlledrequire that resolves React and captured sub-sources only — the
same evaluation model the jail uses, in the venue the approved verdict
unlocks. sampleProps are not used in the host mount; the shipped surface
never renders stub data.
The $action dispatch continues to route through the tree chokepoint, so
host tools remain gated by the same policy, grants, and audit path as the
jailed venue.
Related reading
- Generated UI and apps — the ladder and the default jail.
- Tools and safety — how host tool calls are gated regardless of venue.
- HTTP routes — wire endpoints for ship-diff and the dev injection seam.