fix(uploads): direct-to-upload workspace files + shared transport#4407
fix(uploads): direct-to-upload workspace files + shared transport#4407waleedlatif1 merged 28 commits intostagingfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Introduces workspace-scoped presign + registration APIs. Adds Hardens multipart + storage primitives. Updates UI and tests updated. Workspace Files UI now enforces a 5 GiB per-file limit client-side and shows per-file percent progress; the legacy FormData upload route is capped via Reviewed by Cursor Bugbot for commit c7a6fc9. Configure here. |
️✅ There are no secrets present in this pull request anymore.If these secrets were true positive and are still valid, we highly recommend you to revoke them. 🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request. |
Greptile SummaryThis PR replaces the buffered-FormData proxy path for workspace file uploads with direct-to-storage transfers: presigned PUT for files ≤50MB and chunked multipart for larger files. It adds
Confidence Score: 5/5Safe to merge — all previously identified P1 issues are addressed and no new blocking issues were found. All P1s from prior review iterations (orphan cleanup, quota inflation via zero-size HEAD fallback, TOCTOU in blob HEAD, multipart abort leaks, presigned URL error surfacing, retry-on-register TOCTOU) appear to have been fixed. The remaining findings are P2: a missing null guard in the KB batch presigned response and an undocumented implicit workspaceId requirement on MultipartUploadOptions. Neither is a runtime blocker under normal server behavior. Test coverage is thorough (60 unit tests, new route tests for both endpoints). apps/sim/app/workspace/[workspaceId]/knowledge/hooks/use-knowledge-upload.ts (presignedItems null guard), apps/sim/lib/uploads/client/direct-upload.ts (MultipartUploadOptions.workspaceId implicit requirement) Important Files Changed
Sequence DiagramsequenceDiagram
participant Client
participant PresignedAPI as /workspaces/[id]/files/presigned
participant S3Blob as S3 / Azure Blob
participant RegisterAPI as /workspaces/[id]/files/register
participant MultipartAPI as /api/files/multipart
participant DB as Database
alt Small file (≤50MB)
Client->>PresignedAPI: POST {fileName, contentType, fileSize}
PresignedAPI-->>Client: {presignedUrl, fileInfo, directUploadSupported}
Note over Client,PresignedAPI: hasCloudStorage()=false → directUploadSupported:false → FormData fallback
Client->>S3Blob: PUT file (XHR with progress)
S3Blob-->>Client: 200 OK
Client->>RegisterAPI: POST {key, name, contentType}
RegisterAPI->>S3Blob: HEAD (verify object exists + get size)
RegisterAPI->>DB: INSERT metadata (idempotent)
RegisterAPI-->>Client: {success, file}
else Large file (>50MB) multipart
Client->>MultipartAPI: POST action=initiate {fileName, workspaceId, context}
MultipartAPI-->>Client: {uploadId, key, uploadToken}
Client->>MultipartAPI: POST action=get-part-urls {uploadToken, partNumbers}
MultipartAPI-->>Client: {presignedUrls[]}
loop Per chunk (parallel, concurrency=3, with retry)
Client->>S3Blob: PUT chunk
S3Blob-->>Client: ETag
end
Client->>MultipartAPI: POST action=complete {uploadToken, parts}
MultipartAPI->>S3Blob: CompleteMultipartUpload
MultipartAPI-->>Client: {path, key}
Client->>RegisterAPI: POST {key, name, contentType}
RegisterAPI->>S3Blob: HEAD (verify)
RegisterAPI->>DB: INSERT metadata
RegisterAPI-->>Client: {success, file}
end
Reviews (19): Last reviewed commit: "fix(uploads): add timeout/abort to kb ap..." | Re-trigger Greptile |
a375aa7 to
f0cbdd4
Compare
f0cbdd4 to
75f2c6a
Compare
…error handling - Throw immediately on AbortError in KB retry loop (no useless 14s backoff) - Cleanup S3/Blob object on quota or size-cap rejection in registerUploadedWorkspaceFile - Enforce MAX_WORKSPACE_FILE_SIZE at registration (defense vs presigned PUT lying about size) - Handle non-OK / non-JSON responses in workspace-files upload paths
4e1299c to
7ab4465
Compare
|
@greptile |
|
@cursor review |
|
@greptile |
|
@cursor review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 768fc94. Configure here.
|
@greptile |
|
@cursor review |
|
@greptile |
|
@cursor review |
|
@greptile |
|
@cursor review |
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit c7a6fc9. Configure here.
Summary
missing final boundary while parsing FormDataon flaky networks (10.5MB MP4 repro). Bytes now go client → S3/Azure directly via presigned PUT (≤50MB) or multipart (>50MB), eliminating the buffered-FormData proxy on the Next worker./api/workspaces/[id]/files/presignedand/registerendpoints with cross-tenant key validation, HEAD-verify, and best-effort cleanup on insert failure.lib/uploads/client/direct-upload.ts; migrate KB hook to consume the shared module. CentralizeisNetworkError,isAbortError,getFileContentTypeinfile-utils.ts.Type of Change
Testing
Tested manually with 1MB / 60MB / 4-file drag uploads, mid-upload abort, and disconnect-mid-upload. 60/60 unit tests passing (presigned, register, multipart, direct-upload).
Checklist