Skip to content

rclone to 1.73 and ndk to 29, Internxt, Drime support - #394

Open
thies2005 wants to merge 77 commits into
newhinton:masterfrom
thies2005:master
Open

thies2005 wants to merge 77 commits into
newhinton:masterfrom
thies2005:master

Conversation

@thies2005

Copy link
Copy Markdown

Changes: * New Providers: * Added explicit support for Drime cloud storage. * Added support for Internxt decentralized cloud storage, including a new flow for handling Two-Factor Authentication (2FA). * UI Enhancements: * Updated transfer notifications to display real-time Upload and Download speeds. * Added session statistics to track total data Uploaded and Downloaded. * Documentation: * Updated README.md to reflect the newly supported providers. bumped rclone to 1.73 and ndk to 29

thies2005 and others added 30 commits February 2, 2026 23:45
Internxt requires interactive authentication to connect to their API
and retrieve a mnemonic during config. This change adds internxt to
the list of providers that use the OAuth-style ConfigCreate flow,
enabling proper authentication handling.
…logging

- Add internxt to OAuth-style providers list for interactive multi-step auth
- Internxt requires connecting to their API to get mnemonic and handle 2FA
- Add error logging to RemoteConfigHelper to capture rclone stderr on failure
- This helps debug authentication issues with new backends
- Add InternxtTwoFactorStep and InternxtTwoFactorAction to OauthHelper.java
- Shows dialog for 2FA code input, blocks until user enters code
- Add InternxtFinishStep to handle config completion
- Update ConfigCreate.kt to detect Internxt and use InteractiveRunner
- Pass provider type from DynamicRemoteConfigFragment to ConfigCreate
- Uses CountDownLatch for thread synchronization with UI dialog
- Process all rclone log lines for stats/progress, not just error/warning
- Notification now updates with transfer progress, speed, ETA during sync
- Speed indication was already implemented in StatusObject, just not being used
- Add signing config passwords for release builds
…agement

Implements proactive session healing for OAuth-enabled remotes (Internxt, etc.)

Phase 1 - Go Backend:
- Replace boolean authFailed with stateful authFailCount/nextAuthAllowed
- Add TOTP time window retries (T, T-1, T+1) for clock skew handling
- Implement exponential backoff: 1m, 5m, 15m, 1h, 1h with ±10% jitter
- Max 5 failures before requiring manual re-auth
- Reset authFailCount to 0 on successful operations

Phase 2 - Android WorkManager:
- Create SessionGuardianWorker for 8-hour periodic health checks
- Discover OAuth remotes via config dump (token/access_token/totp_secret)
- Lightweight health probe using rclone lsd --max-depth 1
- Silent healing via Go backend during probe
- Add SessionGuardianScheduler with network/battery constraints

Phase 3 - Android UI:
- Add "Re-authenticate" menu item to remote options
- Manual re-auth triggers existing RemoteConfig with CONFIG_EDIT_TARGET
- Leverages existing OAuth flow and Internxt 2FA UI

Phase 4 - Failsafe Notifications:
- Detect "auth exceeded max retries" error from Go backend
- Show notification with deep-link to Remotes view
- Added checkAndNotifyAuthError() helper for easy integration

This moves from "Hard Fail" to "Resilient Background Healing" model,
preventing silent session drops after 2FA failures or clock skew.

Resolves: Sessions dropping silently for 2FA-enabled remotes after few days
- Enable CGO_ENABLED=1 for Android ARM builds (was disabled)
- Add CC environment variable pointing to NDK cross-compilers
- Support ARM64 Linux as build host (os.arch detection)
- Fixes cross-compilation on ARM64 build machines

Note: This enables native builds on ARM64 Linux hosts when using
the Android NDK with x86_64 toolchains via QEMU or native compilers.
- Skip cross-compiler (CC env var) on Windows builds
- Let Go handle CGO natively on Windows (Go 1.25.6 supports this)
- Only use cross-compiler when available (Linux/Mac builds)

Fixes build failures on Windows AMD64 systems where getCC() returned null
and caused Go build to fail with empty CC environment variable.

Tested on: Windows 10 (amd64) / AMD Ryzen 8845HS
- Document GitHub Actions workflow usage (already working)
- Provide multiple build options (GitHub Actions, MinGW, Docker, skip)
- Include download instructions for APK artifacts
- Explain current Session Guardian implementation status

This helps users on Windows build APKs using CI/CD workflow
- Complete rewrite of android.yml workflow
- Added detailed comments explaining Session Guardian features
- Documented each build step
- Added conditional uploads based on build success
- Included build summary with download instructions
- Added workflow_dispatch for manual triggering

This workflow builds all APK architectures including arm64-v8a
needed for Pixel 9 and other devices.
- Fix line 320: use mrand.Int63n instead of rand.Int63n (import alias)
- Fix line 400: rename offset to truncationOffset to avoid variable shadowing

These errors were preventing rclone compilation in GitHub Actions due to
CGO cross-compilation issues.
- Set CGO_ENABLED=0 to avoid cross-compilation issues
- Session Guardian code uses only standard Go libraries, no CGO needed
- Fixes build failures on GitHub Actions due to missing standard library packages
- Re-enabled CGO (required for Android ARM builds)
- Added go install std step before rclone build to prepare Android std lib
- This should resolve 'could not import' errors when cross-compiling
- Cleaned up duplicate steps in GitHub Actions workflow
- Removed duplicate/corrupted section from buildRclone function
- File had duplicate lines from previous edit
- Now build.gradle has correct structure with std lib build step
- Removed 'android' tag from Go build command
- The android tag was causing import issues with CGO cross-compilation
- Keeping 'noselfupdate' tag to exclude update checking
- This should allow Go to find the standard library packages
- Reverted to CGO_ENABLED=0 (no CGO required for GitHub Actions)
- Removed CC compiler environment variable
- Restored 'android' build tag
- This matches the working configuration before Session Guardian changes
- CGO changes were intended for ARM64 Linux hosts, not CI/CD
- Changed GOOS from 'android' to 'linux' to bypass CGO requirement
- Removed 'android' build tag since we're targeting linux now
- This allows building without CGO, avoiding standard library issues
- Linux ARM binaries should still work on Android (Android is Linux-based)
- Changed Go version from 1.24 to 1.19.8
- This matches the configuration that was working before Session Guardian
- Go 1.24 may have compatibility issues with cross-compilation
- Using proven Go version that was successfully building earlier
- Added build-windows.ps1 - PowerShell build script with menu
- Added build.bat - Simple batch file launcher
- Added WINDOWS_BUILD_GUIDE.md - Detailed build instructions
- Added BUILD_CHECKLIST.md - Environment verification checklist

These files help users build Session Guardian APK locally on Windows
(Ryzen 8845HS) to work around GitHub Actions CGO issues.
- Removed incorrect -x flags (were excluding tasks instead of running)
- Changed to use module-specific task :app:assembleOssDebugArm64-v8a
- Added proper error checking with LASTEXITCODE
- Shows BUILD FAILED message when build exits with error
- Added safety check to verify APK was actually created

This fixes the issue where ARM64 build was failing due to incorrect Gradle syntax.
@thies2005

Copy link
Copy Markdown
Author

Hi,
Sorry for the late reply, we're in exam season and I forgot about this.
To be transparent: yes, I used AI heavily throughout this. The goal was getting Internxt + 2FA working reliably, which this PR never fully accomplished anyway, it kept getting unauthenticated after a few days. I ended up forking rclone directly (thies2005/rclone) and implementing the changes there natively — that's what I'm now using on my server and in the app. So feel free to cherry-pick whatever is useful, but I don't think this initial pull request advances the project.
Regarding distribution: I understand the Play Store concerns, but accessibility for me means non-technical users can find and install the app without knowing what Obtainium is. I will try fixing the app up and then rely on GitHub Releases for now, and the Play Store once things are stable enough or I have the time. F-Droid/Obtainium I will also add alongside. If you have any concerns please reach out.
Greetings from Munich

thies2005 and others added 29 commits June 18, 2026 19:34
…grity)

Phase 1 (critical bugs + security + build unblocking):
- RC-9/11/12/17/18: add return after finish(), null-guard rclone stdout/config
- RC-23/25: null-check Thumbnails remote; fix inverted getDisplayNameCompat
- RC-2: allowBackup=false; RC-4: unexport app-private components
- RC-5: serve() requires creds for remote bind; ServeDialog enforces non-empty
- RC-6/7/8: fix dependencies.yml globs/prefix, SDK 34->35, pin rclone ref (SHA)
- Guard pre-existing NewApi (destroyForcibly/waitFor) for API < 26 in InternxtReauth

Phase 2 (correctness + resource hygiene):
- RC-13: scoped WorkManager cancellation (replace cancelAllWork) across 3 managers
- RC-22: UpdateWorker -> CoroutineWorker, returns real result
- RC-15/16: RcdService thread-safety (final lock, volatile bool, sync spawn)
- RC-10/20/26: drop leaked probe process, guard exitValue, try-with-resources
- RC-21: rewrite update download (GitHub metadata, SHA-256/size verify, WorkManager)
- RC-27: remove duplicate FileProvider
- RC-30: VCP remotes/remotes dedup + main-thread-safe getDocumentType; real upload FileItem
- RC-24: Log2File rotation 10GB->10MB + null ext-dir guard
- RC-3: add credential-storage ADR (design gate)

Phase 0 (RC-1 signing key rotation) intentionally SKIPPED to preserve the
existing GitHub release signature, per constraint.

Verification: ./gradlew testOssDebugUnitTest + lint + assembleOssDebug all green.

Checkpoint: pushing to resume Phase 3 (UI/UX) and later phases on a cloud instance.
Phase 3 — UI/UX, Accessibility & Dark-Mode:
- RC-34: add values-night/colors.xml + values-night-v31 overrides so the
  convenience color aliases (cardColor, iconTint, dividerColor, text*, fabOverlay)
  resolve to dark tokens instead of light. SecondaryCardStyle no longer uses the
  M3-1.2-only colorSurfaceBright (swapped to colorSurfaceVariant).
- RC-33: actionBarSize 12dp -> 56dp (typo). MainViewToolbar contrast fixed
  (colorOnSecondary -> colorOnPrimary); overflow/dialog parents repointed to M3.
- UI-028: wire core-splashscreen (Theme.App.Starting + installSplashScreen in
  MainActivity).
- RC-32: extract every hardcoded UI literal to @string (Run on Failure/Success,
  "Switch preference" placeholder, task id/path placeholders -> tools:text,
  7 Toast/setTitle literals).
- RC-40: add Locale.ROOT to all 14 DefaultLocale toLowerCase() sites.
- RC-35/36: contentDescription on interactive icons, importantForAccessibility
  on decorative settings icons, labelFor on 8 EditTexts, paddingStart/End,
  48dp tap targets, SwitchPreference -> SwitchPreferenceCompat (12 sites).
- RC-37: delete now shows an undo Snackbar; the destructive WorkManager enqueue
  is deferred until the undo window elapses.
- RC-38: cache rclone config-dump JSON in Rclone.getRemotes() (invalidated on
  config()/deleteRemote()); pin state still re-applied fresh each call.
- UI-020/021: fragment_logs empty state; FileExplorerFragment keeps the current
  listing on a transient rclone error instead of blanking.

Phase 4 — Architecture & Tech-Debt:
- RC-28: add RemoteItem INTERNXT/DRIME types + getTypeFromString cases (were
  falling through to -1 / generic icon and colliding in equals/hashCode); add
  RemoteItemTest covering type resolution and distinctness.
- 4B: delete dead rclone/patches/internxt/ Go source (fork already contains it),
  remove no-op fileTree('libs') + dead VERSION_11 ext, drop commented Intent
  blocks and literal-"TAG" logs, fix SyncService "SYNC_SERCVICE" typo.
- RC-31: align okhttp logging-interceptor to 4.12.0; remove unused Glide
  annotationProcessor (no @GlideModule). NOTE: Jackson, legacy-support-v4 and
  streamsupport are KEPT — they are actually imported (the prior audit verdict
  that streamsupport was unused was wrong: java9.util.* is used in 3 files).
- 4D: add kotlinx-coroutines-android + lifecycle-runtime-ktx infrastructure and
  migrate MarkdownView.LoadMarkdownAsset off AsyncTask (executor + View.post).
  The remaining ~26 AsyncTask / 3 IntentService migrations are intentionally
  staged file-by-file per the plan (each its own PR); doing them blind in one
  commit without a compiler was deemed too risky.

Phase 5 — CI, Polish & Docs:
- BUILD-008/009: SHA-pin every uses: across all 4 workflows; replace the
  compromised tj-actions/changed-files@v44 with a post-fix v46 SHA and
  fabasoad/translation-action@main with a pinned tag; add a PR-gated
  ./gradlew testOssDebugUnitTest step to lint.yml.
- BUILD-019: rclone/build.gradle Go-version check now throws GradleException
  instead of logger.error.
- BUILD-021..024, CQ-010/011: fix Go version (1.20/1.19.8 -> 1.25), license URL,
  assembleDebug -> assembleOssDebug, drop fictional usePrebuiltRclone section,
  APK glob roundsync_v -> cloudbridge_v, AGENTS.md CI description (release, not
  debug).
- CQ-021: rename BootReciever/TriggerReciever/ClearReportBroadcastReciever ->
  *Receiver (classes, manifest, imports, Intent refs).

Deferred (documented): full CardView -> MaterialCardView migration (cosmetic),
ListAdapter+DiffUtil migration, edge-to-edge, tablet layouts, and the remaining
AsyncTask -> coroutines migrations — all lower-risk to land with CI feedback.

No build toolchain was available locally; verified via static checks (XML/YAML
parse, import/reference consistency, subagent code review) and CI is the gate.
The Phase 3-5 commit was authored without a build toolchain ('verified via
static checks'). Three independently-fatal build errors slipped through:

1. Duplicate string resources: values/strings.xml redefined internxt_2fa_title
   and internxt_2fa_message (RC-32 extraction collided with the pre-existing
   canonical strings already referenced by OauthHelper/InternxtReauth/ConfigCreate).
   -> mergeOssDebugResources: 'Found item more than one time'. Removed the dupes.

2. Corrupted ConstraintLayout attribute: an a11y edit in fragment_log_item.xml
   mangled the adjacent attribute layout_constraintTop_toTopOf into the invalid
   layout_constraintTopToTopOf (dropped underscore).
   -> AAPT: 'attribute layout_constraintTopToTopOf not found'. Restored the name.

3. Over-strict Go-version gate: BUILD-019 made checkoutRclone throw on mismatch,
   but the check used contains("1.25.0") which rejects compatible patches like
   1.25.11. -> Replaced with a proper major.minor comparison that accepts any
   patch of the required minor and any newer minor, while still failing fast on
   an genuinely incompatible toolchain (BUILD-019 intent preserved).

Verification: ./gradlew testOssDebugUnitTest, lint -x :rclone:buildAll, and
assembleOssDebug all BUILD SUCCESSFUL after these fixes (5 ABI APKs produced).
Release signing key rotation (P0): the committed roundsync.keystore plus the
hardcoded 'android'/'android' passwords in app/build.gradle compromised the
signing identity. Generated a new RSA-4096 key (CN=CloudBridge Release, 25y),
moved credentials into a git-ignored keystore.properties (local) / CB_* env
vars (CI), removed the old keystore from the repo, and added .gitignore rules.
android.yml now decodes the keystore from GitHub Secrets before signing.
NOTE: existing installs signed with the old key cannot be updated in place
(signature mismatch) and need a one-time reinstall.

Correctness fixes:
- UpdateDownloadWorker.sha256(): signed-Byte sign-extension made every digest
  wrong, so in-app updates with a published digest never verified. Mask to
  unsigned (it.toInt() and 0xFF).
- Rclone getRemotes() cache: now volatile and validated against the rclone.conf
  mtime/length on every read, so per-instance caches self-invalidate when
  another Rclone instance (e.g. a config dialog) mutates the config; also fixes
  the cross-thread visibility race. synchronized the fetch to avoid duplicate
  rclone processes.
- UpdateUserchoiceReceiver: enqueueUniqueWork(KEEP) so multiple Download taps
  no longer run concurrent workers writing the same APK.
- RcdService.waitOnline(): stop using a synthetic NullPointerException for
  control flow; real NPEs inside isOnline() are no longer masked as 'not online'.
- EphemeralWorker: recycle the Parcel on the read paths (matches the write side).
- MarkdownView: ioExecutor threads are now daemons (no per-View thread leak).

Security fixes:
- UpdateUserchoiceReceiver + SyncService set exported=false (no callers relied
  on them being exported; closes an arbitrary-sync-trigger surface).
- SafDAVServer: stop logging the local Authorization header on the
  not-implemented path.

Lint: Locale.ROOT for stderr lowercasing; ellipsis char in
internxt_reauth_progress.

Verification: testOssDebugUnitTest, lint, assembleOssDebug, assembleOssRelease
all green; release APK verified signed with the new key.
Upstream iBotPeaches/Apktool removed scripts/linux/apktool from master,
so the wget 404'd and the non-FOSS library scan never ran. Inline a minimal
wrapper that invokes apktool.jar from its own directory instead of fetching
the fragile external script.
Targeting SDK 35 enforces edge-to-edge, so toolbar/content rendered
behind the status bar (text invisible). Explicitly opt out per activity
via WindowCompat.setDecorFitsSystemWindows(window, true), restoring the
pre-35 fit-to-system-bars behavior. OnboardingActivity is left on
edge-to-edge by design.
Replace the hardcoded rclone --transfers 1 with a configurable value.
Adds a ListPreference (1/2/4/8, default 1) under Settings > Background
Work, read by Rclone for sync/download/upload. Persisted through the
JSON settings backup/restore.
setDecorFitsSystemWindows(true) per activity was not reliably keeping
content below the status bar (e.g. the RemoteConfig search bar still sat
under the status line). Add android:windowOptOutEdgeToEdgeEnforcement
to AppTheme (light/night) and the splash Theme.App.Starting so every
window is created with the legacy fit-to-system-bars behavior. The
attribute is API 35+ only and a no-op below that (tools:ignore=NewApi).
Update rCloneRef to the latest thies2005/rclone master and align the
informational rCloneVersion. Verified to cross-compile for all ABIs.
Beta APKs all shared versionCode 20 / versionName 1.0.1, so they were
never real updates and installs stalled. CI now derives versionCode from
the git commit count (*10; ABI offsets use 6-9) and versionName as
<base>-beta.<short-sha>, passed to Gradle via CB_VERSION_CODE /
CB_VERSION_NAME env vars (matching the existing RCX_BUILD_CLI pattern).

Also fix the delete-previous-betas step: it grabbed the release title's
first word ("Beta") instead of the tag, so old betas accumulated and the
newest no longer sorted to the top. Now lists tags via --json and deletes
by the real tag, keeping only the latest beta.
- Add optional per-task --transfers override (DB v7 migration adding
  task_transfers column, Task.transfers field, TaskActivity spinner with
  'Use global setting'/1/2/4/8) that falls back to the global pref when
  unset. Plumb SyncWorker -> Rclone.sync() 8-arg overload.
- Fix silent-success bug for unsupported sync directions: SyncWorker now
  validates the direction and reports a clear UNSUPPORTED_DIRECTION
  failure instead of treating a null rclone process as success. Affects
  legacy/imported bisync (direction 5/6) tasks.
actions/checkout defaults to a shallow depth-1 clone, so
'git rev-list --count HEAD' returned 1 and every beta APK was built
with versionCode 10. Android then refuses the update because the new
APK is not newer than the installed one. Set fetch-depth: '0' so the
full commit count (e.g. 1604 -> versionCode 16040) is used, making
each beta a real, installable update.
Implements the transmission-speed audit findings (P0-P2):

- Raise default --transfers from 1 to 4 (rclone upstream default)
- Hold PARTIAL_WAKE_LOCK + high-perf WifiLock for the duration of
  transfers (EphemeralWorker, SyncWorker, RcdService) so the device
  does not stall in Doze with the screen off; add WAKE_LOCK perm
- Throttle EphemeralWorker notification rebuilds to >=500ms and only
  when content changed (previously rebuilt on every stderr line)
- Add CloudBridgeApp Configuration.Provider (setMaxSchedulerLimit=50)
  and disable the default WorkManager initializer
- Bump safdav SAF write buffer 1KB->64KB and write directly through
  ContentResolver (DocumentsContractAccess.writeFile)
- Bump VirtualContentProvider pipe buffer 4KB->128KB
- Add --transfers/--buffer-size/--multi-thread-streams and
  --vfs-read-chunk-size* flags to serve and rcd
- Move DownloadAndOpen AsyncTask off the shared serial executor
- Speed up share-intent staging copy (64KB + BufferedOutputStream)
- Fix VirtualContentProvider MaxWait reporting success before rcd
  jobs complete (await returns completion state; longer timeouts)
- Parallelize rcd job-status polling over a small executor with
  synchronized access to lastStatus/jobsHandlers
TransferLocks.acquire used a multi-catch on SecurityException and
RuntimeException, which is illegal (SecurityException subclasses
RuntimeException) and broke compilation. Collapse to RuntimeException.

Also align the 'transfers' default in SharedPreferencesBackup from
'1' to '4' so all call sites match the new rclone upstream default
introduced in the perf commit.
The 'Session expired' notification previously launched MainActivity
generically and required the user to find and long-press the remote to
re-authenticate. It now deep-links into the InternxtReauth flow for the
named remote.

- AppErrorNotificationManager: notification intent now carries the
  MAIN_ACTIVITY_START_REAUTH action + remote name; request code varies
  per remote with FLAG_UPDATE_CURRENT so distinct remotes don't alias.
- MainActivity: add onNewIntent (required by singleTop launch mode so a
  foreground tap is not dropped) and a handleReauthIntent branch that
  resolves the remote and launches InternxtReauth directly.
- InternxtReauth: capture secret-filtered rclone stderr and surface it
  in the failure toast instead of a generic 'error creating remote'.
- Bump rCloneRef to the fork commit that restores the auth circuit
  breaker and TOTP clock-skew retry (see rclone fork 94f543c9d).
Adds remote-to-remote sync (direction 7) and copy (direction 8) so tasks
can transfer data between two cloud remotes without a local hop. rclone
performs a server-side copy where the backend pair supports it.

- SyncDirectionObject: new SYNC_REMOTE_TO_REMOTE/COPY_REMOTE_TO_REMOTE
  constants and explicit spinner<->direction mapping (the spinner array
  is sparse, so position can't be derived from the constant value).
- Task: add remoteId2/remoteType2/remotePath2 destination fields plus
  matching DB columns (DatabaseHandler/DatabaseInfo schema bump).
- TaskActivity: destination-remote UI card shown only for cloud-to-cloud
  directions, with validation rejecting identical source/dest paths.
- Rclone.sync: new overload taking a second remote; routes local<->remote
  vs remote-to-remote based on the direction.
- SyncWorker/TasksRecyclerViewAdapter: plumb the new directions through.
- gitignore: ignore stray node_modules/, package*.json and .zcode/.
- Replace F-Droid/IzzyOnDroid badges with Google Play badge
- Update Libraries section to match actual dependencies
- Replace Contributing section with contact blurb (GitHub noreply mail)
- Note regular rclone updates in fork features
- Rebrand store listing to CloudBridge, drop stale Catalan listing
- Add -PnoAbiSplits gradle property to disable ABI splits for bundle
  builds (AGP rejects AAB while splits are enabled)
- Build bundleOssRelease on CI and attach .aab to beta releases
- Stop deleting previous beta releases on each push
Google Play forbids in-app self-updating. The update notification now
opens the GitHub releases page in the browser instead of downloading
and installing APKs. Remove UpdateDownloadWorker and the
REQUEST_INSTALL_PACKAGES / UPDATE_PACKAGES_WITHOUT_USER_ACTION
permissions.
- Landing page, detailed technical documentation and privacy policy
  (required for the Play Store listing)
- Replace dead cloudbridge.schuelken.uk links in README with the
  GitHub Pages URL
…storage permission

- Rename 'Round Sync: Stopping everything' toast to CloudBridge
- Limit WRITE_EXTERNAL_STORAGE to maxSdkVersion 29 (no effect on
  newer APIs, keeps legacy behavior on Android 9 and below)
- Rewrite README About section with correct fork lineage
  (rcloneExplorer -> RCX -> Round-Sync -> CloudBridge)
- Drop stale CLA Assistant / MIT contribution claim
- Point SECURITY.md contact at the project maintainer
- Rebrand issue templates from Round Sync, fix dead CloudBridge.com link
- Fix lint.yml triggers (run on PRs, not master pushes, per AGENTS.md)
- Correct universal APK filename example and Android version (6+)
- Fix flavor comments and Windows build script filename example
… check

The FOSS dependency scan flags com.sharkaboi:AppUpdateChecker as
NonFreeNet, failing the verify-dependencies workflow. The updater is
notification-only now, so the library only wrapped a single GitHub API
call. Query the releases endpoint directly with OkHttp and compare
semantic version prefixes; also keep the found-version state in sync so
the first detection notifies with the correct version.
CB_STORE_FILE pointed at the keystore relative to the repo root, but
app/build.gradle resolves it with file() against the app module dir,
so the keystore was never found and release builds silently fell back
to the ephemeral CI debug key.
Play requires new apps to target API 36+. Changes:
- compileSdk/targetSdk 35 -> 36
- opt out of predictive back (enableOnBackInvokedCallback=false):
  Android 16 enables it by default, which would bypass the app's
  onBackPressed() overrides (10 activities/fragments)
- onCheckedChanged: parameter is non-null in SDK 36 bindings
- strip native debug symbols (SYMBOL_TABLE) so Play can symbolize
  librclone crashes; addresses upload warning
A multi-select delete enqueued one WorkManager job per file (160 files = 160
workers, one rclone process each). Delete commands carried no --use-json-log
and the first foreground promotion ran before the notification manager
existed, so delete workers never promoted to foreground, were stopped by the
background job time limit, and each posted a notification titled 'unused'
with the generic 'Sync was cancelled' text. The saturated queue also kept new
syncs from starting.

- one delete worker per selection: plain files via a single
  'rclone delete --files-from' run, dirs via sequential purge, newline
  names via deletefile fallback; selection passed via a manifest file in
  the cache dir (WorkManager Data is capped at 10 KB)
- EphemeralWorker: create notification manager/title before the first
  setForegroundAsync so deletes promote to foreground (incl. pre-Q)
- delete/purge/deletefile: add --use-json-log --stats=1s and
  --contimeout/--timeout scoped to deletes only
- StatusObject: fold deletion counts across a batch's processes
- Delete/Move notifications: real cancelled titles, count-based batch
  success message
- Settings > General > Background work: 'Cancel all transfers and syncs'
  with confirmation dialog
- CB-SEC-001: sanitize DISPLAY_NAME, block internal file:// URIs, stage in internal cacheDir
- CB-SEC-002: eliminate shell command injection in pull request translations workflow
- CB-SEC-003: set android:exported=false on headless ShortcutServiceActivity
- CB-SEC-004: encrypt safDavPass using Keystore AES/GCM and write decrypted config atomically
- CB-SEC-005: isolate rcd/serve/txt logs to internal filesDir and remove --dump headers
- CB-SEC-006: isolate DownloadAndOpen cache to internal cacheDir with sanitized filenames
- CB-SEC-007: add baseUrl capability token to StreamingService and use constant-time auth check in SafDAVServer
- CB-SEC-008: validate remote names against leading hyphens and insert '--' before positional CLI arguments
- CB-VAL-001: enforce non-empty release signing secrets in CI and keytool validation
- CB-VAL-002: assert 40-character commit SHA and verify HEAD equals RCLONE_REF after checkout
- CB-REL-001..005: guard null intents, workers log2File initialization, process exits, and sync path encoding
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants