handleCreatePasteMultipart silently dropped non-numeric
burn_after_reads values (err == nil guard), so burn_after_reads=abc
created a 201 paste with NO burn budget. Now returns 400 with the
error+code shape ({'code':'burn_invalid'}) matching the JSON path,
where an invalid value fails unmarshal into the int field. An empty
value stays 'unset' like the JSON path's omitempty. Verified live:
burn_after_reads=abc -> 400 burn_invalid; =2 -> 201.
handleRaw only streamed the blob behind an isImageMime gate (#221), so
non-image attachment pastes fell through to empty row.Content and /raw
served 0 bytes. Serve the blob for every attachment mime, passing the
sniffed mime through serveContentType so active-content types (html,
svg, xml) still serve as text/plain per the #34 rule. Regression tests
cover text and html attachments (size, Content-Type, byte equality).
- image pastes render the image scaled to fit the viewer box (aspect
ratio preserved, max-height 70vh), no text/code box below it
- link pill moved under the image as a small inline chip
- /raw serves image attachment bytes as an image instead of empty text
- view details size reports the actual attachment file size