Ghost FTP 0.95.6 — Android SAF provider-progress hardening (development candidate)
Not yet released. Base source version is 0.95.5 (merged); latest confirmed published release when this work began was v0.95.4. GitHub Releases, not these notes, is the source of truth for publication.
Actual changes
- Shared Android
SignedCloudTransfer.streamWithBoundedProgressbounds reads to 1 GiB, rejects more than eight consecutive zero-byte reads, verifies exact declared lengths and checks cancellation before and after streaming. - The primitive is used for provider-backed signed uploads, HTTPS GET staging and final SAF destination copy. This eliminates unbounded busy loops when a DocumentsProvider violates
InputStream.read()'s progress behavior and catches files that change size mid-transfer. - Seven new JVM test cases cover empty/exact bytes, short/excess bytes, nonprogress, transient zero-byte reads, cancellation, invalid size metadata and write errors.
- Existing SHA-256 final SAF read-back, best-effort cleanup, verified public IP connect, system TLS and signed URL privacy measures remain enabled.
Explicit limits
A source that blocks inside InputStream.read() rather than returning zero is not fixed by this guard. Third-party SAF providers, rotation/process death, revoked grants, device disk-full conditions, 1 GiB transfers, and real cloud provider signed GET/PUT still require physical/device/provider testing (#127). Any failure can leave a non-atomic SAF document; app attempts cleanup and warns when denied.
The macOS/Android authenticated Google Drive and other account workflows (#128) are still absent. The 75 screenshot 1:1 visual reference contract is still pending actual installed app comparison. #126 is open pending controlled peer-route/proxy/VPN lab and actual signed-provider success evidence.
Verification
Require the same exact SHA to pass Android lint, JVM tests, APK build and emulator smoke, native Windows/Linux/macOS CI, Rust workspace and FTP/FTPS/SFTP E2E before merge. An unsigned preview, a green static source check or a simulated provider does not constitute a signed production package or physical device acceptance.