HOLD: api: forward the Cloud surface to cmux-platform-staging (staging only)

Closed
TE
3d ago
+4-1

HOLD: do not land until every precondition below is met on cmux-platform-staging. This PR turns cmux-api-staging's Cloud surface over to cmux-platform-staging; with any precondition unmet, Cloud requests on staging are either served locally (no binding) or forwarded to a platform Worker that answers 404 for them.

What this changes

backend/apps/api/wrangler.jsonc, the staging env only:

  • "PLATFORM_SURFACES": "cloud" in vars: the forwarder from #29400 (src/platform-forward.ts) sends NEXT Cloud's ops (cloud:CloudDO owner on /v1/ops and /v1/read) and its machine routes (/v1/cloud/bind, /v1/cloud/keyset, acpmux, client-session, guest) to the platform.
  • "services": [{ "binding": "PLATFORM", "service": "cmux-platform-staging" }]: the binding the forwarder fetches through.

Development and production are untouched. No production flip.

Context: the platform side merged in manaflow-ai/cmux-platform#235, #237 (38f241af) and #236 (6a54e55e). Its CLOUD_DO binds cmux-api's own CloudDO through script_name, so a forwarded request meets the same Durable Object and data (docs/port-cloud-worker.md 3.2).

Preconditions, checked read-only on 2026-10-31

What is already true:

  • cmux-api-staging's live deploy (e736ec5f, 14:50Z) already contains the forwarder (#29400); with this PR unmerged it is inert.
  • cmux-platform-staging is live at 6a54e55e (#236's merge). Its health answers ok; POST /v1/cloud/keyset answers route.not_found (Cloud routes off, as expected).
  • cmux-api-staging has the JWT_PRIVATE_JWK secret.

Still unmet on cmux-platform-staging:

  1. Config PR in cmux-platform (lane work, not a secret). The staging block of cmux-platform's wrangler.jsonc has only COMMIT_SHA. It needs:

    • vars ENVIRONMENT: "staging" (the install-token issuer https://cmux-api/staging; machine routes 404 without it), STACK_PROJECT_ID (cmux-api-staging's), CLOUD_ROUTES_ENABLED: "true";
    • Durable Object bindings to cmux-api-staging's own classes with script_name: "cmux-api-staging": CLOUD_DO (CloudDO), USER_DO (UserDO), TEAM_DO (TeamDO), DOMAIN_DO (DomainDO);
    • the CLOUD_KEYSET_LIMIT rate limit on cmux-api-staging's namespace (1162), so both Workers share one count.

    scripts/check-inert.ts refuses all of this today: CLOUD_ROUTES_ENABLED is in NEVER_VARS for every environment, and CLOUD_DO/USER_DO/CLOUD_KEYSET_LIMIT are development-only. The same PR must move them to allowed-in-staging. Note development does not set CLOUD_ROUTES_ENABLED yet either, so the routes have not been exercised behind the forwarder in any deployed environment.

  2. [outward] Secret JWT_PRIVATE_JWK on cmux-platform-staging, the same value as cmux-api-staging's (which has it). cmux-platform-staging's only secret today is INTERNAL_TOKEN. Setting it copies a signing key between Workers, so it is Leo's step.

  3. [outward] Secret CLOUD_LINK_SIGNING_KEYS on cmux-platform-staging, matching cmux-api-staging. cmux-api-staging does not have this secret either today (its own CloudDO and cloud-link.ts read it), so the key set has to be created and put on cmux-api-staging first, then the same value on cmux-platform-staging. Leo's step.

Order to land: (1) merges and deploys, Leo places (2) and (3), a check shows POST /v1/cloud/keyset on cmux-platform-staging no longer answers route.not_found, then the HOLD line comes off and this PR lands. Rollback is reverting this PR (or removing PLATFORM_SURFACES): the forwarder returns at once with the var unset.

Risk

Staging only. With the binding present and PLATFORM_SURFACES set, a platform that cannot be reached answers a retryable owner.unreachable 503 and the request is not replayed locally. That is why this waits on the preconditions instead of landing ahead of them.

cmux-platform: this is cmux-api config only (the forwarder wiring from #29400); the Cloud code it forwards to already lives in manaflow-ai/cmux-platform.

šŸ¤– Generated with Claude Code

Agent session: agent session


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

HOLD: do not merge until the staging preconditions below are met.

Turns cmux-api-staging's Cloud surface over to cmux-platform-staging. Adds PLATFORM_SURFACES: "cloud" and the PLATFORM service binding to the staging env only; development and production are untouched.

Preconditions

  • cmux-platform-staging must be configured with ENVIRONMENT, STACK_PROJECT_ID, CLOUD_ROUTES_ENABLED, DO bindings to cmux-api-staging's classes, and the shared CLOUD_KEYSET_LIMIT rate limit.
  • JWT_PRIVATE_JWK and CLOUD_LINK_SIGNING_KEYS secrets must be placed on cmux-platform-staging matching cmux-api-staging's values.

With any precondition unmet, forwarded requests either answer 404 from the platform Worker or a retryable 503 if the platform is unreachable. Rollback is reverting this PR or removing PLATFORM_SURFACES.