New first-class attachments concept on the deliverable detail page,
replacing the "stash a Figma URL in the notes" workaround. Two kinds
share one row:
- FILE — uploaded via the existing /data/uploads volume, served
through /api/uploads/deliverables/:id/:filename. 100MB cap.
Images render a thumbnail inline; PDFs/docs get a file icon
+ download link. Blob cleaned up on delete.
- LINK — external URL (Figma / Drive / Dropbox / ad-hoc). Figma URLs
detected against the file/proto/design/board path pattern
and get an in-line iframe preview via Figma's embed host.
Other URLs open in a new tab with an external-link icon.
Schema:
- DeliverableAttachment model + migration. Cascade-deletes with the
parent deliverable. Optional stageDefinitionId tag scopes an asset
to a specific stage (null = whole deliverable).
- Extended serving route's MIME allowlist: PDF, Office docs, CSV,
text, ZIP, AI/PSD. Was tight to video/image-only before.
Plumbing:
- attachment-service with listAttachments / createLink /
createFile / delete. Visibility-scoped (assertProjectVisible via
deliverable.projectId).
- POST /api/deliverables/:id/attachments — content-type discriminates
multipart (file) vs JSON (link). DELETE at the nested route.
- useAttachments / useCreateLinkAttachment / useUploadFileAttachment /
useDeleteAttachment hooks; invalidate ["attachments", deliverableId].
UI panel renders above Pipeline Stages so assets are always in sight.
Read-only for CLIENT_VIEWER; all other roles can upload/paste/delete.
|
||
|---|---|---|
| .. | ||
| migrations | ||
| schema.prisma | ||
| seed-dow.ts | ||
| seed-tracker-data.ts | ||
| seed.ts | ||