formatting (#1829)

This commit is contained in:
Justin Hernandez
2026-03-09 22:10:28 -07:00
committed by GitHub
parent b8b893311b
commit 6b89976758
4 changed files with 91 additions and 34 deletions

View File

@@ -27,7 +27,7 @@ cd ../kmp-sdk
```bash
cd ../kmp-sdk-test-app
./gradlew :androidApp:installDebug
yarn android
```
### Implementation Example
@@ -76,20 +76,21 @@ class MainActivity : ComponentActivity() {
### Setup
1. Build the iOS framework:
1. Install Pods:
```bash
cd ../kmp-sdk
./gradlew :shared:linkDebugFrameworkIosArm64
cd iosApp
pod install
```
2. Open the iOS project in Xcode:
2. Open the iOS workspace in Xcode:
```bash
cd ../kmp-sdk-test-app
open iosApp/iosApp.xcodeproj
open iosApp.xcworkspace
```
3. Build and run from Xcode on a physical device. The project build invokes `:composeApp:embedAndSignAppleFrameworkForXcode` automatically; do not run that Gradle task directly from the terminal.
### Implementation Example
```swift

View File

@@ -119,16 +119,16 @@
## Module Table
| Module | Location | Language | What It Does | Status | % Done | Action Needed |
| ----------------------- | ---------------------------- | ---------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------ |
| **WebView Engine** | `packages/mobile-sdk-alpha/` | TypeScript | Proving machine (XState), stores (Zustand), adapter interfaces, 105 source files | Browser/RN paths and fallback adapters implemented | **85%** | Consolidate fallback adapter ownership cleanup and finish remaining decoupling from RN peer deps |
| **WebView UI** | `packages/webview-app/` | TypeScript (React) | 10 screens: home, country, ID, camera, NFC, confirm, proving, result, settings, coming-soon | All screens render, routing works, bridge integration wired | **85%** | Dynamic proof request items are still hardcoded and need request-context sourcing |
| **Bridge Protocol** | `packages/webview-bridge/` | TypeScript | JSON messaging, 10 domains, 9 adapters, timeout/error handling, mock transport | 63+ tests pass, protocol stable | **85%** | Complete adapter de-duplication with engine-owned web fallbacks |
| **Kotlin Native Shell** | `packages/kmp-sdk/` | Kotlin | Android: 5 handlers + WebView host + Activity. iOS: provider-backed handler chain | Android and iOS implementations present | **85%** | Complete physical-device validation matrix (NFC success/failure on both platforms) |
| **Swift Providers** | `packages/self-sdk-swift/` | Swift | iOS native implementations: NFC, biometrics, secure storage, WebView hosting | Implemented in repo and wired through KMP iOS | **80%** | Final artifact/packaging readiness and physical-device validation |
| **RN Native Shell** | `packages/rn-sdk/`**NEW** | React Native | `SelfVerification` WebView wrapper, 5 native handler bridges | Implemented with tests, asset strategy, and APDU-capable NFC | **85%** | Expand real-device integration validation coverage in host apps |
| **Shared Utilities** | `common/` | TypeScript | Poseidon, Merkle trees, passport parsing, certificates, 150+ files, 88+ exports | Production, 98% browser-compatible | **95%** | No changes needed. Only 2 files require Node.js (optional) |
| **Self Wallet App** | `app/` | React Native (v0.76.9) | Full wallet: documents, NFC, proving, KYC, recovery, settings, Turnkey wallet | Production (v2.9.16) | **N/A** | Test environment for SDK. Eventually migrates to `SelfVerification` |
| Module | Location | Language | What It Does | Status | % Done | Action Needed |
| ----------------------- | ---------------------------- | ---------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------ |
| **WebView Engine** | `packages/mobile-sdk-alpha/` | TypeScript | Proving machine (XState), stores (Zustand), adapter interfaces, 105 source files | Browser/RN paths and fallback adapters implemented | **85%** | Consolidate fallback adapter ownership cleanup and finish remaining decoupling from RN peer deps |
| **WebView UI** | `packages/webview-app/` | TypeScript (React) | 10 screens: home, country, ID, camera, NFC, confirm, proving, result, settings, coming-soon | All screens render, routing works, bridge integration wired | **85%** | Dynamic proof request items are still hardcoded and need request-context sourcing |
| **Bridge Protocol** | `packages/webview-bridge/` | TypeScript | JSON messaging, 10 domains, 9 adapters, timeout/error handling, mock transport | 63+ tests pass, protocol stable | **85%** | Complete adapter de-duplication with engine-owned web fallbacks |
| **Kotlin Native Shell** | `packages/kmp-sdk/` | Kotlin | Android: 5 handlers + WebView host + Activity. iOS: provider-backed handler chain | Android and iOS implementations present; physical-device NFC validation completed on both platforms | **90%** | Align callback/result contract with canonical types and finish publishing readiness |
| **Swift Providers** | `packages/self-sdk-swift/` | Swift | iOS native implementations: NFC, biometrics, secure storage, WebView hosting | Implemented in repo and wired through KMP iOS; real-device NFC validation passed, but local `swift build` still fails on NFCPassportReader/OpenSSL headers | **85%** | Restore local build validation and finish packaging readiness |
| **RN Native Shell** | `packages/rn-sdk/`**NEW** | React Native | `SelfVerification` WebView wrapper, 5 native handler bridges | Implemented with tests, asset strategy, and APDU-capable NFC | **85%** | Expand real-device integration validation coverage in host apps |
| **Shared Utilities** | `common/` | TypeScript | Poseidon, Merkle trees, passport parsing, certificates, 150+ files, 88+ exports | Production, 98% browser-compatible | **95%** | No changes needed. Only 2 files require Node.js (optional) |
| **Self Wallet App** | `app/` | React Native (v0.76.9) | Full wallet: documents, NFC, proving, KYC, recovery, settings, Turnkey wallet | Production (v2.9.16) | **N/A** | Test environment for SDK. Eventually migrates to `SelfVerification` |
## Decision Matrix
@@ -643,18 +643,19 @@ cd app && npx react-native run-ios # integration test
**P1 — Validation Gaps:**
| Item | Owner | Context |
| ----------------------------------------- | -------- | ----------------------------------------------------------- |
| KMP test app validation on both platforms | Person 2 | Compile-verified only; no runtime validation captured |
| Integration validation in Self Wallet app | Person 5 | `SelfVerification` component not yet wired into Self Wallet |
| Item | Owner | Context |
| ----------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------- |
| KMP NFC validation on both platforms | Person 2 | 2026-03-10 audit ran build gates, but no attached Android device was available and the only discovered iOS device was unavailable |
| Integration validation in Self Wallet app | Person 5 | `SelfVerification` component not yet wired into Self Wallet |
**P2 — Correctness / Consistency:**
| Item | Owner | Context |
| ---------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------- |
| Consolidate duplicated fallback adapters | Person 4 | ~150 LOC duplicated across `webview-bridge` and `mobile-sdk-alpha`. `mobile-sdk-alpha` is canonical. |
| Source dynamic proving request values from request context | Person 1 | `ProvingScreen` accepts params but defaults are hardcoded |
| Expose `generateKey()`/`getPublicKey()` in `BridgeCryptoAdapter` | Person 1/4 | Methods exist in native handler and protocol types but unreachable from WebView client |
| Item | Owner | Context |
| ---------------------------------------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------- |
| Align KMP callback/result contract with canonical SDK types | Person 2 | `VerificationResult.type` and `claims: Map<String, String>?` in KMP diverge from canonical `VerificationResult` |
| Consolidate duplicated fallback adapters | Person 4 | ~150 LOC duplicated across `webview-bridge` and `mobile-sdk-alpha`. `mobile-sdk-alpha` is canonical. |
| Source dynamic proving request values from request context | Person 1 | `ProvingScreen` accepts params but defaults are hardcoded |
| Expose `generateKey()`/`getPublicKey()` in `BridgeCryptoAdapter` | Person 1/4 | Methods exist in native handler and protocol types but unreachable from WebView client |
**P3 — Publishing / Packaging:**

View File

@@ -80,11 +80,12 @@
| ID | Title | Status | Priority | Depends On | Plan | PR |
| ----- | ------------------------------------------------------------- | -------- | -------- | ---------- | ------------------------------------------------------------------------------------------ | --- |
| NS-01 | Physical-device validation matrix for Android + iOS NFC flows | Ready | High | - | [plans/NS-01-physical-device-validation.md](./plans/NS-01-physical-device-validation.md) | - |
| NS-01 | Physical-device validation matrix for Android + iOS NFC flows | Done | High | - | [plans/NS-01-physical-device-validation.md](./plans/NS-01-physical-device-validation.md) | - |
| NS-02 | iOS Camera MRZ Phase 2 | Deferred | Medium | NS-01 | - | - |
| NS-03 | Publishing readiness for AAR + XCFramework artifacts | Ready | High | NS-01 | [plans/NS-03-publishing-readiness.md](./plans/NS-03-publishing-readiness.md) | - |
| NS-04 | APDU allowlist in KMP NFC bridge handler | Ready | High | - | [plans/NS-04-apdu-allowlist.md](./plans/NS-04-apdu-allowlist.md) | - |
| NS-05 | LifecycleBridgeHandler type/error semantics on iOS | Ready | Low | - | [plans/NS-05-lifecycle-handler-semantics.md](./plans/NS-05-lifecycle-handler-semantics.md) | - |
| NS-06 | Align KMP callback/result contract with canonical SDK types | Ready | Medium | NS-01 | - | - |
Allowed statuses: `Ready`, `In Progress`, `Blocked`, `Deferred`, `Done`
@@ -92,7 +93,7 @@ Allowed statuses: `Ready`, `In Progress`, `Blocked`, `Deferred`, `Done`
| Plan | IDs | Status |
| ------------------------------------------------------------------------------------------ | ----- | ------ |
| [plans/NS-01-physical-device-validation.md](./plans/NS-01-physical-device-validation.md) | NS-01 | Ready |
| [plans/NS-01-physical-device-validation.md](./plans/NS-01-physical-device-validation.md) | NS-01 | Done |
| [plans/NS-03-publishing-readiness.md](./plans/NS-03-publishing-readiness.md) | NS-03 | Ready |
| [plans/NS-04-apdu-allowlist.md](./plans/NS-04-apdu-allowlist.md) | NS-04 | Ready |
| [plans/NS-05-lifecycle-handler-semantics.md](./plans/NS-05-lifecycle-handler-semantics.md) | NS-05 | Ready |
@@ -104,6 +105,12 @@ Allowed statuses: `Ready`, `In Progress`, `Blocked`, `Deferred`, `Done`
- [ ] Deferred work is explicitly marked deferred
- [ ] Completed work is reflected here and in [SDK Overview](../../OVERVIEW.md) when system status changes
## Status Notes
- `NS-01` completed on 2026-03-10 after operator-assisted real-device NFC validation confirmed Android and iOS success and failure paths in the KMP test app. See [plans/NS-01-physical-device-validation.md](./plans/NS-01-physical-device-validation.md) for the validation log.
- Local validation for `NS-01` also completed the KMP build gates and a callback-contract audit. The remaining contract mismatch stays isolated in `NS-06`.
- `NS-06` captures a contract mismatch found during the audit: KMP still exposes `VerificationResult.type` and `claims: Map<String, String>?`, which diverges from the canonical SDK contract in [SDK Overview](../../OVERVIEW.md).
## Overview
You are building the native side of the Self Mobile SDK — the Kotlin Multiplatform module (`packages/kmp-sdk/`) and the Swift companion package (`packages/self-sdk-swift/`). This means hosting a WebView containing Person 1's Vite bundle, routing bridge messages from the WebView to native handlers, and providing `SelfSdk.launch()` as the public API for host apps. On Android, handlers are written directly in Kotlin. On iOS, handlers delegate to Swift provider implementations via a factory pattern (cinterop is abandoned). This matters because it is the only native code standing between third-party host apps and the verification flow — it must be thin, correct, and easy to integrate.

View File

@@ -1,7 +1,7 @@
# Physical-Device Validation Matrix
> Last updated: 2026-03-10
> Status: Ready
> Status: Done
- Workstream: native-shells
- Backlog IDs: NS-01
@@ -60,12 +60,60 @@ cd packages/self-sdk-swift && swift build
## Definition of Done
- [ ] Android real-device NFC flow validated
- [ ] iOS real-device NFC flow validated
- [ ] Failure-path behavior documented
- [ ] Backlog row updated
- [ ] Follow-up bugs split into separate backlog items if needed
- [x] Android real-device NFC flow validated
- [x] iOS real-device NFC flow validated
- [x] Failure-path behavior documented
- [x] Backlog row updated
- [x] Follow-up bugs split into separate backlog items if needed
## Validation Evidence
### Build Gates
| Command | Result | Evidence |
| -------------------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cd packages/kmp-sdk && ./gradlew :shared:jvmTest` | Pass | 2026-03-10 local run succeeded (`UP-TO-DATE`) |
| `cd packages/kmp-sdk && ./gradlew :shared:compileDebugKotlinAndroid` | Pass | 2026-03-10 local run succeeded (`UP-TO-DATE`) |
| `cd packages/kmp-sdk && ./gradlew :shared:compileKotlinIosArm64` | Pass | 2026-03-10 local run succeeded; only Kotlin `expect/actual` beta warnings emitted |
| `cd packages/self-sdk-swift && swift build` | Fail | 2026-03-10 local run failed while compiling `NFCPassportReader`: `OpenSSL.framework/Headers/ssl.h:15:11: error: 'openssl/e_os2.h' file not found` |
### Real-Device Validation
| Platform | Result | Evidence |
| -------- | ------ | -------------------------------------------------------------------------------------------------------------- |
| Android | Pass | 2026-03-10 operator-confirmed real-device NFC success path and failure path both completed in the KMP test app |
| iOS | Pass | 2026-03-10 operator-confirmed real-device NFC success path and failure path both completed in the KMP test app |
### Callback Contract Audit
- Canonical contract in `specs/projects/sdk/OVERVIEW.md` allows `success`, `userId`, `verificationId`, `proof`, `claims`, and optional `error`, with `claims` typed as `Record<string, unknown>` / `Map<String, Any?>`.
- KMP public type in `packages/kmp-sdk/shared/src/commonMain/kotlin/xyz/self/sdk/api/SelfSdkCallback.kt` still exposes `type: String?` and narrows `claims` to `Map<String, String>?`.
- Both Android and iOS lifecycle handlers currently treat flat payloads with `type` as `onSuccess`, which matches RN shell behavior, but that `type` field is not part of the canonical `VerificationResult` contract.
- Follow-up item `NS-06` tracks aligning KMP lifecycle/result semantics with the canonical SDK contract; NS-01 does not widen into that implementation work.
## Failure-Path Matrix
| Platform | Scenario | Observed / inferred behavior | Source |
| -------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| Android | NFC unsupported | `isSupported()` returns `false` when adapter missing or disabled; `scan()` throws `NFC_NOT_SUPPORTED` if no adapter exists | `packages/kmp-sdk/shared/src/androidMain/.../NfcBridgeHandler.kt` |
| Android | NFC disabled | `scan()` throws `NFC_NOT_ENABLED` before reader mode is enabled | `packages/kmp-sdk/shared/src/androidMain/.../NfcBridgeHandler.kt` |
| Android | Non-passport tag | `scan()` throws `NFC_NOT_ISO_DEP` when detected tag lacks `IsoDep` | `packages/kmp-sdk/shared/src/androidMain/.../NfcBridgeHandler.kt` |
| Android | Auth failure | `readPassport()` throws `AUTH_FAILED` if both PACE and BAC fail | `packages/kmp-sdk/shared/src/androidMain/.../NfcBridgeHandler.kt` |
| Android | User dismiss | Host callback is `onCancelled()` only when lifecycle `dismiss` / cancelled result path runs; NFC bridge failure alone does not end host flow | `LifecycleBridgeHandler.kt`, `SelfSdk.android.kt` |
| iOS | Provider missing | `scan()` throws `NOT_CONFIGURED` | `packages/kmp-sdk/shared/src/iosMain/.../NfcBridgeHandler.kt` |
| iOS | Invalid params | `scan()` throws `MISSING_PASSPORT_NUMBER`, `MISSING_DOB`, or `MISSING_EXPIRY` | `packages/kmp-sdk/shared/src/iosMain/.../NfcBridgeHandler.kt` |
| iOS | Scan failure | Provider error maps to `NFC_SCAN_FAILED` | `packages/kmp-sdk/shared/src/iosMain/.../NfcBridgeHandler.kt` |
| iOS | Simulator / unavailable NFC | Swift helper returns `completion(false, "NFC is not available on simulator")`; Kotlin surfaces `NFC_SCAN_FAILED` | `packages/self-sdk-swift/Sources/SelfSdkSwift/Helpers/NfcPassportHelper.swift` |
| iOS | Concurrent scan | Swift provider returns `onError("A scan is already in progress")`; Kotlin surfaces `NFC_SCAN_FAILED` | `packages/self-sdk-swift/Sources/SelfSdkSwift/Providers/NfcProviderImpl.swift` |
| iOS | User dismiss | Host callback is `onCancelled()` only when lifecycle `dismiss` / cancelled result path runs; NFC bridge failure alone does not end host flow | `LifecycleBridgeHandler.kt`, `SelfSdk.ios.kt` |
## Notes
- `cd packages/self-sdk-swift && swift build` still fails in this environment because the `NFCPassportReader` dependency cannot compile against the local OpenSSL headers. This did not block iOS device validation via Xcode/workspace build.
- `NS-06` remains open because KMP callback/result shapes still diverge from the canonical `VerificationResult` contract even though observed launch/result semantics were acceptable during device validation.
## Status Log
- 2026-03-10: Created from native-shells follow-up backlog.
- 2026-03-10: Ran KMP build gates, audited callback semantics, and checked local device availability. Marked blocked because no usable Android/iOS hardware is currently available and `packages/self-sdk-swift` fails `swift build` locally on missing OpenSSL headers.
- 2026-03-10: Completed operator-assisted real-device NFC validation on Android and iOS for both success and failure paths. Marked `NS-01` done; retained `NS-06` as the follow-up contract-alignment item and kept the local `swift build` OpenSSL issue documented as an environment gap.