Skip to content

Scope createAgentTask to the window's team (REV-2331) - #15564

Open
warp-agent-staging[bot] wants to merge 1 commit into
masterfrom
factory/team-header-agent-tasks
Open

Scope createAgentTask to the window's team (REV-2331)#15564
warp-agent-staging[bot] wants to merge 1 commit into
masterfrom
factory/team-header-agent-tasks

Conversation

@warp-agent-staging

Copy link
Copy Markdown
Contributor

Summary

Scopes createAgentTask to the window's team by sending X-Warp-Team-Uid, using the transport landed in #15557 (REV-2331). Without the header, the server falls through GetActiveTeamOrFallbackToPrincipal to the lowest-id team when deciding a locally-created task's owner (team vs. personal, for billing/visibility purposes).

Of the operations in this group — createAgentTask, updateAgentTask, the runner CRUD (getRunners, upsertRunner, deleteRunner), and upsertCloudEnvironment — only createAgentTask turned out to need (and be able to receive) a header. Each other operation is addressed below with why it was left unscoped.

Changes

  • AIClient::create_agent_task now takes team_scope: Option<RequestTeamScope> and sends it via a new ServerApi::send_team_scoped_graphql_request helper (mirrors send_graphql_request, using the transport's graphql_request_options_with_team).
  • The two window-scoped call sites resolve a real scope and thread it through:
    • terminal_pane.rs::launch_local_no_harness_childchild_agent_launch::prepare_local_oz_child_launch, via ViewContext<PaneGroup>.
    • terminal_pane.rs::launch_local_harness_childlocal_harness_launch::prepare_local_harness_child_launch, same source.
    • Both use RequestTeamScope::from_scope(&UserWorkspaces::as_ref(ctx).team_context_for_view(ctx)), the established pattern from Scope /ai/transcribe to the window's team #15554.
  • Two call sites are left deliberately unscoped (marked inline, see below), so create_agent_task's team_scope parameter is Option rather than mandatory.

Left unscoped, with reasons

  • create_agent_task from warp agent run (app/src/ai/agent_sdk/mod.rs::initialize_new_task): this is the headless CLI path (AgentDriverRunner::setup_and_run_driver, driven by RunAgentArgs). There is no window, and RunAgentArgs — unlike RunCloudArgs, which has ObjectScope/--team — has no team flag to resolve one from. Passing None preserves today's behavior.
  • create_agent_task from the TUI (crates/warp_tui/src/orchestration_model.rs::begin_local_oz_child_launch): the TUI does have its own window/team-per-window concept (see team_menu.rs), but the constructors that turn a WindowId into a TeamContext/RequestTeamScope (UserWorkspaces::team_context_for_view and friends) are pub(crate) to the app crate and not exposed across the crate boundary to warp_tui. Exposing one felt like a bigger call than this PR should make unilaterally, so I left it None and flagged it here rather than adding a new public constructor.
  • update_agent_task: server-side (logic/ai/ambient_agents/update_agent_task.go), this resolver never calls GetActiveTeamOrFallbackToPrincipal — authorization is entirely by workload token / task ownership, not active team. Sending the header would be a no-op. Its only call sites are inside the headless AgentDriver background process anyway (no ViewContext reachable there, regardless of how the task was launched), so there's no live scope to send even if the server did consume it.
  • get_runners: server-side logic.GetRunners returns everything the principal can see across every team plus personal (via GetAccessibleGenericStringObjectsByFormat), with no per-team filter. Scoping it would be a no-op.
  • delete_runner: authorized entirely off the resolved runner object (ResolveRunnerConfig + AgentPlatformRunnersDeleteAction); no team parameter enters the resolver at all.
  • upsert_runner (create path, oz runner create): already names its team explicitly via input.owner (resolved from --team/--personal/sole-team in common::resolve_owner), so per the "already names a team" rule this must keep sending no header — and does.
  • upsert_runner (update path, oz runner update): owner is intentionally None on update (an update shouldn't reassign ownership), and the server does fall through GetActiveTeamOrFallbackToPrincipal for the resulting team value, which factory-uid and registry-credential-owner validation then use. This is a real instance of the bug. But RunnerCommandRunner::update_runner is a headless CLI path (oz runner update) with no window, and UpdateRunnerArgs has no --team flag to resolve one from. I could derive the runner's own current owner from the get_runners() lookup already performed here (existing.scope.uid), but that would require a second construction path outside RequestTeamScope/TeamScope, which the brief for this migration explicitly rules out. Flagging this rather than building new CLI/infra scope plumbing unprompted.
  • upsert_cloud_environment: not called by this client at all (no Rust codegen or call site references it) — nothing to scope.

Verification

  • ./script/format
  • cargo clippy -p warp --lib --tests -- -D warnings — clean
  • cargo check -p warp --lib --tests — clean
  • ./script/bundle --channel oss --nouniversal --check-only — clean (only pre-existing, unrelated warnings in warp_terminal)
  • cargo nextest run -p warp -E 'test(local_harness_launch) or test(child_agent_launch) or test(terminal_pane)' — 27 tests passed
  • Could not build/test crates/warp_tui in this sandbox: cargo check -p warp_tui --lib --tests fails on unmodified master too, with a pre-existing, unrelated E0046 missing get_cursor_shape error in crates/warpui. My one-line change there (passing None plus a comment) is a minimal, mechanical addition to an existing call site.

@cla-bot cla-bot Bot added the cla-signed label Aug 26, 2026
@warp-agent-staging
warp-agent-staging Bot marked this pull request as ready for review August 26, 2026 05:23
@warp-agent-staging

warp-agent-staging Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

This PR was generated with Warp.

Comment @warp-factory on this PR to send it follow-up work.

View run View conversation View on Slack

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants