Skip to content

PROD-250 docs: sandbox constrain governance - #157

Open
salamisandwich77 wants to merge 445 commits into
developfrom
docs/constrain-temporal-python-integration
Open

PROD-250 docs: sandbox constrain governance#157
salamisandwich77 wants to merge 445 commits into
developfrom
docs/constrain-temporal-python-integration

Conversation

@salamisandwich77

@salamisandwich77 salamisandwich77 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Governed Sandbox Commands

Documentation for running an authorized command inside an isolated sandbox instead of on the host.

A CONSTRAIN verdict stops a Temporal activity before its body runs. The plugin derives an argument vector from an application-owned registry, executes it in a sandbox over mutual TLS, and returns a bounded typed result. Workflow input can select a registered command but never construct one.

Pages

Page Covers
Concept Verdicts, routing, at-most-once dispatch, fail-closed behavior
Quick Start Provision the sandbox, create the rule, run a Worker whose activity is routed into it
Provisioning Release lines, policy templates, verification, how the service is supervised, launcher flags
Native Provider Seatbelt on macOS, bubblewrap on Linux, egress proxy, violation evidence
OpenShell Provider Optional microVM, prepared VM cache, OCI registry mode, CA trust
Command Profiles Registry reference: argument types, typed result schemas, admission rules
Console Evidence sandbox_execution span fields and the bounded activity result

Providers

native is the default and needs no extra runtime: it applies a compiled, SHA-256 pinned profile through the OS sandbox. openshell is optional and provides a guest-kernel boundary through a microVM, at the cost of a prepared image cache and a hypervisor.

Provider selection is explicit and fails closed. There is no fallback.

Running the service

Provisioning starts the service in the terminal, where Ctrl-C stops it and drains work in flight. --detach runs it in the background in its own process group, and --systemd has systemd supervise it and restart it on failure.

Use markdown link syntax [name](url) instead of name: url, add
blockquote project description, and remove shell-style comments
from the header.
Define overview, integration, configuration, and organization tags
in tags.yml that were referenced in doc frontmatter but undefined.
…r/footer, and justfile

- Generate individual .md files for each doc page (llms.txt spec convention)
- Links in llms.txt now point to .md URLs instead of HTML
- Add description and footer as plugin options in docusaurus config
- Support URL env var override for local testing
- Add justfile with build/serve recipes
Enhance llms.txt plugin with individual .md files, configurable heade…
Add llms_description field to all 42 doc pages so the llms.txt plugin
can append short descriptions after each link, helping LLMs assess
relevance before fetching. Update the plugin with a formatIndexLine
helper that prefers llms_description, falling back to description.
Rewrite the README with project setup, llms.txt documentation, and
deployment environments.
New developer guide page explaining the llms.txt, llms-full.txt, and
individual .md files that OpenBox publishes, with integration guidance
for IDE assistants, custom agents, and RAG pipelines.
Add llms_description frontmatter and link descriptions to llms.txt
The docs live on a dedicated subdomain (docs.openbox.ai), so the /docs/
path segment is redundant. This changes routeBasePath from '/docs' to '/'
so URLs like docs.openbox.ai/docs/getting-started become
docs.openbox.ai/getting-started.

- Set routeBasePath: '/' in docs preset config
- Change docs/index.mdx slug from / to /overview to avoid conflict with homepage
- Update docsRouteBasePath in search plugin config
- Update all internal links across 44 files (~200 references)
- Update footer links in docusaurus.config.js
- Update README generated files path
Remove /docs prefix from documentation URLs
Add llms-ctx.txt output to the Docusaurus plugin matching the llms_txt2ctx
reference format (fastcore XML). Move llmxctx Python reference tool to
reference/llmxctx/ and add just commands (build-ctx, diff-ctx) for generating
and comparing output against the reference implementation.
Add llms-ctx.txt output to the Docusaurus plugin matching the llms_txt2ctx
reference format (fastcore XML). Move llmxctx Python reference tool to
reference/llmxctx/ and add just commands (build-ctx, diff-ctx) for generating
and comparing output against the reference implementation.
Add llms-ctx.txt generation and reference comparison tooling
Convert 11 PNG screenshots to WebP format (lossless for UI screenshots,
q90 for smaller images), reducing total image size from 3.1 MB to 1.3 MB
(59% reduction). Compress social_preview.png via palette optimization
(396 KB to 84 KB). Update all doc references to use .webp.
Convert images to WebP and compress social preview
… headers

- Fix CONTINUE/SOFTBLOCK to canonical ALLOW/HALT in core-concepts diagram
- Add sitemap config: lastmod dates, exclude /tags/** and /search, drop
  deprecated changefreq/priority
- Move vercel.json into website/ so headers apply in Vercel builds
- Add Strict-Transport-Security header with preload
- Add Cache-Control for /img/* assets (24h + 7d stale-while-revalidate)
Sandbox isolation introduced both providers and what each uses, then a
Providers section restated the same two facts a few paragraphs later. The
second section keeps only what it added: how a provider is selected and that
selection never falls back.

The microVM now says what it buys, a guest-kernel boundary, where the
providers are first introduced rather than in the repeat. One heading was
title case among sentence case.
A newly registered agent has Require signed requests turned on. The example
on this page does not sign: it passes openbox_url and openbox_api_key and
nothing else. A reader who registers an agent and follows the page therefore
fails at the first governed activity.

The failure is hard to diagnose, because Core answers 401 and the SDK
reports "Invalid API key" when no signer is configured. The key is usually
correct.

Requirements now states the default and gives the two ways forward: clear
the checkbox, or pass agent_did and agent_private_key. Troubleshooting
carries the same under the message a reader actually sees.
The page documented one route to the sandbox, the policy rule. A behavioral
rule reaches the same place and the page said nothing about it.

The two differ in what a reader has to build. A policy rule matches the
activity by name, so one activity is enough. Every behavioral trigger names
an action the agent performed, such as http_get or file_write, and none of
them fire when an activity merely starts. A CONSTRAIN verdict stops the
activity body, so the constrained activity cannot emit its own trigger. The
Worker therefore needs a second activity: the first performs the action, the
second is the one the rule constrains.

Section 6 adds that activity, the workflow call, the registration, and the
rule settings. Troubleshooting covers the case where the trigger event never
occurs because the policy rule stopped the activity that would emit it.
Step 2 and step 3 now carry matching tabs, Policy rule and Behavioral rule,
linked by a shared group so choosing one in either step selects it in both.
A reader follows one route instead of reading a second route appended after
the first. The separate section 6 is gone, since the tabs carry it.

The signing note claimed a new agent requires signed requests, stated as a
property of the product. It is a checkbox in agent settings. Registering an
agent provisions a DID and turns the checkbox on, and an agent without a DID
does not show it at all. The note now says where the setting is and that the
reader controls it.

The page becomes .mdx, which Tabs requires. The document id and the URL do
not change.
Docusaurus draws the caret of a collapsible sidebar entry with a background
image on ::after. The review highlight wrote content into that same
pseudo-element, so on Governed Sandbox Commands the dot printed on top of the
arrow and took the caret's grey rather than green.

A plain link keeps its dot on ::after. A collapsible link now takes the dot
on ::before, which leaves the caret alone.
The behavioral tab carried three fragments and told the reader to graft them
onto the policy example. It now carries both files whole, so either tab is a
complete Worker that can be copied without reconstruction.

Writing them out exposed a difference the fragments hid. A policy rule takes
the profile from the activity input, so that input carries profile_id. A
behavioral rule names the profile itself, so it does not. Running the
behavioral example while a policy rule is still enabled therefore fails with
GovernedCommandInputError, which reads as a product fault rather than a
missed step. Troubleshooting now names it, and the tab says it plainly.

Step 4 showed one result shape. The behavioral workflow returns both
activities, so that step gains the same tabs.

Step 5 was called Prove the policy, which now collides with the Policy rule
tab. It is the network policy, and it says so.

The OpenBoxAuthError entry still described signing as a property of the
product. It is a checkbox, matching the correction already made in
Requirements.
Checked every console instruction against openbox-fe rather than against the
older written guides.

The behavioral tab is labelled Behavior, not Behaviors. Its Create Rule
control opens a four step wizard, Basic Info, Trigger, States, Enforcement,
and the pages now name the step a reader is on. Trigger is a searchable list
grouped by category under Select Trigger Semantic Type. Profile ID is a text
box that CONSTRAIN requires, and its placeholder is already post-batch.

Sessions is not a page under Verify. The Verify tab holds a session selector
and a view toggle, so a reader picks the session there and switches the view
to Tree.
The page told a reader to leave step 3 empty, because the wizard allows it.
The server does not: the rule contract marks states as an array of minimum
length one, so creating the rule fails with 422 Unprocessable Entity.

Step 3 now asks for a prior state, and troubleshooting names the error.
The console cannot see the Worker registry, so the Profile ID box accepts any
string and a typo surfaces only when the rule fires. The page now says so,
next to the step where the name is typed.
The instruction to type post-batch into Profile ID assumed the field exists
in the console. It lives only on feat/PROD-318-behavioral-constrain in
openbox-fe, 22 lines added on top of develop. A console built from develop
shows no box, so a reader on the current staging console tries a field that
is not there.

The step now states that the box appears only when that verdict is selected,
and the behavior section carries the same merge note.
The base sandbox section carries a policy CONSTRAIN only. Behavioral rules
move to a separate pull request, because every layer they need is still in
draft: the frontend editor, the backend contract, and Core. Shipping the
docs now would describe a console that cannot create the rule.

Removed from this PR:

- quick-start step 2 behavioral tab, step 3 behavioral files, step 4
  behavioral result, and the behavioral troubleshooting entries
- concept two-rule-type sentence
- error-handling behavioral failure row
- behaviors.md additions
- the behavioral mentions in governance-decisions, native-provider,
  sandbox-execution, and troubleshooting

The behavioral branch docs/PROD-318-behavioral-constrain-docs carries the
full coverage and stands ready as its own pull request.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants