- Remove temp-xxx optimistic inserts from submitComment/submitReply
- Wait for API response, then insert real comment into timeline
- Add Loader2 spinner to comment/reply submit buttons during loading
- Remove hover card from Markdown.tsx (will be handled via NodeView later)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Sanitize Content-Disposition filenames to prevent header injection (strip control chars, quotes, semicolons)
- Add CloudFront cookie refresh middleware so cookies are re-issued when expired
- Log errors in groupAttachments instead of silently swallowing them
- Move useFileUpload hook to shared/hooks/ per project architecture conventions
- Add uploadWithToast helper to deduplicate try/catch/toast pattern across 3 components
- Refactor ApiClient.uploadFile to reuse auth headers, 401 handling, and error parsing
- Allow empty MIME types client-side (let server sniff and decide)
- Constrain Image extension max-width in rich-text-editor to prevent layout overflow
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add attachment table with workspace/issue/comment associations
- Upload handler creates attachment record when workspace context exists
- Add GET /api/issues/{id}/attachments and DELETE /api/attachments/{id}
- Frontend passes issueId context during uploads for tracking
- Add Attachment type, listAttachments, deleteAttachment to API client
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CommentInput: remove border-t divider, position submit button inside
editor area (bottom-right) for cleaner look
- CommentCard: add !gap-0 to override Card's default gap-4
- CommentInput/ReplyInput: strip trailing empty lines from markdown
before submit to prevent extra blank lines in rendered comments
- BoardCard: use normal text color for title instead of muted+hover
- Timeline: coalesce same actor + same action within 2 min window,
keeping only the final result (e.g. 5 status changes → 1)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract shared timeAgo utility, remove duplicates from comment-card and issue-detail
- Remove unused replies prop from CommentCard
- Fix recursive delete to remove all descendant replies, not just direct children
- Improve formatActivity with human-readable status/priority labels and actor names
- Validate parent comment exists and belongs to same issue before creating reply
- Add priority_changed activity recording in activity listeners
- Fix activity SQL query to sort ASC (was DESC, then re-sorted in handler)
- Fix reply-input layout alignment and test submit button selector
- Minor: .gitignore additions, button dark mode aria-expanded fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace recursive Card-in-Card with flat thread layout:
- One Card per comment thread, parent + all replies flat inside
- Replies separated by border-t, not nested Cards
- CommentRow component handles each individual comment (header + content + edit)
- Three-dot menu shows active state when open (data-[popup-open])
- ReplyInput simplified: avatar + editor + submit button, no extra border container
- Nested replies collected recursively but rendered flat
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>