Skip to content

docs(rfc): add RFC-0011 multi-player support design#1980

Open
derekwaynecarr wants to merge 1 commit into
NVIDIA:mainfrom
derekwaynecarr:decarr/multi-player-design
Open

docs(rfc): add RFC-0011 multi-player support design#1980
derekwaynecarr wants to merge 1 commit into
NVIDIA:mainfrom
derekwaynecarr:decarr/multi-player-design

Conversation

@derekwaynecarr

@derekwaynecarr derekwaynecarr commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

This RFC introduces multi-player support for OpenShell by adding workspaces as hard isolation boundaries, expanding the role model to three user roles (Platform Admin, Workspace Admin, User), and
introducing workspace-scoped access control. Machine workloads authenticate via OIDC workload identity using the same multi-provider OIDC mechanism as human users, with no stored API keys or secrets. The
Sandbox Supervisor is clarified as a separate principal type with sandbox-scoped JWT authentication, distinct from the user role model. The Kubernetes compute driver gains two workspace mapping modes —
managed (default), which creates gateway-scoped Kubernetes namespaces (openshell-{gateway-id}-{workspace-name}), and operator mode for 1:1 passthrough to pre-existing namespaces. A three-tier policy
layering model replaces the current mutual-exclusion approach. Audit trail attribution follows the Kubernetes pattern — events are emitted as structured OCSF JSONL and forwarded to external SIEM systems
rather than queried through a gateway API. The design preserves backwards compatibility for single-player deployments via a default workspace.

Related Issue

#1977

Changes

  • Workspaces as first-class resources and hard isolation boundaries for sandboxes, providers, and policies, with a default workspace for backwards compatibility
  • Expanded role model from two-tier (admin/user) to three user roles: Platform Admin, Workspace Admin, User
  • Sandbox Supervisor separated from role model as a distinct principal type with sandbox-scoped JWT authentication, static method allowlists, and per-handler scope guards
  • Machine identity via OIDC workload identity — CI/CD pipelines and agent harnesses authenticate using short-lived OIDC tokens from their platform (GitHub Actions, GitLab CI, GCP) with no stored secrets;
    workspace membership maps OIDC subjects to workspace access
  • Workspace-scoped access — all workspace members can access any sandbox in the workspace; credential isolation happens at the workspace boundary
  • Principal attribution handled by OCSF audit events forwarded to external SIEM, not fields on resources or a gateway query API — follows the Kubernetes audit log pattern
  • Authorization enforcement extends the existing #[rpc_auth] macro with workspace_role and global_role attributes, a WorkspaceScoped trait on request messages, and a single authorize_workspace()
    call per handler
  • Kubernetes workspace mapping with two modes: managed (default, creates openshell-{gateway-id}-{workspace-name} with DNS-1123 validation) and operator (1:1 name passthrough to pre-existing K8s
    namespaces)
  • Cluster-wide list/watch with label filtering replaces single-namespace watcher
  • Provider credential scoping to workspaces with no raw credential visibility for non-admin roles
  • Three-tier policy layering (gateway default → workspace baseline → sandbox policy) replacing mutual-exclusion model; enforcement modes use most-restrictive-wins, allowlists use union across tiers,
    gateway-wide deny rules override allows at any tier
  • Control-plane and sandbox-level audit events emitted as OCSF JSONL with principal subject and workspace attribution, forwarded to external log aggregation via standard shipping tools
  • Per-workspace quotas for concurrent sandboxes, GPU allocations, and sandbox lifetime as DoS and abuse protection
  • Enterprise multi-consumer gateway deployment pattern with OpenClaw integration example
  • Storage uniqueness shifts from (object_type, name) to (object_type, workspace, name) with backfill to default workspace
  • End-to-end appendix walkthroughs: workspace lifecycle (create → member → provider → sandbox → delete) and sandbox supervisor lifecycle (JWT mint → connect → credential fetch → cross-sandbox rejection)
  • Cross-workspace sandbox sharing deferred to future work

Testing

  • mise run pre-commit passes
  • Unit tests added/updated
  • E2E tests added/updated (if applicable)

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

@derekwaynecarr derekwaynecarr requested review from a team, maxamillion and mrunalp as code owners June 23, 2026 13:37
@copy-pr-bot

copy-pr-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
@derekwaynecarr derekwaynecarr force-pushed the decarr/multi-player-design branch from 3713b9b to 85e9054 Compare June 23, 2026 14:16
@drew

drew commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Could we rename this to RFC-0011? I'll reserve the number in our tracker 😄.

Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
@johntmyers johntmyers changed the title docs(rfc): add RFC 1977 multi-player support design docs(rfc): add RFC-0011 multi-player support design Jun 25, 2026
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment thread rfc/1977-multi-player-design/README.md Outdated
Comment on lines +234 to +236
- **Agent orchestration.** One agent's service account creates sandboxes for
sub-agents, each getting their own sandbox principal. The parent service
account retains visibility.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the parent service account create "sub" service accounts?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does each sandbox have to use a unique sercice account or can it be shared, but still maintain a unique agent identity using the pod name in it's SPIFFE id for example?

@dhirajsb

dhirajsb commented Jul 1, 2026

Copy link
Copy Markdown

We are missing a persona in this approach. CMIW, but the user persona as modeled sounds more like an end-user who's directly interacting with an agent in a Sandbox.

OpenShell multi-user architecture should support agentic app development for app developers. It should leverage K8s rbac for access control in app namespaces. It should also decouple policy management through Gateway in such a way that app developers or app workloads (or compromised workloads) can't override certain org/platform wide security policies enforced via Gateway.

I hope that makes sense.

Comment thread rfc/1977-multi-player-design/README.md Outdated
@rhuss

rhuss commented Jul 2, 2026

Copy link
Copy Markdown

Great RFC, this fills a real gap.

My comments above are coming from a Kubernetes perspective, specifically looking at how well this proposal maps to the operator discussion in #1719. I'm not suggesting the gateway should copy the Kubernetes multi-tenancy model for Docker, VM, or bare-metal drivers. But for Kubernetes deployments, we should be careful about which existing platform concepts we can reuse (namespaces, RBAC, Secret management, admission control) so that the integration feels native to operators and platform teams already running that ecosystem.

Both proposed Kubernetes modes (managed and operator) map OpenShell namespaces (or "workspaces") to K8s namespaces. The difference is who provisions the namespace (gateway in managed mode, external tooling in operator mode), not the conceptual relationship. In both cases, providers can reference credentials managed by the cluster's secret infrastructure (external-secrets-operator, Vault). The gateway keeps its own workspace model, roles, and credential scoping for non-K8s drivers where none of that exists.

That said, there's an impedance mismatch worth checking. K8s RBAC maps well to control plane operations: who can create/delete OpenShellSandbox CRs (assuming we end up with such an abstraction), who can manage providers and policies in a namespace. But OpenShell also has a data plane authorization concern: who can exec into a running sandbox, stream relay output, share a session, or view audit logs. That's runtime authorization through the gateway's gRPC endpoints, and K8s RBAC has no reach there. The RFC's five-role model is needed for these data plane operations even in Kubernetes deployments. Trying to force runtime access checks into K8s RBAC (like SubjectAccessReview for every gRPC call) would be awkward and break parity with non-K8s drivers.

So in practice, K8s RBAC covers "who can deploy what" (platform admins install the operator, team leads manage CRs in their namespace), while the gateway's auth model from this RFC covers "who can do what at runtime" (exec, relay, session sharing). Both are needed, with clear boundaries.

One thing worth considering on phasing: if the operator (#1719) is being designed in parallel, operator mode (Phase 3) is the simpler starting point for Kubernetes (no ClusterRole for namespace create/delete, no naming conventions, no race conditions). It might make sense to design these together rather than sequentially.

@rhuss rhuss mentioned this pull request Jul 2, 2026
@derekwaynecarr derekwaynecarr force-pushed the decarr/multi-player-design branch 3 times, most recently from a9a578b to 158abf2 Compare July 7, 2026 00:41
@dhirajsb

dhirajsb commented Jul 7, 2026

Copy link
Copy Markdown

For AI Fatory at NVIDIA, the requirements are as follows:

  • One cluster gateway: HA OpenShell control plane in openshell-system, backed by PostgreSQL (core architecture RFC).
  • App-local data plane: Sandboxes, PVCs, service accounts and warm pools stay in each application namespace.
  • Trusted namespace placement: Gateway derives the target namespace from identity and platform policy—not arbitrary user input (platform integration proposal).
  • Warm allocation: App-specific SandboxTemplate + SandboxWarmPool; gateway creates SandboxClaim objects (Agent Sandbox extensions).
  • Central governance: Cluster maximum policy → app baseline → sandbox-specific restrictions (managed maximum policies).
  • Platform integration: Namespace operator installs RBAC, SCC, NetworkPolicy, quotas, TLS identity and Vault/ESO-backed Secrets.

I believe this proposal covers them all at a high level, but please correct it if anything is missing.

@derekwaynecarr

Copy link
Copy Markdown
Collaborator Author

@dhirajsb this proposal covers your requested items, but some items would need to be handled post this rfc. I will discuss in more detail in community call, but here is a quick summary.

  1. One cluster gateway: HA OpenShell control plane in openshell-system, backed by PostgreSQL
  • Covered. The RFC designs for a single gateway per compute region (Enterprise Deployment section, line 426). PostgreSQL backing and HA are existing infrastructure concerns outside this RFC's scope, already covered by RFC 0001.
  1. App-local data plane: Sandboxes, PVCs, service accounts and warm pools stay in each application namespace
  • Partially covered. The RFC maps workspaces to K8s namespaces (operator mode, line 382-396), so sandboxes land in per-app namespaces. How we address warm pool allocation or template-based sandbox creation is likely a configuration of the workspace, but I would add those settings once we settle on the core segmentation of the OpenShell control plane.
  1. Trusted namespace placement: Gateway derives target namespace from identity and platform policy — not arbitrary user input
  • Covered. Operator mode (line 382-396) does a 1:1 workspace-to-namespace mapping, but the workspace is currently set by the caller via --workspace flag. The RFC's workspace membership model constrains which workspaces a principal can target.
  1. Warm allocation: App-specific SandboxTemplate + SandboxWarmPool; gateway creates SandboxClaim objects
  • Not covered. The RFC covers workspace isolation and RBAC but not sandbox lifecycle optimizations like warm pools, which are good things to configure against the workspace after this rfc is accepted.
  1. Central governance: Cluster maximum policy → app baseline → sandbox-specific restrictions
  • Covered. The three-tier policy layering (lines 259-291) maps directly: tier 1 (gateway default = cluster maximum) → tier 2 (workspace floor = app baseline) → tier 3 (sandbox policy = sandbox-specific).
    The comment links Enterprise permission modes with managed maximum policies #2109 for managed maximum policies, which aligns with tier 1 deny rules and enforcement modes.
  1. Platform integration: Namespace operator installs RBAC, SCC, NetworkPolicy, quotas, TLS identity and Vault/ESO-backed Secrets
  • Covered. Operator mode (line 382-396) assumes pre-provisioned namespaces, which is the model where an external namespace operator handles RBAC, SCC, NetworkPolicy, and secrets. The RFC describes the OpenShell side of consuming those namespaces.

mandatory access control prevents processes in one namespace from reading
files, secrets, or process state belonging to another.

**Sandbox escape threat model.** Container breakout is the dominant concern in

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mention VMs/kata as another layer of protection here?

variable. The explicit `--workspace` flag takes precedence over the environment
variable.

```shell

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLI to switch current active workspace could be considered.

@derekwaynecarr derekwaynecarr force-pushed the decarr/multi-player-design branch 4 times, most recently from 0ecd5ea to 42f502e Compare July 7, 2026 15:45

A future extension could allow sharing a sandbox with a principal who is not a
member of the workspace. The motivating use case: a platform team runs a
"shared-tools" workspace containing sandboxes with internal services (a test

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think internal services like a database or a mock API would be in a sandbox. Those would just be in another namespace, and the agent sandboxes would need to be configured such that they had network access to those services.

Maybe there's some other use case for shared-tools, but these don't seem to be valid use cases.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A shared sandboxed agent for pair programming or tightly collaborating with the same agent instance makes more sense to me.

@derekwaynecarr derekwaynecarr Jul 7, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, makes sense. i read this as a sandbox that had a client with credentials to speak to the database, not the literal database, unless it was like sqlite or something. i can tweak.

Every resource belongs to exactly one workspace. A `default` workspace exists
for single-player backwards compatibility. Workspace creation is admin-only:
Platform Admins create workspaces and assign Workspace Admins. Self-service
workspace creation can be added later as a gateway configuration option.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was looking for this line as I was thinking about something @drew asked in a community call. If you have a workspace with 2 sandboxes, one of which you would like to share while keeping the other private you will need a second workspace, which will require an admin to create for you.

@derekwaynecarr derekwaynecarr force-pushed the decarr/multi-player-design branch 4 times, most recently from e6e1da5 to 1e6cd08 Compare July 8, 2026 15:45
Signed-off-by: Derek Carr <decarr@redhat.com>
@derekwaynecarr derekwaynecarr force-pushed the decarr/multi-player-design branch from 1e6cd08 to 7d26c03 Compare July 8, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

10 participants