Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
14 KiB
14 KiB
Scratchpad — Ticket Comment Clipboard Image Attachments
- Plan slug:
ticket-comment-clipboard-image-attachments - Created:
2026-03-01
What This Is
Working notes for implementing clipboard image paste support in ticket comments, with attachment-backed rendering and outbound email inline-image support.
Decisions
- (2026-03-01) Paste behavior is immediate upload, not deferred-until-submit.
- (2026-03-01) Uploaded clipboard images are persisted as ticket documents/files.
- (2026-03-01) Render saved comment images from attachment-serving URLs, not embedded
data:imagepayloads. - (2026-03-01) Outbound ticket-comment emails should render pasted images inline via CID attachments.
- (2026-03-01) Cancel flow must offer keep/delete choice when pasted images were uploaded.
- (2026-03-01) Delete choice on cancel is hard delete (remove metadata + stored object), not soft detach.
Discoveries / Constraints
- (2026-03-01) Existing inbound email work already converts
data:image/CID content into ticket document attachments; this plan should reuse those attachment rendering and storage patterns where possible. - (2026-03-01) Clipboard image flows are user-driven and must avoid storing raw base64 image strings in persisted comment payloads.
- (2026-03-01) Cancel-delete safety must prevent removing artifacts that are already referenced by submitted comments.
Commands / Runbooks
- (2026-03-01) Scaffolded plan folder with:
python3 /Users/roberisaacs/.codex/skills/alga-plan/scripts/scaffold_plan.py "Ticket Comment Clipboard Image Attachments" --slug ticket-comment-clipboard-image-attachments
Links / References
- Related plan:
ee/docs/plans/2026-02-27-inbound-email-embedded-images-and-original-eml/ - Related plan:
ee/docs/plans/2026-02-27-inbound-email-inapp-artifact-persistence-remaining-work/ - Related plan:
ee/docs/plans/2026-03-01-unified-inbound-email-pointer-queue/
Open Questions
- Confirm final max size/count limits for clipboard image uploads, or reuse existing ticket attachment limits exactly.
- Confirm whether cancel-delete prompt supports per-image selection or all-or-nothing delete in first version.
- (2026-03-01) F001 implemented: ticket comment editor now supports clipboard image paste handling via BlockNote
uploadFilewiring inTextEditor, enabled fromTicketConversationwhen the new feature flag is on. - (2026-03-01) Implementation notes: introduced
packages/tickets/src/lib/clipboardImageUtils.tsfor MIME detection, deterministic naming, and pre-upload validation; this utility underpins paste-image handling. - (2026-03-01) Commands:
npx vitest run src/lib/clipboardImageUtils.test.ts(packages/tickets),npx vitest run src/test/unit/notifications/ticketCommentInlineImageEmail.test.ts(server),npx vitest run src/blocknoteUtils.image.test.ts(packages/formatting),npx tsc -p packages/tickets/tsconfig.json --noEmit,npx tsc -p server/tsconfig.json --noEmit. - (2026-03-01) F002 implemented: ticket comment image uploads now start immediately on paste via
TextEditoruploadFilewiring andTicketConversation.handleClipboardImageUpload, without waiting for comment submit. - (2026-03-01) F003 implemented: Persist pasted images through ticket document/file pipeline via
uploadDocumentand returned document/file ids in comment image URLs. - (2026-03-01) F004 implemented: Deterministic clipboard image naming added through
createClipboardImageFilenameand upload-time file renaming (clipboard-image-YYYYMMDD-HHMMSS-SEQ.ext). - (2026-03-01) F005 implemented: BlockNote image upload placeholder path is enabled by providing
uploadFileto editor configuration for pasted images. - (2026-03-01) F006 implemented: Successful upload resolves placeholder to attachment-backed image node using
/api/documents/view/<fileId>URL payload from upload handler. - (2026-03-01) F007 implemented: Upload failure path now propagates upload/validation errors through editor upload API so users can retry/remove via BlockNote image error controls.
- (2026-03-01) F008 implemented: Comment content now persists attachment-backed image URLs (document view endpoints) instead of raw
data:imagebodies. - (2026-03-01) F009 implemented: Ticket comment rendering path now uses saved attachment-serving URLs for inline images in BlockNote-rendered comment content.
- (2026-03-01) F010 implemented: Attachment image serving auth strengthened in
/api/documents/view/[fileId]for ticket-associated document access checks. - (2026-03-01) F011 implemented: Outbound ticket-comment email flow now maps comment image URLs into ticket document lookup + inline image processing model.
- (2026-03-01) F012 implemented: Outbound email now builds CID inline attachments for eligible ticket-comment images via storage-backed attachment generation.
- (2026-03-01) F013 implemented: Outbound comment HTML image
srcvalues are rewritten tocid:references matching generated inline attachments. - (2026-03-01) F014 implemented: Outbound processing now falls back to original attachment URL when CID conversion/download fails, preserving renderability.
- (2026-03-01) F015 implemented: Ticket compose state now tracks uploaded clipboard draft images (document/file/url identity) for subsequent cancel handling.
- (2026-03-01) F016 implemented: Canceling a draft with uploaded clipboard images now prompts keep-vs-delete through confirmation dialog copy and actions.
- (2026-03-01) F017 implemented: Delete option on cancel now hard-deletes selected draft clipboard images through server action + document deletion pipeline.
- (2026-03-01) F018 implemented: Draft hard delete now guards against non-owned/not-ticket/non-image/already-referenced artifacts before deletion.
- (2026-03-01) F019 implemented: Clipboard upload path now validates image MIME prefix and maximum file size before upload begins.
- (2026-03-01) F020 implemented: Non-image paste/plain-text behavior remains on existing path; clipboard image logic is isolated to image upload flow only.
- (2026-03-01) F021 implemented: Clipboard image paste flow is now rollout-gated behind
ticket-comment-clipboard-imagesfeature flag in ticket details. - (2026-03-01) F022 implemented: Added client/server observability logs for upload outcomes, cancel keep/delete actions, and outbound CID vs fallback outcomes.
- (2026-03-01) T001 implemented:
clipboardImageUtils.test.tsverifies image MIME clipboard items are extracted while non-image entries are ignored. EOF && git add ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/tests.json ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/SCRATCHPAD.md && git commit -m "test(T001): cover clipboard image MIME filtering"- (2026-03-01) T002 implemented:clipboardImageUtils.test.tsverifies multi-image clipboard extraction preserves deterministic input order for per-image upload jobs. EOF && git add ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/tests.json ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/SCRATCHPAD.md && git commit -m "test(T002): verify deterministic multi-image upload ordering"- (2026-03-01) T003 implemented: addedTicketConversation.clipboard.contract.test.tsasserting upload is wired via editoruploadFilecallback and that submit handler does not invokeuploadDocument, enforcing immediate pre-submit upload flow. EOF && git add packages/tickets/src/components/ticket/TicketConversation.clipboard.contract.test.ts ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/tests.json ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/SCRATCHPAD.md && git commit -m "test(T003): assert immediate clipboard upload wiring"- (2026-03-01) T004 implemented: contract coverage verifies pasted-image upload path appends file toFormDataand callsuploadDocumentwithticketIdscope. - (2026-03-01) T005 implemented:
clipboardImageUtils.test.tsvalidates deterministic clipboard filename output format. EOF && git add ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/tests.json ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/SCRATCHPAD.md && git commit -m "test(T005): verify deterministic clipboard filename pattern"- (2026-03-01) T006 implemented: contract coverage confirmsuploadFilewiring inTicketConversationso BlockNote can render in-flight upload placeholder UI for pasted images. - (2026-03-01) T007 implemented: contract test validates successful upload return payload includes attachment-backed URL, enabling placeholder replacement with persisted image node. EOF && git add ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/tests.json ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/SCRATCHPAD.md && git commit -m "test(T007): assert placeholder success replacement payload"- (2026-03-01) T008 implemented: contract test covers explicit upload error throws for validation and upload failures, feeding editor error affordances.
- (2026-03-01) T009 implemented: contract assertion validates failure propagation strategy that enables editor retry path to re-run upload callback after prior failure.
- (2026-03-01) T010 implemented: added contract assertions that pasted-image serialization path emits attachment-serving URLs (
/api/documents/view/...) and does not embeddata:imagepayload content. - (2026-03-01) T011 implemented:
blocknoteUtils.image.test.tsnow includes non-image paragraph conversion regression assertions for markdown + HTML outputs. EOF && git add ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/tests.json ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/SCRATCHPAD.md && git commit -m "test(T011): add non-image serialization regression assertions"- (2026-03-01) T012 implemented: addedCommentItem.clipboardImage.contract.test.tsverifying saved BlockNote JSON is parsed and rendered throughRichTextViewerfor inline comment image display. - (2026-03-01) T013 implemented: route contract coverage asserts ticket-associated document access checks include guard branch for users without resolved ticket/contact scope.
EOF && git add ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/tests.json ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/SCRATCHPAD.md && git commit -m "test(T013): cover unauthorized ticket-image route guard branch"- (2026-03-01) T014 implemented: route contract test asserts ticket-associated branch grants access (
hasPermission = true) when contact/client scope matches associated ticket. - (2026-03-01) T015 implemented:
ticketCommentInlineImageEmail.test.tsverifies comment image attachment URLs are collected/mapped for outbound email composition. - (2026-03-01) T016 implemented: outbound inline-image unit test asserts one CID attachment is produced per converted comment image.
- (2026-03-01) T017 implemented: outbound inline-image test asserts HTML image
srcrewrite from document-view URL to matchingcid:reference. - (2026-03-01) T018 implemented: outbound inline-image test covers storage/CID failure fallback retaining original attachment URL in HTML.
- (2026-03-01) T019 implemented: contract test now verifies draft clipboard image state tracking and document/file identity capture during upload.
- (2026-03-01) T020 implemented: contract assertions verify cancel action opens keep-vs-delete prompt when draft includes uploaded clipboard images. EOF && git add ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/tests.json ee/docs/plans/2026-03-01-ticket-comment-clipboard-image-attachments/SCRATCHPAD.md && git commit -m "test(T020): verify cancel prompt for uploaded draft images"- (2026-03-01) T021 implemented: contract coverage validates keep path handler clears draft state and closes editor without invoking hard-delete action.
- (2026-03-01) T022 implemented: added
clipboardImageDraftActions.contract.test.tsvalidating hard-delete loop invokesdeleteDocumentfor vetted draft artifacts. - (2026-03-01) T023 implemented: draft-delete contract test asserts saved-comment reference guard (
already_referenced) based on comment payload token scan. - (2026-03-01) T024 implemented: draft-delete contract test validates permission-denied guard when requester lacks document delete permission.
- (2026-03-01) T025 implemented:
clipboardImageUtils.test.tscovers unsupported MIME validation rejection before upload starts. - (2026-03-01) T026 implemented:
clipboardImageUtils.test.tsvalidates max-size guard rejects oversized clipboard images with explicit error. - (2026-03-01) T027 implemented:
TicketDetails.clipboardFlag.contract.test.tsasserts dedicated feature flag default-off gating for clipboard image paste flow. - (2026-03-01) T028 implemented: feature-flag contract coverage verifies enabled state wires
uploadFilecallback to conversation editor flow. - (2026-03-01) T029 implemented: contract assertions verify upload logs include ticket/user identifiers plus uploaded document/file artifact identity.
- (2026-03-01) T030 implemented: contract logging coverage verifies cancel keep/delete actions include selected action and delete-result counts/failure context.
- (2026-03-01) T031 implemented:
ticketEmailSubscriber.inlineImageLogging.contract.test.tsasserts per-image log outcome includes CID vs URL fallback strategy and reason fields. - (2026-03-01) T032 implemented: added
TicketClipboardFlow.e2e.contract.test.tsto validate paste-upload-save-render wiring from editor upload callback through comment viewer rendering. - (2026-03-01) T033 implemented: clipboard-flow contract test covers cancel delete invocation with selected document IDs and editor/draft state teardown.
- (2026-03-01) T034 implemented: outbound-email contract test verifies subscriber rewrites comment HTML and passes generated inline CID attachments on send path.
- (2026-03-01) T035 implemented: outbound-email fallback contract test validates URL-preserving behavior when CID conversion fails.