Skip to content

[WAL-1345] feat(mdoc): add mobile BLE proximity transport - #2157

Open
szijpeter wants to merge 9 commits into
feature/wal-1344-mdoc-proximity-enginefrom
feature/wal-1345-ble-proximity-transport
Open

[WAL-1345] feat(mdoc): add mobile BLE proximity transport#2157
szijpeter wants to merge 9 commits into
feature/wal-1344-mdoc-proximity-enginefrom
feature/wal-1345-ble-proximity-transport

Conversation

@szijpeter

@szijpeter szijpeter commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

This adds the Kotlin Multiplatform BLE transport for ISO mdoc proximity presentation defined by WAL-1345.

The work is stacked directly on walt-id/waltid-identity#2155, which provides the radio-independent transport and holder-protocol contracts. Until #2155 merges, this PR targets its feature branch so the review delta contains only WAL-1345. After #2155 merges, replay the WAL-1345-only commits onto current main and retarget this PR.

Architecture contract: walt-id/waltid-architecture#60.

What Changed

Shared BLE transport

  • Adds validated transaction UUID, central-client/peripheral-server/dual-role, and GATT-only/L2CAP-preferred models that prevent illegal role and bearer combinations.
  • Implements BLEIdent HKDF-SHA-256 verification from the complete tagged EDeviceKeyBytes, normalizes supported public-key export encodings before COSE conversion, and provides ISO GATT chunking/reassembly, L2CAP length framing, message limits, truncation detection, and dynamic LE PSM validation.
  • Provides deterministic role and bearer races, serialized sends, one receive consumer, bounded preparation setup and post-connection inactivity, normalized errors, structured cancellation, and idempotent cleanup; a prepared listener remains available for the session-owned engagement lifetime, and the selected connection is completed and closed exactly once.
  • Moves opaque session messages only; engagement construction, session cryptography, requests, consent, trust, and wallet policy remain in the shared proximity engine and wallet layers.

Android and Apple adapters

  • Implements Android scanning/advertising, both GATT roles, negotiated MTU handling, notification backpressure, and insecure LE L2CAP client/listener channels from API 30.
  • Implements the equivalent CoreBluetooth central/peripheral GATT roles and L2CAP open/publish paths on iOS, including legacy and current disconnect callbacks and draining the final State characteristic write before teardown.
  • Binds GATT-discovered L2CAP channels to the same peer while preserving the standard's direct-L2CAP path when the PSM is carried in Device Engagement.
  • Reports permissions, Bluetooth state, and missing runtime capabilities through the shared capability contract without launching permission UI.
  • Adds a role-aware, side-effect-free prerequisite probe that reuses the configured provider's native capability checks, allowing the Wallet SDK to report readiness before generating session material.

Building-block decision

  • Adds an ADR with the authorized ISO DIS baseline, exact BlueFalcon, kmp-ble, Multipaz, and GOV.UK inputs, responsibility split, and qualification boundary.
  • Selects walt-owned common protocol/lifecycle code over thin native Android and Apple adapters. No third-party BLE runtime, copied upstream source, or new native package dependency is added.

Architecture Notes

  • ISO roles, UUID/Ident, framing, limits, races, timeouts, errors, and cleanup are shared; platform code is limited to Bluetooth APIs, callbacks, sockets, and streams.
  • The shared proximity engine owns the advertised engagement lifetime; BLE bounds adapter setup and post-connection inactivity without imposing a shorter local listener expiry.
  • Platform objects and dependency types never cross the public common contract. Consumers enter through the public provider factory; concrete platform providers remain internal.
  • GATT remains mandatory. L2CAP is advertised and attempted only when the selected policy and platform permit it; malformed PSM data fails closed.
  • A fresh retry belongs to the wallet/session layer and requires fresh engagement and ephemeral material.

Caveats and Follow-Ups

  • Wallet SDK integration is in walt-id/waltid-identity#2159, with Compose Android, Compose iOS, and native SwiftUI journeys in walt-id/waltid-identity#2160.
  • The DIS specifies a fixed four-byte L2CAP length but not its byte order. This implementation uses unsigned big-endian encoding, matching the inspected Multipaz behavior, and records external interoperability as the reconciliation gate.
  • Cross-device GATT/L2CAP reliability, external-reader interoperability, and release qualification remain in WAL-1349.

Breaking

  • None for existing consumers. This introduces a new mobile transport module and public provider factory for the unreleased Wallet SDK.

@szijpeter szijpeter added the ci:mobile Run mobile related CI workflows for this PR label Aug 27, 2026
@szijpeter szijpeter self-assigned this Aug 27, 2026
@linear-code

linear-code Bot commented Aug 27, 2026

Copy link
Copy Markdown

WAL-1345

@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: ac00caed-cbc5-455f-b894-ef74a8eae0c9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@szijpeter
szijpeter force-pushed the feature/wal-1344-mdoc-proximity-engine branch from 7a5eb5d to 4215bb9 Compare August 27, 2026 22:52
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch from e98c918 to c942326 Compare August 27, 2026 22:53
@szijpeter
szijpeter force-pushed the feature/wal-1344-mdoc-proximity-engine branch from 4215bb9 to 37308f0 Compare August 28, 2026 03:45
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch from c942326 to 192f96d Compare August 28, 2026 03:45
@sonarqubecloud

Copy link
Copy Markdown

@szijpeter
szijpeter marked this pull request as ready for review August 28, 2026 06:29
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch from 0b77716 to e0a2d60 Compare August 28, 2026 15:01
@szijpeter
szijpeter force-pushed the feature/wal-1344-mdoc-proximity-engine branch 2 times, most recently from 87069a1 to 334b97e Compare August 28, 2026 15:22
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch 2 times, most recently from 2bf7b90 to 8b8f050 Compare August 28, 2026 18:23
@szijpeter
szijpeter force-pushed the feature/wal-1344-mdoc-proximity-engine branch from 334b97e to 1ba6463 Compare August 28, 2026 18:23
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch from 8b8f050 to 6cb7f09 Compare August 31, 2026 10:14
@szijpeter
szijpeter force-pushed the feature/wal-1344-mdoc-proximity-engine branch from 1ba6463 to 0034d23 Compare August 31, 2026 10:14
@sonarqubecloud

Copy link
Copy Markdown

@szijpeter
szijpeter force-pushed the feature/wal-1344-mdoc-proximity-engine branch from 0034d23 to 336775a Compare September 1, 2026 14:55
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch from 6cb7f09 to fc34a85 Compare September 1, 2026 14:55
@szijpeter
szijpeter force-pushed the feature/wal-1344-mdoc-proximity-engine branch from 336775a to 9a70398 Compare September 2, 2026 08:54
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch from fc34a85 to 1b478ed Compare September 2, 2026 08:54
@szijpeter
szijpeter force-pushed the feature/wal-1344-mdoc-proximity-engine branch from 9a70398 to 11ca286 Compare September 2, 2026 14:58
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch 2 times, most recently from 4482fd3 to b29213c Compare September 2, 2026 19:37
@szijpeter
szijpeter force-pushed the feature/wal-1344-mdoc-proximity-engine branch 2 times, most recently from 8d2c611 to 1575eca Compare September 3, 2026 14:12
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch from b29213c to 69dd7b3 Compare September 3, 2026 14:12
@szijpeter
szijpeter force-pushed the feature/wal-1344-mdoc-proximity-engine branch from 1575eca to 1aa432d Compare September 4, 2026 12:04
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch 3 times, most recently from 5aeb71a to 8b86426 Compare September 4, 2026 13:11
@szijpeter
szijpeter force-pushed the feature/wal-1345-ble-proximity-transport branch from 8b86426 to 318e945 Compare September 4, 2026 14:38
@sonarqubecloud

sonarqubecloud Bot commented Sep 4, 2026

Copy link
Copy Markdown

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

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

Labels

ci:mobile Run mobile related CI workflows for this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant