Skip to content

Governed transport runtime v1

REST and MCP separate their interface from the strategy used to invoke it. Generation without --execution-policy remains direct, with every existing REST/MCP artifact byte preserved. Supplying a policy explicitly opts into the governed local-process runtime. Both modes execute trusted code. Governed mode is not a filesystem or network sandbox.

Contracts and versioning

Capability IR v1, Readiness v1 and InvocationContract have no execution fields or changed semantics. apizr.rest/v1 and apizr.mcp/v1 retain their route/Tool contracts; OpenAPI and mcp-tools.json are byte-identical between modes for the same selection. Execution strategy is separately declared by apizr.execution-bundle/v1, binding apizr.execution/v1, apizr.runtime/v1 and apizr.local-process/v1.

The original interface artifacts did not encode a mandatory process lifetime. Direct mode preserves their historical lifetime; the separately versioned, explicitly selected execution policy declares the governed lifetime. No silent version reinterpretation or REST/MCP v2 is introduced. Canonical transport manifests keep their existing shape: the artifact hash map binds the new execution bridge and its files. The CLI presentation adds execution.mode (direct or governed); governed presentation also names policy/backend versions. Existing schema_version and files fields remain available.

Runtime reuse and embedding

apizr.governed.embedding copies the installed execution implementation into apizr_governed/, changing only package imports. Framing, supervision, timeout, environment filtering, worker lifecycle, exact-byte loading, callable verification, argument reconstruction, output conversion and error sanitization are shared with apizr execute. There is no REST/MCP-specific worker or manual fork of that logic.

The embedded dependency closure contains the typed IR/Readiness/interface models, canonical serializers and plan validators required to validate complete RuntimePlans. It includes interface type lowering to verify linkage to the IR, never source analysis or a second eligibility policy. The Inspection model definition is copied verbatim from the installed module; analyzer/reporting entry points and source-AST classification are omitted. Package initializers are empty. No source analyzer, notebook exporter, legacy generator or documentation is copied. Only the selected REST or MCP adapter is included.

The bootstrap loads the explicit embedded package with importlib; it does not modify sys.path. A worker starts using an argument array with isolated Python: python -I <bundle>/execution/worker.py. It activates that same package and runs the same worker implementation in the fresh invocation directory. Generated requirements add the reviewed Pydantic 2 floor used by the typed validators; they never require outerspace-apizr. Standalone REST and MCP are tested in environments without Apizr; MCP also works without FastAPI installed.

Artifacts and content bindings

A governed bundle adds:

execution/
    bundle.json
    policy.json
    plans/<capability-name>.json
    worker.py
apizr_governed/
    capabilities/       # typed validation models, no source analyzer
    readiness/          # typed validation models, no assessment engine
    interfaces/         # contract validation and shared invocation
    execution/          # the shared execution implementation
    governed/           # bundle validation and the selected adapter
    inspection.py       # the inspection value model only

The bridge declares its schema/backend/transport, policy path and digest, transport contract digest, and a mapping from each selected capability ID to its plan path and digest. Exactly one validated RuntimePlan is emitted per selected capability. Its artifact map hashes all non-manifest files, including policy/plans, executable source, IR/readiness, embedded code and public interface document. The transport manifest hashes the bridge as well. Neither manifest hashes itself; there is no circular digest dependency.

The chain remains independently visible: source → IR → readiness → interface → policy → per-capability runtime plan → execution bundle → transport artifact map. Canonical bytes contain no build-host availability, timestamp, PID, hostname, absolute deployment path, runtime environment values or random identifier. Plans are content-bound artifacts, not signed attestations. No Continuum Attest, signatures or SLSA fields are introduced.

Build host versus runtime host

Static generation calls execution planning with check_availability=False. This checks requirements against the declared local-process contract, not os.name on the build machine. Unsupported network/filesystem/subprocess controls and unknown required effects still refuse generation. Runtime validation always checks actual backend availability. No host availability flag is serialized into the plan.

The backend currently requires POSIX facilities, tested on Linux and macOS. Unavailable deployment hosts fail at server startup before serving requests. Output writing independently retains its existing filesystem-capability and exclusive-directory checks; host-independent artifact bytes do not promise that all host filesystems support safe writing. Python support remains 3.11–3.14.

Startup and invocation

GovernedRuntime checks the transport manifest, bridge version/hash, backend, policy digest, plan digests, artifact presence/hashes and source/IR/readiness/ interface linkage. Paths cannot escape the bundle root. It does not import user source. REST routes and MCP Tools use the existing shared contracts.

Startup retains the transport manifest digest as an in-memory anchor. Every call revalidates the bound artifacts before launching a worker, so source, policy, plan, worker or manifest modifications become a sanitized call failure while the server stays alive. Restoring the original bytes allows subsequent calls again. The worker rechecks exact executable content and callable shape before invocation. A bundled notebook retains its original bytes and executes its bound transformed Python. Only the worker crosses the trusted source-import boundary.

These are content/integrity checks, not protection against an attacker who controls the bootstrap, interpreter or all initial artifacts. Runtime code must be trusted before it can validate data. The operating system and installed dependencies remain trusted, and no authenticity guarantee is claimed.

Supervision runs in a transport thread to keep its event loop responsive; user code runs in its fresh process. There is no worker pool. Ordinary process-group children are terminated during cleanup; deliberately detached descendants remain outside the supported controls. Module/global/default state does not survive calls.

Transport mappings

Execution outcome REST MCP Tool result
success 200 with finite JSON value Normal structured result
invalid_input 422, Invalid request arguments Invalid tool arguments
timeout 504, Execution timed out Tool execution timed out
Every other execution failure 500, Internal server error Tool execution failed

All worker/binding/policy/result/output/integrity failures use this consistent server-error rule; no internal worker status, traceback, stderr or private path is forwarded. Invalid REST JSON also returns generic 422. Unknown MCP Tool names keep Unknown tool. MCP SDK v2, protocol 2026-07-28, stdio and Streamable HTTP remain supported; the executor has no MCP-specific semantics.

Request binding preserves positional-only/keyword-only arguments, omitted defaults and explicit-null distinctions. Return annotations remain non-enforcing. Governed REST deliberately accepts only finite JSON-compatible results; direct REST's FastAPI encoder can serialize additional Python objects. Governed mode does not coerce those objects. Source exceptions, including intentional framework HTTP exceptions, cross the sanitized execution boundary rather than retaining direct REST's special HTTPException behavior. Direct mode is unchanged.

State, environment and limits

Behavior Direct (default) Governed (opt-in)
Source import Server startup Fresh worker per call
Globals / mutable defaults Persist in server Reset each call
Timeout boundary Existing in-process behavior OS process termination
Input/output protocol limits Existing transport behavior Execution policy limits
Source environment Server environment Clean/allowlisted worker environment
File/network access Host access Host access; no filesystem/network sandbox

The server may inherit its environment normally; the worker receives only the policy-selected names unless full inheritance is explicitly requested. Values are never inserted into artifacts or failure diagnostics. Trusted code can deliberately return values it can access; this is not a secret-filtering service.

Input/output limits bound the worker protocol, not the web server's HTTP body buffering or total process memory. A fresh CWD is not filesystem isolation. There are no memory cgroups, OCI/Docker execution, namespaces, seccomp, privilege/mount restrictions, subprocess isolation or detached-descendant containment.

Verification and deferred work

Direct artifact hashes are pinned to the pre-integration baselines. Governed manifest goldens run on Python 3.11–3.14 and bind all emitted file hashes. Bounded Hypothesis tests exercise determinism, argument parity, allowlists, source mutation and output boundaries. A common conformance corpus runs through direct/governed REST/MCP and explicit execution. Real REST, MCP stdio and MCP HTTP tests exercise hangs, crashes, sanitization and tampering, then call a healthy capability again. Audit hooks in real transport processes reject any target-source execution there. Strict Pyright and a separate branch-aware 90% integration floor are required, alongside all existing quality/security/coverage gates.

Issue #44 is the opt-in transport integration addressed here. Issue #45 remains open for genuine stronger host and detached-descendant containment.

An independent v2 OCI transport bridge is now available through explicit v2 policy/image options. This page and existing v1 bundles retain their local-process semantics.