Skip to content

feat(moq-native): add platform TLS verifier selection#1960

Open
Qizot wants to merge 1 commit into
moq-dev:mainfrom
Qizot:tls-verifier
Open

feat(moq-native): add platform TLS verifier selection#1960
Qizot wants to merge 1 commit into
moq-dev:mainfrom
Qizot:tls-verifier

Conversation

@Qizot

@Qizot Qizot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

This PR adds an ability to set what kind of TLS verifier will be used when connecting with a server.

The previous approach didn't work on iOS and android platforms. The current approach allows the user to choose and also provides a sane defaults for each platform (it should be backwards compatible for platforms other than ios/android/macos).

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @Qizot, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds platform-native TLS certificate verification support targeting Android, iOS, and macOS. A new ClientTlsVerifier enum (Default, Platform, WebPki, NativeRoots) is introduced in moq-native with an associated verifier field on the TLS Client config, a refactored Verification policy enum, and updated Client::build logic that delegates to rustls-platform-verifier when Verification::Platform is selected. The quiche backend explicitly rejects the platform verifier with an error. On the FFI layer, a corresponding MoqTlsVerifier UniFFI enum and an Android JNI entry point (Java_dev_moq_PlatformTLS_initializeNative) are added. The Kotlin side gains a PlatformTLS singleton that loads the native library and calls through to the JNI initializer, backed by a new rustls-platform-verifier Kotlin dependency.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding platform TLS verifier selection in moq-native.
Description check ✅ Passed The description is directly related to the changes, describing TLS verifier selection and platform-specific defaults.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
rs/moq-native/src/tls.rs (1)

62-66: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the new public error variants.

Error is public, so the new variants should have rustdoc in addition to their #[error(...)] display text.

Proposed docs
+	/// Returned when platform verification is selected together with custom TLS roots.
 	#[error("TLS platform verifier cannot be combined with custom TLS roots")]
 	PlatformVerifierWithCustomRoots,

+	/// Returned when platform verification is requested on a target/backend that cannot use it.
 	#[error("TLS platform verifier is not supported by {0}")]
 	PlatformVerifierUnsupported(&'static str),

As per coding guidelines, “Document every exported public API symbol: each exported Rust item and each exported JS/TS symbol, including notable public members, must have a doc comment.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rs/moq-native/src/tls.rs` around lines 62 - 66, The new public Error variants
in tls.rs are missing rustdoc even though Error is exported. Add doc comments to
PlatformVerifierWithCustomRoots and PlatformVerifierUnsupported in the Error
enum, using their variant names to describe when each is returned, while keeping
the existing #[error(...)] display strings unchanged.

Source: Coding guidelines

rs/moq-ffi/src/android.rs (1)

1-16: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add module-level and exported-symbol docs.

Per coding guidelines, every Rust module root needs a //! doc block and each exported public symbol needs a doc comment. This module has neither a top-level //! block nor a doc comment on the public Java_dev_moq_PlatformTLS_initializeNative JNI entry point.

📝 Suggested docs
+//! Android JNI entry points for initializing the platform TLS verifier.
+
 use jni::EnvUnowned;
 use jni::errors::ThrowRuntimeExAndDefault;
 use jni::objects::{JClass, JObject};

+/// JNI entry point invoked by `dev.moq.PlatformTLS.initializeNative` to wire up
+/// the rustls platform verifier with the Android `Context`.
 #[unsafe(no_mangle)]
 pub extern "system" fn Java_dev_moq_PlatformTLS_initializeNative<'local>(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rs/moq-ffi/src/android.rs` around lines 1 - 16, Add a top-level module doc
block for this Rust module and a doc comment for the exported JNI entry point.
In android.rs, add a `//!` module-level description at the top of the file, and
document `Java_dev_moq_PlatformTLS_initializeNative` with a brief explanation of
what the native initializer does so the exported symbol meets the coding
guidelines.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@kt/moq/build.gradle.kts`:
- Line 101: The moq Gradle module depends on rustls-platform-verifier, but the
current repository setup does not expose that artifact. Update the Gradle
configuration around build.gradle.kts to wire in the custom on-disk rustls
Android repository used for rustls:rustls-platform-verifier:0.1.1, and ensure
the repository is available before the implementation dependency in the moq
module is resolved.

In `@rs/moq-native/src/quiche.rs`:
- Around line 181-184: The quiche verification path in quiche.rs is ignoring the
webpki_roots policy when certs is empty, so explicit WebPki selection can fall
back to quiche defaults instead of the configured Mozilla/WebPKI roots. Update
the Verification::Roots handling to either install equivalent roots on the
builder even when certs is empty, or fail fast with an unsupported-verifier
error rather than silently proceeding. Use the Verification::Roots match branch
and the builder.with_root_certificates flow as the primary places to adjust.

---

Nitpick comments:
In `@rs/moq-ffi/src/android.rs`:
- Around line 1-16: Add a top-level module doc block for this Rust module and a
doc comment for the exported JNI entry point. In android.rs, add a `//!`
module-level description at the top of the file, and document
`Java_dev_moq_PlatformTLS_initializeNative` with a brief explanation of what the
native initializer does so the exported symbol meets the coding guidelines.

In `@rs/moq-native/src/tls.rs`:
- Around line 62-66: The new public Error variants in tls.rs are missing rustdoc
even though Error is exported. Add doc comments to
PlatformVerifierWithCustomRoots and PlatformVerifierUnsupported in the Error
enum, using their variant names to describe when each is returned, while keeping
the existing #[error(...)] display strings unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 93fda425-6875-4a5d-a60b-42b27a08fbe2

📥 Commits

Reviewing files that changed from the base of the PR and between 7c6d4dd and f442eeb.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • kt/moq/build.gradle.kts
  • kt/moq/src/androidMain/kotlin/dev/moq/PlatformTLS.kt
  • rs/moq-ffi/Cargo.toml
  • rs/moq-ffi/build.sh
  • rs/moq-ffi/src/android.rs
  • rs/moq-ffi/src/lib.rs
  • rs/moq-ffi/src/session.rs
  • rs/moq-native/Cargo.toml
  • rs/moq-native/src/quiche.rs
  • rs/moq-native/src/tls.rs

Comment thread kt/moq/build.gradle.kts
dependsOn(jvmAndAndroidMain)
dependencies {
implementation("net.java.dev.jna:jna:5.18.1@aar")
implementation("rustls:rustls-platform-verifier:0.1.1")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Is a custom maven repo for the verifier configured anywhere in the Gradle setup?
rg -nP -C2 'rustlsPlatformVerifier|findRustlsPlatformVerifier|rustls-platform-verifier-android' kt/ 2>/dev/null
# What android-support version does the Rust crate resolve to?
cargo metadata --format-version 1 --manifest-path rs/moq-ffi/Cargo.toml 2>/dev/null \
  | jq -r '.packages[] | select(.name=="rustls-platform-verifier-android") | .version'

Repository: moq-dev/moq

Length of output: 149


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== build files =='
git ls-files 'kt/**/build.gradle.kts' 'kt/**/settings.gradle.kts' 'kt/**/gradle.properties' 'kt/**/gradle/libs.versions.toml' | sed 's#^`#-` #'

echo
echo '== rustls references =='
rg -n --hidden --glob '!**/build/**' --glob '!**/.gradle/**' 'rustls-platform-verifier|rustlsPlatformVerifier|findRustlsPlatformVerifier|cargo metadata|rustls' kt rs .github . 2>/dev/null | sed -n '1,200p'

echo
echo '== target file excerpt =='
cat -n kt/moq/build.gradle.kts | sed -n '1,180p'

Repository: moq-dev/moq

Length of output: 21397


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== target file size =='
wc -l kt/moq/build.gradle.kts

echo
echo '== target file around dependency block =='
sed -n '70,120p' kt/moq/build.gradle.kts | cat -n

Repository: moq-dev/moq

Length of output: 2135


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== relevant files =='
git ls-files | rg '^(kt/moq/build\.gradle\.kts|kt/.*/build\.gradle\.kts|.*Cargo\.toml|.*settings\.gradle(\.kts)?|.*libs\.versions\.toml)$' | sed -n '1,200p'

echo
echo '== kt/moq/build.gradle.kts excerpt =='
sed -n '1,180p' kt/moq/build.gradle.kts | cat -n

echo
echo '== search for repository declarations =='
rg -n --hidden --glob '!**/build/**' --glob '!**/.gradle/**' 'maven\s*\{|mavenLocal\(|mavenCentral\(|url\s*=\s*uri\(|rustls-platform-verifier' kt . 2>/dev/null | sed -n '1,200p'

Repository: moq-dev/moq

Length of output: 8887


🌐 Web query:

rustls-platform-verifier-android Maven Central published rustls-platform-verifier 0.1.1

💡 Result:

The crate rustls-platform-verifier-android version 0.1.1 is published on crates.io [1], not Maven Central [2][3]. It serves as an internal implementation detail for the rustls-platform-verifier Rust crate to provide necessary Kotlin/JVM components for Android certificate validation [4][1]. Because it is not available on Maven Central, the project uses a mechanism where the Android components are bundled within the Rust crate [5][4]. To integrate this in an Android project, developers typically use a provided Gradle script helper [2][6]. This script works by locating the downloaded crate on the local file system (where Cargo stores it), identifying the internal Maven-compatible directory structure contained within that crate, and registering it as a local Maven repository for the Gradle build [2][5][6]. This allows the build system to treat the local files as a Maven dependency without the need for the artifact to be hosted on a public repository like Maven Central [4][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== root search for rustls / custom repo plumbing =='
rg -n --hidden --glob '!**/build/**' --glob '!**/.gradle/**' \
  'rustls-platform-verifier-android|rustls-platform-verifier|cargo metadata|mavenLocal\(|maven \{|url\s*=\s*uri\(' . | sed -n '1,200p'

echo
echo '== build file around dependencies and repositories =='
sed -n '1,180p' kt/moq/build.gradle.kts | cat -n

Repository: moq-dev/moq

Length of output: 8654


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== gradle files =='
git ls-files 'kt/**/build.gradle.kts' 'kt/**/settings.gradle.kts' | sed -n '1,200p'

echo
echo '== kt/moq/build.gradle.kts =='
cat -n kt/moq/build.gradle.kts | sed -n '1,180p'

echo
echo '== kt settings/root build excerpts =='
for f in $(git ls-files 'kt/**/settings.gradle.kts' 'kt/**/build.gradle.kts' | grep -v '^kt/moq/build.gradle.kts$'); do
  echo "--- $f ---"
  cat -n "$f" | sed -n '1,220p'
done

Repository: moq-dev/moq

Length of output: 7118


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== kt tree =='
find kt -maxdepth 2 -type f | sort | sed -n '1,200p'

echo
echo '== rustls / maven repo helpers in kt scripts =='
rg -n --hidden --glob '!**/build/**' --glob '!**/.gradle/**' \
  'rustls-platform-verifier|cargo metadata|mavenRepo|mavenLocal|repositories\s*\{|url\s*=\s*uri\(|artifactId|find.*repo' kt/scripts kt/moq kt/settings.gradle.kts 2>/dev/null | sed -n '1,240p'

echo
echo '== kt/settings.gradle.kts =='
cat -n kt/settings.gradle.kts | sed -n '1,220p'

Repository: moq-dev/moq

Length of output: 1786


Add the rustls Android repository for this dependency.
mavenCentral()/google() don’t provide rustls:rustls-platform-verifier:0.1.1, so this implementation(...) needs the custom on-disk repo wired in somewhere in the Gradle setup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kt/moq/build.gradle.kts` at line 101, The moq Gradle module depends on
rustls-platform-verifier, but the current repository setup does not expose that
artifact. Update the Gradle configuration around build.gradle.kts to wire in the
custom on-disk rustls Android repository used for
rustls:rustls-platform-verifier:0.1.1, and ensure the repository is available
before the implementation dependency in the moq module is resolved.

Comment on lines +181 to +184
Verification::Roots { certs, .. } => {
if !certs.is_empty() {
builder = builder.with_root_certificates(certs);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Do not silently drop webpki_roots for quiche.

Verification::Roots { webpki_roots: true, certs: [] } is now a valid policy, but this branch ignores the flag and leaves quiche using its implicit defaults. That means explicit WebPki selection—and Android’s default verifier—may not actually use the configured Mozilla/WebPKI roots in this backend. Either install equivalent roots for quiche or return an unsupported-verifier error instead of proceeding.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rs/moq-native/src/quiche.rs` around lines 181 - 184, The quiche verification
path in quiche.rs is ignoring the webpki_roots policy when certs is empty, so
explicit WebPki selection can fall back to quiche defaults instead of the
configured Mozilla/WebPKI roots. Update the Verification::Roots handling to
either install equivalent roots on the builder even when certs is empty, or fail
fast with an unsupported-verifier error rather than silently proceeding. Use the
Verification::Roots match branch and the builder.with_root_certificates flow as
the primary places to adjust.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant