transfer-resume
Durable transfer resume
Receipt-v1 is implemented and tested locally. Production rollout and a live cross-node restore rehearsal remain pending. It proves receipt of the captured artifact and the restore command's result; it does not independently prove database, app, route or TLS health.
Start and resume a pull
Run the source with hostssh transfer --serve --resumable and its existing TLS certificate,
key and capture command. The stage directory must be private (0700); one source process
holds its lease. Keep the same directory across source restarts.
On the receiver:
hostssh transfer --pull "$TRANSFER_KEY" --from source.example:8443 \
--source-pin "$SOURCE_SPKI_PIN" --restore-cmd /path/to/restore-script \
--resume --receive-dir /private/path/transfer-receive
Add --pin "$SHARE_PIN" when the key requires a share PIN. The source TLS SPKI pin
and share PIN have different purposes and are not interchangeable.
Repeat the same command after a receiver interruption, using the same endpoint, key,
PIN and receive directory. The default receive directory is /etc/hostssh/state/transfer-receive.
The directory is created as 0700; an existing non-private directory is rejected.
A kernel lock prevents concurrent receivers from using the same checkpoint and releases
automatically if the process dies. Keep the source running with the same stage directory.
What is durable
Each authenticated 64 KiB frame is written and synced before the signed checkpoint advances. On restart, the receiver verifies its checkpoint identity and file prefix. Bytes beyond the last checkpoint are discarded and replayed. Corrupt checkpoints or payloads fail closed.
After receiving the whole artifact, the receiver verifies its SHA-256 and length, records durable receipt, and acknowledges the exact source attempt. The source persists a receipt before deleting staged bytes. If the acknowledgement response is lost, repeating the command retries that receipt without recapturing the source. Different permitted uses have independent frame-encryption keys. Continuations do not consume another permitted use.
The source's existing policy remains: initial redemption uses key expiry/PIN/mode/use limits; an established transfer continues within its 24-hour stage lease. Acknowledgements do not extend that lease. The running source checks expiry every minute and skips active streams. Cleanup errors are reported and remote object identifiers are retained for retry.
A restore failed or was interrupted
The receiver retains the verified artifact. Review the destination: the restore command may have partially changed it. Repeating the command normally refuses to rerun that restore. After resolving the cause and deciding that retry is safe, explicitly add:
--retry-restore
The retry reads the retained artifact; after an acknowledged receipt, it needs no recapture or network request. A completed restore is recorded so rerunning the command cannot blindly repeat it. Successful restores remove the local payload but keep the small completion record. Failed/interrupted payloads remain until resolved or deliberately removed by the operator. Do not delete a receive directory while a transfer or restore is active.
Older sources and limits
The receiver first checks capability without sending a transfer key. It refuses unsupported
sources and does not silently downgrade. Upgrade the source, or explicitly select the old
behavior with --resume --legacy-resume. Legacy mode has same-process reconnect only;
receiver restart, retained restore artifacts and receipt acknowledgement are not guaranteed.
--legacy-resume cannot be combined with --retry-restore.
Do not downgrade a source while it holds active receipt-v1 attempts. Source and receiver need disk space for their retained artifacts (S3 staging replaces the source payload copy). This version syncs each frame and reads the source artifact once to compute its digest; large local/S3 transfers need workload-specific performance and storage-cost validation. Process-crash tests do not substitute for hardware power-loss or live migration rehearsals.