Skip to content

AeroFTP v3.6.0

Choose a tag to compare

@github-actions github-actions released this 22 Apr 14:30
· 1079 commits to main since this release

[3.6.0] - 2026-04-22

AeroSync UX Upgrade + Critical SSH Host-Key Fix

Release focused on making the AeroSync optimized-transfer path visible to the user and on a critical SSH host-key dialog fix. The optimization logic has been progressively landed over the last weeks; this release is the moment it becomes visible in the product.

Added

  • Delta Savings widget in AeroSync: when a file travels through the optimized transfer path during sync, an inline badge next to the file's status marks it; at the end of the run an "Optimized transfer" summary card aggregates N files · bytes saved · speedup. When the effective speedup falls below 1.5x the card switches to a neutral "Optimized transfer" variant to avoid misleading framing. The widget is fully theme-aware across light/dark/tokyo/cyber and hidden entirely when no file benefited from the path. Translated in all 47 supported languages.
  • Per-file breakdown in aeroftp_sync_tree MCP tool: the response now carries summary.delta_files[] (array of {path, bytes_sent, total_size, speedup}) capped at 500 entries, plus a summary.delta_files_truncated flag when a run crosses the cap. Aggregate counters in summary.delta_savings keep counting past the cap. Both keys are omitted on runs where no file used the optimized path, preserving the absence-vs-null contract with the existing delta_savings block.

Fixed

  • Critical: Host Key Changed dialog no longer reappears after Accept: the russh library reports the changed-key line number as 1-based; the internal sftp_remove_host_key command was treating it as a 0-based array index, which meant Accept surgically removed the line after the stale entry instead of the stale one itself. Repeated Accept clicks piled valid entries on top of the original stale one, and every subsequent connection hit the stale line first and re-triggered the dialog. The fix uses 1-based indexing correctly and now also prunes any other plaintext entry for the same (host, port, algorithm) tuple that matches the incoming key's algorithm — so files already corrupted by earlier broken attempts get cleaned up in the same pass. 11 new unit tests pin the regression cases (line zero rejected, 1-based indexing, duplicate pruning, host-mismatch corruption guard, hashed-entry tolerance).

Changed

  • Optimized transfer path reachable from SyncPanel on SFTP: earlier releases had the decision wired in the unified sync core only — AeroSync UI actually iterates per-file commands that never entered that branch. This release extends the decision to upload_file / download_file / provider_upload_file / provider_download_file so sessions with SFTP + SSH key authentication + a capable remote now actually exercise the optimization in the day-to-day UI flow. The decision remains self-gated (silent fallback to classic when the session is not eligible); hard rejections (SSH host-key mismatch, permission denied) surface as transfer errors without silent retry.
  • TransferEvent now propagates optional delta_stats: the event emitted to the frontend on complete carries per-file stats from the optimized path when applicable (serialized with skip_serializing_if, absent for classic transfers — no wire overhead for non-SFTP providers). Frontend accumulates these into the session-level summary client-side.

MCP (pre-release carryovers from v3.6.0 cycle)

  • aeroftp_read_file soft-truncate dentro hard cap: oversized file (oltre preview_kb ma entro il cap 1 MB) ritornano contenuto troncato con truncated:true invece di errore duro. Il validator rifiuta solo oltre il hard cap 1 MB. Elimina i retry forzati che gli agent facevano quando incontravano file appena oltre la finestra di preview richiesta.
  • aeroftp_check_tree espone compare_method anche sul gruppo match: il JSON di ritorno ora include groups.match dettagliato alla pari di differ/missing_local/missing_remote. Ogni entry porta compare_method: "checksum" | "size" così l'agent sa se il match è stato crittograficamente verificato o è fallback dimensionale (tipicamente su FTP che non ha checksum server-side).

Build / CI

  • Dedicated fallback-fixture CI lane: delta-sync-integration.yml gains a second job running against the password-only SFTP Docker fixture. Covers the silent-fallback branch (password-only sessions) and the hard-rejection contract so a regression on those paths cannot ship unnoticed. Protected by nick-fields/retry@v3 (2 attempts, 10s wait) for Docker-on-runner flakiness. Both jobs block PRs on failure.

Internals

  • SyncReport domain types expanded: DeltaSavingsSummary (aggregate) and new DeltaFileEntry (per-file breakdown) are public types; DELTA_FILES_CAP = 500 exposed as a crate-level constant. The accumulator is one branch driving both aggregate and per-file tracking — impossible to drift.
  • Stderr sanitizer hardened: /home/<user>, /Users/<user>, C:\Users\<user> and .ssh/* path segments redacted before fallback_reason / hard_error messages flow to UI, logs, or MCP responses. Message capped at 512 characters to keep response arrays bounded.
  • RsyncStats.warnings downgraded to pub(crate): entries may contain remote file paths and must not leak without sanitization.

Downloads:

  • Windows: .msi installer, .exe, or .zip portable (no installation required)
  • macOS: .dmg disk image
  • Linux: .deb, .rpm, .snap, or .AppImage

Download AeroFTP