Use Hopya
Private images and draft recovery
Upload images to task bodies and discussions, recover drafts, and understand private access and cleanup.
v0.3.0 referenceReviewed
On this page
Use Add image, paste a file, or drop one into a task body, new-task/subtask body, comment, reply, or Document discussion. Select an inserted image to edit its description or remove it.
| Upload rule | Limit / behavior |
|---|---|
| Formats | PNG, JPEG, GIF, WebP |
| Size | 10 MiB per file; 16,384 pixels per side; at most 40 megapixels |
| Validation | Raster containers/dimensions checked; no transcoding or antivirus scanner |
| Rejected rendering | SVG, HTML, data URLs, arbitrary paths, remote image URLs |
| External HTML paste | Text retained; image must be uploaded as a file |
Saving and drafts
- Upload the file; new task bodies do not need a saved task first.
- Insert the returned private image reference into your text.
- Save/post to claim it together with the content and audit.
| State | Recovery / ownership |
|---|---|
| Text and successful references | Tab sessionStorage, scoped to account/workspace/target; cleared only on successful save or explicit discard |
| Failed save | Draft/upload remain available for retry |
| Saved-task draft | Retains baseline revision; changed server version needs explicit reload/reconciliation |
| Closed reply | Draft retained for reopening |
| Uploading/failed files | Page memory survives composer close/reopen; retry/remove controls available |
| Reload/tab close | Pending file bytes lost; unload guard warns; successful references remain in recovered text |
| Range-comment selection | Not recovered on reload; post recovered text generally or select a fresh range |
| Server upload expiry | 24 hours, even while browser stays open; remove/reupload expired references before save |
Save/post waits for uploads and insertion retries. Over-limit bodies reject the entire edit rather than cutting image URLs. Browser-storage failures are visible; late uploads cannot insert into a different task/reply.
Removing an image node does not delete its saved attachment. Task-body images become ordinary task attachments on commit. Explicit attachment deletion revokes them. Copied committed URLs retain their original resource/comment ownership; deleting the source comment/attachment revokes copied references too.
Image upload API and reference limits
| Field / response | Contract |
|---|---|
| Endpoint | Authenticated POST /api/v1/workspaces/:wid/images |
| File fields | {name,contentType,data}; canonical base64 |
kind | task-body, task-comment, document-comment |
resourceId | Existing target; may be omitted only for a new task body |
| Result | Private url, forced-download downloadUrl, expiresAt; opaque IDs, no keys/secrets/capabilities |
| Active drafts | At most 50 uploads per account |
| Body references | At most 100; ordinary  Markdown |
Content mutations validate and claim pending images transactionally. Only the uploader with current target/upload permissions can preview a draft.
Permissions, bytes and cleanup
| Operation | Required access |
|---|---|
| Task-body upload | items:read + items:write |
| Comment upload | Target read + comments:create |
| Pending read | Uploader identity + current upload permission |
| Committed read | Current membership + target read, checked again after storage wait |
Site-administrator status does not bypass image permissions. Inline routes validate raster bytes and derive MIME; ordinary downloads stay forced application/octet-stream attachments.
| Inline response | Value |
|---|---|
Paths (after /api/v1) | /workspaces/:wid/images/:imageId/inline; /workspaces/:wid/items/:id/attachments/:attachmentId/inline |
| Headers | nosniff, sandbox, same-origin resource policy, private, no-store |
| Exposure | No anonymous bucket, public capability, or redirect |
Exported links are not image backups. Workspace export v8 includes committed image/attachment metadata, never bytes, keys, backend locations, pending drafts, or secrets. Links require the original instance; restore needs both the database and private object store.
Storage cleanup and export metadata
- Additive migration
0010_rich_text_imageslinks metadata to opaquestorage_objectskeys and workspace/resource composite keys. - Task/Document/workspace deletion cascades metadata. Comment tombstones revoke their images immediately; replies retain their own images, and later permanent removal is safe.
- Discarded/expired drafts and compensated failed uploads enter the existing bounded cleanup ledger. Each sweep expires up to 100 draft rows, preserves live references, and retries failed physical/ledger deletions. Keep backend cleanup guidance when changing drivers.
- Both service and snapshot exports retain IDs, resource/comment ownership, attachment links, name/MIME/size/timestamps. Document-comment entries require
documents:read; task export preserves image Markdown.
Gallery
| Interaction | Behavior |
|---|---|
| Cover | First rendered task-body image; excludes code examples and unsupported URLs |
| More images | Named previous/next buttons; announced position/description; no automatic cycling |
| Open task | Separate from carousel controls |
| Loading | Explicit loading/failure/retry states |
| Mobile | 44px carousel targets; existing bounded task/grid rendering |
Verification boundaries
| Covered upstream | Still needs verification |
|---|---|
| API/unit checks: permissions, raster rejection, claim/audit rollback, tombstones, cleanup failures, safe exports, Markdown round-trip, image order, upload-queue retention | Rendered clipboard/drop, browser recovery, keyboard/focus carousel, physical mobile layout |
| Local AWS-SDK S3 mock: private signed storage, failure compensation, live revocation | Operator S3 service and actual device codecs |
These are upstream verification records, not browser tests run for this documentation site.