Repository navigation
ci: platform-prod-secrets mints a fresh link keyset and drops the JWT copy - #32593
Conversation
… copy cmux-platform-production takes over NEXT Cloud's CloudDO with a fresh namespace. Production never issued a link token and only Cloud VMs verify them, against the keyset the platform itself serves, so the job mints a fresh CLOUD_LINK_SIGNING_KEYS (scripts/cmux-next/release/mint-link-keyset.mjs) and pipes it into wrangler when the Worker lacks it. JWT_PRIVATE_JWK is dropped: the platform verifies cmux-api's install tokens against cmux-api's public JWKS. test-node/link-keyset-mint.test.ts checks the minted value against parseSigningKeys, signingKid and publicKeyset. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-006ebbba01a09f9367e7
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Shipped in:
|
…put, failing closed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-006ebbba01a09f9367e7
|
Review (codex gpt-6.1-sol high, sweep, via the review router; full diff from merge base ddcaf92 to this head): BLOCK at 77d9d50 [P2] [blocking] .github/workflows/platform-prod-secrets.yml:59 - The initial secret listing is stale when the workflow reaches |
|
Review (codex gpt-6.1-sol high): SHIP at e2abf03 First pass at 77d9d50 blocked on the non-atomic list-then-put; the delta re-reads the list right before each put and makes that check fail closed (Cloudflare offers no create-if-absent). Re-review of the delta: narrowed race acceptable for this dispatch-only one-off; mint format matches parseSigningKeys, no value reaches logs or disk, empty or failed mint puts nothing, runs-on unchanged, test wired into backend.yml test:node. Follow-ups: none |
…atch) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-006ebbba01a09f9367e7
What.
.github/workflows/platform-prod-secrets.yml(dispatch-only, environmentcmux-next-production) now puts two secrets on thecmux-platform-productionWorker instead of three:CLOUD_LINK_SIGNING_KEYS: when the Worker lacks it, the job mints a fresh value with the newscripts/cmux-next/release/mint-link-keyset.mjsand pipes it intowrangler secret put. The environment'ssecrets.CLOUD_LINK_SIGNING_KEYSis no longer read.CLOUD_FREESTYLE_API_KEY: unchanged (from the environment'sFREESTYLE_API_KEY, only when missing).JWT_PRIVATE_JWK: dropped from env and the loop.Why. The platform takes over NEXT Cloud's CloudDO with a fresh namespace. Production has never issued a Cloud link token, and link tokens are verified only by Cloud VMs, against the keyset the platform itself serves (the bind answer and
GET /v1/cloud/keyset, both forwarded to the platform). Nothing verifies a link across Workers, so a fresh keyset minted for the platform is correct and cmux-api's copy (a Worker secret only) is not needed. The platform verifies cmux-api's install tokens against cmux-api's public JWKS (a separate cmux-platform change), so it needs noJWT_PRIVATE_JWKcopy.Format.
{"active":"<kid>","keys":{"<kid>":{"kty":"OKP","crv":"Ed25519","x":...,"d":...,"kid":"<kid>"}}}, kidproduction-<YYYY-MM-DD>(UTC), matching/^[A-Za-z0-9._-]{1,64}$/. This is whatparseSigningKeysaccepts inbackend/apps/api/src/link-token.ts(and the identical cmux-platform parser). One kid with nopublished_atsigns at once (signingKid), which is what we want since no production VM holds an older keyset.Guarantees.
echo, no file, noset -x.wrangler secret listdoes not show it.set -euo pipefail, the mint is a command substitution (a failed mint stops the job), and an empty value is refused before anything is put. The script itself exits non-zero, printing nothing, on a bad kid or an unexpected JWK shape.runs-onis unchanged. The checkout is sparse (just the mint script) withpersist-credentials: false.Tests.
backend/apps/api/test-node/link-keyset-mint.test.ts(Node vitest, runs in the backend workflow'stest:nodestep; the mint script was added to that workflow's paths):parseSigningKeysaccepts the output, exactly one kid, it is the active kid,signingKid(keys, Date.now())returns it,publicKeysethas nod, two runs differ, and a bad prefix exits 2 with empty stdout. Passed locally (3/3).python3 tests/test_ci_linux_single_size.py,tests/test_ci_fork_runner_routing.py,tests/test_ci_no_single_size_pins.py,tests/test_ci_checkout_network_diagnostics.py,tests/test_ci_actionlint_covers_every_workflow.py: all pass.Agent session: agent session
🤖 Generated with Claude Code
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Reworks
platform-prod-secrets.ymlsocmux-platform-productiongets a freshly minted Cloud link signing keyset instead of a copy fromcmux-next-production, and dropsJWT_PRIVATE_JWKfrom the workflow.Production never issued a link token, and link tokens are verified only by Cloud VMs against the keyset the platform itself serves. The platform verifies cmux-api's install tokens against cmux-api's public JWKS, so it needs no private JWK copy.
scripts/cmux-next/release/mint-link-keyset.mjsmints a single Ed25519 kid (production-<UTC date>) that signs immediately; the workflow pipes its stdout intowrangler secret putonly when the Worker lacks the secret.CLOUD_FREESTYLE_API_KEYis unchanged.link-keyset-mint.test.tsruns in the backendtest:nodestep and validates the keyset againstparseSigningKeys,signingKid, andpublicKeyset; the mint script was added to that workflow's trigger paths.feat-cmux-next.Written for commit 6cab35d. Summary will update on new commits.