docs(website): sync dev docs from a3ed8c79cf
@@ -1,8 +1,8 @@
|
||||
snapshots:
|
||||
dev:
|
||||
source-ref: 2f1ea658fe9c2a2f7ea453b55759af6d6da181d2
|
||||
source-sha: 2f1ea658fe9c2a2f7ea453b55759af6d6da181d2
|
||||
version: 0.1.2.dev1
|
||||
source-ref: a3ed8c79cfa162f1f490bc0dea1cb4191e8b83d9
|
||||
source-sha: a3ed8c79cfa162f1f490bc0dea1cb4191e8b83d9
|
||||
version: 0.1.2.dev2
|
||||
latest:
|
||||
source-ref: 4ce767fc0cadad773c398e15109c0286f4b7aa30
|
||||
source-sha: 4ce767fc0cadad773c398e15109c0286f4b7aa30
|
||||
|
||||
@@ -10,122 +10,103 @@ position: 2
|
||||
|
||||

|
||||
|
||||
OpenShell separates control-plane state from sandbox enforcement. The gateway
|
||||
owns sandbox state, policy, providers, and access, and uses formal verification
|
||||
to evaluate proposed policy changes before they are approved. A compute driver
|
||||
provisions the workload and its isolation boundary.
|
||||
OpenShell governs what agents can do in two ways: it instruments the kernel to enforce policy on every file access, system call, and network connection at runtime, and it uses formal verification to check what a policy change would allow before it is applied.
|
||||
|
||||
The trusted supervisor runs outside the workload. `openshell-sandbox` runs
|
||||
inside it, owns the agent process, and mediates its network requests. All other
|
||||
workload egress is denied. The supervisor initiates one connection to the
|
||||
gateway for configuration, credentials, logs, and interactive sessions.
|
||||
- **Kernel-level enforcement.** Each agent runs in an isolated sandbox. Kernel controls confine which files it can access and which system calls it can make, and every network connection passes through a policy check before it leaves the sandbox. Agents never see real credentials; OpenShell adds them only to requests bound for approved endpoints.
|
||||
- **Formally verified policy changes.** Before a policy change is approved, OpenShell uses formal verification to flag risky new access it would grant, such as reaching a new host with credentials or calling a new API method, so those changes wait for human review.
|
||||
|
||||
The **gateway** is the control plane: it manages the lifecycle of sandboxes and
|
||||
provides connectivity and management of sandboxes to end users and operators.
|
||||
When you create a sandbox, its **compute driver** provisions a **workload** and
|
||||
a separate **supervisor**, establishes their protected channel, and builds the
|
||||
isolation boundary; the **supervisor** confirms that boundary before starting the
|
||||
**agent** and then connects back to the gateway for policy, credentials, logs,
|
||||
and interactive sessions.
|
||||
|
||||
## What Each Piece Does
|
||||
|
||||
| Component | What it does |
|
||||
|---|---|
|
||||
| [Gateway](/how-it-works/gateways/overview) | Checks who you are and remembers everything about your sandboxes. It delivers policy and settings, attaches providers, decides who can do what, and coordinates connections into sandboxes. |
|
||||
| [Compute runtime](/how-it-works/sandboxes/runtimes) | Creates the sandbox, starts the supervisor and the workload, sets up the private channel between them, and builds the network fence. It reports status back and cleans up when the sandbox goes away. |
|
||||
| [Supervisor](#inside-the-sandbox-boundary) | Lives on the trusted side of the boundary. It checks requests against policy, supplies credentials, resolves DNS, opens approved connections, and keeps the link to the gateway alive. It works with every runtime through one [isolation backend](/extensibility/isolation-backends) interface to confirm the boundary, start the agent, run commands, forward connections, and see network requests. |
|
||||
| [OpenShell Sandbox](#inside-the-sandbox-boundary) | Lives inside the boundary with the agent. It owns the agent's processes, knows which program made each request, applies process controls, and forwards TCP and DNS traffic to the supervisor. |
|
||||
| [Outer network fence](/security/best-practices#deny-by-default-egress) | Denies all network egress from the workload except its protected connection to the supervisor. Each runtime builds this with its own native tools. |
|
||||
| [Policy prover](/how-it-works/policies/prover) | Runs in the gateway and uses formal verification to check each proposed policy change before approval. It flags changes such as new credentialed reach, new HTTP methods, or access to cloud metadata endpoints, and any finding blocks auto-approval. It also ships as the standalone `openshell-prover` command for checking a policy against a boundary in CI. |
|
||||
| [**Sandbox**](#inside-the-sandbox-boundary) | Lives inside the boundary with the agent. It owns the agent's processes, knows which program made each request, applies process controls, and forwards TCP and DNS traffic to the **supervisor**. |
|
||||
| [Outer network fence](/security/best-practices#deny-by-default-egress) | Denies all network egress from the workload except its protected connection to the **supervisor**. Each runtime builds this with its own native tools. |
|
||||
| [**Supervisor**](#inside-the-sandbox-boundary) | Lives on the trusted side of the boundary. It checks requests against policy, supplies credentials, resolves DNS, opens approved connections, and keeps the link to the gateway alive. It works with every runtime through one [isolation backend](/extensibility/isolation-backends) interface to confirm the boundary, start the agent, run commands, forward connections, and see network requests. |
|
||||
| [Policies](/how-it-works/policies/overview) | Describe what the agent can touch: files, processes, network destinations, API calls, and where provider credentials can go. |
|
||||
| [Providers](/how-it-works/providers/overview) | Connect a service name to a stored credential. The supervisor hands that credential out only where policy allows it. |
|
||||
| [Providers](/how-it-works/providers/overview) | Connect a service name to a stored credential. The **supervisor** hands that credential out only where policy allows it. |
|
||||
| [Policy prover](/how-it-works/policies/prover) | Runs in the gateway and uses formal verification to check agent-proposed network rules. It flags changes such as new credentialed reach, new HTTP methods, or access to cloud metadata endpoints; any finding blocks auto-approval. It also ships as the standalone `openshell-prover` command for checking a policy against a boundary in CI. |
|
||||
| [Gateway](/how-it-works/gateways/overview) | Checks who you are and remembers everything about your sandboxes. It delivers policy and settings, attaches providers, decides who can do what, and coordinates connections into sandboxes. |
|
||||
| [Compute runtime](/how-it-works/sandboxes/runtimes) | Creates the sandbox, starts the **supervisor** and the workload, sets up the private channel between them, and builds the network fence. It reports status back and cleans up when the sandbox goes away. |
|
||||
|
||||
## Inside the Sandbox Boundary
|
||||
|
||||
The supervisor and `openshell-sandbox` sit on opposite sides of the boundary.
|
||||
The supervisor is trusted and makes the decisions. `openshell-sandbox` shares
|
||||
The **supervisor** and **sandbox** sit on opposite sides of the boundary.
|
||||
The **supervisor** is trusted and makes the decisions. The **sandbox** shares
|
||||
the boundary with the untrusted agent, so it never makes policy decisions. It
|
||||
reports what the agent is trying to do and lets the supervisor decide.
|
||||
reports what the agent is trying to do and lets the **supervisor** decide.
|
||||
|
||||
`openshell-sandbox` launches the agent as an owned child and provides exec,
|
||||
The **sandbox** launches the agent as an owned child and provides exec,
|
||||
terminal streams, signals, process status, and loopback forwarding. In the
|
||||
current Linux backend, the workload uses one non-root identity and no Linux
|
||||
capabilities. Landlock limits filesystem access; seccomp user notification
|
||||
stages network operations. The sandbox identifies the calling executable from
|
||||
stages network operations. The **sandbox** identifies the calling executable from
|
||||
trusted process observations.
|
||||
|
||||

|
||||
|
||||
### The protected channel
|
||||
### Mediated Channel
|
||||
|
||||
The supervisor and `openshell-sandbox` talk over the OpenShell Sandbox Protocol:
|
||||
The **supervisor** and **sandbox** talk over the OpenShell Sandbox Protocol:
|
||||
one mutually authenticated HTTP/2 connection that carries many independent
|
||||
streams. The compute driver picks the transport: a Unix socket for Docker and
|
||||
Podman, TCP for Kubernetes, or vsock for MicroVM. Authentication and protocol
|
||||
behavior are the same on all of them. The supervisor presents a
|
||||
behavior are the same on all of them. The **supervisor** presents a
|
||||
sandbox-specific credential, as described in
|
||||
[How Components Authenticate](#how-components-authenticate).
|
||||
|
||||

|
||||

|
||||
|
||||
Each TCP connection gets its own stream with its own backpressure, so a slow
|
||||
download can't block DNS, exec, or process control.
|
||||
|
||||
| Guarantee | How `openshell-sandbox` provides it | What the supervisor gets |
|
||||
| Guarantee | How the **sandbox** provides it | What the **supervisor** gets |
|
||||
|---|---|---|
|
||||
| Process ownership | Runs the agent as an owned child and keeps its process and terminal state. | Handles to wait on, attach to, signal, exec in, and stop the agent. |
|
||||
| Program identity | Identifies the calling program from trusted `/proc` data. | The real program behind each request, not a path the agent claims. |
|
||||
| Network mediation | Intercepts TCP opens and DNS queries with seccomp and hands them over. | Requests that wait for a policy decision before going anywhere. |
|
||||
| Fail closed | Holds launch until the supervisor confirms, and freezes the agent if the connection drops. | A short window to reconnect, or a stopped workload. |
|
||||
| Fail closed | Holds launch until the **supervisor** confirms, and freezes the agent if the connection drops. | A short window to reconnect, or a stopped workload. |
|
||||
|
||||
Together these mean the agent can't run before its controls are confirmed,
|
||||
signals and exec reach only this sandbox's processes, and the agent can't get
|
||||
around TCP or DNS mediation.
|
||||
|
||||
### Starting an agent safely
|
||||
|
||||
The supervisor's `OpenShellRuntimeBackend` implements the shared
|
||||
[Isolation Backend](/extensibility/isolation-backends) interface using the
|
||||
Sandbox Protocol. Before the agent runs, it walks through a fixed series of
|
||||
steps:
|
||||
|
||||
```text
|
||||
Attach → Bound → Confirmed → Ready → Running
|
||||
```
|
||||
|
||||
The compute driver supplies the transport and a runtime descriptor. The backend
|
||||
binds that descriptor to the admitted sandbox during attach, then confirms the
|
||||
workload identity, launch controls, and outer network fence before starting the
|
||||
agent. Each step must succeed before the next one begins. A stale or mismatched
|
||||
boundary cannot launch the workload.
|
||||
|
||||
### How a network request travels
|
||||
|
||||
Say the agent tries to call an API. Here's what happens, and it works the same
|
||||
way on every runtime:
|
||||
|
||||
1. The agent opens a TCP connection or makes a DNS lookup.
|
||||
2. `openshell-sandbox` notes which program made the request.
|
||||
3. The request travels over the Sandbox Protocol to the supervisor.
|
||||
4. The supervisor checks the request against policy and adds any credentials the
|
||||
policy allows.
|
||||
5. If the request is allowed, the supervisor opens the real connection and
|
||||
relays the traffic.
|
||||
2. The **sandbox** identifies the calling program.
|
||||
3. The request travels over the Sandbox Protocol to the **supervisor**.
|
||||
4. The **supervisor** checks it against policy and adds any credentials policy
|
||||
allows.
|
||||
5. If allowed, the **supervisor** opens the real connection and relays traffic.
|
||||
|
||||
The protected channel to the supervisor is the only network path allowed out of
|
||||
the workload boundary. The outer fence denies all other network egress. The
|
||||
agent cannot reach an external service, the gateway, DNS, or another private
|
||||
address directly.
|
||||
The mediated channel to the **supervisor** is the workload's only allowed egress
|
||||
path. The outer fence denies everything else, so the agent can't reach a
|
||||
service, the gateway, DNS, or another private address directly.
|
||||
|
||||
## How Each Runtime Builds the Boundary
|
||||
|
||||
Every runtime follows the same contract, but each one uses the tools it already
|
||||
has to place the supervisor, connect it to the sandbox, and fence off the
|
||||
has to place the **supervisor**, connect it to the **sandbox**, and fence off the
|
||||
network.
|
||||
|
||||
| Runtime | Where the supervisor runs | How it talks to the sandbox | How direct egress is blocked |
|
||||
| Runtime | Where the **supervisor** runs | How it talks to the **sandbox** | How direct egress is blocked |
|
||||
|---|---|---|---|
|
||||
| Docker | Its own container | Authenticated Unix socket on a driver-owned volume | Workload container has networking turned off |
|
||||
| Podman | Its own container | Authenticated Unix socket on a driver-owned volume | Workload container has networking turned off |
|
||||
| Kubernetes | Its own pod | Private service with mutual TLS | NetworkPolicy allows only the supervisor service |
|
||||
| Kubernetes | Its own pod | Private service with mutual TLS | NetworkPolicy allows only the **supervisor** service |
|
||||
| VM | A process on the host | Authenticated vsock | Guest has no network device |
|
||||
|
||||
The runtime's job is to build the boundary and prove it's in place. It never
|
||||
decides whether a request is allowed. That decision always belongs to the shared
|
||||
supervisor and policy engine, which is why the same policy behaves the same way
|
||||
**supervisor** and policy engine, which is why the same policy behaves the same way
|
||||
everywhere.
|
||||
|
||||
Runtimes can differ in how they report readiness and which features they
|
||||
@@ -137,38 +118,38 @@ do.
|
||||
Three connections tie a sandbox together. The gateway is the only component
|
||||
that signs credentials, and every credential names exactly one sandbox.
|
||||
|
||||

|
||||

|
||||
|
||||
| Connection | Who connects | How it's protected |
|
||||
|---|---|---|
|
||||
| Supervisor to gateway | The supervisor dials out to the gateway. | A gateway JWT, over TLS when the gateway has TLS enabled. |
|
||||
| Supervisor to `openshell-sandbox` | The supervisor dials into the workload over the driver's private channel. | Mutual TLS, plus a sandbox JWT. |
|
||||
| Agent to supervisor | The agent never connects directly. `openshell-sandbox` relays its traffic over the connection above. | Covered by the supervisor-to-sandbox channel. |
|
||||
| **Supervisor** to gateway | The **supervisor** dials out to the gateway. | A gateway JWT, over TLS when the gateway has TLS enabled. |
|
||||
| **Supervisor** to **sandbox** | The **supervisor** dials into the workload over the driver's private channel. | Mutual TLS, plus a sandbox JWT. |
|
||||
| Agent to **supervisor** | The agent never connects directly. The **sandbox** relays its traffic over the connection above. | Covered by the supervisor-to-sandbox channel. |
|
||||
|
||||
### Getting the first credential
|
||||
|
||||
The supervisor needs a starting credential to prove which sandbox it belongs
|
||||
The **supervisor** needs a starting credential to prove which sandbox it belongs
|
||||
to. How it gets one depends on the runtime:
|
||||
|
||||
- **Docker, Podman, and MicroVM.** The driver hands the supervisor its initial
|
||||
tokens directly, in files only the supervisor can read.
|
||||
- **Kubernetes.** The supervisor presents its pod's ServiceAccount token. The
|
||||
- **Docker, Podman, and MicroVM.** The driver hands the **supervisor** its initial
|
||||
tokens directly, in files only the **supervisor** can read.
|
||||
- **Kubernetes.** The **supervisor** presents its pod's ServiceAccount token. The
|
||||
gateway asks the Kubernetes driver to verify the token and confirm that the
|
||||
pod belongs to the expected sandbox before it issues any JWTs.
|
||||
|
||||
Either way, the gateway checks the claim against its own record of the sandbox
|
||||
before returning credentials.
|
||||
|
||||
### Two JWTs, two jobs
|
||||
### Gateway and Sandbox JWTs
|
||||
|
||||
The gateway issues a pair of JWTs for each run of a sandbox:
|
||||
|
||||
- **Gateway JWT.** Sent with every supervisor call to the gateway. It allows
|
||||
only the calls a supervisor needs, such as fetching policy, pushing logs, and
|
||||
- **Gateway JWT.** Sent with every **supervisor** call to the gateway. It allows
|
||||
only the calls a **supervisor** needs, such as fetching policy, pushing logs, and
|
||||
relaying sessions. It is not a user credential and can't manage other
|
||||
sandboxes.
|
||||
- **Sandbox JWT.** Sent with every supervisor call to `openshell-sandbox`.
|
||||
`openshell-sandbox` holds only the gateway's public key, so it can verify the
|
||||
- **Sandbox JWT.** Sent with every **supervisor** call to the **sandbox**.
|
||||
The **sandbox** holds only the gateway's public key, so it can verify the
|
||||
token but can never create one.
|
||||
|
||||
Each token works only on its own connection. Both are bound to one sandbox and
|
||||
@@ -178,9 +159,9 @@ working.
|
||||
|
||||
### Renewing and revoking
|
||||
|
||||
The supervisor keeps its tokens in memory and renews both together before they
|
||||
The **supervisor** keeps its tokens in memory and renews both together before they
|
||||
expire. Renewal works only while the sandbox still exists, so deleting a
|
||||
sandbox cuts off its supervisor.
|
||||
sandbox cuts off its **supervisor**.
|
||||
|
||||
Shared deployments, such as Kubernetes, should set `gateway_jwt.ttl_secs` so
|
||||
tokens expire. Local single-user gateways can leave it unset, which issues
|
||||
@@ -188,20 +169,20 @@ tokens that last for the life of the sandbox run.
|
||||
|
||||
### What the agent can see
|
||||
|
||||
The agent shares its side of the boundary with `openshell-sandbox`, so
|
||||
`openshell-sandbox` holds nothing worth stealing: no gateway signing key, no
|
||||
The agent shares its side of the boundary with the **sandbox**, so
|
||||
the **sandbox** holds nothing worth stealing: no gateway signing key, no
|
||||
gateway JWT, and no provider credentials. It can verify that it's talking to
|
||||
the right supervisor, but it can't impersonate one.
|
||||
the right **supervisor**, but it can't impersonate one.
|
||||
|
||||
If the supervisor disconnects, `openshell-sandbox` freezes the agent. Only the
|
||||
same supervisor process can reconnect and resume it. A new supervisor can't
|
||||
If the **supervisor** disconnects, the **sandbox** freezes the agent. Only the
|
||||
same **supervisor** process can reconnect and resume it. A new **supervisor** can't
|
||||
take over a running sandbox, even with valid credentials.
|
||||
|
||||
## Working With Your Existing Infrastructure
|
||||
|
||||
OpenShell plugs into the tools you already use, including container runtimes,
|
||||
schedulers, secret stores, identity providers, image pipelines, storage, and
|
||||
device plugins. The gateway and supervisor define how OpenShell behaves.
|
||||
device plugins. The gateway and **supervisor** define how OpenShell behaves.
|
||||
Drivers translate that behavior into whatever your platform understands and
|
||||
report back what happened. This keeps platform-specific details out of the core
|
||||
control plane and the policy model.
|
||||
|
||||
@@ -97,7 +97,7 @@ phases = ["validate"]
|
||||
|
||||
The gateway supports `http://`, `https://`, and `unix://` interceptor endpoints. When gateway JWT signing is configured, authenticated network interceptors use `https://`; Unix sockets remain available for local integrations. HTTPS uses platform trust roots unless `tls_ca_cert_path` supplies a private CA, and normal hostname verification remains enabled. The gateway calls `Describe` and builds an immutable execution plan during startup. An unavailable service, invalid manifest, missing credential, or unauthorized configured binding prevents the gateway from starting.
|
||||
|
||||
When gateway JWT signing is configured, the gateway authenticates every call to the interceptor with a short-lived token. [Extension Authentication](/extensibility/overview#authentication) describes how your service validates it. Set `allow_insecure_transport = true` to use a plaintext `http://` endpoint without authentication, for local development or on a network that already authenticates callers.
|
||||
When gateway JWT signing is configured, the gateway authenticates every call to the interceptor with a short-lived token. [Authenticating Extensions](/extensibility/overview#authenticating-extensions) describes how your service validates it. Set `allow_insecure_transport = true` to use a plaintext `http://` endpoint without authentication, for local development or on a network that already authenticates callers.
|
||||
|
||||
Registration is static. Restart the gateway after adding, removing, or changing an interceptor. See [Gateway Configuration](/how-it-works/gateways/configuration#gateway-interceptors) for the complete field reference.
|
||||
|
||||
|
||||
@@ -8,13 +8,21 @@ description: "Understand how OpenShell adapts to deployment-specific infrastruct
|
||||
keywords: "OpenShell Extensions, Middleware, Interceptors, Drivers, Isolation Backends, Protocol Negotiation"
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Extensibility sits at the core of OpenShell. OpenShell is designed to run
|
||||
everywhere and adapt to the infrastructure, governance, and workload
|
||||
requirements of each deployment. Its extension points add deployment-specific
|
||||
behavior while preserving the same API, policy model, and security boundaries.
|
||||
|
||||
You can extend each layer of OpenShell:
|
||||
|
||||
- **Control plane:** Gateway interceptors govern API operations.
|
||||
- **Data plane:** Middleware processes agent traffic, and isolation backends
|
||||
control the sandboxed workload.
|
||||
- **Infrastructure:** Drivers connect OpenShell to compute runtimes and secret
|
||||
stores.
|
||||
|
||||
## Extension Points
|
||||
|
||||
### [Middleware](/extensibility/supervisor-middleware)
|
||||
@@ -42,7 +50,63 @@ Isolation backends connect the supervisor to the sandbox runtime. They provide
|
||||
a consistent contract for process launch, terminal streams, signals, status,
|
||||
and runtime-specific isolation inside the provisioned workload.
|
||||
|
||||
## Authentication
|
||||
## Building Extensions
|
||||
|
||||
Start with the narrowest extension point that owns the behavior you need. Keep
|
||||
control-plane governance in an interceptor, infrastructure integration in a
|
||||
driver, application traffic processing in middleware, and workload control in
|
||||
an isolation backend. Each extension uses a typed contract so OpenShell keeps
|
||||
ownership of authentication, policy enforcement, secrets, and public API
|
||||
behavior.
|
||||
|
||||
Built-in and external implementations follow the same contracts and validation
|
||||
rules. The extension-specific pages describe their APIs, configuration, and
|
||||
security boundaries.
|
||||
|
||||
### gRPC and Transports
|
||||
|
||||
External extensions implement protobuf-defined gRPC services. The transport
|
||||
depends on where the extension runs and which OpenShell components must reach
|
||||
it:
|
||||
|
||||
| Extension | Integration | Supported transport |
|
||||
| --- | --- | --- |
|
||||
| Gateway interceptor | The gateway calls the interceptor service. | TCP with `http://` or `https://`, or a local Unix domain socket with `unix://`. |
|
||||
| Supervisor middleware | The gateway discovers the service, and sandbox supervisors evaluate traffic through it. | TCP with `http://` or `https://`. The endpoint must be reachable from both the gateway and supervisors, so Unix sockets are not supported. |
|
||||
| Compute or credential driver | The gateway calls an external driver service. | A local Unix domain socket. |
|
||||
| OpenShell isolation backend | The supervisor connects to the sandbox boundary through the OpenShell Sandbox Protocol. | A private Unix socket, TLS over TCP, or virtio-vsock selected and provisioned by the compute driver. |
|
||||
|
||||
Use Unix domain sockets when the gateway and extension share a host. Use
|
||||
`https://` when a service crosses a host or pod boundary. Plaintext `http://`
|
||||
is intended for explicitly enabled development deployments; authenticated
|
||||
network extensions use TLS and short-lived gateway-issued credentials. Refer
|
||||
to [Authenticating Extensions](#authenticating-extensions) for how services validate those credentials.
|
||||
|
||||
The [governance interceptor example](https://github.com/NVIDIA/OpenShell/tree/main/examples/governance-interceptor)
|
||||
and [content guard middleware example](https://github.com/NVIDIA/OpenShell/tree/main/examples/supervisor-middleware-content-guard)
|
||||
include complete gRPC services, gateway configuration, and smoke tests. For
|
||||
runtime integrations, refer to the first-party
|
||||
[Docker compute driver](https://github.com/NVIDIA/OpenShell/tree/main/crates/openshell-driver-docker)
|
||||
and [VM compute driver](https://github.com/NVIDIA/OpenShell/tree/main/crates/openshell-driver-vm).
|
||||
|
||||
### Protocol Negotiation
|
||||
|
||||
Before OpenShell uses a compute driver, credential driver, gateway interceptor,
|
||||
or supervisor middleware service, both peers exchange
|
||||
`openshell.extension.v1.PeerMetadata`. The metadata identifies the protocol and
|
||||
implementation versions, supported capabilities, and capabilities required
|
||||
from the other peer. Family-specific features remain in their typed protocols.
|
||||
|
||||
OpenShell accepts compatible minor versions when both capability requirements
|
||||
are satisfied. It rejects different major versions, missing metadata, or an
|
||||
unmet required capability during startup. Built-in and external service
|
||||
extensions follow the same compatibility checks.
|
||||
|
||||
Use `openshell gateway info` to inspect the negotiated extension families,
|
||||
implementation versions, protocol versions, and capabilities active on a
|
||||
gateway.
|
||||
|
||||
## Authenticating Extensions
|
||||
|
||||
When the gateway has JWT signing configured, OpenShell sends a short-lived bearer token with every call to a [gateway interceptor](/extensibility/gateway-interceptors) or [supervisor middleware](/extensibility/supervisor-middleware) service. Validate it to confirm the call comes from your gateway or one of its sandboxes.
|
||||
|
||||
@@ -81,59 +145,3 @@ Set `allow_insecure_transport = true` on a registration to use a plaintext `http
|
||||
- Tokens are bearer credentials: a captured token works until it expires.
|
||||
- Extension tokens share the gateway's signing key, so you can't rotate or revoke them separately.
|
||||
- mTLS client authentication and overlapping key rotation aren't available.
|
||||
|
||||
## Building Extensions
|
||||
|
||||
Start with the narrowest extension point that owns the behavior you need. Keep
|
||||
control-plane governance in an interceptor, infrastructure integration in a
|
||||
driver, application traffic processing in middleware, and workload control in
|
||||
an isolation backend. Each extension uses a typed contract so OpenShell keeps
|
||||
ownership of authentication, policy enforcement, secrets, and public API
|
||||
behavior.
|
||||
|
||||
Built-in and external implementations follow the same contracts and validation
|
||||
rules. The extension-specific pages describe their APIs, configuration, and
|
||||
security boundaries.
|
||||
|
||||
### gRPC and Transports
|
||||
|
||||
External extensions implement protobuf-defined gRPC services. The transport
|
||||
depends on where the extension runs and which OpenShell components must reach
|
||||
it:
|
||||
|
||||
| Extension | Integration | Supported transport |
|
||||
| --- | --- | --- |
|
||||
| Gateway interceptor | The gateway calls the interceptor service. | TCP with `http://` or `https://`, or a local Unix domain socket with `unix://`. |
|
||||
| Supervisor middleware | The gateway discovers the service, and sandbox supervisors evaluate traffic through it. | TCP with `http://` or `https://`. The endpoint must be reachable from both the gateway and supervisors, so Unix sockets are not supported. |
|
||||
| Compute or credential driver | The gateway calls an external driver service. | A local Unix domain socket. |
|
||||
| OpenShell isolation backend | The supervisor connects to the sandbox boundary through the OpenShell Sandbox Protocol. | A private Unix socket, TLS over TCP, or virtio-vsock selected and provisioned by the compute driver. |
|
||||
|
||||
Use Unix domain sockets when the gateway and extension share a host. Use
|
||||
`https://` when a service crosses a host or pod boundary. Plaintext `http://`
|
||||
is intended for explicitly enabled development deployments; authenticated
|
||||
network extensions use TLS and short-lived gateway-issued credentials. Refer
|
||||
to [Authentication](#authentication) for how services validate those credentials.
|
||||
|
||||
The [governance interceptor example](https://github.com/NVIDIA/OpenShell/tree/main/examples/governance-interceptor)
|
||||
and [content guard middleware example](https://github.com/NVIDIA/OpenShell/tree/main/examples/supervisor-middleware-content-guard)
|
||||
include complete gRPC services, gateway configuration, and smoke tests. For
|
||||
runtime integrations, refer to the first-party
|
||||
[Docker compute driver](https://github.com/NVIDIA/OpenShell/tree/main/crates/openshell-driver-docker)
|
||||
and [VM compute driver](https://github.com/NVIDIA/OpenShell/tree/main/crates/openshell-driver-vm).
|
||||
|
||||
### Protocol Negotiation
|
||||
|
||||
Before OpenShell uses a compute driver, credential driver, gateway interceptor,
|
||||
or supervisor middleware service, both peers exchange
|
||||
`openshell.extension.v1.PeerMetadata`. The metadata identifies the protocol and
|
||||
implementation versions, supported capabilities, and capabilities required
|
||||
from the other peer. Family-specific features remain in their typed protocols.
|
||||
|
||||
OpenShell accepts compatible minor versions when both capability requirements
|
||||
are satisfied. It rejects different major versions, missing metadata, or an
|
||||
unmet required capability during startup. Built-in and external service
|
||||
extensions follow the same compatibility checks.
|
||||
|
||||
Use `openshell gateway info` to inspect the negotiated extension families,
|
||||
implementation versions, protocol versions, and capabilities active on a
|
||||
gateway.
|
||||
|
||||
@@ -53,7 +53,7 @@ timeout = "500ms"
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="audience" type="string" default="urn:openshell:extension:middleware:<name>">
|
||||
Token audience. Refer to [Extension Authentication](/extensibility/overview#authentication).
|
||||
Token audience. Refer to [Authenticating Extensions](/extensibility/overview#authenticating-extensions).
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="allow_insecure_transport" type="boolean" default="false">
|
||||
@@ -62,7 +62,7 @@ timeout = "500ms"
|
||||
|
||||
At startup, the gateway contacts every registered service to read its capabilities and verify [protocol compatibility](/extensibility/overview#protocol-negotiation). The gateway does not start if a service is unavailable or incompatible. [Gateway Configuration](/how-it-works/gateways/configuration#supervisor-middleware-services) describes the full TOML context.
|
||||
|
||||
When the gateway has JWT signing configured, OpenShell authenticates every call to your service with a short-lived token. [Extension Authentication](/extensibility/overview#authentication) describes how your service validates it.
|
||||
When the gateway has JWT signing configured, OpenShell authenticates every call to your service with a short-lived token. [Authenticating Extensions](/extensibility/overview#authenticating-extensions) describes how your service validates it.
|
||||
|
||||
## Attach Middleware in Policy
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ These guides cover the rest of the service contract:
|
||||
When OpenShell calls your service, what it receives, and what it can return for HTTP requests, HTTP responses, and WebSocket messages.
|
||||
</Card>
|
||||
|
||||
<Card title="Extension Authentication" href="/extensibility/overview#authentication">
|
||||
<Card title="Authenticating Extensions" href="/extensibility/overview#authenticating-extensions">
|
||||
|
||||
How to verify that calls to your service come from your OpenShell gateway.
|
||||
</Card>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -->
|
||||
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="920" viewBox="0 0 1440 920" role="img" aria-labelledby="title desc">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1220" height="395" viewBox="0 0 1220 395" role="img" aria-labelledby="title desc">
|
||||
<title id="title">OpenShell extension points</title>
|
||||
<desc id="desc">Gateway interceptors and drivers extend the control plane. Middleware and isolation backends extend the OpenShell runtime. Middleware connects approved traffic to external services, while the compute driver provisions the sandbox boundary.</desc>
|
||||
<desc id="desc">Two rows read left to right. Data plane: the sandboxed agent reaches the supervisor through the isolation backend, and supervisor middleware processes requests before they reach models and APIs. Control plane: you reach the gateway through interceptors, and gateway drivers connect it to runtimes and secret stores.</desc>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#334155"/>
|
||||
@@ -16,101 +16,60 @@
|
||||
.label { font: 700 18px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
||||
.small { font: 500 14px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #475569; }
|
||||
.tag { font: 700 12px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #579000; letter-spacing: .06em; }
|
||||
.tiny { font: 700 12px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #475569; }
|
||||
.panel { fill: #f8fafc; stroke: #cbd5e1; stroke-width: 2; }
|
||||
.box { fill: #ffffff; stroke: #cbd5e1; stroke-width: 2; }
|
||||
.trusted { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.extension { fill: #f2f9e8; stroke: #76b900; stroke-width: 2.5; }
|
||||
.dark { fill: #1f2937; stroke: #111827; stroke-width: 2; }
|
||||
.line { fill: none; stroke: #334155; stroke-width: 2.5; marker-end: url(#arrow); }
|
||||
.provision { fill: none; stroke: #334155; stroke-width: 2.5; stroke-dasharray: 8 7; marker-end: url(#arrow); }
|
||||
.flow { fill: none; stroke: #579000; stroke-width: 3; marker-end: url(#arrow-green); }
|
||||
</style>
|
||||
</defs>
|
||||
|
||||
<rect width="1440" height="920" rx="20" fill="#ffffff"/>
|
||||
<rect width="1220" height="395" rx="20" fill="#ffffff"/>
|
||||
|
||||
<text x="35" y="50" class="section">GATEWAY (CONTROL PLANE)</text>
|
||||
<text x="1115" y="50" class="section">EXTERNAL SERVICES</text>
|
||||
<text x="785" y="240" class="section">OPENSHELL RUNTIME (DATA PLANE)</text>
|
||||
<text x="30" y="41" class="section">DATA PLANE</text>
|
||||
<rect x="30" y="70" width="180" height="90" rx="14" class="dark"/>
|
||||
<text x="120.0" y="112" text-anchor="middle" class="label" style="fill:#fff">Agent</text>
|
||||
<text x="120.0" y="136" text-anchor="middle" class="small" style="fill:#d1d5db">sandboxed workload</text>
|
||||
<rect x="250" y="70" width="200" height="90" rx="15" class="extension"/>
|
||||
<text x="350.0" y="96" text-anchor="middle" class="tag">EXTENSION POINT</text>
|
||||
<text x="350.0" y="123" text-anchor="middle" class="label">Isolation backend</text>
|
||||
<text x="350.0" y="145" text-anchor="middle" class="small">launch · exec · mediate</text>
|
||||
<rect x="490" y="55" width="430" height="120" rx="18" class="trusted"/>
|
||||
<text x="510" y="112" class="label">Supervisor</text>
|
||||
<text x="510" y="136" class="small">policy · credentials</text>
|
||||
<rect x="690" y="70" width="210" height="90" rx="15" class="extension"/>
|
||||
<text x="795.0" y="96" text-anchor="middle" class="tag">EXTENSION POINT</text>
|
||||
<text x="795.0" y="123" text-anchor="middle" class="label">Middleware</text>
|
||||
<text x="795.0" y="145" text-anchor="middle" class="small">inspect · transform · deny</text>
|
||||
<rect x="970" y="70" width="220" height="90" rx="14" class="box"/>
|
||||
<text x="1080.0" y="112" text-anchor="middle" class="label">Models, APIs</text>
|
||||
<text x="1080.0" y="136" text-anchor="middle" class="small">external services</text>
|
||||
<path d="M210 115 H248" class="line"/>
|
||||
<path d="M450 115 H488" class="line"/>
|
||||
<path d="M650 115 H688" class="line"/>
|
||||
<path d="M900 115 H968" class="flow"/>
|
||||
|
||||
<g transform="translate(0,40)">
|
||||
|
||||
<!-- Gateway control plane -->
|
||||
<rect x="30" y="30" width="710" height="780" rx="20" class="panel"/>
|
||||
|
||||
<rect x="250" y="105" width="270" height="100" rx="15" class="trusted"/>
|
||||
<text x="385" y="148" text-anchor="middle" class="label">API Server</text>
|
||||
<text x="385" y="177" text-anchor="middle" class="small">auth · state · lifecycle</text>
|
||||
|
||||
<rect x="235" y="270" width="300" height="110" rx="15" class="extension"/>
|
||||
<text x="385" y="300" text-anchor="middle" class="tag">EXTENSION POINT</text>
|
||||
<text x="385" y="332" text-anchor="middle" class="label">Gateway interceptors</text>
|
||||
<text x="385" y="360" text-anchor="middle" class="small">modify · validate · observe</text>
|
||||
|
||||
<rect x="80" y="475" width="270" height="115" rx="15" class="extension"/>
|
||||
<text x="215" y="505" text-anchor="middle" class="tag">EXTENSION POINT</text>
|
||||
<text x="215" y="537" text-anchor="middle" class="label">Credential driver</text>
|
||||
<text x="215" y="565" text-anchor="middle" class="small">stores secret handles</text>
|
||||
|
||||
<rect x="420" y="475" width="270" height="115" rx="15" class="extension"/>
|
||||
<text x="555" y="505" text-anchor="middle" class="tag">EXTENSION POINT</text>
|
||||
<text x="555" y="537" text-anchor="middle" class="label">Compute driver</text>
|
||||
<text x="555" y="565" text-anchor="middle" class="small">places sandboxes</text>
|
||||
|
||||
<rect x="80" y="670" width="270" height="70" rx="14" class="box"/>
|
||||
<text x="215" y="712" text-anchor="middle" class="label">Credential store</text>
|
||||
|
||||
<path d="M385 205 V270" class="line"/>
|
||||
<path d="M385 380 V425 H215 V475" class="line"/>
|
||||
<path d="M385 425 H555 V475" class="line"/>
|
||||
<path d="M215 590 V670" class="line"/>
|
||||
|
||||
<!-- External services -->
|
||||
<rect x="1110" y="30" width="250" height="80" rx="14" class="box"/>
|
||||
<text x="1235" y="64" text-anchor="middle" class="label">Services and models</text>
|
||||
<text x="1235" y="90" text-anchor="middle" class="small">APIs · tools · inference</text>
|
||||
|
||||
<!-- Runtime data plane -->
|
||||
<rect x="780" y="220" width="630" height="590" rx="20" class="panel"/>
|
||||
|
||||
<rect x="820" y="265" width="240" height="120" rx="15" class="trusted"/>
|
||||
<text x="940" y="308" text-anchor="middle" class="label">Supervisor</text>
|
||||
<text x="940" y="337" text-anchor="middle" class="small">policy · credentials</text>
|
||||
<text x="940" y="360" text-anchor="middle" class="small">network mediation</text>
|
||||
|
||||
<rect x="1110" y="265" width="250" height="120" rx="15" class="extension"/>
|
||||
<text x="1235" y="295" text-anchor="middle" class="tag">EXTENSION POINT</text>
|
||||
<text x="1235" y="327" text-anchor="middle" class="label">Middleware</text>
|
||||
<text x="1235" y="355" text-anchor="middle" class="small">inspect · transform · deny</text>
|
||||
|
||||
<rect x="820" y="500" width="240" height="115" rx="15" class="extension"/>
|
||||
<text x="940" y="530" text-anchor="middle" class="tag">EXTENSION POINT</text>
|
||||
<text x="940" y="562" text-anchor="middle" class="label">Isolation backend</text>
|
||||
<text x="940" y="590" text-anchor="middle" class="small">controls the workload</text>
|
||||
|
||||
<rect x="1110" y="475" width="250" height="175" rx="16" fill="#ffffff" stroke="#76b900" stroke-width="2.5" stroke-dasharray="9 7"/>
|
||||
<text x="1235" y="512" text-anchor="middle" class="tag">SANDBOX BOUNDARY</text>
|
||||
<rect x="1140" y="540" width="190" height="78" rx="13" class="dark"/>
|
||||
<text x="1235" y="574" text-anchor="middle" style="font:700 18px -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;fill:#fff">Agent</text>
|
||||
<text x="1235" y="600" text-anchor="middle" style="font:500 13px -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;fill:#d1d5db">workload</text>
|
||||
|
||||
<path d="M1060 325 H1110" class="line"/>
|
||||
<path d="M940 385 V500" class="line"/>
|
||||
<path d="M1060 557 H1110" class="line"/>
|
||||
<path d="M1235 265 V110" class="flow"/>
|
||||
|
||||
<path d="M690 532 H760 V700 H1235 V650" class="provision"/>
|
||||
<text x="795" y="688" class="tiny">PROVISION</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="780" y="835" width="18" height="18" rx="4" class="trusted"/>
|
||||
<text x="810" y="850" class="small">Core component</text>
|
||||
<rect x="960" y="835" width="18" height="18" rx="4" class="extension"/>
|
||||
<text x="990" y="850" class="small">Extension point</text>
|
||||
<rect x="1145" y="835" width="18" height="18" rx="4" class="dark"/>
|
||||
<text x="1175" y="850" class="small">Workload</text>
|
||||
<rect x="1250" y="835" width="18" height="18" rx="4" fill="#ffffff" stroke="#76b900" stroke-width="2" stroke-dasharray="5 4"/>
|
||||
<text x="1280" y="850" class="small">Sandbox boundary</text>
|
||||
</g>
|
||||
<text x="30" y="231" class="section">CONTROL PLANE</text>
|
||||
<rect x="30" y="260" width="180" height="90" rx="14" class="box"/>
|
||||
<text x="120.0" y="302" text-anchor="middle" class="label">You</text>
|
||||
<text x="120.0" y="326" text-anchor="middle" class="small">CLI · SDK · TUI</text>
|
||||
<rect x="250" y="260" width="200" height="90" rx="15" class="extension"/>
|
||||
<text x="350.0" y="286" text-anchor="middle" class="tag">EXTENSION POINT</text>
|
||||
<text x="350.0" y="313" text-anchor="middle" class="label">Interceptors</text>
|
||||
<text x="350.0" y="335" text-anchor="middle" class="small">modify · validate · observe</text>
|
||||
<rect x="490" y="245" width="430" height="120" rx="18" class="trusted"/>
|
||||
<text x="510" y="302" class="label">Gateway</text>
|
||||
<text x="510" y="326" class="small">auth · state · API</text>
|
||||
<rect x="690" y="260" width="210" height="90" rx="15" class="extension"/>
|
||||
<text x="795.0" y="286" text-anchor="middle" class="tag">EXTENSION POINT</text>
|
||||
<text x="795.0" y="313" text-anchor="middle" class="label">Drivers</text>
|
||||
<text x="795.0" y="335" text-anchor="middle" class="small">compute · credentials</text>
|
||||
<rect x="970" y="260" width="220" height="90" rx="14" class="box"/>
|
||||
<text x="1080.0" y="302" text-anchor="middle" class="label">Infrastructure</text>
|
||||
<text x="1080.0" y="326" text-anchor="middle" class="small">runtimes · secret stores</text>
|
||||
<path d="M210 305 H248" class="line"/>
|
||||
<path d="M450 305 H488" class="line"/>
|
||||
<path d="M650 305 H688" class="line"/>
|
||||
<path d="M900 305 H968" class="line"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 5.2 KiB |
@@ -18,6 +18,7 @@
|
||||
.tiny { font: 700 12px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #475569; }
|
||||
.box { fill: #ffffff; stroke: #cbd5e1; stroke-width: 2; }
|
||||
.trusted { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.owned { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.line { fill: none; stroke: #334155; stroke-width: 2.5; marker-end: url(#arrow); }
|
||||
.flow { fill: none; stroke: #579000; stroke-width: 3; marker-start: url(#arrow-green); marker-end: url(#arrow-green); }
|
||||
</style>
|
||||
@@ -52,7 +53,7 @@
|
||||
|
||||
<!-- Sandbox -->
|
||||
<rect x="1010" y="70" width="230" height="160" rx="18" fill="#ffffff" stroke="#76b900" stroke-width="3" stroke-dasharray="10 7"/>
|
||||
<rect x="1030" y="115" width="190" height="90" rx="14" class="box"/>
|
||||
<rect x="1030" y="115" width="190" height="90" rx="14" class="owned"/>
|
||||
<text x="1125" y="155" text-anchor="middle" class="label">openshell-sandbox</text>
|
||||
<text x="1125" y="180" text-anchor="middle" class="small">workload-side server</text>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
@@ -19,6 +19,7 @@
|
||||
.box { fill: #ffffff; stroke: #cbd5e1; stroke-width: 2; }
|
||||
.soft { fill: #f8fafc; stroke: #cbd5e1; stroke-width: 2; }
|
||||
.trusted { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.owned { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.green { fill: #f2f9e8; stroke: #76b900; stroke-width: 2.5; }
|
||||
.dark { fill: #1f2937; stroke: #111827; stroke-width: 2; }
|
||||
.line { fill: none; stroke: #334155; stroke-width: 2.5; marker-end: url(#arrow); }
|
||||
@@ -68,7 +69,7 @@
|
||||
|
||||
<rect x="875" y="330" width="275" height="280" rx="18" fill="#ffffff" stroke="#76b900" stroke-width="3" stroke-dasharray="10 7"/>
|
||||
<text x="900" y="360" class="tiny">WORKLOAD POD</text>
|
||||
<rect x="900" y="385" width="225" height="78" rx="13" class="box"/>
|
||||
<rect x="900" y="385" width="225" height="78" rx="13" class="owned"/>
|
||||
<text x="1012" y="417" text-anchor="middle" class="label">OpenShell Sandbox</text>
|
||||
<text x="1012" y="443" text-anchor="middle" class="small">process and syscall boundary</text>
|
||||
<path d="M1012 463 V493" class="line"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
@@ -20,6 +20,7 @@
|
||||
.soft { fill: #f8fafc; stroke: #cbd5e1; stroke-width: 2; }
|
||||
.green { fill: #f2f9e8; stroke: #76b900; stroke-width: 2.5; }
|
||||
.trusted { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.owned { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.dark { fill: #1f2937; stroke: #111827; stroke-width: 2; }
|
||||
.line { fill: none; stroke: #334155; stroke-width: 2.5; marker-end: url(#arrow); }
|
||||
.flow { fill: none; stroke: #579000; stroke-width: 3; marker-end: url(#arrow-green); }
|
||||
@@ -55,8 +56,8 @@
|
||||
|
||||
<!-- Sandbox -->
|
||||
<rect x="920" y="70" width="320" height="420" rx="18" fill="#ffffff" stroke="#76b900" stroke-width="3" stroke-dasharray="10 7"/>
|
||||
<rect x="945" y="105" width="270" height="210" rx="14" class="box"/>
|
||||
<text x="1080" y="150" text-anchor="middle" class="label">OpenShell Sandbox</text>
|
||||
<rect x="945" y="105" width="270" height="210" rx="14" class="owned"/>
|
||||
<text x="1080" y="150" text-anchor="middle" class="label">Sandbox</text>
|
||||
<text x="1080" y="174" text-anchor="middle" class="tiny">VERIFIES, NEVER SIGNS</text>
|
||||
<text x="1080" y="225" text-anchor="middle" class="small">Gateway public key only</text>
|
||||
<text x="1080" y="255" text-anchor="middle" class="small">Checks the sandbox JWT</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.6 KiB |
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -->
|
||||
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="540" viewBox="0 0 1280 540" role="img" aria-labelledby="title desc">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="420" viewBox="0 0 1280 420" role="img" aria-labelledby="title desc">
|
||||
<title id="title">OpenShell sandbox enforcement flow</title>
|
||||
<desc id="desc">The sandbox workload and trusted supervisor are separate boundaries. All workload network egress is denied except the authenticated Sandbox Protocol connection to the supervisor.</desc>
|
||||
<desc id="desc">The sandbox workload and trusted supervisor are separate boundaries. All workload network egress is denied except the authenticated Sandbox Protocol connection to the supervisor. The OpenShell Sandbox holds a local policy.local file that carries proposed policy changes to the supervisor's policy enforcement for review, and receives the reloaded policy back.</desc>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#334155"/>
|
||||
@@ -21,13 +21,16 @@
|
||||
.soft { fill: #f8fafc; stroke: #cbd5e1; stroke-width: 2; }
|
||||
.green { fill: #f2f9e8; stroke: #76b900; stroke-width: 2.5; }
|
||||
.trusted { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.owned { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.dark { fill: #1f2937; stroke: #111827; stroke-width: 2; }
|
||||
.flow { fill: none; stroke: #579000; stroke-width: 3; marker-end: url(#arrow-green); }
|
||||
.blocked { fill: none; stroke: #c2413b; stroke-width: 2.5; stroke-dasharray: 8 7; }
|
||||
.policy { fill: none; stroke: #475569; stroke-width: 2; stroke-dasharray: 6 6; marker-end: url(#arrow); }
|
||||
.chip { fill: #eff6ff; stroke: #3b82f6; stroke-width: 1.5; }
|
||||
</style>
|
||||
</defs>
|
||||
|
||||
<rect width="1280" height="540" rx="20" fill="#ffffff"/>
|
||||
<rect width="1280" height="420" rx="20" fill="#ffffff"/>
|
||||
|
||||
<g transform="translate(0,-50)">
|
||||
|
||||
@@ -37,10 +40,12 @@
|
||||
<rect x="75" y="205" width="125" height="94" rx="14" class="dark"/>
|
||||
<text x="137" y="245" text-anchor="middle" style="font:700 20px -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;fill:#fff">Agent</text>
|
||||
<text x="137" y="270" text-anchor="middle" style="font:500 13px -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;fill:#d1d5db">process</text>
|
||||
<rect x="240" y="190" width="130" height="124" rx="14" class="box"/>
|
||||
<text x="305" y="230" text-anchor="middle" class="label">OpenShell</text>
|
||||
<text x="305" y="254" text-anchor="middle" class="label">Sandbox</text>
|
||||
<text x="305" y="282" text-anchor="middle" class="small">process owner</text>
|
||||
<rect x="240" y="190" width="130" height="124" rx="14" class="owned"/>
|
||||
<text x="305" y="222" text-anchor="middle" class="label">OpenShell</text>
|
||||
<text x="305" y="244" text-anchor="middle" class="label">Sandbox</text>
|
||||
<text x="305" y="264" text-anchor="middle" class="small">process owner</text>
|
||||
<rect x="253" y="278" width="104" height="24" rx="6" class="chip"/>
|
||||
<text x="305" y="294" text-anchor="middle" class="tiny">policy.local</text>
|
||||
<path d="M200 252 H240" class="flow"/>
|
||||
<circle cx="220" cy="228" r="13" fill="#579000"/>
|
||||
<text x="220" y="233" text-anchor="middle" class="step">1</text>
|
||||
@@ -76,6 +81,9 @@
|
||||
<text x="935" y="360" text-anchor="middle" class="small">Checks destination, binary,</text>
|
||||
<text x="935" y="381" text-anchor="middle" class="small">L7 rules, and credentials</text>
|
||||
|
||||
<path d="M357 290 H410 V170 H935 V190" class="policy"/>
|
||||
<text x="670" y="163" text-anchor="middle" class="tiny">POLICY.LOCAL PROPOSE / RELOAD (ASYNC)</text>
|
||||
|
||||
<rect x="1080" y="190" width="160" height="124" rx="14" class="box"/>
|
||||
<text x="1160" y="230" text-anchor="middle" class="label">Upstream</text>
|
||||
<text x="1160" y="254" text-anchor="middle" class="label">service</text>
|
||||
@@ -83,23 +91,5 @@
|
||||
<path d="M1010 252 H1080" class="flow"/>
|
||||
<circle cx="1045" cy="228" r="13" fill="#579000"/>
|
||||
<text x="1045" y="233" text-anchor="middle" class="step">4</text>
|
||||
|
||||
<text x="45" y="485" class="section">LAUNCH GATE</text>
|
||||
<line x1="150" y1="520" x2="1130" y2="520" stroke="#cbd5e1" stroke-width="4"/>
|
||||
<g>
|
||||
<circle cx="180" cy="520" r="20" fill="#ffffff" stroke="#64748b" stroke-width="3"/>
|
||||
<text x="180" y="555" text-anchor="middle" class="tiny">ATTACH</text>
|
||||
<circle cx="380" cy="520" r="20" fill="#ffffff" stroke="#64748b" stroke-width="3"/>
|
||||
<text x="380" y="555" text-anchor="middle" class="tiny">BOUND</text>
|
||||
<circle cx="580" cy="520" r="20" fill="#f2f9e8" stroke="#76b900" stroke-width="4"/>
|
||||
<text x="580" y="555" text-anchor="middle" class="tiny">CONFIRMED</text>
|
||||
<circle cx="780" cy="520" r="20" fill="#f2f9e8" stroke="#76b900" stroke-width="4"/>
|
||||
<text x="780" y="555" text-anchor="middle" class="tiny">READY</text>
|
||||
<circle cx="980" cy="520" r="20" fill="#76b900" stroke="#579000" stroke-width="4"/>
|
||||
<text x="980" y="526" text-anchor="middle" class="step">✓</text>
|
||||
<text x="980" y="555" text-anchor="middle" class="tiny">RUNNING</text>
|
||||
</g>
|
||||
<path d="M600 485 H950" stroke="#76b900" stroke-width="2"/>
|
||||
<text x="775" y="477" text-anchor="middle" class="small">Agent cannot start until the boundary is confirmed</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 6.5 KiB |
@@ -18,6 +18,7 @@
|
||||
.tiny { font: 700 12px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #475569; }
|
||||
.box { fill: #ffffff; stroke: #cbd5e1; stroke-width: 2; }
|
||||
.trusted { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.owned { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.dark { fill: #1f2937; stroke: #111827; stroke-width: 2; }
|
||||
.line { fill: none; stroke: #334155; stroke-width: 2.5; marker-end: url(#arrow); }
|
||||
.flow { fill: none; stroke: #579000; stroke-width: 3; marker-start: url(#arrow-green); marker-end: url(#arrow-green); }
|
||||
@@ -44,8 +45,8 @@
|
||||
|
||||
<!-- Sandbox boundary -->
|
||||
<rect x="920" y="70" width="320" height="440" rx="18" fill="#ffffff" stroke="#76b900" stroke-width="3" stroke-dasharray="10 7"/>
|
||||
<rect x="945" y="105" width="270" height="290" rx="14" class="box"/>
|
||||
<text x="1080" y="150" text-anchor="middle" class="label">OpenShell Sandbox</text>
|
||||
<rect x="945" y="105" width="270" height="290" rx="14" class="owned"/>
|
||||
<text x="1080" y="150" text-anchor="middle" class="label">Sandbox</text>
|
||||
<text x="1080" y="174" text-anchor="middle" class="tiny">PROCESS AND SYSCALL BOUNDARY</text>
|
||||
<text x="1080" y="225" text-anchor="middle" class="small">Owns the agent process</text>
|
||||
<text x="1080" y="255" text-anchor="middle" class="small">Identifies each program</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -->
|
||||
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="760" viewBox="0 0 1280 760" role="img" aria-labelledby="title desc">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="870" viewBox="0 0 1280 870" role="img" aria-labelledby="title desc">
|
||||
<title id="title">OpenShell system architecture</title>
|
||||
<desc id="desc">User interfaces connect to the gateway, which uses the policy prover to formally verify proposed policy changes before approval. The OpenShell Runtime places a trusted supervisor separately from a network-isolated sandbox workload. The workload's only allowed network path is its mediated connection to the supervisor, which connects to approved external services.</desc>
|
||||
<desc id="desc">User interfaces connect to the gateway, which uses the policy prover to formally verify proposed policy changes before approval. The OpenShell Runtime places a trusted supervisor separately from a network-isolated sandbox workload. The workload's only allowed network path is its mediated connection to the supervisor, which connects to approved external services. The policy lifecycle strip shows the supervisor proposing a policy change, the gateway's policy prover checking it, a human approving it, and the supervisor reloading the approved policy.</desc>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#334155"/>
|
||||
@@ -21,96 +21,123 @@
|
||||
.soft { fill: #f8fafc; stroke: #cbd5e1; stroke-width: 2; }
|
||||
.green { fill: #f2f9e8; stroke: #76b900; stroke-width: 2.5; }
|
||||
.trusted { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.owned { fill: #eff6ff; stroke: #3b82f6; stroke-width: 2.5; }
|
||||
.dark { fill: #1f2937; stroke: #111827; stroke-width: 2; }
|
||||
.line { fill: none; stroke: #334155; stroke-width: 2.5; marker-end: url(#arrow); }
|
||||
.flow { fill: none; stroke: #579000; stroke-width: 3; marker-end: url(#arrow-green); }
|
||||
.blocked { fill: none; stroke: #c2413b; stroke-width: 2.5; stroke-dasharray: 8 7; }
|
||||
.dashed { fill: none; stroke: #475569; stroke-width: 2; stroke-dasharray: 6 6; marker-end: url(#arrow); }
|
||||
</style>
|
||||
</defs>
|
||||
|
||||
<rect width="1280" height="760" rx="20" fill="#ffffff"/>
|
||||
<rect width="1280" height="870" rx="20" fill="#ffffff"/>
|
||||
|
||||
<g transform="translate(0,-80)">
|
||||
<text x="45" y="116" class="section">USER INTERFACES</text>
|
||||
<rect x="40" y="130" width="760" height="120" rx="18" class="soft"/>
|
||||
<rect x="75" y="156" width="180" height="68" rx="12" class="box"/>
|
||||
<text x="165" y="197" text-anchor="middle" class="label">CLI</text>
|
||||
<rect x="310" y="156" width="180" height="68" rx="12" class="box"/>
|
||||
<text x="400" y="197" text-anchor="middle" class="label">SDK</text>
|
||||
<rect x="545" y="156" width="180" height="68" rx="12" class="box"/>
|
||||
<text x="635" y="197" text-anchor="middle" class="label">TUI</text>
|
||||
<rect x="40" y="130" width="760" height="84" rx="18" class="soft"/>
|
||||
<rect x="75" y="146" width="180" height="48" rx="12" class="box"/>
|
||||
<text x="165" y="177" text-anchor="middle" class="label">CLI</text>
|
||||
<rect x="310" y="146" width="180" height="48" rx="12" class="box"/>
|
||||
<text x="400" y="177" text-anchor="middle" class="label">SDK</text>
|
||||
<rect x="545" y="146" width="180" height="48" rx="12" class="box"/>
|
||||
<text x="635" y="177" text-anchor="middle" class="label">TUI</text>
|
||||
|
||||
<text x="845" y="116" class="section">EXTERNAL SERVICES</text>
|
||||
<rect x="840" y="130" width="400" height="120" rx="18" class="soft"/>
|
||||
<rect x="865" y="156" width="160" height="68" rx="12" class="box"/>
|
||||
<text x="945" y="185" text-anchor="middle" class="label">Services</text>
|
||||
<text x="945" y="207" text-anchor="middle" class="small">APIs and tools</text>
|
||||
<rect x="1045" y="156" width="170" height="68" rx="12" class="box"/>
|
||||
<text x="1130" y="185" text-anchor="middle" class="label">Models</text>
|
||||
<text x="1130" y="207" text-anchor="middle" class="small">inference APIs</text>
|
||||
<rect x="840" y="130" width="400" height="84" rx="18" class="soft"/>
|
||||
<rect x="865" y="146" width="160" height="48" rx="12" class="box"/>
|
||||
<text x="945" y="165" text-anchor="middle" class="label">Services</text>
|
||||
<text x="945" y="185" text-anchor="middle" class="small">APIs and tools</text>
|
||||
<rect x="1045" y="146" width="170" height="48" rx="12" class="box"/>
|
||||
<text x="1130" y="165" text-anchor="middle" class="label">Models</text>
|
||||
<text x="1130" y="185" text-anchor="middle" class="small">inference APIs</text>
|
||||
|
||||
<text x="45" y="326" class="section">GATEWAY (CONTROL PLANE)</text>
|
||||
<rect x="40" y="340" width="360" height="460" rx="18" class="soft"/>
|
||||
<rect x="85" y="380" width="290" height="70" rx="14" class="trusted"/>
|
||||
<text x="230" y="410" text-anchor="middle" class="label">API Server</text>
|
||||
<text x="230" y="434" text-anchor="middle" class="small">API, authentication, lifecycle, relays</text>
|
||||
<rect x="85" y="490" width="290" height="70" rx="14" class="box"/>
|
||||
<text x="230" y="520" text-anchor="middle" class="label">Policy prover</text>
|
||||
<text x="230" y="544" text-anchor="middle" class="small">formal verification of policy changes</text>
|
||||
<rect x="85" y="600" width="290" height="70" rx="14" class="box"/>
|
||||
<text x="230" y="630" text-anchor="middle" class="label">Durable state</text>
|
||||
<text x="230" y="654" text-anchor="middle" class="small">sandboxes · policies · providers · settings</text>
|
||||
<rect x="85" y="710" width="290" height="70" rx="14" class="green"/>
|
||||
<text x="230" y="740" text-anchor="middle" class="label">Compute driver</text>
|
||||
<text x="230" y="764" text-anchor="middle" class="small">places and fences each sandbox</text>
|
||||
<path d="M230 450 V490" class="line"/>
|
||||
<path d="M85 415 H60 V635 H85" class="line"/>
|
||||
<path d="M230 670 V710" class="line"/>
|
||||
<text x="45" y="286" class="section">GATEWAY (CONTROL PLANE)</text>
|
||||
<rect x="40" y="300" width="360" height="450" rx="18" class="soft"/>
|
||||
<rect x="85" y="340" width="290" height="70" rx="14" class="trusted"/>
|
||||
<text x="230" y="370" text-anchor="middle" class="label">API Server</text>
|
||||
<text x="230" y="394" text-anchor="middle" class="small">API, authentication, lifecycle, relays</text>
|
||||
<rect x="85" y="450" width="290" height="50" rx="14" class="box"/>
|
||||
<text x="230" y="481" text-anchor="middle" class="label">Policy prover</text>
|
||||
<rect x="85" y="540" width="290" height="70" rx="14" class="box"/>
|
||||
<text x="230" y="570" text-anchor="middle" class="label">Durable state</text>
|
||||
<text x="230" y="594" text-anchor="middle" class="small">sandboxes · policies · providers · settings</text>
|
||||
<rect x="85" y="650" width="290" height="70" rx="14" class="green"/>
|
||||
<text x="230" y="680" text-anchor="middle" class="label">Compute driver</text>
|
||||
<text x="230" y="704" text-anchor="middle" class="small">places and fences each sandbox</text>
|
||||
<path d="M 230 410 V 450" class="line"/>
|
||||
<path d="M 85 375 H 60 V 575 H 85" class="line"/>
|
||||
<path d="M 230 610 V 650" class="line"/>
|
||||
|
||||
<text x="485" y="326" class="section">OPENSHELL RUNTIME (DATA PLANE)</text>
|
||||
<rect x="480" y="340" width="760" height="460" rx="18" fill="#f8fafc" stroke="#94a3b8" stroke-width="2" stroke-dasharray="10 7"/>
|
||||
<text x="485" y="286" class="section">OPENSHELL RUNTIME (DATA PLANE)</text>
|
||||
<rect x="480" y="300" width="760" height="450" rx="18" fill="#f8fafc" stroke="#94a3b8" stroke-width="2" stroke-dasharray="10 7"/>
|
||||
|
||||
<rect x="530" y="405" width="240" height="290" rx="16" class="trusted"/>
|
||||
<text x="650" y="445" text-anchor="middle" class="label">Supervisor</text>
|
||||
<text x="650" y="469" text-anchor="middle" class="tiny">GOVERNS THE AGENT</text>
|
||||
<text x="650" y="515" text-anchor="middle" class="small">Policy evaluation</text>
|
||||
<text x="650" y="545" text-anchor="middle" class="small">Credential resolution</text>
|
||||
<text x="650" y="575" text-anchor="middle" class="small">DNS and proxying</text>
|
||||
<text x="650" y="605" text-anchor="middle" class="small">Agent session multiplexing</text>
|
||||
<line x1="565" y1="630" x2="735" y2="630" stroke="#bfdbfe" stroke-width="1.5"/>
|
||||
<text x="650" y="662" text-anchor="middle" class="small">Maintains the gateway session</text>
|
||||
<rect x="530" y="365" width="240" height="290" rx="16" class="trusted"/>
|
||||
<text x="650" y="405" text-anchor="middle" class="label">Supervisor</text>
|
||||
<text x="650" y="429" text-anchor="middle" class="tiny">GOVERNS THE AGENT</text>
|
||||
<text x="650" y="475" text-anchor="middle" class="small">Policy evaluation</text>
|
||||
<text x="650" y="505" text-anchor="middle" class="small">Credential resolution</text>
|
||||
<text x="650" y="535" text-anchor="middle" class="small">DNS and proxying</text>
|
||||
<text x="650" y="565" text-anchor="middle" class="small">Agent session multiplexing</text>
|
||||
<line x1="565" y1="590" x2="735" y2="590" stroke="#bfdbfe" stroke-width="1.5"/>
|
||||
<text x="650" y="622" text-anchor="middle" class="small">Maintains the gateway session</text>
|
||||
|
||||
<rect x="880" y="390" width="315" height="270" rx="18" fill="#ffffff" stroke="#76b900" stroke-width="3" stroke-dasharray="10 7"/>
|
||||
<text x="1037" y="423" text-anchor="middle" class="tiny">SANDBOX · NETWORK ISOLATED</text>
|
||||
<text x="1037" y="442" text-anchor="middle" class="tiny">(CONTAINER · VM)</text>
|
||||
<rect x="910" y="452" width="255" height="86" rx="14" class="box"/>
|
||||
<text x="1037" y="489" text-anchor="middle" class="label">OpenShell Sandbox</text>
|
||||
<text x="1037" y="514" text-anchor="middle" class="small">process owner and syscall boundary</text>
|
||||
<rect x="910" y="570" width="255" height="60" rx="14" class="dark"/>
|
||||
<text x="1037" y="597" text-anchor="middle" style="font:700 18px -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;fill:#fff">Agent</text>
|
||||
<text x="1037" y="618" text-anchor="middle" style="font:500 13px -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;fill:#d1d5db">untrusted workload</text>
|
||||
<path d="M1037 538 V570" class="line"/>
|
||||
<rect x="880" y="350" width="315" height="270" rx="18" fill="#ffffff" stroke="#76b900" stroke-width="3" stroke-dasharray="10 7"/>
|
||||
<text x="1037" y="383" text-anchor="middle" class="tiny">SANDBOX · NETWORK ISOLATED</text>
|
||||
<text x="1037" y="402" text-anchor="middle" class="tiny">(CONTAINER · VM)</text>
|
||||
<rect x="910" y="412" width="255" height="86" rx="14" class="box"/>
|
||||
<text x="1037" y="449" text-anchor="middle" class="label">Sandbox</text>
|
||||
<text x="1037" y="474" text-anchor="middle" class="small">process owner and syscall boundary</text>
|
||||
<rect x="910" y="530" width="255" height="60" rx="14" class="dark"/>
|
||||
<text x="1037" y="557" text-anchor="middle" style="font:700 18px -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;fill:#fff">Agent</text>
|
||||
<text x="1037" y="578" text-anchor="middle" style="font:500 13px -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;fill:#d1d5db">untrusted workload</text>
|
||||
<path d="M 1037 498 V 530" class="line"/>
|
||||
|
||||
<path d="M910 495 H770" class="flow"/>
|
||||
<text x="840" y="474" text-anchor="middle" class="tiny">MEDIATED CHANNEL</text>
|
||||
<path d="M1037 630 V651" class="blocked"/>
|
||||
<line x1="1028" y1="651" x2="1046" y2="669" stroke="#c2413b" stroke-width="3"/>
|
||||
<line x1="1046" y1="651" x2="1028" y2="669" stroke="#c2413b" stroke-width="3"/>
|
||||
<path d="M 910 455 H 770" class="flow"/>
|
||||
<text x="840" y="434" text-anchor="middle" class="tiny">MEDIATED CHANNEL</text>
|
||||
<path d="M 1037 590 V 611" class="blocked"/>
|
||||
<line x1="1028" y1="611" x2="1046" y2="629" stroke="#c2413b" stroke-width="3"/>
|
||||
<line x1="1046" y1="611" x2="1028" y2="629" stroke="#c2413b" stroke-width="3"/>
|
||||
|
||||
<rect x="880" y="690" width="315" height="84" rx="12" class="green"/>
|
||||
<text x="1037" y="714" text-anchor="middle" class="tiny">WORKLOAD NETWORK RULE</text>
|
||||
<text x="1037" y="739" text-anchor="middle" class="label">Deny all egress</text>
|
||||
<text x="1037" y="760" text-anchor="middle" class="small">except to the supervisor</text>
|
||||
<rect x="880" y="650" width="315" height="84" rx="12" class="green"/>
|
||||
<text x="1037" y="674" text-anchor="middle" class="tiny">WORKLOAD NETWORK RULE</text>
|
||||
<text x="1037" y="699" text-anchor="middle" class="label">Deny all egress</text>
|
||||
<text x="1037" y="720" text-anchor="middle" class="small">except to the supervisor</text>
|
||||
|
||||
<path d="M420 250 V286 H330 V380" class="line"/>
|
||||
<text x="438" y="279" class="tiny">gRPC / HTTP</text>
|
||||
<path d="M530 500 H420 V435 H375" class="line"/>
|
||||
<text x="465" y="468" text-anchor="middle" class="tiny">OUTBOUND</text>
|
||||
<text x="465" y="484" text-anchor="middle" class="tiny">SESSION</text>
|
||||
<path d="M375 735 H480" class="line"/>
|
||||
<text x="427" y="717" text-anchor="middle" class="tiny">PROVISION</text>
|
||||
<path d="M 420 214 V 246 H 330 V 340" class="line"/>
|
||||
<text x="438" y="239" class="tiny">gRPC / HTTP</text>
|
||||
<path d="M 530 460 H 420 V 395 H 375" class="line"/>
|
||||
<path d="M 375 675 H 480" class="line"/>
|
||||
|
||||
<path d="M750 405 V286 H1040 V250" class="flow"/>
|
||||
<text x="790" y="279" class="tiny">POLICY-APPROVED EGRESS</text>
|
||||
<path d="M 750 365 V 246 H 1040 V 214" class="flow"/>
|
||||
<text x="790" y="239" class="tiny">POLICY-APPROVED EGRESS</text>
|
||||
</g>
|
||||
|
||||
<text x="45" y="740" class="section">POLICY LIFECYCLE</text>
|
||||
<rect x="40" y="754" width="1200" height="100" rx="18" class="soft"/>
|
||||
|
||||
<path d="M700 575 V737 H1070 V769" class="dashed"/>
|
||||
<text x="850" y="720" text-anchor="middle" class="tiny">SUPERVISOR PROPOSES</text>
|
||||
<path d="M200 769 V727 H600 V575" class="dashed"/>
|
||||
<text x="400" y="705" text-anchor="middle" class="tiny">APPROVED POLICY RELOADED</text>
|
||||
|
||||
<rect x="65" y="769" width="270" height="70" rx="14" class="box"/>
|
||||
<text x="200" y="799" text-anchor="middle" class="label">Policy reloads</text>
|
||||
<text x="200" y="821" text-anchor="middle" class="small">supervisor retries</text>
|
||||
|
||||
<rect x="355" y="769" width="270" height="70" rx="14" class="box"/>
|
||||
<text x="490" y="795" text-anchor="middle" class="label">You approve</text>
|
||||
<text x="490" y="815" text-anchor="middle" class="small">manual by default</text>
|
||||
<text x="490" y="833" text-anchor="middle" class="tiny">or auto — no new risk found</text>
|
||||
|
||||
<rect x="645" y="769" width="270" height="70" rx="14" class="box"/>
|
||||
<text x="780" y="799" text-anchor="middle" class="label">Gateway prover checks</text>
|
||||
<text x="780" y="821" text-anchor="middle" class="small">flags risky new access</text>
|
||||
|
||||
<rect x="935" y="769" width="270" height="70" rx="14" class="box"/>
|
||||
<text x="1070" y="799" text-anchor="middle" class="label">Agent proposes</text>
|
||||
<text x="1070" y="821" text-anchor="middle" class="small">via policy.local</text>
|
||||
|
||||
<path d="M935 804 H915" class="dashed"/>
|
||||
<path d="M645 804 H625" class="dashed"/>
|
||||
<path d="M355 804 H335" class="dashed"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 9.5 KiB |