Repository navigation
feat(gateway): multi-sandbox approval inbox via streaming proposal updates #1612
Description
Problem Statement
The agent-driven policy approval loop landing in #1097 / #1528 ships a single-sandbox CLI/TUI review flow as the locked MVP. Reviewers operating across multiple sandboxes today must either watch the TUI per-sandbox or poll GetDraftPolicy per sandbox via gRPC.
This is workable for a developer running one or two sandboxes, but blocks two patterns we are already seeing from real customer adoption:
- Platform teams running cohorts of agents (e.g., 20-team rollouts) where a small reviewer pool needs a single inbox view across the fleet instead of N tabs.
- Web/Slack approval adapters built on top of the gRPC contract — without a streaming or aggregated surface they have to long-poll per sandbox to keep an inbox UI live.
The #1062 umbrella explicitly lists "Multi-sandbox approval inbox" under Follow-Up Themes and "Multi-sandbox push inbox / WatchProposals" as an MVP non-goal. This issue promotes that follow-up theme into a discrete tracking item.
Proposed Design
Add an aggregated proposal inbox surface to the existing gRPC service so reviewers see one prioritized stream across all sandboxes they have access to.
Two surfaces:
ListProposalInbox— unary RPC. Aggregates pending (and optionally approved/rejected) draft chunks across sandboxes the caller hasconfig:readfor, with pagination and filtering (sandbox label selector, status, age, has-finding). Returns the sameDraftChunkshape used byGetDraftPolicyplus asandbox_reffield so the client can disambiguate.WatchProposalInbox— server-streaming RPC. Emits inbox-level deltas (chunk added, status changed, reloaded) so a long-lived UI does not have to poll. Resumable via an opaque cursor so disconnects do not require a full re-list.
Both RPCs reuse the existing RBAC model (caller's config:read set defines visibility; admin role required for write RPCs which remain per-chunk and per-sandbox). Both reuse the existing DraftChunk, validation_result, and audit shapes — no new schema beyond the inbox envelope and the cursor.
CLI surface: extend openshell rule get with --all-sandboxes and add openshell rule watch as a stream consumer for terminal use. TUI: extend the existing SandboxDraft pane into a Dashboard-scope inbox tab as a follow-up; out of scope for this issue beyond defining the contract.
Alternatives Considered
- Per-sandbox long-polling from clients. Workable for small N but does not scale to fleet review and produces N times the gateway load. Forces every partner-built approval UI to reinvent aggregation.
- Push to external webhook/Slack from the gateway. Couples the gateway to specific transport adapters and pushes auth/retry concerns into the core. Better implemented as a partner adapter on top of
WatchProposalInbox. - In-place expansion of
GetDraftPolicyto acceptsandbox_id=*. Conflates the per-sandbox and fleet shapes, weakens RBAC scoping in a single RPC, and gives no path to streaming.
Agent Investigation
- Confirmed the loop is single-sandbox by design today: `crates/openshell-server/src/grpc/policy.rs` exposes `GetDraftPolicy`, `ApproveDraftChunk`, etc., all scoped to one sandbox.
- Confirmed in OpenShell Agent-Driven Policy Management #1062: "Multi-sandbox push inbox / `WatchProposals`" is an explicit MVP non-goal and "Multi-sandbox approval inbox" is listed under Follow-Up Themes.
- TUI (`crates/openshell-tui/src/sandbox_draft.rs`) ties inbox state to a specific sandbox screen; no Dashboard-scope inbox exists.
- gRPC service contract (`proto/openshell.proto`) is the natural extension point; streaming RPCs are already used elsewhere in the service.
Related
- Parent umbrella: OpenShell Agent-Driven Policy Management #1062
- Builds on: feat(gateway): persist and validate agent policy proposal operations #1097, feat(policy): add agentic approval loop #1528
- Adjacent: Python and TypeScript SDK Support #1044 (SDK consumers of this surface)
Activity
github-actions commentedon Jun 13, 2026
This issue has had no activity for 14 days and is now marked stale. It may be closed in 7 days if there is no further activity. Comment or remove the state:stale label to keep it open.
zredlined commentedon Jul 2, 2026
Closing as deferred/not currently roadmap-committed. A multi-sandbox approval inbox is a useful enterprise follow-up, but it is not required for the managed maximum policy MVP in #2109. We can reopen or file a fresh issue when fleet approval UX is prioritized.