Repository navigation
fix(deploy): use the cloud workspace id for cloud API calls - #342
Conversation
resolveWorkspaceToken returned the relaycast workspace id as `workspace`, so after `agentworkforce login` every cloud call built from it (deployments list, destroy, deploy, runs, trigger, integrations, runtime-credentials, local-surface) hit /api/v1/workspaces/<rw_id>/... and got 403 Forbidden. - Return descriptor.cloudWorkspaceId as `workspace`; expose the relaycast id separately as `relaycastWorkspaceId`. - Drop the silent cloudWorkspaceId -> relaycastWorkspaceId fallback in the resolve normalizer. A missing cloud id (or one that is really a relay id, as @agent-relay/cloud's own normalizer falls back to) now fails with an actionable error. - local-surface looks up fleet node enrollments by the relaycast id (they are keyed by relayWorkspaceId) and uses the cloud id elsewhere. - Reject a relaycast workspace key (rk_...) in WORKFORCE_WORKSPACE_TOKEN up front; cloud APIs only accept cloud bearers and it 401s later. - `agentworkforce login` prints the cloud workspace id, warns when absent. - Docs: explain cloud vs relaycast ids and the correct token source for the WORKFORCE_WORKSPACE_ID/TOKEN override. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (11)
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe deploy package now validates cloud workspace IDs and tokens separately from Relaycast identifiers. CLI login reports the cloud workspace ID or warns when it is missing. Local-surface enrollment lookup uses the Relaycast workspace ID. ChangesWorkspace identity and CLI behavior
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix Sequence Diagram(s)sequenceDiagram
participant CLI
participant WorkspaceAuthResolver
participant CloudAPIs
participant FleetEnrollmentAPI
CLI->>WorkspaceAuthResolver: Resolve workspace credentials
WorkspaceAuthResolver-->>CLI: Cloud workspace ID, Relaycast workspace ID, and token
CLI->>CloudAPIs: Send cloud request with cloud workspace ID
CLI->>FleetEnrollmentAPI: Look up enrollment with Relaycast workspace ID
Merge Risk: ⚪ Minimal · up to Cloud commands now use the cloud workspace ID and fail with clear guidance when it is missing. Fleet enrollment keeps using the Relaycast ID. I found no merge-blocking risk in the supplied changes. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The change strengthens workspace identity separation and rejects known Relaycast credentials before cloud operations. No newly introduced security weakness was established. Cloud authorization scope and recovery behavior for interrupted or concurrent login and enrollment remain unverified. Retained concerns Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 6 files. (5 skipped: 5 unsupported.) ✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. A rabbit checks the workspace name, Comment |
There was a problem hiding this comment.
Devin Review found 1 potential issue.
2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4b07199. Configure here.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4b07199ab7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ent lookup Env-override auth (WORKFORCE_WORKSPACE_ID + WORKFORCE_WORKSPACE_TOKEN) carries only the cloud workspace id; fleet enrollments are keyed by the relaycast id. Resolve it via /api/v1/workspaces/<id>/resolve before the lookup, falling back to the given id. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
End-to-end verification (real CLI binaries)OLD = published 1. Prod API (
|
| Case | Request | Result |
|---|---|---|
| OLD, login session | GET /workspaces/rw_…/deployments |
200 (our relay id happens to be bound, so it works here) |
| NEW, login session | GET /workspaces/<cloud-uuid>/deployments |
200 |
NEW, --workspace <cloud-uuid> |
/resolve then /workspaces/<cloud-uuid>/deployments |
200 |
NEW, env override: cloud id + cloud-auth.json accessToken (documented CI path) |
/workspaces/<cloud-uuid>/deployments |
200 |
OLD, env override with the rk_ key from workspaces.json (old agents README recipe) |
/workspaces/<cloud-uuid>/deployments |
401 unauthorized |
NEW, same rk_ recipe |
no request sent | fails fast: "WORKFORCE_WORKSPACE_TOKEN is a relaycast workspace key (rk_...) …" with fix steps |
2. Customer condition: relaycast id not bound to an app workspace
Our account's only workspace has a bound relay id, so this case was run against a local stub. The stub follows cloud's rules: /resolve returns the descriptor shape from resolve-workspace-request.ts, and /deployments applies resolveDeploymentWorkspace (an unbound rw_ id gets 403; a UUID gets 200). The CLI binaries are real.
| Case | OLD 4.1.59 | NEW |
|---|---|---|
Relaycast id unbound, cloudWorkspaceId present |
GET /workspaces/rw_bbbb2222/deployments → list failed: 403 {"error":"Forbidden","code":"forbidden"}, the customer's exact error |
GET /workspaces/<cloud-uuid>/deployments → 200, "No deployed agents found." |
/resolve returns cloudWorkspaceId: null |
silently uses rw_… → 403 |
no deployments call; actionable error naming the relaycast id and the fix (agentworkforce login / --workspace <cloud-workspace-id> / support) |
Unit/integration: deploy 297/297, cli 396/396, local-surface 19/19, mcp-workforce 27/27; CI check green.
4.1.60 includes AgentWorkforce/workforce#342: cloud API calls use the cloud workspace id (fixes 403 on deploy / deployments list / destroy after login), rk_ keys in WORKFORCE_WORKSPACE_TOKEN are rejected up front, and login prints the cloud workspace id. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
4.1.61 is the current `latest` and carries the AgentWorkforce/workforce#342 cloud-workspace-id fix; the release was re-cut after npm propagation lag on 4.1.60. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Problem
After
agentworkforce login,deployments list,destroyanddeployfail with403 {"error":"Forbidden","code":"forbidden"}from/api/v1/workspaces/<id>/deployments.resolveWorkspaceToken(packages/deploy/src/login.ts) returnedworkspace: descriptor.relaycastWorkspaceId. Cloud APIs are scoped by thecloud workspace id (UUID). Using
descriptor.cloudWorkspaceIdreturns 200.On top of that, the resolve normalizer fell back to the relaycast id
(
cloudWorkspaceId: … ?? relaycastWorkspaceId), and so does@agent-relay/cloud'sactive-workspace normalizer (it falls back to
workspaceId, the relay id). Cloud's/resolvereturnscloudWorkspaceId: nullfor a relay workspace with no cloud binding,so a missing id was silently replaced with an id that cloud rejects.
Audit
Every
/api/v1/workspaces/<id>/…call in the CLI takes its id fromresolveWorkspaceToken().workspace:deploy(deploy.ts,modes/cloud,connect.ts,modes/sandbox-client.ts)deployments list,runs,trigger(list-command.ts)destroyenvintegrations(integrations-list.ts)local-surfacelocal-surfacefleet enrollment lookupfleetstore keyed byrelayWorkspaceIdSo the fix goes at the source, plus one targeted change in local-surface.
Changes
resolveWorkspaceTokenreturns the cloud workspace id asworkspaceand exposesrelaycastWorkspaceIdseparately for relaycast/fleet consumers.id (the SDK fallback case), the CLI stops with an actionable error. The error
names the relaycast id and tells the user to re-run
agentworkforce loginorpass
--workspace <cloud-workspace-id>.local-surfacelooks up fleet enrollments with the relaycast id and uses thecloud id everywhere else.
WORKFORCE_WORKSPACE_TOKENset to a relaycast workspace key (rk_…, thekeyin
workspaces.json) is now rejected up front with guidance. Cloud requestauth never accepts those keys, so it could only ever 401. The token value is
never echoed.
agentworkforce loginprints the cloud workspace id, and warns when theworkspace has no linked cloud workspace.
packages/cli/README.md(cloudvs relaycast ids, correct token source for the CI override). Also fixed the
customer onboarding doc, the weekly-digest example and the mcp-workforce README.
CHANGELOG
[Unreleased]entry.Tests
These fail on
mainand pass with the fix:login.test.ts: explicit--workspacereturns the cloud id; the activeworkspace (via
workspaces.json) returns the cloud id; a missingcloudWorkspaceIdfails loudly; the SDK relay-id fallback is rejected; anrk_env token is rejected and not echoed. (5 fail on main.)local-surface-command.test.ts: cloud id for cloud APIs, relaycast id forthe enrollment lookup.
deploy-command.test.ts: login prints the cloud id, or warns when it is absent.pnpm testresults: deploy 297/297, cli 395/395, local-surface 19/19, mcp-workforce 27/27.Release note
Needs a patch release of
@agentworkforce/deploy,@agentworkforce/cliandagentworkforce. It is not published by this PR.🤖 Generated with Claude Code
Note
Medium Risk
Changes central workspace auth resolution used by most CLI cloud commands; behavior is stricter (fail-fast) but corrects mis-scoped API paths and bad tokens.
Overview
Fixes 403 Forbidden (and confusing 401) after
agentworkforce loginby scoping cloud API calls to the cloud workspace UUID, not therw_…relaycast id.resolveWorkspaceToken(@agentworkforce/deploy) now returns the cloud id asworkspace, addsrelaycastWorkspaceIdfor relaycast/fleet only, and stops when resolve omits a real cloud id (including when normalizers would silently fall back to a relay id).WORKFORCE_WORKSPACE_TOKENvalues that look like relaycast keys (rk_…) are rejected up front with setup guidance.agentworkforce loginprints the cloud workspace id and warns if the workspace has no linked cloud workspace.local-surfaceuses the cloud id for deployments andPOST /api/v1/fleet/local-surface, but still keys fleet enrollment off the relaycast id (with a resolve call when CI env auth only has the cloud id).Docs and changelog clarify cloud vs relaycast ids and correct CI env vars for
deploy,deployments list,destroy,runs,trigger, and related commands.Reviewed by Cursor Bugbot for commit 04a4659. Bugbot is set up for automated code reviews on this repo. Configure here.