Conversation
…gs 1.10.0, wasm-bindings 1.10.0)
## Summary - Upgrades the `check-swift` CI runner from `warp-macos-13-arm64-6x` to `warp-macos-15-arm64-6x` ## Test plan - [ ] Verify `check-swift` jobs pass on the new macOS 15 runner for both x86_64 and aarch64 targets 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- Macroscope's pull request summary starts here --> <!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. --> <!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. --> > [!NOTE] > ### Upgrade `check-swift` CI runner from macOS 13 to macOS 15 > Updates the runner label in [test-bindings-check.yml](.github/workflows/test-bindings-check.yml) from `warp-macos-13-arm64-6x` to `warp-macos-15-arm64-6x`. > > <!-- Macroscope's review summary starts here --> > > <sup><a href="https://app.macroscope.com">Macroscope</a> summarized dbf0310.</sup> > <!-- Macroscope's review summary ends here --> > <!-- macroscope-ui-refresh --> <!-- Macroscope's pull request summary ends here --> Co-authored-by: Sprite <[email protected]> Co-authored-by: Claude Opus 4.6 <[email protected]>
<!-- Macroscope's pull request summary starts here --> <!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. --> <!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. --> ### Add intent hash to MLS staged commit log events and rename `ProcessedWelcome` to `ReceivedWelcome` - Adds a `hash` field to `MLSReceivedStagedCommit` and `GroupSyncStagedCommitPresent` log events in [`mls_sync.rs`](https://github.com/xmtp/libxmtp/pull/3268/files#diff-160aadcd7de477c1116260a79601a0548842f3bd91bf16bd8443debb66ce6684), sourced from `message_envelope.payload_hash` and `intent_hash` respectively. - Renames the `ProcessedWelcome` event variant to `ReceivedWelcome` in [`event_logging.rs`](https://github.com/xmtp/libxmtp/pull/3268/files#diff-b892bd1dce497466fd9fa05752e7d5858b05185df4cfbc2acd1e03982cfcca14) and updates the emission site in [`welcome_sync.rs`](https://github.com/xmtp/libxmtp/pull/3268/files#diff-5ad5d6ca4506c4960727c32b22b9168a128f14af4d61497cd168ba5c80fb43f5). - Behavioral Change: any log consumers filtering on the `ProcessedWelcome` event name must update to `ReceivedWelcome`. <!-- Macroscope's review summary starts here --> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized f773819.</sup> <!-- Macroscope's review summary ends here --> <!-- macroscope-ui-refresh --> <!-- Macroscope's pull request summary ends here -->
## Summary Several default RPC endpoints in `chain_urls_default.json` are broken or unreliable in production, causing identity update validation failures: | Chain | Old | New | Reason | |---|---|---|---| | eip155:137 (Polygon) | `polygon.llamarpc.com` | `polygon.publicnode.com` | DNS failure | | eip155:42161 (Arbitrum) | `arbitrum.llamarpc.com` | `arb1.arbitrum.io/rpc` | DNS failure | | eip155:1 (Ethereum) | `eth.llamarpc.com` | `ethereum-rpc.publicnode.com` | Cloudflare 429 rate limit under load | | eip155:8453 (Base) | `base.llamarpc.com` | `mainnet.base.org` | Cloudflare 429 rate limit under load | | eip155:10 (Optimism) | `rpc.ankr.com/optimism` | `mainnet.optimism.io` | Ankr started requiring API keys | All new endpoints verified responding with correct chain IDs.
## Summary Adds a generic, binding-agnostic builder pattern macro system (`napi_builder`, `wasm_builder`, `uniffi_builder`) for cross-platform bindings in libxmtp. - **`crates/xmtp_macro/src/builder.rs`** — Core builder expansion engine driven by `AnnotationConfig` (struct/impl/constructor/setter annotations, setter style, prefix). Fully binding-agnostic. - **`SetterStyle` enum** — `NapiThis` (NAPI `This<'scope>` injection for JS chaining), `Consuming` (wasm_bindgen `mut self -> Self`), `MutRefChain` (`&mut self -> &mut Self` for UniFFI/tests). - **`setter_prefix`** — `"set_"` for NAPI/WASM (avoids conflicts with auto-generated field property getters), `""` for UniFFI. - **`setter_impl_ann`** — Splits constructor and setter impl blocks for UniFFI (Arc<Self> incompatible with `&mut self`). - **Field modes** — `required` (constructor param), `optional` (Option<T> with setter), `default` (literal expression), `skip` (Default::default, no setter). - Preserves non-builder struct-level attributes (e.g. `#[allow(dead_code)]`). ### Testing - **12 macro unit tests** (`crates/xmtp_macro/src/builder_test.rs`) — field modes, setter styles, prefix, struct attributes - **6 UniFFI Rust tests** (`bindings/mobile/src/builder_test.rs`) — constructor, setters, defaults, skip, chaining - **4 Node TypeScript tests** (`bindings/node/test/Builder.test.ts`) — constructor, chaining, defaults via `yarn build:test` - **4 WASM TypeScript tests** (`bindings/wasm/test/Builder.test.ts`) — same coverage, Chromium + Firefox via Playwright ## Test plan - [x] `cargo test -p xmtp_macro` — 12 tests pass - [x] `cargo test -p xmtpv3 --lib -- builder_test` — 6 tests pass - [x] `dev/lint` — clean - [x] Node TS tests pass (`yarn build:test && yarn test`) - [x] WASM TS tests pass (`yarn build:test && yarn test`) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
#3215) ## Summary Introduces `BackendBuilder` and `Backend` types for Node and WASM bindings, enabling pre-configured API backend construction via the new builder macro system. **Stacked on:** #3214 (cross-platform builder pattern macros) ### New types - **`XmtpEnv`** enum in `xmtp_configuration` — 7 network environments (Local, Dev, Production, TestnetStaging, TestnetDev, Testnet, Mainnet) with centralized URL resolution from constants. - **`BackendBuilder`** (Node + WASM) — Uses `napi_builder`/`wasm_builder` macros. Required `env` field, optional `api_url`, `gateway_host`, `readonly`, `app_version` setters, plus `authCallback`/`authHandle` methods. Builds a `Backend`. - **`Backend`** — Wraps `XmtpClientBundle` with env/host getters. Passed to `createClientWithBackend()`. - **`createClientWithBackend()`** (Node + WASM) — Creates a client from a pre-built Backend, reducing constructor params by extracting API config into the Backend. - **`validate_and_resolve()`** in `xmtp_api_d14n::config` — Shared validation logic for env→URL resolution, `is_secure` inference, and auth requirement checking. ### Code deduplication - Extracted shared helpers `build_store`, `parse_nonce`, and `create_client_inner` in Node bindings — both `createClient` and `createClientWithBackend` delegate to the same inner function. - Extracted shared helpers `build_store` and `create_client_inner` in WASM bindings — same pattern. - Made `v3_host` optional in `ClientBundleBuilder` (previously required) since `BackendBuilder` resolves it from `XmtpEnv`. ## Test plan - [x] `cargo test -p xmtp_configuration` — XmtpEnv tests pass - [x] `cargo check -p bindings_node` — compiles clean - [x] `nix develop .#wasm -- cargo check -p bindings_wasm --target wasm32-unknown-unknown` — compiles clean - [x] `dev/lint` — clean - [x] All macro and mobile builder tests still pass 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…3217) ## Summary - Update all static (free-standing) API functions in Node and WASM bindings to accept `&Backend` instead of raw `v3_host`/`gateway_host`/`is_secure` parameters - Internally use `MessageBackendBuilder::from_bundle()` to create API clients from the pre-built `ClientBundle` inside Backend, consistent with `create_client_with_backend()` - Remove `TrackedStatsClient` wrapping from these functions (no longer needed with `from_bundle()` path) ### Affected functions **Node (`@xmtp/node-bindings`):** | Function | Params removed | |---|---| | `getInboxIdForIdentifier` | `host`, `gatewayHost`, `isSecure` | | `isInstallationAuthorized` | `host`, `gatewayHost` | | `isAddressAuthorized` | `host`, `gatewayHost` | | `revokeInstallationsSignatureRequest` | `host`, `gatewayHost` | | `applySignatureRequest` | `host`, `gatewayHost` | | `inboxStateFromInboxIds` | `host`, `gatewayHost` | **WASM (`@xmtp/wasm-bindings`):** | Function | Params removed | |---|---| | `getInboxIdForIdentifier` | `host`, `gatewayHost`, `isSecure` | | `revokeInstallationsSignatureRequest` | `host`, `gatewayHost` | | `applySignatureRequest` | `host`, `gatewayHost` | | `inboxStateFromInboxIds` | `host`, `gatewayHost` | All functions now take `backend: &Backend` as their first parameter instead. ## Test plan - [x] `cargo check -p bindings_node` passes - [x] `cargo check -p bindings_wasm --target wasm32-unknown-unknown` passes - [x] `./dev/lint-rust` passes clean - [ ] Downstream SDK tests updated to pass `Backend` instead of raw host strings 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Dismissing my prior approval and re-evaluating approvability for da3a7ef
|
Claude finished @github-actions[bot]'s task —— View job PR Review CompleteReview Date: March 3, 2026, 21:24 UTC This release PR (1.10.0) contains significant architectural changes beyond version bumps, contrary to the macroscopeapp review. I've identified several important concerns: 🔴 Critical Issues1. Security: Mutex Poison Handling in Node Bindings (bindings/node/src/client/backend.rs:36-42) The code uses *self.auth_callback.lock().expect("lock poisoned") = Some(callback.clone());Recommendation: Return a proper error instead of panicking: .map_err(|_| napi::Error::from_reason("Failed to acquire lock"))?2. Security: TLS Validation Logic (crates/xmtp_api_d14n/src/config/backend_config.rs:22-25) The Recommendation: Rename to 3. Confusing Error Recovery Pattern (crates/xmtp_api_d14n/src/queries/client_bundle.rs:184-248) The Recommendation: Add a warning log or return an error when both are set to make the behavior explicit.
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3261 +/- ##
==========================================
- Coverage 73.52% 73.38% -0.15%
==========================================
Files 452 452
Lines 56677 56832 +155
==========================================
+ Hits 41673 41705 +32
- Misses 15004 15127 +123 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
fixes device sync tests in mobile bindings, android, and ios so it correctly verifies functionality <!-- Macroscope's pull request summary starts here --> <!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. --> <!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. --> > [!NOTE] > ### Fix device sync mobile bindings tests for iOS, Android, and Rust > - Adds new tests for the full device sync request flow in [Rust bindings](https://github.com/xmtp/libxmtp/pull/3288/files#diff-04f42fcf088abf13f3a20c3e154feac6341b3e9938a0f46f831a23b21a0aed74), [Android](https://github.com/xmtp/libxmtp/pull/3288/files#diff-33ca4980924b8d59d5ffc62a9e4dd6a5a30413b2183b9a946f9bba9faa3ac79f), and [iOS](https://github.com/xmtp/libxmtp/pull/3288/files#diff-c046ca278ac5c7d2a98b0d5353c906570b0a18bfe3a192448723a3ef4ceab6fa), covering message replication, consent sync, and archive-based history restore. > - Replaces fixed delays with polling loops and explicit `sendSyncRequest` calls to make tests deterministic and less flaky. > - Adds archive upload/process tests (`testSyncDeviceArchive`) on both Android and iOS that validate pre-installation history is restored via a pinned archive. > - Updates `getrandom` from 0.3 to 0.4 with the `sys_rng` feature in the workspace hack crate to unblock builds. > - Behavioral Change: `testDisablingHistoryTransferDoesNotTransfer` now explicitly creates clients with `deviceSyncEnabled=false/true` and tightens assertions around which messages are visible post-sync. > > <!-- Macroscope's review summary starts here --> > > <sup><a href="https://app.macroscope.com">Macroscope</a> summarized 190a4e7.</sup> > <!-- Macroscope's review summary ends here --> > <!-- Macroscope's pull request summary ends here --> --------- Co-authored-by: cameronvoell <[email protected]> Co-authored-by: Dakota Brink <[email protected]>
| Client.create( | ||
| account = alixWallet, | ||
| options = createClientOptions(api = localApi, deviceSyncEnabled = false), | ||
| ) | ||
| val alixGroup = alixClient.conversations.newGroup(listOf(boClient.inboxId)) | ||
| val messageIdNotExpectedOnClient2 = alixGroup.send("hi") | ||
| delay(2000) | ||
| val initialMessageCount = alixGroup.messages().size | ||
| assertEquals(initialMessageCount, 1) | ||
| assertEquals(initialMessageCount, 2) | ||
| val alixClient2 = | ||
| Client.create( | ||
| account = alixWallet, | ||
| options = | ||
| ClientOptions( | ||
| ClientOptions.Api(XMTPEnvironment.LOCAL, false), | ||
| appContext = context, | ||
| dbEncryptionKey = dbEncryptionKey, | ||
| dbDirectory = context.filesDir.absolutePath.toString(), | ||
| ), | ||
| options = createClientOptions(api = localApi, deviceSyncEnabled = true), | ||
| ) |
There was a problem hiding this comment.
🟢 Low library/HistorySyncTest.kt:307
In testDisablingHistoryTransferDoesNotTransfer, alixClient and alixClient2 are created via direct Client.create() calls instead of the createClient() helper. This skips the cleanup tracking in createdClients, so dropLocalDatabaseConnection() is never called during tearDown(), leaving database connections and files leaked. Consider using createClient() to ensure automatic cleanup.
val localApi = ClientOptions.Api(XMTPEnvironment.LOCAL, false)
- val alixClient =
- Client.create(
- account = alixWallet,
- options = createClientOptions(api = localApi, deviceSyncEnabled = false),
- )
+ val alixClient = createClient(alixWallet, api = localApi, deviceSyncEnabled = false)
val alixGroup = alixClient.conversations.newGroup(listOf(boClient.inboxId))
val messageIdNotExpectedOnClient2 = alixGroup.send("hi")
delay(2000)
val initialMessageCount = alixGroup.messages().size
assertEquals(initialMessageCount, 2)
- val alixClient2 =
- Client.create(
- account = alixWallet,
- options = createClientOptions(api = localApi, deviceSyncEnabled = true),
- )
+ val alixClient2 = createClient(alixWallet, api = localApi, deviceSyncEnabled = true)🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file sdks/android/library/src/androidTest/java/org/xmtp/android/library/HistorySyncTest.kt around lines 307-320:
In `testDisablingHistoryTransferDoesNotTransfer`, `alixClient` and `alixClient2` are created via direct `Client.create()` calls instead of the `createClient()` helper. This skips the cleanup tracking in `createdClients`, so `dropLocalDatabaseConnection()` is never called during `tearDown()`, leaving database connections and files leaked. Consider using `createClient()` to ensure automatic cleanup.
Evidence trail:
- HistorySyncTest.kt lines 306-310 and 318-322: Direct `Client.create()` calls creating `alixClient` and `alixClient2`
- BaseInstrumentedTest.kt line 25: `private val createdClients = mutableListOf<Client>()` - tracking list
- BaseInstrumentedTest.kt lines 67-74: `createClient()` helper that adds to tracking list via `createdClients.add(client)` at line 73
- BaseInstrumentedTest.kt lines 40-60: `tearDown()` method that calls `dropLocalDatabaseConnection()` only on clients in `createdClients` (line 45)
ApprovabilityVerdict: Needs human review This release PR (1.10.0) includes version bumps, new BackendBuilder abstractions, new builder macros, API surface changes, and documented breaking changes to history sync behavior. The automated release bot author has no code ownership of the modified files, so designated owners should verify this release before merging. You can customize Macroscope's approvability policy. Learn more. |
|
release changes merged to main via #3327 |
Release 1.10.0
This PR was created by the Create Release Branch workflow.
Checklist
Note
Release v1.10.0 with Backend builder API and unified environment configuration
BackendBuilderandBackendtypes to Node and WASM bindings, replacing discrete host/gateway parameters acrosscreateClient,getInboxIdByIdentity,revokeInstallationsSignatureRequest,applySignatureRequest, andfetchInboxStatesByInboxIdsxmtp_macro::napi_builder,wasm_builder, anduniffi_builderproc-macro attribute that generates binding-specific constructors and chainable setters from annotated structsXmtpEnvenum to node/wasm bindings andxmtp_configurationcrate with centralized/decentralized variants and avalidate_and_resolveconfig helperClientBundleBuildernow supports D14n mode with gateway-only configuration; V3 and D14n are selected automatically based on which hosts are providedGrpcUrlsProduction::NODEnow resolves tohttps://api.production.xmtp.network:5558instead of the gRPC endpointv3_host/gatewayHost/isSecurenow require aBackendinstance; theencryptionKeyparameter is ignored in WASM client creation with a warning logged when providedMacroscope summarized 5c42da5.