Feature #120: image paste/drop attachments #129
No reviewers
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub!129
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/issue-120"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements Forgejo issue #120 per the plan + R1 + review (R1 normative on conflict).
What: paste (Ctrl/Cmd+V) or drop an image onto the issue-create textarea or the thread comment composer uploads it and inserts
at the cursor.Backend (
internal/issues, §12):POST /{o}/{r}/api/attachments(authenticated+read, LimitReader 8 MiB cap to 413 with no Content-Length requirement per B1, spool+hash, client sha optional-when-present per S4, magic-byte allowlist PNG/JPEG/GIF/WebP with SVG to 415, Create-only content-addressed, 201 record) +GET|HEAD /{o}/{r}/attachments/<sha>/<name>via ChainRepo/HandleRepo (in-package static contract per B3: ETag/304/206/416/HEAD, re-sniffed Content-Type,private, immutable, nosniff) +[attachments] max_image_bytes(default 8MiB, setup-schema-pending per S3). One seam correction from the review: the byte route rides ChainRepo/HandleRepo (repo_extra.go), not the Handle ExtraRoutes chain — the core router only sends lane paths to the api seam (verified against the live server).Frontend: SDK
attachments.js+ sharedattachUpload.js(alt escaping S1, placeholder replace, 64 KiB pre-check) + onPaste/onDrop glue in IssueNew.jsx and CommentComposer (uploader prop, wired by Issue.jsx only — PR adoption needs the Pull.jsx markdown switch per S6) + ui.css img rule. Sanitizer untouched, no new deps.Docs: 02 §12 + Decisions (incl. B2 discovery-exempt, S7 ceiling/sweep, dedup oracle), 06 private-cache-class note, 11 config row.
Tests: table-driven httptest for every handler/rejection (96.1% package cover, -race clean), headless node suites (288/288), real-Chromium paste drive dark+light ending with rendered images and zero console errors (screenshots in /tmp/opencode/drive120-*.png on the dev host).
Backend (internal/issues): POST /{o}/{r}/api/attachments (auth+read, 8 MiB LimitReader cap to 413, spool+hash, optional client sha, magic allowlist PNG/JPEG/GIF/WebP, SVG to 415, Create-only content-addressed, 201 record) + GET|HEAD /{o}/{r}/attachments/<sha>/<name> via ChainRepo HandleRepo (in-package static contract: ETag/304/206/416/HEAD, sniffed Content-Type, private immutable, nosniff). [attachments] max_image_bytes struct+default+validation+docs. Frontend: SDK attachments.js, shared attachUpload.js, onPaste/onDrop glue in IssueNew + CommentComposer (wired by Issue.jsx), ui.css img rule. Docs: 02 §12 + Decisions, 06 private-cache-class note, 11 config row.