You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Tauri plugin's mobile discovery commands cross a Rust ↔ Swift/Kotlin FFI boundary where command names are matched by string at runtime. CI today only cargo checks the Rust half of that boundary; the Swift and Kotlin handlers are never compiled or contract-checked. As a result, a rename or signature drift on the native side is a silent runtime failure (an unknown method-class bug) that only surfaces during manual on-device testing.
The genuinely un-automatable part is behavioral: real multicast mDNS over a LAN (advertise, browse, self-echo, resolution timing) needs a device on a real network. But the contract/wiring — do the renamed symbols still line up across Rust, Swift, and Kotlin — is deterministically testable without a device, and currently isn't tested at all.
run_mobile_plugin("browse_peers_start", …) in Rust must match @objc func browse_peers_start (Swift) and @Command fun browse_peers_start (Kotlin). A mismatch compiles fine on each side independently but fails only at runtime, on-device.
Analogous failure already hit this cycle: a stale Deno .dylib produced IrohError: unknown method: advertisePeer after the dispatch keys were renamed — the same silent contract-drift class, just on a different adapter.
Impact
Mobile discovery command renames or additions can ship broken and only be caught during slow, easy-to-forget manual device verification. P2 — the workaround (on-device testing) exists but is manual and not enforced, so regressions can reach a release.
Remediation
String-parity contract test (cheap, deterministic, no device). Enumerate the command strings the Rust plugin invokes via run_mobile_plugin("…") and assert that set equals the set of @objc handlers declared in Swift and @Command handlers declared in Kotlin (and vice-versa). A pure text/AST scan that runs in milliseconds and would have caught the feat(discovery): standardize desktop mDNS on DNS-SD for iOS/Android interop #330 rename with certainty.
Native compile jobs in CI. Add xcodebuild/swift build for the iOS plugin sources and gradle assemble for the Android sources. This won't exercise the network but catches signature drift, missing symbols, and API misuse.
(Optional) Rust-side unit tests for the record-mapping logic (service_record_from_mobile, TXT parsing) — no radio required.
Explicitly out of scope
Real multicast mDNS behavior (advertise/browse/self-echo/endpoint resolution) needs a device on a real LAN and stays a manual verification step. This issue only closes the gap on the contract, not the behavior.
Acceptance criteria
A CI-run test fails if a Rust-invoked mobile command string has no matching Swift @objc handler and Kotlin @Command handler (and fails on orphaned handlers in the other direction).
CI compiles the iOS Swift plugin sources and the Android Kotlin plugin sources (build-only, no device).
The checks run as part of the standard CI pipeline (or a clearly-gated mobile job) so a native contract break blocks merge.
Docs state which discovery aspects are covered by CI vs. which require manual on-device verification.
Context
Split out of #330 to keep that PR focused on getting the DNS-SD wire format and the peer-vs-generic API right. Refs #329, #330.
Summary
The Tauri plugin's mobile discovery commands cross a Rust ↔ Swift/Kotlin FFI boundary where command names are matched by string at runtime. CI today only
cargo checks the Rust half of that boundary; the Swift and Kotlin handlers are never compiled or contract-checked. As a result, a rename or signature drift on the native side is a silent runtime failure (anunknown method-class bug) that only surfaces during manual on-device testing.The genuinely un-automatable part is behavioral: real multicast mDNS over a LAN (advertise, browse, self-echo, resolution timing) needs a device on a real network. But the contract/wiring — do the renamed symbols still line up across Rust, Swift, and Kotlin — is deterministically testable without a device, and currently isn't tested at all.
Evidence
crates/iroh-http-tauri/src/mobile_mdns.rs, the iOSIrohHttpPlugin.swift, and the AndroidIrohHttpPlugin.kt(commit79433ef). Only the Rust side was verified viacargo check --target aarch64-apple-ios-sim; the Swift/Kotlin changes are flagged "device-untested" in the PR plan.run_mobile_plugin("browse_peers_start", …)in Rust must match@objc func browse_peers_start(Swift) and@Command fun browse_peers_start(Kotlin). A mismatch compiles fine on each side independently but fails only at runtime, on-device..dylibproducedIrohError: unknown method: advertisePeerafter the dispatch keys were renamed — the same silent contract-drift class, just on a different adapter.Impact
Mobile discovery command renames or additions can ship broken and only be caught during slow, easy-to-forget manual device verification. P2 — the workaround (on-device testing) exists but is manual and not enforced, so regressions can reach a release.
Remediation
run_mobile_plugin("…")and assert that set equals the set of@objchandlers declared in Swift and@Commandhandlers declared in Kotlin (and vice-versa). A pure text/AST scan that runs in milliseconds and would have caught the feat(discovery): standardize desktop mDNS on DNS-SD for iOS/Android interop #330 rename with certainty.xcodebuild/swift buildfor the iOS plugin sources andgradle assemblefor the Android sources. This won't exercise the network but catches signature drift, missing symbols, and API misuse.service_record_from_mobile, TXT parsing) — no radio required.Explicitly out of scope
Real multicast mDNS behavior (advertise/browse/self-echo/endpoint resolution) needs a device on a real LAN and stays a manual verification step. This issue only closes the gap on the contract, not the behavior.
Acceptance criteria
@objchandler and Kotlin@Commandhandler (and fails on orphaned handlers in the other direction).Context
Split out of #330 to keep that PR focused on getting the DNS-SD wire format and the peer-vs-generic API right. Refs #329, #330.