Skip to content

feat(api)!: replace implicit workspace selection with typed scope selectors #3048

Description

@drew

User Story

As an API or SDK client, I want workspace scope represented explicitly in request types, so that I can distinguish one workspace, the default workspace, and all workspaces without relying on empty strings or mutually exclusive booleans.

Problem Statement

Many requests document an empty workspace string as selecting default. Several also pair workspace with all_workspaces and describe mutual exclusion only in comments. Proto3 scalar fields cannot distinguish an omitted string from an explicitly empty string, and the wire type permits contradictory combinations.

Impact / Why This Matters

Clients cannot express intent precisely, generated SDKs must reproduce prose-only validation, and future changes to default-workspace behavior would require a breaking request-shape change. The ambiguity is especially visible in Kubernetes operator mode, where the gateway's logical default workspace may not be usable as a Kubernetes namespace.

Proposed Design

Introduce a reusable, presence-aware workspace selector for requests that need scope. It should distinguish:

  • one explicitly named workspace;
  • all authorized workspaces, where the RPC supports it; and
  • omitted scope, only if OpenShell deliberately retains a documented default-workspace behavior.

Use a message or oneof so contradictory states are unrepresentable. Do not introduce magic string sentinels.

Acceptance Criteria

  • All affected public requests use the same typed workspace-selection convention.
  • A request cannot encode both one workspace and all workspaces.
  • Omitted, empty, default, and all-workspaces behavior is explicitly decided and documented.
  • Authorization is evaluated against the selected scope consistently.
  • Rust, Python, TypeScript, and Go SDKs expose the same scope choices idiomatically.
  • CLI and TUI behavior remains intentional and documented, including commands that omit --workspace.
  • Old fields are removed or migrated with reserved names/tags and migration guidance.
  • Tests cover named, default/omitted, all-workspaces, unauthorized, and malformed cases.

Alternatives Considered

Keep workspace plus all_workspaces and enforce mutual exclusion in handlers. This leaves invalid states in every generated client and does not solve presence ambiguity. Use workspace: "-" as an all-workspaces sentinel. This is compact but introduces magic-string semantics without adopting a broader hierarchical resource-name convention.

Agent Investigation

The current protobuf contains repeated workspace plus all_workspaces patterns, and the Python, TUI, and other clients construct those fields directly. Kubernetes operator-mode default workspace semantics are separately discussed in #2971.

Related: #2565, #2971. Source audit: https://gist.github.com/mrunalp/e80942c1544a0225ee588796a41ab30b.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions