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.

Documentation: reference table
Upload ruleLimit / behavior
FormatsPNG, JPEG, GIF, WebP
Size10 MiB per file; 16,384 pixels per side; at most 40 megapixels
ValidationRaster containers/dimensions checked; no transcoding or antivirus scanner
Rejected renderingSVG, HTML, data URLs, arbitrary paths, remote image URLs
External HTML pasteText retained; image must be uploaded as a file

Saving and drafts

  1. Upload the file; new task bodies do not need a saved task first.
  2. Insert the returned private image reference into your text.
  3. Save/post to claim it together with the content and audit.
Saving and drafts: reference table
StateRecovery / ownership
Text and successful referencesTab sessionStorage, scoped to account/workspace/target; cleared only on successful save or explicit discard
Failed saveDraft/upload remain available for retry
Saved-task draftRetains baseline revision; changed server version needs explicit reload/reconciliation
Closed replyDraft retained for reopening
Uploading/failed filesPage memory survives composer close/reopen; retry/remove controls available
Reload/tab closePending file bytes lost; unload guard warns; successful references remain in recovered text
Range-comment selectionNot recovered on reload; post recovered text generally or select a fresh range
Server upload expiry24 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
Saving and drafts: reference table
Field / responseContract
EndpointAuthenticated POST /api/v1/workspaces/:wid/images
File fields{name,contentType,data}; canonical base64
kindtask-body, task-comment, document-comment
resourceIdExisting target; may be omitted only for a new task body
ResultPrivate url, forced-download downloadUrl, expiresAt; opaque IDs, no keys/secrets/capabilities
Active draftsAt most 50 uploads per account
Body referencesAt most 100; ordinary ![description](private-inline-path) 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

Permissions, bytes and cleanup: reference table
OperationRequired access
Task-body uploaditems:read + items:write
Comment uploadTarget read + comments:create
Pending readUploader identity + current upload permission
Committed readCurrent 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.

Permissions, bytes and cleanup: reference table
Inline responseValue
Paths (after /api/v1)/workspaces/:wid/images/:imageId/inline; /workspaces/:wid/items/:id/attachments/:attachmentId/inline
Headersnosniff, sandbox, same-origin resource policy, private, no-store
ExposureNo 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_images links metadata to opaque storage_objects keys 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: reference table
InteractionBehavior
CoverFirst rendered task-body image; excludes code examples and unsupported URLs
More imagesNamed previous/next buttons; announced position/description; no automatic cycling
Open taskSeparate from carousel controls
LoadingExplicit loading/failure/retry states
Mobile44px carousel targets; existing bounded task/grid rendering

Verification boundaries

Verification boundaries: reference table
Covered upstreamStill needs verification
API/unit checks: permissions, raster rejection, claim/audit rollback, tombstones, cleanup failures, safe exports, Markdown round-trip, image order, upload-queue retentionRendered clipboard/drop, browser recovery, keyboard/focus carousel, physical mobile layout
Local AWS-SDK S3 mock: private signed storage, failure compensation, live revocationOperator S3 service and actual device codecs

These are upstream verification records, not browser tests run for this documentation site.