feat: v1.1.0 — 25+ native workers, secure chains, DevTools, security hardening#5
Merged
vietnguyentuan2019 merged 11 commits intomainfrom Apr 5, 2026
Merged
feat: v1.1.0 — 25+ native workers, secure chains, DevTools, security hardening#5vietnguyentuan2019 merged 11 commits intomainfrom
vietnguyentuan2019 merged 11 commits intomainfrom
Conversation
### Tier 1 — Critical bugs
| Task | Description | Status |
|------|-------------|--------|
| T1-1 | Auth token sanitization — `TaskStore.sanitizeConfig()` strips `authToken`, `cookies`, `password`, `secret` before SQLite persist. Both Android (`TaskStore.kt`) and iOS (`TaskStore.swift`) | ✅ Done |
| T1-2 | Main thread SQLite I/O — `handleAllTasks` on iOS and Android now dispatches to background queue/IO scope | ✅ Done |
| T1-3 | iOS `handleCancelAll` missing `taskNotifTitles.removeAll()` and `taskAllowPause.removeAll()` | ✅ Done |
| T1-4 | Android chain persistence — new `ChainStore.kt` (SQLite) + `resumePendingChains()` called on engine attach | ✅ Done |
### Tier 2 — Improvements
| Task | Description | Status |
|------|-------------|--------|
| T2-1 | Task store TTL — `cleanupAfterDays` param in `initialize()` → `TaskStore.deleteCompleted(olderThanMs:)` | ✅ Done |
| T2-2 | HTTPS enforcement — `enforceHttps: bool` param in `initialize()` → `SecurityValidator.enforceHttps` flag | ✅ Done |
| T2-3 | Custom worker className validation at Dart layer (regex + max length 256 chars) | ✅ Done |
| T2-4 | Builder pattern for `HttpDownloadWorker` — `copyWith()` + `withNotification()` / `withAuth()` / `withResume()` / `withChecksum()` convenience methods | ✅ Done |
| T2-5 | `sealed class Worker` (Dart 3.0 exhaustive pattern matching) replacing `abstract base class` | ✅ Done |
### Tier 3 — Advanced / New Features
| Task | Description | Status |
|------|-------------|--------|
| T3-1 | iOS Actor-based task state — `TaskActor.swift` created as drop-in replacement for `DispatchQueue + [String: Task]`. **NOT yet integrated into NativeWorkmanagerPlugin.swift** (deliberately deferred as too large a refactor; file is ready as
`utils/TaskActor.swift`) | ✅ Ready |
| T3-2 | `parallelHttpUpload` worker — Mirror of `parallelHttpDownload` but for uploads. Each file uploaded as a separate concurrent request with per-host concurrency limit (`HostConcurrencyManager`), retry-per-file, rich progress. All three layers
complete. | ✅ Done |
| T3-3 | DartWorker progress reporting — `NativeWorkManager.reportDartWorkerProgress(taskId, progress, message)` from background Dart isolate → `MethodChannel('dev.brewkits/dart_worker_channel')` → `FlutterEngineManager` (both platforms) →
`ProgressReporter` → Flutter EventChannel | ✅ Done |
| T3-4 | `ioScope` separation in Android plugin — `CoroutineScope(Dispatchers.IO + SupervisorJob())` for all SQLite and heavy I/O; main `scope` for WorkManager callbacks | ✅ Done |
---
…2.3.7
Worker Registry (T3-5):
- Android: per-worker ConcurrentHashMap registry in SimpleAndroidWorkerFactory
alongside legacy setUserFactory (backward compat preserved)
Bandwidth throttling (T3-6):
- Android: BandwidthThrottle wraps OkHttp ResponseBody via token-bucket
- iOS: BandwidthThrottle actor streams via URLSession.bytes (iOS 15+),
graceful no-op on iOS 14
- Dart: bandwidthLimitBytesPerSecond field added to HttpDownloadWorker
Request signing HMAC-SHA256 (T3-7):
- Android: RequestSigner applied in HttpDownload/Upload/Request/Sync workers
- iOS: RequestSigner applied in all four HTTP workers
- Dart: RequestSigning config added to all four HTTP worker classes
Troubleshooting guide (T2-6):
- doc/TROUBLESHOOTING.md with iOS/Android chain differences table,
setup, background execution, custom workers, debugging tips
Chain tests (T2-7):
- Integration tests: cancel-after-first-step + resume-remaining-steps
Build fixes for kmpworkmanager 2.3.7:
- WorkerResult.Success.data changed from Map to JsonObject:
migrate all 25+ worker sites to buildJsonObject { put(...) }
- Add kotlinx-serialization-json dependency to android/build.gradle
- TaskTrigger.BatteryOkay/BatteryLow/DeviceIdle/StorageLow removed;
mapped to TaskTrigger.OneTime() with constraints
- Add ScheduleResult.DEADLINE_ALREADY_PASSED branch to when expression
- Add @OptIn(AndroidOnly::class) for TaskTrigger.ContentUri
- Add missing withContext + OkHttpClient imports to NativeWorkmanagerPlugin
- Fix return@downloadBlock → return@withContext for early-return sites
before the downloadBlock label definition
- Fix existingBytes == 0 → 0L (Long/Int type mismatch)
- Fix okio.buffer(tracked) → tracked.buffer() (Okio 3.x API)
- Fix destinationFile used before declaration in ParallelHttpDownloadWorker
- Fix sealed class Worker → abstract class Worker (cross-file subclassing)
- Fix UploadFile duplicate export conflict in workers.dart
Full analysis of native_workmanager covering: - Architecture deep-dive (3-layer, KMP engine, design patterns) - Feature evaluation from PO / BA / Senior Dev perspectives - Pros/cons matrix with severity ratings - Competitor comparison (workmanager, flutter_background_service, background_fetch) - Development roadmap (Phase 1–3, P0/P1/P2 features) - Feasibility assessment and market positioning - KPI targets and enterprise adoption strategy - Technical metrics (codebase size, benchmarks, test coverage)
…1..L-4) Critical: - C-1: ParallelHttpDownloadWorker now parses & applies certificatePinning, tokenRefresh, requestSigning on Android and iOS (including 401 retry with token refresh in each chunk download and sequential fallback) - C-2: confirmed showNotification/notificationTitle/notificationBody handled at plugin layer for all worker types (no ghost issue) High: - H-1: AppContextHolder.appContext annotated @volatile for JVM visibility - H-2: BGTaskSchedulerManager Task closures use [weak self] to prevent strong-reference cycle on expirationHandler and executeWorker closures - H-3: PdfWorker.kt — SecurityValidator.validateFilePathSafe() called for all inputPaths, outputPath, imagePaths before File() construction - H-3 (iOS): PdfWorker.swift — SecurityValidator.validateFilePath() called before every URL(fileURLWithPath:) construction - H-4: Both SecurityValidators now block fe80::/10 IPv6 link-local (was only blocking ::1 loopback and fc00::/7 ULA) - H-5: HttpDownloadWorker and ParallelHttpDownloadWorker use Files.move(ATOMIC_MOVE) + AtomicMoveNotSupportedException fallback instead of non-atomic File.renameTo() Medium: - M-1: ParallelHttpDownloadWorker.kt validates checksumAlgorithm against allowlist before MessageDigest.getInstance(); returns shouldRetry=false for unsupported algorithm (not a transient error) - M-2: WebSocketWorker replaces awaitTermination(2s) on shared OkHttp dispatcher (always times out) with coroutine delay(250ms) - M-3: OfflineRetryPolicy._pow() replaced by math.pow(); delayFor() guards against infinite result with maxDelay fallback; maxRetries capped at 100 - M-4: HttpUploadWorker.swift boundary changed from static let to instance let so each upload uses a unique UUID boundary Low: - L-1: OfflineRetryPolicy assert updated; NaN caught by >= 1.0 check; Infinity clamped in delayFor via isFinite guard - L-2: confirmed false positive — iOS calculateChecksum already switches on algorithm string for MD5/SHA-1/SHA-256/SHA-512 - L-3: PdfWorker.swift SecurityValidator.validateFilePath() guards added - L-4: OfflineQueue.cancel() removes from _pending list before firing native cancels, eliminating scheduling race window All 1622 Dart unit tests pass.
…tability fixes - Add Flutter DevTools extension for real-time background task monitoring. - Fix iOS SIGKILL by implementing task expiration stop() protocol. - Fix Android 14 ForegroundServiceStartNotAllowedException via permission handling. - Restore missing HttpSecurityHelper and TaskEventBus native components. - Hardened ZipSlip and Path Traversal protections in native workers. - Fix various Kotlin compilation errors and resource leaks. - Standardized project versioning to v1.2.0 across all files.
…errors - Re-create HttpSecurityHelper.swift with CertificatePinningConfig and makeURLSession. - Move TokenRefreshConfig and AuthTokenManager to HttpSecurityHelper for better organization. - Fix 'Cannot find CertificatePinningConfig/makeURLSession in scope' errors in ParallelHttpDownloadWorker and HttpUploadWorker.
… KMPBridge - Move TokenRefreshConfig and AuthTokenManager back to KMPBridge.swift to ensure visibility in existing Xcode project. - Keep CertificatePinningConfig and makeURLSession in HttpSecurityHelper.swift. - This fixes compilation errors when newly created files are not automatically picked up by Xcode.
Core additions: - 25+ production-grade native workers (PDF, WebSocket, Crypto, File, Media) - Secure task chains with SQLite persistence and per-step retry - DartWorker.timeoutMs exposed in Dart API - LoggingMiddleware: HTTP POST telemetry after each task - registerMiddleware is now idempotent (upsert semantics) - Remote trigger support (FCM/APNs) without waking Flutter - DevTools extension for real-time task inspection - Smart Flutter Engine caching (5-min TTL after DartWorker) - Adaptive engine disposal on memory pressure Security: - AES-256-GCM encryption/decryption workers - Certificate pinning and HMAC request signing - SSRF protection blocking private/loopback IPs - Zip-bomb and zip-slip hardening Android fixes: - getTasksByTag/getAllTags/getTaskStatus now fall back to SQLite - SQLite stores consolidated to single DB with proper migrations - MiddlewareStore singleton prevents redundant DB connections - DFS cycle detection prevents StackOverflowError in task graphs iOS fixes: - resumePendingGraphs() restarts interrupted graphs on launch - executeWorkerStateless uses IosWorkerFactory for all worker types - Race conditions in OfflineQueue fixed with atomic barrier blocks - WorkerResult type mismatch in graph tasks resolved Example app: - All event listeners guard isStarted to prevent false "Task failed" toast - Photo backup and image process demos use real JPEG download chains - RenderFlex overflow fixed on small screens Tests: - Unit tests: 724 passed - Integration tests: 63/63 Android, 63/63 iOS README: - Redesigned logo (hexagon, clean at small sizes) - Quick Start moved to top; platform support table added - Workers reorganised into categorised table - Real-world use-case examples added (photo backup, encrypt+upload, periodic sync)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
.thenAll(), data flow between stepsregisterMiddlewareidempotent — upsert semantics; second call replaces, never accumulatesDartWorker.timeoutMs— per-task callback timeout now exposed in Dart APIonTrimMemory/ low-memory signalSecurity
Fixes
resumePendingGraphs()restarts interrupted chains on launchWorkerResulttype mismatch in graph tasks resolvedgetTasksByTag/getAllTags/getTaskStatusfall back to SQLite correctlyisStarted— eliminates false "Task failed" toastsTests
Packages
native_workmanager→ v1.1.0native_workmanager_gen→ v1.0.0 (first release)Test plan
dart analyze lib/— no issuesflutter pub publish --dry-run— clean (only uncommitted files warning)