fix(plugin): fail fast on upload protocol drift

This commit is contained in:
Dotta
2026-05-13 15:43:00 -05:00
committed by Chris Farhood
parent 9035b70aa9
commit 9b275c332a
2 changed files with 25 additions and 5 deletions
@@ -123,6 +123,15 @@ export class FastUploadInterceptor {
}; };
} }
const activeUpload = this.findActiveUploadForCommand(command);
if (activeUpload) {
this.buffers.delete(activeUpload.tempPath);
return {
action: "error",
message: `Fast upload protocol violation for ${activeUpload.upload.targetPath}; retry the upload from the beginning.`,
};
}
return { action: "passthrough", reason: "no upload pattern" }; return { action: "passthrough", reason: "no upload pattern" };
} }
@@ -133,4 +142,13 @@ export class FastUploadInterceptor {
get pendingCount(): number { get pendingCount(): number {
return this.buffers.size; return this.buffers.size;
} }
private findActiveUploadForCommand(command: string): { tempPath: string; upload: BufferedUpload } | null {
for (const [tempPath, upload] of this.buffers) {
if (command.includes(`'${tempPath}'`)) {
return { tempPath, upload };
}
}
return null;
}
} }
@@ -46,7 +46,7 @@ describe("FastUploadInterceptor", () => {
).toMatchObject({ action: "passthrough", reason: "finalize without buffered state" }); ).toMatchObject({ action: "passthrough", reason: "finalize without buffered state" });
}); });
it("does not intercept chunks with padding before the end", () => { it("fails fast when an unrecognized command targets an active upload", () => {
const interceptor = new FastUploadInterceptor(); const interceptor = new FastUploadInterceptor();
const target = "/workspace/file.bin"; const target = "/workspace/file.bin";
@@ -56,10 +56,12 @@ describe("FastUploadInterceptor", () => {
), ),
).toMatchObject({ action: "ack" }); ).toMatchObject({ action: "ack" });
expect( const decision = interceptor.decide(`printf '%s' 'aGVs=bG8=' >> '${target}.paperclip-upload.b64'`);
interceptor.decide(`printf '%s' 'aGVs=bG8=' >> '${target}.paperclip-upload.b64'`), expect(decision).toMatchObject({
).toMatchObject({ action: "passthrough", reason: "no upload pattern" }); action: "error",
expect(interceptor.pendingCount).toBe(1); message: expect.stringContaining("Fast upload protocol violation"),
});
expect(interceptor.pendingCount).toBe(0);
}); });
it("fails fast when data arrives after a padded chunk", () => { it("fails fast when data arrives after a padded chunk", () => {