Commit f0f76cc
feat: migrate legacy native modules to Nitro Modules (#22)
* feat: add react-native-native-logger module
Unified native logging module with static OneKeyLog API that self-initializes
on first call, replacing react-native-file-logger's JS-configured approach.
- iOS: CocoaLumberjack backend with custom log file naming (app- prefix) and message-only formatter
- Android: SLF4J + logback-android backend
- Nitro HybridObject bridge for JS layer (write, getLogFilePaths, deleteLogFiles)
- Consistent log file naming across platforms (app- prefix + date)
- Same log config as existing: 20MB max, 3 files, daily rolling, {CachesDir}/logs
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: code review fixes for native-logger module
- Remove unnecessary CocoaLumberjack import from iOS NativeLogger.swift
- Add else branch in Android NativeLogger.kt write() for unknown levels
- Use detachAndStopAllAppenders() in Android OneKeyLog to prevent duplicate logcat
- Unify iOS logsDirectory path to use computed property (remove duplication)
- Add sortedBy to Android getLogFilePaths() for consistent ordering with iOS
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: integrate OneKeyLog into native modules
Add file-based logging via OneKeyLog to 5 native modules:
- device-utils: UI style changes, foldable detection, spanning state
- keychain-module: keychain operations success/failure with OSStatus
- cloud-kit-module: CloudKit CRUD operations and query results
- check-biometric-auth-changed: biometric state change detection
- get-random-values: error-only logging for SecRandomCopyBytes/SecureRandom
Each module declares a dependency on ReactNativeNativeLogger (iOS podspec)
and compileOnly project dependency (Android build.gradle where applicable).
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: add NativeLogger test page to example app
Add test page with log directory viewer, write operations (custom message,
all levels, batch), and file management (refresh, delete). Registers
the native-logger module in the example app route and package.json.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* chore: bump version to 1.1.20
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* chore: add native-logger as default dependency in module template
New modules created via create-nitro-module.js will now include
OneKeyLog dependency out of the box (podspec, build.gradle, imports).
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: address code review issues for native-logger module
- Replace force unwrap with safe unwrap in iOS logsDirectory
- Use detachAppender instead of detachAndStopAllAppenders on Android
- Handle applicationContext null gracefully in Android OneKeyLog
- Log failures in getLogFilePaths and deleteLogFiles (iOS + Android)
- Redact keychain key names in log output for security
- Replace setTimeout with await in test page
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: remove key names from keychain logs and improve comments
- Remove all key name references from Keychain log messages for security
- Add detailed comment explaining maximumNumberOfLogFiles off-by-one
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: security hardening for native-logger module
HIGH:
- H-2: Replace unsafe /tmp/logs fallback with no-op when context is null
- H-3: Apply iOS file protection (completeUntilFirstUserAuthentication)
- H-1: Add 4KB message truncation to prevent disk abuse
MEDIUM:
- M-1: Attach file appender to named "OneKey" logger instead of ROOT
to prevent capturing third-party SLF4J output
- M-2: Change compileOnly to implementation to prevent NoClassDefFoundError
- M-3: Truncation also mitigates log injection via oversized messages
- M-5: Fix TOCTOU race in iOS log archive with retry loop
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: final review fixes for native-logger
- P1: deleteLogFiles skips active app-latest.log to avoid breaking
logger's open file handle (iOS + Android)
- P2: Android logger uses retry-able cached getter instead of by-lazy,
so if applicationContext is null at first access, logging can
recover once context becomes available
- P3: Log warning if iOS archive TOCTOU retry loop exhausts 1000 attempts
- P4: Remove unused OneKeyLog imports from module template
- P5: Use NSString.appendingPathComponent for iOS path construction
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: fix. missing log dir
* fix: audit fixes across integrated native modules
- P1: Replace force unwrap with guard let in ReactNativeGetRandomValues (iOS)
- P2: Remove duplicate error logging in KeychainModule wrapper (Core already logs)
- P2: Change biometric auth change log level from warn to info
- P2: Add @volatile to windowLayoutInfo for thread-safe reads from Promise.async
- P2: Use error.localizedDescription in CloudKit logs for consistency
- P3: Remove unnecessary UserDefaults.synchronize() call
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: add timestamp format for native log writes and copy button for log dir
- Native-side log writes now use `HH:mm:ss | LEVEL : [tag] message` format
- JS-side log writes remain unformatted (raw message preserved)
- Add copy-to-clipboard button for log directory path in test page
- Integrate native-logger into example app and update pod dependencies
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add startup log in native layer for iOS and Android
- iOS: call OneKeyLog via ObjC bridge (OneKeyLogBridge) to avoid
Clang module build failure with NitroModules C++ headers
- Android: call OneKeyLog.info directly in MainApplication.onCreate
- Both log "Application started" with native timestamp format
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use correct autolinked Gradle project name for native-logger
React Native autolinking generates project names from scoped npm
package names by replacing `@`/`/` with `_`, so
`@onekeyfe/react-native-native-logger` becomes
`:onekeyfe_react-native-native-logger`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: auto-init OneKeyLog via ContentProvider before Application.onCreate
ContentProvider.onCreate() runs between attachBaseContext() and
Application.onCreate(), so the logger is ready for the earliest
app-level startup logs. Consuming apps no longer need to call
OneKeyLog.init() manually.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add native modules migrated from legacy bridge architecture
Add 5 new Nitro modules and extend device-utils for migrating all legacy
RCTBridgeModule/ReactContextBaseJavaModule code to New Architecture:
- react-native-bundle-update: JS bundle OTA update with SHA256 verification,
ZIP extraction, PGP signature validation, and download progress events
- react-native-app-update: Android APK download/install with notification
progress (iOS stub)
- react-native-perf-memory: Memory usage reporting (RSS) for iOS and Android
- react-native-splash-screen: Legacy splash screen for Android < 12 (iOS stub)
- react-native-webview-checker: Android WebView package info and Google Play
Services availability check (iOS stub)
- react-native-device-utils: Extended with LaunchOptions, ExitApp, and
startup time tracking
All modules use OneKeyLog for logging and follow the Nitro callback listener
pattern for events (replacing NativeEventEmitter).
* feat: add example test pages for new native modules
Add test pages for BundleUpdate, AppUpdate, PerfMemory, SplashScreen,
and WebViewChecker modules. Also add LaunchOptions and ExitApp tests
to the existing DeviceUtils test page.
* fix: critical security and reliability fixes for bundle-update and app-update
- Use custom urlSession instead of URLSession.shared to prevent HTTPS bypass via HTTP redirects (iOS bundle-update)
- Add HTTPS redirect detection after download completes (iOS bundle-update)
- Enforce TLS 1.2 minimum on URLSession configuration (iOS bundle-update)
- Use defer to guarantee isDownloading reset on all error paths (iOS bundle-update)
- Wrap downloadAPK in try/finally to guarantee isDownloading reset (Android app-update)
- Make verifyASC throw instead of silently succeeding without GPG verification (Android app-update)
- Fix response.body!! force-unwrap crash in downloadASC (Android app-update)
- Add readTimeout to OkHttpClient to prevent indefinite hangs (Android app-update)
- Make testVerification return false instead of true when GPG is unimplemented (both platforms)
- Remove dead downloadThread field and unused MessageDigest import (Android app-update)
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: implement GPG signature verification for bundle-update and app-update
Port GPG verification from app-monorepo desktop implementation to native modules:
- iOS bundle-update: Gopenpgp framework integration via dynamic ObjC calls with graceful fallback
- Android bundle-update: BouncyCastle bcpg for PGP cleartext signature verification
- Android app-update: Full verifyASC implementation with SHA256 hash comparison
- Embed OneKey developer GPG public key for signature validation
- Add real test signatures from app-monorepo for testVerification()
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: high severity issues across native modules
- native-logger: replace thread-unsafe SimpleDateFormat with DateTimeFormatter (Android),
add NSLock around DateFormatter calls (iOS)
- native-logger: add android.util.Log fallback when file logger is unavailable (Android)
- bundle-update: add DispatchQueue for thread-safe access to listeners/isDownloading (iOS)
- app-update: validate file paths against app directories to prevent path traversal (Android)
- webview-checker: use WebView.getCurrentWebViewPackage() API 26+ with fallback candidates (Android)
- device-utils: replace exit(0) with UIApplication suspend to avoid App Store rejection (iOS)
- bundle-update: add symlink detection after zip extraction (Android)
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: medium severity issues across native modules
- Fix Base64 encoding inconsistency between iOS/Android in get-random-values
- Fix UTF-8 truncation at buffer boundaries in bundle-update readFileContent
- Fix dead downloadTask property in iOS bundle-update, use session invalidation
- Fix non-atomic write in bundle-update writeFallbackUpdateBundleDataFile
- Fix clearCache not actually clearing cached files in app-update
- Downgrade CloudKit recordID logging from info to debug level
- Add ProGuard consumer rules for logback-android in native-logger
- Flush log buffers before getLogFilePaths on both platforms
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: vendor Gopenpgp xcframework into bundle-update module
Integrate Gopenpgp v3.3.0 xcframework directly into app-modules so
app-monorepo no longer needs to separately import the GPG framework.
Replace dynamic ObjC runtime calls (NSClassFromString/NSSelectorFromString)
with direct typed Gopenpgp API imports for type safety and clarity.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: migrate lite-card logging to NativeLogger and remove sensitive data from logs
Replace all android.util.Log and NSLog calls in react-native-lite-card
with OneKeyLog (NativeLogger) for unified file-based logging. Remove
plaintext PIN logging, cardInfo dumps, certificate serial numbers, and
APDU response data from log output. Add native-logger as dependency
on both Android (build.gradle) and iOS (podspec).
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: migrate background-thread logging to NativeLogger
Replace NSLog with OneKeyLog in BackgroundRunnerReactNativeDelegate.
This was the last remaining module using direct system logging.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: replace @import with dynamic dispatch for NativeLogger in background-thread .mm files
@import ReactNativeNativeLogger fails in Objective-C++ (.mm) files because
C++ modules (-fcxx-modules) are not enabled. Introduce BTLogger as an internal
wrapper that dynamically dispatches to OneKeyLog via ObjC runtime, and add a
startup log in BackgroundThreadManager to verify the logging path works.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: pod install to sync new headers and dependencies
Re-ran pod install to pick up LaunchOptions.hpp for ReactNativeDeviceUtils
and sync ReactNativePerfMemory + ReactNativeNativeLogger dependency changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: replace @import with dynamic dispatch for NativeLogger in lite-card module
Same issue as BackgroundThread — @import ReactNativeNativeLogger fails because
the module's umbrella header includes C++ headers, making the entire module
unbuildable without -fcxx-modules. Introduce LCLogger as a dynamic dispatch
wrapper and replace all direct OneKeyLog calls.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add missing deepLink parameter to LaunchOptions initializer
The nitrogen-generated LaunchOptions struct now requires a deepLink
field. Update all call sites to pass deepLink (nil for non-URL launches,
extracted from LaunchOptionsKey.url otherwise).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: yarn install to link new workspace packages
Re-ran yarn install to generate node_modules symlinks for
react-native-bundle-update and react-native-app-update.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add initialization log in parent TurboModule entry points
Log via BTLogger/LCLogger in getTurboModule: of BackgroundThread and
ReactNativeLiteCard to verify dynamic dispatch to OneKeyLog works
as soon as the module is loaded by JS.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use module-qualified class name and typed IMP for OneKeyLog dispatch
NSClassFromString(@"OneKeyLog") returns nil because Swift classes need
the module-qualified name (ReactNativeNativeLogger.OneKeyLog). Also
switch from performSelector to methodForSelector with typed function
pointer, matching the working pattern in OneKeyLogBridge.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: pod install to add app-update, bundle-update and related pods
Re-ran pod install to register ReactNativeAppUpdate, ReactNativeBundleUpdate
and their dependencies (Gopenpgp, ReactNativeSplashScreen, ReactNativeWebViewChecker)
in the Xcode project. Pods count 91 → 96.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add override keyword to ReactNativeBundleUpdate init
HybridReactNativeBundleUpdateSpec (Nitro base class) already defines
init(), so the subclass must use override init() + super.init().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: fix compilation errors in ReactNativeBundleUpdate
- Add missing `import SSZipArchive`
- Convert Gopenpgp ObjC error-pointer APIs to Swift throwing syntax:
builderWithKey.new() and verifyCleartext/signatureError now use try
- Add override/super.init() was already fixed in previous commit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: fix remaining BundleUpdate compilation errors
- Use `any CryptoPGPVerifyProtocol` for verify handle type (Swift
existential protocol)
- SSZipArchive.unzipFile is a throwing method, use do/try/catch
instead of guard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: security hardening across native modules
- Restrict skipGPGVerification to debug builds only (bundle-update)
- Remove plain JSON fallback in GPG signature verification
- Require bundle verification before activation via setCurrentUpdateBundleData
- Restrict getSha256FromFilePath to bundle directories only
- Enforce HTTPS for all download URLs (app-update)
- Verify APK signing certificate matches installed app
- Require verifyAPK before installAPK
- Fix buildFile path validation when context is null (app-update)
- Add decompression bomb protection (512MB limit) for zip extraction
- Sanitize version strings before use in file paths
- Add constant-time hash comparison (secureCompare)
- Fix isDownloading flag reset with try/finally (Android bundle-update)
- Add HTTPS redirect validator for all redirect hops (iOS bundle-update)
- Gate NFC/APDU debug logging behind FLAG_DEBUGGABLE (lite-card)
- Add sensitive data redaction for JS log writes (native-logger)
- Return filenames instead of absolute paths from getLogFilePaths
- Add log injection protection (newline stripping) in OneKeyLog
- Change keychain iCloud sync default to false
- Add upper bound validation for getRandomBase64 (64KB)
- Remove sensitive data from error messages (app-update)
- Fix file:/// prefix stripping to use removePrefix
- Fix clearBundle data race on isDownloading (iOS)
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: comprehensive security hardening across all native modules (round 2)
- bundle-update: disable insecure verifyBundle path, add decompression bomb protection, unconditional downgrade protection
- app-update: TOCTOU protection with hash verification, modern APK signature API, disable redirects, ASC size limit
- native-logger: expanded sensitive data patterns (WIF, xprv, Bearer), rate limiting, tag sanitization
- lite-card: redact APDU data from logs, clear PINs after use, semaphore timeouts, PIN validation, memory cleanup
- background-thread: deny cross-sandbox routing by default, add error logging in catch blocks
- keychain: atomic add-or-update instead of delete-then-add race condition
- cloud-kit: input validation for record IDs/types, query results limit
- biometric: migrate domain state from UserDefaults to Keychain
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: security hardening round 3 - metadata validation, downgrade protection, hash validation
- bundle-update(Android): parseMetadataJson now throws on parse failure instead of returning empty map that could bypass file validation
- bundle-update(Android+iOS): version downgrade check rejects non-numeric version when current is numeric, preventing bypass via malformed version strings
- app-update(Android): SHA256 hash from ASC file validated as 64-char lowercase hex, not just length check
- lite-card(Android): mCardConnection marked @volatile for cross-thread visibility
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* Update KeychainModuleCore.swift
* feat: replace debug-mode GPG skip with MMKV DevSettings toggle
Replace the previous `isDebuggable()` / `#if DEBUG` guard with a
runtime check of two MMKV keys read from the host app's
"onekey-app-setting" store:
- onekey_developer_mode_enabled (DevSettings master switch)
- onekey_bundle_skip_gpg_verification (skip-GPG sub-toggle)
GPG / SHA-256 verification is now skipped only when **both** keys are
true, making it possible to test the skip path on release builds in a
controlled way without shipping a permanently open backdoor.
Changes:
- BundleUpdate iOS/Android: add isDevSettingsEnabled / isSkipGPGEnabled
helpers; apply to verifyBundleASC, verifyExtractedBundle,
setCurrentUpdateBundleData, and startup SHA256 check
- AppUpdate Android: add isDevSettingsEnabled; apply to verifyASC
- Remove skipGPGVerification field from BundleVerifyASCParams /
BundleInstallParams (callers no longer need to pass it)
- Add MMKV compileOnly dependency to Android build.gradle files
- Add MMKV pod dependency to ReactNativeBundleUpdate.podspec
- Example app: add DevSettings Skip-GPG test panel with live toggles
and "Verify All Local Bundles" button; add react-native-mmkv dep
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: add saveDeviceToken to DeviceUtils and make exitApp a no-op on iOS
- Add saveDeviceToken(token) API (iOS + Android) that persists the
push-notification device token to UserDefaults / SharedPreferences
under key "1k_device_token"
- Update getDeviceTokenString (iOS) to prefer the JS-saved token over
the raw APNs Data token set by AppDelegate, with graceful fallback
- Make exitApp() a no-op on iOS: Apple prohibits programmatic
termination (App Store guideline 2.4.5); removes the suspend selector
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: add logging for invalid byteLength in GetRandomValues
Log a warning via OneKeyLog before throwing the error when an
out-of-range byteLength is passed to getRandomBase64 on both
iOS and Android, making it easier to diagnose bad callers.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: implement Android legacy splash screen with SplashScreenBridge
Port SplashScreenView, SplashViewController, SplashImageResizeMode, and
SplashScreenBridge from app-monorepo Java to Kotlin for Android API < 31
compatibility. iOS implementation is intentionally a no-op since
expo-splash-screen handles it via the launch storyboard.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: merge react-native-webview-checker into react-native-device-utils
Add WebViewPackageInfo and GooglePlayServicesStatus types plus
getCurrentWebViewPackageInfo() and isGooglePlayServicesAvailable()
methods to DeviceUtils. Delete the standalone webview-checker module.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: add WebView & Play Services examples to DeviceUtils test page
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* update podfile
* chore: update Podfile.lock to v1.1.21, remove ReactNativeWebviewChecker
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: fix iOS build errors in BundleUpdate (MMKV and SSZipArchive API)
- Rename initializeMMKV(nil) to initialize(rootDir: nil) for latest MMKV
- Fix SSZipArchive.payloadSize call to include error parameter
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: remove SSZipArchive payloadSize call that fails to compile
The payloadSizeForArchiveAtPath:error: method is not visible to Swift
in SSZipArchive 2.4.3. The zip file size check on disk already provides
decompression bomb protection.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: pass archived path to super.didArchiveLogFile to prevent crash
After moving the log file to its archived name, the super call must
receive the new path. Passing the original (now nonexistent) path
caused an unhandled ObjC exception in DDLogFileManagerDefault.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: add download bundle test with platform-specific default URLs
iOS default: uni-test.onekey-asset.com 5016000 bundle
Android default: uni.onekey-asset.com 5019002 bundle
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: redesign BundleUpdateTestPage with step-by-step pipeline UI
Replace flat button layout with a modern dark-themed pipeline:
- 3 sequential steps: Download → Verify → Install
- Animated progress bar (percentage on Android, indeterminate on iOS)
- Step indicators with status colors (pending/active/completed/error)
- Dev settings and utilities in collapsible sections
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: fix missing funcs
* fix: move PGP signature to verifyBundleASC step in BundleUpdateTestPage
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: add comprehensive logging to AppUpdate and BundleUpdate native modules
Add detailed input params and execution status logging to all functions
in both modules for easier debugging. Fix verifyBundle to perform SHA256
verification instead of throwing unsupported error.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: add logging to all remaining BundleUpdate functions (iOS + Android)
Add OneKeyLog calls to every function that was missing logging:
addDownloadListener, removeDownloadListener, clearAllJSBundleData,
getWebEmbedPath, getJsBundlePath, getNativeAppVersion, isBundleExists,
verifyExtractedBundle, listLocalBundles, getSha256FromFilePath, and
all test* functions. Every function now logs input params and results.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: fix Android build errors across native modules
- Change Promise<Void> to Promise<Unit> in AppUpdate and BundleUpdate
to match updated Nitro codegen specs
- Fix smart cast issue with signatures in verifyAPK by extracting to
local vals
- Add missing deepLink parameter to LaunchOptions in DeviceUtils
- Replace NitroModules.applicationContext with BuildConfig.DEBUG in
lite-card LogUtil (module doesn't depend on nitro-modules)
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: add BuildConfig import to lite-card LogUtil
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: use host app FLAG_DEBUGGABLE instead of library BuildConfig.DEBUG
Library module's BuildConfig.DEBUG won't reflect the host app's build
type. Use Utils.getApp().applicationInfo.flags to check FLAG_DEBUGGABLE
at runtime, which correctly detects the host app's debug state.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: redesign AppUpdateTestPage with pipeline UI matching BundleUpdateTestPage
Dark theme, card layout, step-by-step pipeline (Download → Verify → Install)
with animated progress bar, collapsible utilities section, and platform info.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* Update BundleUpdateTestPage.tsx
* feat: improve app-update download with sandbox path fix, error logging, and APK cache verification
- Fix relative path resolution: resolve to cacheDir/apks/ instead of root /
- Add detailed error logging in buildFile and downloadAPK catch block
- Verify existing APK via ASC SHA256 before re-downloading
- Extract shared computeSha256 helper to reduce duplication
- Update clearCache to clean cacheDir/apks/ directory (APK + ASC files)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: remove filePath from AppUpdate API, derive from downloadUrl
filePath is now inferred internally from the download URL's last path
segment instead of being passed as a parameter.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: fix remaining params.filePath reference in installAPK
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: fix download progress events and prevent duplicate downloads in native layer
- Fix event type mismatch: JS now listens for 'downloading' instead of 'update/downloading'
- Native downloadAPK throws error instead of silently returning when already downloading
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* Update AppUpdateTestPage.tsx
* fix: skip packageName and certificate checks in debug builds, still log results
In verifyAPK and installAPK, debug builds (FLAG_DEBUGGABLE) now run all
comparisons and log match/mismatch results but skip throwing exceptions,
allowing testing with different-signed APKs.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: add Download ASC and Verify ASC steps to AppUpdate pipeline
Pipeline now has 5 steps: Download APK → Download ASC → Verify ASC →
Verify APK → Install APK. Removed redundant ASC buttons from utilities.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* refactor: unify AppUpdate event types with update/ prefix
Align with BundleUpdate convention: update/start, update/downloading,
update/downloaded, update/error.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: add BouncyCastle provider dependency and registration for GPG verification
- Add bcprov-jdk15to18 dependency (was missing, only bcpg was included)
- Register BouncyCastleProvider at class init to fix "cannot create signature: no provider"
- Add try/catch logging in verifyASC to capture exceptions before they propagate
- Applied to both app-update and bundle-update modules
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use BouncyCastle provider instance instead of string name to avoid Android built-in BC conflict
Android ships a stripped-down "BC" provider that doesn't support SHA256withRSA.
Passing our own BouncyCastleProvider() instance directly bypasses the name lookup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add FileProvider config for APK install intent
- Declare FileProvider in library manifest (auto-merged into host app)
- Add file_paths.xml exposing cacheDir/apks/ for FileProvider access
- Add REQUEST_INSTALL_PACKAGES permission
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: move bcProvider to BundleUpdateStoreAndroid where it's used
bcProvider was in ReactNativeBundleUpdate companion but used in
BundleUpdateStoreAndroid.verifyGPGAndExtractSha256, causing unresolved
reference error.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* feat: add download progress logging and error catch in bundle-update downloadBundle
- Log progress percentage at each 1% increment during download
- Add catch block to log exceptions before propagating
- Deduplicate sendEvent calls by only emitting on progress change
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update BundleUpdateTestPage.tsx
* feat: add download progress logging in iOS bundle-update
- Log progress percentage at each 1% increment during URLSession download
- Deduplicate progress callbacks by tracking previous progress value
- Reset progress state on delegate reset
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add diagnostic logging for bundle download file creation
- Ensure parent directory exists before FileOutputStream
- Log totalBytesRead, fileExists, and fileSize after download completes
- Helps diagnose ENOENT issue after download
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update BundleUpdateTestPage.tsx
* Update BundleUpdateTestPage.tsx
* Update BundleUpdateTestPage.tsx
* fix: add detailed diagnostic logging to getJsBundlePath on Android and iOS
Each validation step that can silently return null/empty now logs the specific failure reason,
making it easy to diagnose why getJsBundlePath returns empty after bundle install.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update BundleUpdateTestPage.tsx
* feat: migrate signature storage from SharedPreferences/UserDefaults to file
Store signatures as files at <bundleDir>/asc/<version>-signature.asc instead
of SharedPreferences (Android) / UserDefaults (iOS) to avoid storage size
issues with multiple versions. Also adds listAscFiles API and fixes
installBundle passing empty signature in example.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add logging to writeSignatureFile and readSignatureFile on both platforms
Log file existence, size, and path on write; log existence and content size
on read to help diagnose signature storage issues.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add filePath field to AscFileInfo in listAscFiles API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: expose BundleUpdateStore to ObjC runtime and bump to 1.1.22
Add @objcMembers and NSObject inheritance to BundleUpdateStore so
AppDelegate can access it via NSClassFromString + KVC, avoiding direct
Nitro module imports that cause Clang dependency scanner failures.
* Update package.json
* Update Podfile.lock
* fix: address PR review security and robustness issues
- AppUpdate: verify GPG signature before trusting ASC hash in tryVerifyExistingApk
- AppUpdate: use constant-time secureCompare for SHA256 hash comparison
- SplashScreen: set isAlreadyHidden only after successful hide
- SplashScreen: add cancellation to searchForRootView polling loop
- BiometricAuth: handle nil evaluatedPolicyDomainState explicitly
- GetRandomValues: reject non-integer byteLength (iOS + Android)
- AppUpdate iOS: use monotonically increasing listener IDs
- Keychain: fix misleading enableSync comment to match actual default
- Remove all README.md files from native-modules
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* fix: use onekey-app-dev-setting MMKV instance and require dual check for GPG skip
- Change MMKV instance ID from onekey-app-setting to onekey-app-dev-setting
across bundle update (Android/iOS) and app update (Android)
- Add isSkipGPGEnabled() to app update module requiring both dev mode
and skip-GPG toggle to bypass ASC verification (matching bundle update behavior)
- Update test page MMKV instance ID
* chore: bump native modules and views version to 1.1.23
* fix: address Copilot review - stack traces, import Security, FileProvider authority
- Add exception stack traces to error logs in MiUtil.kt and ReactNativeGetRandomValues.kt
- Add explicit `import Security` in ReactNativeGetRandomValues.swift
- Use module-specific FileProvider authority `appupdate.fileprovider` to avoid conflicts
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
* chore: bump native modules and views version to 1.1.24
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Happy <yesreply@happy.engineering>1 parent 54fd2df commit f0f76cc
211 files changed
Lines changed: 17432 additions & 452 deletions
File tree
- example/react-native
- android/app/src/main/java/com/example
- ios
- example.xcodeproj
- example
- pages
- native-modules
- native-logger
- android
- src/main
- cpp
- java/com/margelo/nitro/nativelogger
- ios
- src
- react-native-app-update
- android
- src/main
- cpp
- java/com/margelo/nitro/reactnativeappupdate
- res/xml
- ios
- src
- react-native-background-thread
- ios
- react-native-bundle-update
- android
- src/main
- cpp
- java/com/margelo/nitro/reactnativebundleupdate
- ios
- Frameworks/Gopenpgp.xcframework
- ios-arm64_x86_64-simulator/Gopenpgp.framework
- Headers
- Modules
- ios-arm64/Gopenpgp.framework
- Headers
- Modules
- src
- react-native-check-biometric-auth-changed
- ios
- react-native-cloud-kit-module
- ios
- react-native-device-utils
- android
- src/main/java/com/margelo/nitro/reactnativedeviceutils
- ios
- src
- react-native-get-random-values
- android
- src/main/java/com/margelo/nitro/reactnativegetrandomvalues
- ios
- react-native-keychain-module
- ios
- react-native-lite-card
- android
- src/main/java/com/onekeyfe/reactnativelitecard
- nfc/broadcast
- onekeyLite
- nfc
- utils
- ios
- Classes
- OKNFTLite
- Utils
- react-native-perf-memory
- android
- src/main
- cpp
- java/com/margelo/nitro/reactnativeperfmemory
- ios
- src
- react-native-splash-screen
- android
- src/main
- cpp
- java/com/margelo/nitro/reactnativesplashscreen
- ios
- src
- native-views/react-native-skeleton
- scripts/nitro/template
- android
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| 26 | + | |
25 | 27 | | |
26 | 28 | | |
27 | 29 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
0 commit comments