cmux-next iPhone: production naming (cnx -> cmux-mobile) in code, wire names and backend

Merged
AZ
17d ago
+5744-5316

Summary

The cmux-next iPhone app, its Mac host and its Worker were built under the development tag "cnx". This renames every "cnx" identifier in shipped code, scripts, CI and infrastructure to production naming. Nothing shipped outside cmux INTERNAL, so wire names change outright, with no period where both are accepted (the user's decision). Builds up to 1.2.0 stop connecting; the next TestFlight build and a cmux NEXT build of this branch work together.

Most of the diff is one scripted commit (628acefd, paths and identifiers). The later commits are hand-written: storage migrations, test vectors, lockfiles, regenerated uniffi bindings, the builder gate and docs.

Naming map

OldNew
cnx-ios/cmux-next-ios/
Swift package CnxKit, modules Cnx* (CnxTerminal, CnxLive, …), types Cnx*CmuxMobileKit, CmuxMobile* (CmuxMobileTerminal, CmuxMobileLive, …), CmuxMobile*
App target / product CnxApp, CnxApp.xcodeproj, CnxApp-*.entitlementsCmuxMobileApp
Rust crates cnx-link, cnx-hostd, cnx-fficmux-mobile-link, cmux-mobile-host, cmux-mobile-link-ffi (cmux-tui already has cmux-mobile-ffi)
uniffi module CnxFFI / CnxFFIFFI, CnxFFI.xcframework, error CnxErrorCmuxMobileLinkFFI / CmuxMobileLinkFFIFFI, CmuxMobileLinkFFI.xcframework, CmuxMobileError (cmux-tui already has CmuxMobileFFI)
Mac CnxHostSupervisor, CnxApproverSync, CnxHost*, Cnx* in CmuxNextMobile/CnxHost/MobileHostSupervisor, MobileHostApproverSync, MobileHost* in CmuxNextMobile/MobileHost/
Bundled Contents/Resources/bin/cnx-hostd, Xcode phase "Bundle cnx-hostd"Contents/Resources/bin/cmux-mobile-host, "Bundle cmux-mobile-host"
scripts/cmux-next/build-cnx-hostd.sh, bundle-cnx-hostd.sh; CMUX_NEXT_CNX_HOSTD_BIN/_ARCHS, CMUX_NEXT_REQUIRE_CNX_HOSTD, CMUX_NEXT_CNX_API_URLbuild-mobile-host.sh, bundle-mobile-host.sh; CMUX_NEXT_MOBILE_HOST_BIN/_ARCHS, CMUX_NEXT_REQUIRE_MOBILE_HOST, CMUX_NEXT_MOBILE_API_URL
Env vars and build settings CNX_* (CNX_CONTROL, CNX_API_BASE, CNX_TAG, …), Info.plist keys CNX*CMUX_MOBILE_*, CmuxMobile* (CmuxMobileAPIBase, …)
Bundle ids dev.cmux.cnx (Debug), dev.cmux.cnx.cnx (Demo), dev.cmux.cnx.<tag>, dev.cmux.cnx.proddev.cmux.mobile, dev.cmux.mobile.demo (default tag demo), dev.cmux.mobile.<tag>, dev.cmux.mobile.prod. TestFlight stays dev.cmux.app.internal
Logger subsystem dev.cmux.cnxdev.cmux.mobile
WebSocket subprotocol cnx.v1cmux-mobile.v1
Signature contexts cnx-link-auth-v1, cnx-mac-identity-v1, cnx-chief-answer-v1cmux-mobile-link-auth-v1, cmux-mobile-mac-identity-v1, cmux-mobile-chief-answer-v1
H.264 SEI tag UUID cnx-video-tag-v1 (16 bytes)cmux-mobile-vid1 (16 bytes)
Worker↔hub headers x-cnx-claim, -subprotocol, -attachment, -owner-keyx-cmux-mobile-*
WebRTC data channels cnx-link, cnx-inputcmux-mobile-link, cmux-mobile-input
Push payload key cnx, categories CNX_<KIND>cmuxMobile, CMUX_MOBILE_<KIND>
Workers cnx-ios-api-dev, cnx-ios-api-prodcmux-mobile-api-dev, cmux-mobile-api-prod
Hosts cnx-ios-api.cmux.dev, cnx-ios-api-dev.debussy.workers.devmobile-api.cmux.dev, cmux-mobile-api-dev.debussy.workers.dev
CI: workflow names "cnx-ios INTERNAL builder", artifacts cnx-ios-internal-*, keychain cnx-internal-next, build root ~/cnx-ios-builds"cmux-next iPhone INTERNAL builder", cmux-mobile-internal-*, cmux-mobile-internal, ~/cmux-mobile-builds
tests/test_cnx_ios_test_notes_retry.pytests/test_cmux_next_ios_test_notes_retry.py

Not renamed: git branches (feat-cnx-*, rc/cnx-ios-builder, rc/cnx-ios-internal-*), Packages/iOS/CmuxTabsKit and CmuxConversation (byte-identical with upstream), cmux-tui source comments and webview design prototypes (other areas; historical labels), evidence logs under cmux-next-ios/verify.

Storage (no re-pairing)

  • iOS, at launch before anything reads them (LegacyStorage): every cnx.* UserDefaults key moves to cmuxMobile.* (a value the new build already wrote wins), including the inner keys of signed-out accounts' saved records; Application Support cnx-chief-outbox.json, cnx-cloud-chief-outbox.json and cnx-live/ are renamed.
  • iOS Keychain: device ids move from service dev.cmux.cnx.device to dev.cmux.mobile.device. While the old service can't be read (a launch before first unlock), the app uses a temporary id and stores nothing, so the id a Mac approved is never shadowed.
  • Unchanged, so nothing to migrate: the TestFlight bundle id and its keychain group, the Stack token service and the phone's Secure Enclave keys (<bundle id>.phone-keys), the Mac identity Keychain service (<bundle id>.iphone-host.identity).
  • Mac: the host state folder <Application Support>/<bundle id>/cnx-host (device id, paired phones, removal marker) moves to cmux-mobile-host.
  • A Mac keeps its approvals: it stores phone keys, not signatures, and both sides sign under the new contexts.

Backend and infrastructure (done)

ResourceBeforeNow
Dev Workercnx-ios-api-devcmux-mobile-api-dev, renamed in place (same script, secrets, hub namespace), version 82529407 (API 0.11.0)
Prod Workercnx-ios-api-prodcmux-mobile-api-prod, renamed in place, version f0691e03 (API 0.11.0)
Prod hostcnx-ios-api.cmux.devmobile-api.cmux.dev (custom domain added); the old domain is removed
Dev / prod Hyperdrivecmux-next-ios-dev / cmux-next-ios (same ids)cmux-mobile-dev / cmux-mobile-prod, repointed, caching off
Dev databasecmux/cmux-next-ios-dev (earlier cmux/cnx-ios)cmux/cmux-mobile-dev, role cmux-mobile-api; rows copied (615 devices, 4 prefs); old database deleted after a final export
Prod databasecmux/cmux-next-ios (earlier cmux/cnx-ios-prod)cmux/cmux-mobile-prod, role cmux-mobile-api; rows copied (14 devices, 2 prefs, 2 push tokens); old database kept until an authenticated prod smoke passes
Leftover Workers from the first naming attemptcmux-next-ios-api, cmux-next-ios-api-dev, cnx-ios-api-userhub-dev-dev, domain cmux-next-ios-api.cmux.devdeleted

Durable Object namespaces keep the label they were created with (cnx-ios-api-*_TeamHub); Cloudflare keeps it on a Worker rename and never shows it outside the dashboard.

Continuous TestFlight builder

The signing job runs rc/cnx-ios-builder's frozen copy of the workflow and testflight-build.sh, which use cnx-ios/ paths. Until an admin fast-forwards that branch to a feat-cmux-next commit with this change, the trigger skips with a message naming the step (new gate in ios_internal_builder.py, tested) instead of dispatching doomed runs; the last upload stays installable. Admin step: git push origin <feat-cmux-next sha>:refs/heads/rc/cnx-ios-builder, then copy scripts/ci/ios_internal_builder.py to the builder mini and delete its old ~/cnx-ios-builds (documented in plans/cmux-next/ios-testflight-builder-DESIGN.md).

PR #22557 (What to Test notes) edits the same builder files and uses cnx-ios/ paths; whichever lands second takes the other's paths.

Testing

At 6f207fae (or the commit named):

  • Rust (rbx, cargo fmt --check, cargo clippy --workspace --all-targets -D warnings, cargo test --workspace --locked): green, 17 test binaries.
  • CmuxMobileKit swift test on mini-cmux11s: 857 tests passed (8a6ccdaa).
  • CmuxNext (later runs at the merged head stop at an unrelated base compile error in CmuxNextFilesTests/TransferProgressGateTests.swift, fixed on feat-cmux-next by #22572) swift test --filter 'CmuxNextMobileTests|CmuxNextMobileHostTests' on mini-cmux11s (793270c3): 66 tests, 1 failure PhoneAccessGateTests.everyAllowedCommandHasAFieldList, unrelated to the rename (DaemonLanePolicy only had comment changes here).
  • Worker tsc and vitest on mini-cmux11s: 64 tests passed. Live scripts/smoke.ts (CMUX_MOBILE_TEAM=personal) against https://cmux-mobile-api-dev.debussy.workers.dev: all checks passed.
  • iOS Production builds (simulator and device, unsigned) on mini-cmux11s and check-production-binary.sh: pass; bundle dev.cmux.mobile.prod, CmuxMobileAPIBase https://mobile-api.cmux.dev.
  • uniffi bindings regenerated by build-xcframework.sh on the mini (checksums follow the crate name) and committed.
  • Fleet Release build f94a7b2f (1fd739e9): built a universal cmux-mobile-host and bundled it. Fleet Debug build 6ede9642 (8a6ccdaa): bundled it.
  • bundle-mobile-host.sh with CONFIGURATION=Release and a universal binary: copies it to Contents/Resources/bin/cmux-mobile-host; CMUX_NEXT_REQUIRE_MOBILE_HOST=1 with no binary fails. (scripts/cmux-next/tests/bundle-cnx-hostd-release.test.sh does not exist on this base.)
  • Package.resolved policy: the renamed path triggered the check on a latent * in Frameworks/.gitignore; it now ignores only *.xcframework/.
  • Python: tests/test_ios_internal_builder.py (27, new gate case), test_cmux_next_ios_test_notes_retry.py, test_app_store_rules.py, notices test_compose_notices.py, test_toolchain_notices.py: pass. prepush-gate.py: no new violations.

Changelog

Changed: The cmux-next iPhone app and its Mac host use their production names and the service at mobile-api.cmux.dev; update both the iPhone app and cmux NEXT (builds from before this change can't connect to newer ones)

Proof

Live run over the real link, new phone build (Debug sim, 6f207fae) against the new Mac build (fleet tagged mobilenaming, 8a6ccdaa, hidden rig on mini-cmux11s, settings via open --env), dev Worker cmux-mobile-api-dev:

FlowResult
PairPass: sign-in 2.3 s, the rig Mac's workspace on the phone 0.8 s later; the Mac's paired list has only the phone's id; after a relaunch the same id, no setup, connected in 3.8 s
TerminalPass: New Terminal 3.5 s; echo naming-$((6*7)) printed naming-42 on the Mac 0.9 s after Send
Browser tabPass: example.com rendered 2.0 s after Return; frames on the media lane (carrier=webrtc-track)
Transport switchPass: WebRTC → WireGuard (TURN relay) 6.2 s, WireGuard → WebRTC direct 6.4 s; the terminal echoed after each

Mac side: cmux-mobile-host ran from Contents/Resources/bin, only CMUX_MOBILE_* variables in its environment, its log has no "cnx". Recordings stay on the laptop (~/cmux-next-ios-e2e/naming/).

CI on this PR

Reds that are not from this change (same on the base or in files this PR does not touch): crash-class rule hits in FilesPaneView+Actions.swift and MarkdownOmnibarBar.swift; localization needs_review in AccountsActions.xcstrings; workspace package groups (CmuxConversation, CmuxTabsKit missing from cmux.xcworkspace); workflow guards for macos-matrix-fuzz.yml, test-ios.yml, shallow fetch and bundle-suite tests.

🤖 Generated with Claude Code