add rn-sdk example app and fix capture package consumption - #2245
add rn-sdk example app and fix capture package consumption#2245seshanthS wants to merge 2 commits into
Conversation
…mers
Three packaging bugs found by integrating the packages into a fresh app:
- Podspecs: vendored static xcframeworks' Swift modules (Headers/*.swiftmodule)
were never on the Swift frontend's search path, so canImport(SelfSdkNfc/
SelfSdkOcr) was silently false and both modules compiled as unavailable
stubs even with the binaries present; the NFC pod additionally failed to
link (SELF_NFC_AVAILABLE-guarded ObjC extern module references the
compiled-out Swift class). CocoaPods' XCFrameworkIntermediates copy can't
serve as the search path — its per-framework rsync --delete clobbers the
merged Headers dir — so SWIFT_INCLUDE_PATHS points at the vendored slices
directly, per SDK.
- postinstall (rn-nfc-passport): the dist Mixpanel/SelfNFCPassportReader
swiftinterfaces were emitted without
-module-interface-preserve-types-as-written, so Mixpanel-module types are
self-qualified (Mixpanel.Properties) and shadowed by the Mixpanel class,
failing interface compilation. Strip the qualifier after extraction;
becomes a no-op once fixed artifacts ship from self-sdk-dist.
- package.json exports: Metro resolves the "import" condition to the tsup
ESM build, where lazy require('react-native') becomes a __require shim
Metro never registers as a dependency — it throws at runtime and the
try/catch returns undefined, so NativeModules resolution silently fails
(rn-nfc-passport entirely; rn-sdk's optional peers: nfc-manager,
biometrics, keychain, react-native-fs). Add a "react-native" exports
condition pointing at the CJS build; Node/Vite are unaffected.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…NFC flow
New workspace cloned from rn-sdk-test-app's known-good RN 0.83.9 + New Arch
config, demonstrating third-party consumption of @selfxyz/rn-sdk with the
optional capture packages:
- SelfVerification in self-app mode (WebView-driven MRZ camera scan + NFC
chip read onboarding) and disclose mode (request with disclosures routes
straight to /disclose/request)
- DirectCaptureScreen: standalone package usage — startScanning() for MRZ,
then scan/scanPassport with the MRZ-derived BAC keys
- capability panel via isMrzScannerAvailable/isSelfPassportReaderAvailable
Unlike the test app, the Xcode project does NOT link the self-sdk-swift SPM
package — its transitive SPM OpenSSL/NFCPassportReader/Mixpanel collide with
the CocoaPods-delivered copies ("Multiple commands produce OpenSSL.framework").
The KMP bridge path is intentionally out of scope here.
Validated: iOS Debug device build succeeds with real capture binaries;
Android debug build installs and completes MRZ scan + NFC chip read
on-device. Both apps' metro blockLists updated to exclude each other's
react copies.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📝 WalkthroughWalkthroughThe PR adds React Native export conditions and native framework integration fixes. It also adds a complete React Native example app with verification, MRZ capture, NFC capture, Android configuration, iOS configuration, and workspace build settings. ChangesSDK integration fixes
React Native example app
Estimated code review effort: 5 (Critical) | ~120 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: a571820e-77d7-4315-b123-8f53a5c724f5
⛔ Files ignored due to path filters (15)
packages/rn-sdk-example-app/Gemfile.lockis excluded by!**/*.lockpackages/rn-sdk-example-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.pngis excluded by!**/*.pngpackages/rn-sdk-example-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.pngis excluded by!**/*.pngpackages/rn-sdk-example-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.pngis excluded by!**/*.pngpackages/rn-sdk-example-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.pngis excluded by!**/*.pngpackages/rn-sdk-example-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.pngis excluded by!**/*.pngpackages/rn-sdk-example-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.pngis excluded by!**/*.pngpackages/rn-sdk-example-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.pngis excluded by!**/*.pngpackages/rn-sdk-example-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.pngis excluded by!**/*.pngpackages/rn-sdk-example-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.pngis excluded by!**/*.pngpackages/rn-sdk-example-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.pngis excluded by!**/*.pngpackages/rn-sdk-example-app/android/gradle/wrapper/gradle-wrapper.jaris excluded by!**/*.jarpackages/rn-sdk-example-app/ios/Podfile.lockis excluded by!**/*.lockpackages/rn-sdk-example-app/ios/SelfRNExampleApp.xcworkspace/contents.xcworkspacedatais excluded by!**/*.xcworkspace/contents.xcworkspacedatapnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (51)
packages/rn-mrz-scanner/package.jsonpackages/rn-mrz-scanner/selfxyz-rn-mrz-scanner.podspecpackages/rn-nfc-passport/package.jsonpackages/rn-nfc-passport/scripts/postinstall.jspackages/rn-nfc-passport/selfxyz-rn-nfc-passport.podspecpackages/rn-sdk-example-app/.gitignorepackages/rn-sdk-example-app/App.tsxpackages/rn-sdk-example-app/DirectCaptureScreen.tsxpackages/rn-sdk-example-app/Gemfilepackages/rn-sdk-example-app/README.mdpackages/rn-sdk-example-app/android/app/build.gradlepackages/rn-sdk-example-app/android/app/debug.keystorepackages/rn-sdk-example-app/android/app/proguard-rules.propackages/rn-sdk-example-app/android/app/src/debug/AndroidManifest.xmlpackages/rn-sdk-example-app/android/app/src/main/AndroidManifest.xmlpackages/rn-sdk-example-app/android/app/src/main/java/com/selfxyz/rnexample/MainActivity.ktpackages/rn-sdk-example-app/android/app/src/main/java/com/selfxyz/rnexample/MainApplication.ktpackages/rn-sdk-example-app/android/app/src/main/res/drawable/rn_edit_text_material.xmlpackages/rn-sdk-example-app/android/app/src/main/res/values/strings.xmlpackages/rn-sdk-example-app/android/app/src/main/res/values/styles.xmlpackages/rn-sdk-example-app/android/app/src/main/res/xml/nfc_tech_filter.xmlpackages/rn-sdk-example-app/android/build.gradlepackages/rn-sdk-example-app/android/gradle.propertiespackages/rn-sdk-example-app/android/gradle/libs.versions.tomlpackages/rn-sdk-example-app/android/gradle/wrapper/gradle-wrapper.propertiespackages/rn-sdk-example-app/android/gradlewpackages/rn-sdk-example-app/android/gradlew.batpackages/rn-sdk-example-app/android/settings.gradlepackages/rn-sdk-example-app/app.jsonpackages/rn-sdk-example-app/babel.config.cjspackages/rn-sdk-example-app/index.jspackages/rn-sdk-example-app/ios/.xcode.envpackages/rn-sdk-example-app/ios/Podfilepackages/rn-sdk-example-app/ios/SelfRNExampleApp.xcodeproj/project.pbxprojpackages/rn-sdk-example-app/ios/SelfRNExampleApp.xcodeproj/xcshareddata/xcschemes/SelfRNExampleApp.xcschemepackages/rn-sdk-example-app/ios/SelfRNExampleApp/AppDelegate.swiftpackages/rn-sdk-example-app/ios/SelfRNExampleApp/Images.xcassets/AppIcon.appiconset/Contents.jsonpackages/rn-sdk-example-app/ios/SelfRNExampleApp/Images.xcassets/Contents.jsonpackages/rn-sdk-example-app/ios/SelfRNExampleApp/Info-Debug.plistpackages/rn-sdk-example-app/ios/SelfRNExampleApp/Info.plistpackages/rn-sdk-example-app/ios/SelfRNExampleApp/LaunchScreen.storyboardpackages/rn-sdk-example-app/ios/SelfRNExampleApp/PrivacyInfo.xcprivacypackages/rn-sdk-example-app/ios/SelfRNExampleApp/SelfRNExampleApp.entitlementspackages/rn-sdk-example-app/ios/scripts/pod-install-with-cache-fix.shpackages/rn-sdk-example-app/metro.config.cjspackages/rn-sdk-example-app/package.jsonpackages/rn-sdk-example-app/react-native.config.cjspackages/rn-sdk-example-app/tsconfig.jsonpackages/rn-sdk-test-app/metro.config.cjspackages/rn-sdk/package.jsonturbo.json
| patchSwiftInterfaces(name); | ||
| log(`installed ios/Frameworks/${name}.xcframework`); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Patch existing xcframework installations.
patchSwiftInterfaces(name) runs only after a new extraction. main() skips existing .xcframework directories before this call. An existing workspace installation can therefore retain the invalid interfaces and disable NFC capture.
Call patchSwiftInterfaces(name) before continuing for an existing framework.
| android:icon="@mipmap/ic_launcher" | ||
| android:roundIcon="@mipmap/ic_launcher_round" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
Add the referenced launcher icon resources.
Line 16 and Line 17 reference @mipmap/ic_launcher and @mipmap/ic_launcher_round. The supplied resource set for this new app contains no matching mipmap resources. Android resource linking will fail before the app can build.
Add both launcher icon resources or reference existing resources.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d05366911f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| `${name}.xcframework missing after extracting ${name}-${version}.xcframework.zip` | ||
| ); | ||
| } | ||
| patchSwiftInterfaces(name); |
There was a problem hiding this comment.
Patch cached frameworks before returning
When ios/Frameworks already contains all three artifacts—such as after pulling this change into an existing SDK checkout—shouldSkip() returns frameworks already present and main() exits before this new patch runs. Those cached swiftinterfaces therefore retain the broken Mixpanel. qualification, so rerunning pnpm install leaves NFC unavailable; apply the patch to existing artifacts before the early return, not only immediately after extraction.
Useful? React with 👍 / 👎.
| the same token-gated Maven repo. **Without the token the app still builds, but both capture | ||
| modules compile as stubs and the capability panel shows `unavailable`.** |
There was a problem hiding this comment.
Do not promise tokenless Android builds
On a clean machine without locally published SDK artifacts, omitting SELF_SDK_GITHUB_TOKEN removes the only repository that can provide the private xyz.self.sdk:* dependencies, while the app and capture modules declare those dependencies unconditionally (for example xyz.self.sdk:shared:0.1.3). Gradle consequently fails dependency resolution rather than compiling capture stubs, so the documented tokenless behavior is only true for iOS or for developers who already populated mavenLocal().
Useful? React with 👍 / 👎.
| <key>NFCReaderUsageDescription</key> | ||
| <string>Needed to read passport NFC chip for identity verification.</string> |
There was a problem hiding this comment.
Add the passport AID to both iOS plists
When the example runs its primary NFC flow on an iPhone, both Info-Debug.plist and Info.plist provide only the usage description and omit com.apple.developer.nfc.readersession.iso7816.select-identifiers. The reader therefore cannot select the eMRTD ISO-7816 applet; add A0000002471001 as done by app/ios/Self/Info.plist, including in the Debug plist used by the documented device workflow.
Useful? React with 👍 / 👎.
| CLANG_ENABLE_MODULES = YES; | ||
| CODE_SIGN_ENTITLEMENTS = SelfRNExampleApp/SelfRNExampleApp.entitlements; | ||
| CURRENT_PROJECT_VERSION = 1; | ||
| DEVELOPMENT_TEAM = 5B29R5LYHQ; |
There was a problem hiding this comment.
Remove the committed Apple development team
A third-party developer opening this example inherits team 5B29R5LYHQ, which they do not control, so physical-device signing initially fails until the project file is edited. This also contradicts the README instruction to set the team locally and not commit DEVELOPMENT_TEAM; remove the setting from both Debug and Release so each consumer can select their own team without carrying a repository change.
Useful? React with 👍 / 👎.
| - `SELF_SDK_GITHUB_TOKEN` (a GitHub token with `read:packages` on `selfxyz/self-sdk-dist`) | ||
| exported **before `pnpm install`**. The capture packages' postinstall downloads the iOS |
There was a problem hiding this comment.
Require repository access for iOS framework downloads
A token granted only read:packages can authenticate to the Maven package registry but cannot read releases from the private selfxyz/self-sdk-dist repository. Both iOS postinstall scripts call the private repository Releases API, so a developer following this prerequisite receives a 404 and silently gets unavailable capture stubs; document private-repository/Contents read access in addition to read:packages.
Useful? React with 👍 / 👎.
Summary
packages/rn-sdk-example-app, a consumer example app exercising the full@selfxyz/rn-sdkflow — WebView-driven MRZ + NFC onboarding (self-app mode), direct-to-disclose mode, and standalone usage of@selfxyz/rn-mrz-scanner/@selfxyz/rn-nfc-passport— validated on-device (Android MRZ scan + NFC chip read completed; iOS Debug device build green with real capture binaries).require('react-native')silently throws.self-sdk-swiftSPM package (KMP bridge out of scope) — its transitive SPM OpenSSL/NFCPassportReader/Mixpanel collide with the CocoaPods-delivered copies.Changes
RN SDK packaging (
packages/rn-mrz-scanner,packages/rn-nfc-passport,packages/rn-sdk)SWIFT_INCLUDE_PATHSpointing at the vendored xcframework slices'Headers/socanImport(SelfSdkNfc/SelfSdkOcr)is true when the binaries are present. CocoaPods'XCFrameworkIntermediatescopy cannot serve this — its per-frameworkrsync --deleteclobbers the merged Headers dir.rn-nfc-passportpostinstall: patch the downloaded Mixpanel/SelfNFCPassportReader swiftinterfaces, stripping theMixpanel.self-qualification that fails to compile (interfaces were emitted without-module-interface-preserve-types-as-written; the class shadows the module). Becomes a no-op once fixed artifacts ship from self-sdk-dist."react-native"exports condition pointing at the CJS build. Metro previously resolved theimportcondition, where tsup turns lazyrequire('react-native')into a__requireshim Metro never registers — soNativeModulesresolution silently returnedundefined(rn-nfc-passportentirely;rn-sdk's optional peers nfc-manager/biometrics/keychain/react-native-fs).New example app (
packages/rn-sdk-example-app)rn-sdk-test-app's known-good RN 0.83.9 + New Arch config (PodfileRCT_NEW_ARCH_ENABLEDxcconfig fix, self-wallet asset copy build phase, token-gated self-sdk-dist maven, NFC entitlement + TECH_DISCOVERED filter, monorepo metro blockList).App.tsx: capability panel, self-app onboarding launch, and a disclose-mode launch (request withdisclosuresroutes the WebView straight to/disclose/request).DirectCaptureScreen.tsx: drives the capture packages directly —startScanning()for MRZ, then platform-splitscanPassport/scanchip read with the MRZ-derived BAC keys.com.selfxyz.rnexample(NFC entitlement needs an explicit App ID); noSelfSdkSwiftSPM reference.Config/infra
turbo.json:@selfxyz/rn-sdk-example-app#buildentry.packages/rn-sdk-test-app/metro.config.cjs: blockList the new app's react copies (and vice versa) to avoid duplicate-React failures.pnpm-lock.yamlfor the new workspace.Test Plan
pnpm lint && pnpm typespassespnpm --filter @selfxyz/rn-sdk-example-app typespassespnpm --filter @selfxyz/rn-sdk build && pnpm --filter @selfxyz/rn-mrz-scanner build && pnpm --filter @selfxyz/rn-nfc-passport build,pod install, then Debug device build succeeds withSELF_SDK_GITHUB_TOKENset (verified locally: BUILD SUCCEEDED; bundle containsself-wallet/index.html, one OpenSSL on the link line)./gradlew :app:assembleDebugwith token set; on-device capability panel showsmrzCamera: available/nfc: available(verified locally: MRZ scan + NFC chip read completed on a physical device)packages/rn-nfc-passport/ios/Frameworks, re-run postinstall, interfaces come back patched (verified locally)Native Consolidation Checklist
cd app && yarn jest:run/yarn workspace @selfxyz/rn-sdk-test-app test)🤖 Generated with Claude Code
Summary by CodeRabbit