cmux-next iPhone: production naming (cnx -> cmux-mobile) in code, wire names and backend
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
| Old | New |
|---|---|
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-*.entitlements | CmuxMobileApp |
Rust crates cnx-link, cnx-hostd, cnx-ffi | cmux-mobile-link, cmux-mobile-host, cmux-mobile-link-ffi (cmux-tui already has cmux-mobile-ffi) |
uniffi module CnxFFI / CnxFFIFFI, CnxFFI.xcframework, error CnxError | CmuxMobileLinkFFI / 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_URL | build-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.prod | dev.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.cnx | dev.cmux.mobile |
WebSocket subprotocol cnx.v1 | cmux-mobile.v1 |
Signature contexts cnx-link-auth-v1, cnx-mac-identity-v1, cnx-chief-answer-v1 | cmux-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-key | x-cmux-mobile-* |
WebRTC data channels cnx-link, cnx-input | cmux-mobile-link, cmux-mobile-input |
Push payload key cnx, categories CNX_<KIND> | cmuxMobile, CMUX_MOBILE_<KIND> |
Workers cnx-ios-api-dev, cnx-ios-api-prod | cmux-mobile-api-dev, cmux-mobile-api-prod |
Hosts cnx-ios-api.cmux.dev, cnx-ios-api-dev.debussy.workers.dev | mobile-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.py | tests/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): everycnx.*UserDefaults key moves tocmuxMobile.*(a value the new build already wrote wins), including the inner keys of signed-out accounts' saved records; Application Supportcnx-chief-outbox.json,cnx-cloud-chief-outbox.jsonandcnx-live/are renamed. - iOS Keychain: device ids move from service
dev.cmux.cnx.devicetodev.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 tocmux-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)
| Resource | Before | Now |
|---|---|---|
| Dev Worker | cnx-ios-api-dev | cmux-mobile-api-dev, renamed in place (same script, secrets, hub namespace), version 82529407 (API 0.11.0) |
| Prod Worker | cnx-ios-api-prod | cmux-mobile-api-prod, renamed in place, version f0691e03 (API 0.11.0) |
| Prod host | cnx-ios-api.cmux.dev | mobile-api.cmux.dev (custom domain added); the old domain is removed |
| Dev / prod Hyperdrive | cmux-next-ios-dev / cmux-next-ios (same ids) | cmux-mobile-dev / cmux-mobile-prod, repointed, caching off |
| Dev database | cmux/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 database | cmux/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 attempt | cmux-next-ios-api, cmux-next-ios-api-dev, cnx-ios-api-userhub-dev-dev, domain cmux-next-ios-api.cmux.dev | deleted |
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 teston 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 failurePhoneAccessGateTests.everyAllowedCommandHasAFieldList, unrelated to the rename (DaemonLanePolicy only had comment changes here). - Worker
tscandviteston mini-cmux11s: 64 tests passed. Livescripts/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; bundledev.cmux.mobile.prod,CmuxMobileAPIBasehttps://mobile-api.cmux.dev. - uniffi bindings regenerated by
build-xcframework.shon the mini (checksums follow the crate name) and committed. - Fleet Release build f94a7b2f (1fd739e9): built a universal
cmux-mobile-hostand bundled it. Fleet Debug build 6ede9642 (8a6ccdaa): bundled it. bundle-mobile-host.shwithCONFIGURATION=Releaseand a universal binary: copies it toContents/Resources/bin/cmux-mobile-host;CMUX_NEXT_REQUIRE_MOBILE_HOST=1with no binary fails. (scripts/cmux-next/tests/bundle-cnx-hostd-release.test.shdoes not exist on this base.)- Package.resolved policy: the renamed path triggered the check on a latent
*inFrameworks/.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, noticestest_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:
| Flow | Result |
|---|---|
| Pair | Pass: 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 |
| Terminal | Pass: New Terminal 3.5 s; echo naming-$((6*7)) printed naming-42 on the Mac 0.9 s after Send |
| Browser tab | Pass: example.com rendered 2.0 s after Return; frames on the media lane (carrier=webrtc-track) |
| Transport switch | Pass: 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