Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Review Summary by QodoAdd file attachment support for chat and ticket workflows across web, widget, and backend
WalkthroughsDescription• Comprehensive file attachment support for chat and ticket workflows across web, widget, and backend systems • New supportAttachments backend module with mutations for generating upload URLs, finalizing uploads, and managing attachment lifecycle with TTL-based cleanup • Shared attachment types, validators, and client-side upload orchestration utilities in web-shared package • Database schema additions for storing attachment references in messages, tickets, and comments with proper indexing • Inbox conversation UI enhancements with attachment input, pending attachment display, and removal capability • Ticket detail and creation UI updates with attachment upload support and download links for sent attachments • Widget conversation and ticket components updated with full attachment workflow integration • Comprehensive test coverage including attachment upload validation, lifecycle management, authorization checks, and UI rendering • Test data cleanup utilities and E2E test helpers for attachment management Diagramflowchart LR
Client["Client Apps<br/>Web/Widget"]
Upload["Upload Handler<br/>Generate URL"]
Storage["File Storage"]
Finalize["Finalize Upload<br/>Bind to Message/Ticket"]
DB["Database<br/>Messages/Tickets/Comments"]
Display["Display Attachments<br/>with Download Links"]
Client -->|"Select Files"| Upload
Upload -->|"Get Upload URL"| Storage
Client -->|"Upload File"| Storage
Client -->|"Finalize Upload"| Finalize
Finalize -->|"Store Attachment ID"| DB
DB -->|"Fetch with Attachments"| Display
Display -->|"Render Links"| Client
File Changes1. packages/convex/convex/supportAttachments.ts
|
Code Review by Qodo
1.
|
CI Feedback 🧐A test triggered by this PR failed. Here is an AI-generated analysis of the failure:
|
There was a problem hiding this comment.
Pull request overview
Adds end-to-end support-attachment uploads for inbox replies, widget chat, and ticket workflows by introducing a shared attachment domain, Convex backend support (schema + mutations), and UI rendering/compose-state management across web and widget clients.
Changes:
- Introduces shared
web-sharedattachment helpers (validation, MIME inference, size formatting, upload flow). - Adds Convex
supportAttachmentsmodule + schema updates and wires attachments into messages/tickets read + send/create/comment flows. - Updates Web Inbox, Web Tickets, and Widget chat/tickets UI to upload, preview, remove, and render attachments; adds/updates tests.
Reviewed changes
Copilot reviewed 40 out of 41 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/web-shared/src/supportAttachments.ts | New shared attachment types + validation + upload helper. |
| packages/web-shared/src/index.ts | Exports attachment helpers/types from web-shared. |
| packages/convex/tests/supportAttachments.test.ts | Integration tests covering upload validation/auth/binding/cleanup. |
| packages/convex/tests/runtimeTypeHardeningGuard.test.ts | Ensures new supportAttachments module follows typed-ref conventions. |
| packages/convex/convex/tickets.ts | Binds staged attachments on ticket create/comment; resolves descriptors in queries. |
| packages/convex/convex/testing/helpers/supportAttachments.ts | Test-only helpers for expiring/cleaning staged uploads and checking storage. |
| packages/convex/convex/testing/helpers/cleanup.ts | Extends test workspace cleanup to delete support attachments + stored files. |
| packages/convex/convex/testing/helpers.ts | Exposes new support-attachment test helpers in the testing API. |
| packages/convex/convex/testData/cleanup.ts | Ensures e2e test-data cleanup also deletes attachments referenced by tickets/messages. |
| packages/convex/convex/supportAttachments.ts | New backend module for upload URL generation, finalize, binding, descriptor resolution, cleanup. |
| packages/convex/convex/supportAttachmentTypes.ts | Shared validators/constants for attachment limits and allowed MIME types. |
| packages/convex/convex/schema/supportAttachmentTables.ts | Adds supportAttachments table and indexes. |
| packages/convex/convex/schema/outboundSupportTables.ts | Adds attachmentIds fields to tickets and ticketComments schema. |
| packages/convex/convex/schema/inboxConversationTables.ts | Adds attachmentIds to inbox message schema. |
| packages/convex/convex/schema.ts | Registers the new support-attachment tables in the Convex schema. |
| packages/convex/convex/messages.ts | Adds attachmentIds to send/list; binds staged uploads; resolves attachment descriptors in list results. |
| packages/convex/convex/_generated/api.d.ts | Updates generated API typings to include support-attachment modules/schema. |
| openspec/changes/add-chat-and-ticket-file-uploads/tasks.md | Marks related openspec tasks as completed. |
| apps/widget/src/styles.css | Adds composer/attachment UI styles for widget chat and tickets. |
| apps/widget/src/icons.tsx | Adds Paperclip icon. |
| apps/widget/src/hooks/useWidgetTicketFlow.ts | Adds attachment state + upload/remove flow for ticket create/comment in widget. |
| apps/widget/src/hooks/convex/useConversationViewConvex.ts | Exposes supportAttachment upload/finalize refs in widget conversation hook. |
| apps/widget/src/components/conversationView/types.ts | Adds attachments to message type. |
| apps/widget/src/components/conversationView/MessageList.tsx | Renders message attachments in widget conversation thread. |
| apps/widget/src/components/conversationView/Footer.tsx | Adds attachment input, queued previews, disable states for widget chat composer. |
| apps/widget/src/components/conversationView/Footer.test.tsx | Tests widget composer layout with pending attachments. |
| apps/widget/src/components/TicketDetail.tsx | Renders ticket/comment attachments + queued reply attachments in widget ticket detail. |
| apps/widget/src/components/TicketDetail.test.tsx | Tests rendering and removal of queued ticket-reply attachments. |
| apps/widget/src/components/TicketCreate.tsx | Adds attachment upload + queued previews to widget ticket creation. |
| apps/widget/src/components/ConversationView.tsx | Adds attachment upload + pending state + error handling to widget chat flow. |
| apps/widget/src/Widget.tsx | Wires ticket attachment state/actions from hooks into ticket components. |
| apps/web/src/app/tickets/page.tsx | Adds attachment upload + preview + error handling to web ticket create modal. |
| apps/web/src/app/tickets/hooks/useTicketsConvex.ts | Adds upload/finalize refs and attachment descriptors to ticket query/mutation types. |
| apps/web/src/app/tickets/[id]/page.tsx | Renders ticket/comment attachments; adds comment composer attachment upload/preview. |
| apps/web/src/app/inbox/page.tsx | Adds pending attachments + upload/remove flow in inbox reply UI state. |
| apps/web/src/app/inbox/inboxRenderTypes.ts | Adds support attachment descriptors to inbox message render type. |
| apps/web/src/app/inbox/hooks/useInboxMessageActions.ts | Includes attachmentIds in send + improves optimistic preview for attachment-only replies. |
| apps/web/src/app/inbox/hooks/useInboxConvex.ts | Exposes attachment upload/finalize mutations for inbox UI. |
| apps/web/src/app/inbox/InboxThreadPane.tsx | Adds attachment upload button, pending previews/removal, and attachment rendering in thread. |
| apps/web/src/app/inbox/InboxThreadPane.test.tsx | Updates snippet-control expectations + adds attachment rendering/interaction test. |
| apps/web/e2e/widget.spec.ts | Skips an email-capture dismiss test due to UI change. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 48 out of 49 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Partially completed - the upload spoofing hardening is improved, but not all the way to magic-byte sniffing. We now require an allowlisted extension from the normalized filename on both the client and backend in supportAttachments.ts (line 70) and supportAttachments.ts (line 57), and added regression coverage in supportAttachments.test.ts (line 151) and supportAttachments.test.ts (line 8). I did not add signature checks, because the current finalizeUpload boundary is a Convex mutation and ctx.storage.get() is only available in actions. Doing true magic-byte validation would need a larger refactor of that finalize flow.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 51 out of 52 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return { | ||
| message: `"${file.name}" is larger than 10 MB.`, | ||
| nextAction: "Choose a smaller file and try again.", | ||
| }; |
There was a problem hiding this comment.
This oversize error message also interpolates file.name (which may be path-like). Consider using the normalized base file name here as well for consistency with the allowlist validation and to avoid displaying path fragments.
| export function getSupportAttachmentMimeType(file: Pick<File, "name" | "type">): string | null { | ||
| return inferMimeTypeFromFileName(normalizeSupportAttachmentFileName(file.name)); | ||
| } |
There was a problem hiding this comment.
getSupportAttachmentMimeType accepts Pick<File, "name" | "type"> but doesn't use type at all (it infers solely from the normalized file name). Consider removing type from the accepted shape or renaming the function to make the extension-based behavior explicit, to avoid callers assuming the browser-provided MIME type is being validated.
| return { | ||
| message: `Unsupported file type for "${file.name}".`, | ||
| nextAction: "Use PNG, JPG, GIF, WEBP, PDF, TXT, CSV, JSON, or ZIP files.", | ||
| }; |
There was a problem hiding this comment.
This error message uses file.name directly, which can include path-like prefixes (e.g. C:\\fakepath\\...). Since you already normalize file names for validation, consider using the normalized base name in user-facing messages to avoid leaking/printing path-like strings and to keep messaging consistent.
This pull request adds support for file attachments in the inbox conversation reply UI. It introduces the ability to upload, display, and remove attachments when composing a reply, and updates the message display to show attachments. The changes span the UI components, test coverage, and hooks for managing attachment state and backend integration.
Attachment Support in Inbox UI:
InboxThreadPaneto support pending attachments, attachment uploading state, and new callbacks for uploading/removing attachments. Attachments are now displayed both for sent messages and pending replies, with file size formatting and removal capability. The reply input and send button are disabled appropriately during upload. [1] [2] [3] [4] [5] [6]Test Coverage:
Inbox Message Actions and State Management:
pendingAttachmentsin state, include attachment IDs in message sending, and improve optimistic UI for attachment-only replies. [1] [2] [3]Backend Integration for Attachments:
Miscellaneous:
These changes collectively enable a seamless file attachment experience in the inbox reply workflow, with full state management and test coverage.