Skip to content

feat(kubernetes): map workspaces to sandbox namespaces #2486

Description

@dhirajsb

Problem Statement

OpenShell now has logical workspaces, but the Kubernetes compute driver still
creates every Agent Sandbox resource in one configured namespace. Workspace
isolation is therefore logical only: platform operators cannot map each
OpenShell workspace to its own pre-provisioned Kubernetes namespace while
retaining one shared gateway.

This is a focused prerequisite for the broader platform-managed sandbox request
in #1678 and the operator-managed model in RFC 0011.

Proposed Design

Add an explicit workspace-to-namespace mapping to the Kubernetes driver:

  • Configure a map of OpenShell workspace names to existing Kubernetes
    namespaces.
  • Resolve the target namespace from DriverSandbox.workspace before creating
    the Agent Sandbox Sandbox resource.
  • Reject sandbox creation for an unmapped workspace when mapping mode is
    enabled; never silently fall back to another tenant's namespace.
  • Keep the existing single namespace behavior when no mapping is configured
    for backward compatibility.
  • Make get, delete, list, watch, event lookup, and SCC discovery
    namespace-aware across the configured namespace set.
  • Preserve the logical workspace label and resource-name mapping so the gateway
    can reconstruct the workspace from Kubernetes objects.
  • Do not create or delete namespaces; namespace lifecycle remains
    platform-owned.
  • Surface the map through gateway TOML and Helm values, and document the
    required namespaced RBAC.

Prefer bounded namespaced API clients over unrestricted cluster-wide
create/delete permissions. A separately installed workspace chart can bind the
shared gateway ServiceAccount in each mapped namespace. Tests should cover
mapped creation, unmapped fail-closed behavior, duplicate namespace mappings,
cross-namespace list/watch, delete/get resolution, and legacy single-namespace
mode.

Alternatives Considered

  • Workspace name always equals namespace: simple but cannot integrate with
    platform naming conventions or existing namespaces.
  • Caller-supplied namespace on every sandbox request: more flexible, but
    expands the trusted API surface and requires a separate authorization policy
    to prevent namespace confusion.
  • Cluster-wide list/watch/create/delete: operationally simple but grants
    broader permissions than a configured namespace allowlist.
  • One gateway per namespace: works with the current driver but duplicates
    control-plane state and operations.

Agent Investigation

Checklist

  • I've reviewed existing issues and the architecture docs
  • This is a design proposal, not a "please build this" request

Activity

  1. dhirajsb commented on Jul 27, 2026

    @dhirajsb
    ContributorAuthor

    📋 triage-agent

    Triage Assessment

    Classification: feature-valid

    Summary

    The runtime limitation is confirmed and an explicit, fail-closed
    workspace-to-namespace allowlist is feasible. The scope is broader than
    sandbox creation because lifecycle watches, events, SCC discovery, and
    Kubernetes ServiceAccount bootstrap authentication also assume one namespace.

    Investigation

    The Kubernetes driver builds create/get/list/delete/watch clients from one
    config.namespace. Gateway pod and Sandbox owner validation is likewise
    namespaced. This issue is not a duplicate: #1678 is a broader
    platform-managed namespace/Secret/claim proposal, and draft RFC 0011 describes
    identity-based operator namespaces rather than an arbitrary explicit map.

    Recommendation

    Treat this as a focused prerequisite to #1678. Before implementation,
    maintainers should confirm whether explicit mapping supplements RFC 0011's
    operator mode and should coordinate namespaced RBAC with #2485.

  2. dhirajsb commented on Jul 27, 2026

    @dhirajsb
    ContributorAuthor

    I am happy to contribute the implementation for this feature rather than leaving it as a request for another contributor.

    I have a working experimental implementation on my fork: https://github.com/dhirajsb/OpenShell/tree/codex/k8s-workspace-namespace-mapping

    The spike adds an explicit, fail-closed workspace-to-Kubernetes-namespace map and applies it across sandbox create/get/list/delete/watch behavior, OpenShift SCC lookup, and Kubernetes ServiceAccount bootstrap authentication. It preserves the existing single-namespace behavior when no map is configured and includes Rust and Helm tests that pass locally.

    If maintainers confirm how this should align with RFC 0011 and the namespaced RBAC work in #2485, I can rebase the branch onto current main, incorporate the requested direction, and submit the PR with this issue linked.

  3. lbelyaev commented on Jul 27, 2026

    @lbelyaev

    The fail-closed-on-unmapped default is the right call, and worth treating as non-negotiable: namespace_for_workspace erroring when a configured map has no entry for the workspace — rather than falling back to the legacy namespace — is exactly right, because a silent fallback would put one tenant's sandbox in another tenant's namespace, which is the failure this is meant to prevent. We run a workspace-scoped model and treat any silent widening of a tenant boundary as a defect, not a convenience.

    On the RFC 0011 coordination question you raised: this mapping and the workspace-authorization work in #2445 are two enforcement layers for the same tenant boundary, and they key the same way. Your workspace_namespaces map is keyed by workspace name; #2445 resolves workspace membership by name too (get_message_by_name(&workspace, &subject)). If a workspace is deleted and a new one is created with the same name, both layers can rebind to it off that reused name — independently. If they rebind out of step (one config updated, one stale), a caller authorized for the new workspace could resolve into the old workspace's namespace, or the reverse. Keying both to the workspace's identity rather than its name closes that and keeps the two layers from disagreeing — which is the coordination point worth settling with #2445 before either lands.

    Second, on attribution: once sandboxes for different workspaces live in different namespaces, the namespace becomes part of the audit story. I see the created object carries LABEL_SANDBOX_WORKSPACE and lands in the resolved namespace, so the pairing is present at creation — but the workspace→namespace resolution itself isn't recorded as a durable fact, only reconstructable from the label plus wherever the object currently lives. If the map config changes later, re-deriving which namespace a historical sandbox belonged to leans on the current map. Recording the resolved namespace alongside the workspace label at creation would make attribution self-contained rather than dependent on config that may have moved.

  4. dhirajsb commented on Aug 4, 2026

    @dhirajsb
    ContributorAuthor

    @NVIDIA/openshell-codeowners, could you please help with triage on this proposal?

    Does an explicit, fail-closed workspace-to-namespace mapping sound useful for the shared-gateway deployment model? If so, would you be comfortable moving this through validation/acceptance and approving me to contribute the implementation as a PR?

    I have an experimental, tested branch linked above and can revise it to address the identity and durable-attribution feedback in this thread. I would also appreciate guidance on whether this should be folded into #1678, RFC-0011, #2445, or another implementation already in progress.

  5. removed
    state:triage-neededOpened without agent diagnostics and needs triage
    on Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions