fix: expose ssh transfer verification

This commit is contained in:
Codex
2026-05-30 08:31:52 +00:00
parent 277e28ce97
commit 91564b3784
4 changed files with 67 additions and 6 deletions
+30
View File
@@ -33,6 +33,11 @@ interface SshFileTransferStat {
sha256: string;
}
interface SshFileTransferEndpointStat extends SshFileTransferStat {
side: "local" | "remote";
path: string;
}
interface SshFileTransferWriteResult {
strategy: "argv" | "stdin" | "chunked-stdin";
chunks: number;
@@ -68,6 +73,10 @@ export async function runSshFileTransferOperation(
const write = await writeRemoteFileVerified(invocation, executor, builders, options.remotePath, content);
const remote = await statRemoteFile(invocation, executor, builders, options.remotePath);
assertTransferStat("upload final remote verification", options.remotePath, expected, remote);
const verification = buildTransferVerification(
{ side: "local", path: localPath, ...expected },
{ side: "remote", path: options.remotePath, ...remote },
);
process.stdout.write(`${JSON.stringify({
ok: true,
command: "ssh upload",
@@ -78,6 +87,7 @@ export async function runSshFileTransferOperation(
bytes: expected.bytes,
sha256: expected.sha256,
verified: true,
verification,
transfer: write,
}, null, 2)}\n`);
return 0;
@@ -89,6 +99,10 @@ export async function runSshFileTransferOperation(
const local = await readFile(localPath);
const localStat = { bytes: local.length, sha256: sha256HexBuffer(local) };
assertTransferStat("download final local verification", localPath, read.remote, localStat);
const verification = buildTransferVerification(
{ side: "remote", path: options.remotePath, ...read.remote },
{ side: "local", path: localPath, ...localStat },
);
process.stdout.write(`${JSON.stringify({
ok: true,
command: "ssh download",
@@ -99,6 +113,7 @@ export async function runSshFileTransferOperation(
bytes: read.remote.bytes,
sha256: read.remote.sha256,
verified: true,
verification,
transfer: {
strategy: "chunked-read",
chunks: read.chunks,
@@ -274,6 +289,21 @@ function assertTransferStat(label: string, pathName: string, expected: SshFileTr
});
}
function buildTransferVerification(source: SshFileTransferEndpointStat, target: SshFileTransferEndpointStat): Record<string, unknown> {
return {
automatic: true,
algorithm: "sha256",
checked: ["bytes", "sha256"],
verified: source.bytes === target.bytes && source.sha256 === target.sha256,
source,
target,
match: {
bytes: source.bytes === target.bytes,
sha256: source.sha256 === target.sha256,
},
};
}
function sha256HexBuffer(value: Buffer): string {
return createHash("sha256").update(value).digest("hex");
}