Store imported PDFs as encrypted, deduplicated attachments
Stage two of PDF support: the file can now get in and out. No viewer yet — that is next. A PDF is an attachment like any other, so it inherits everything already built: encryption at rest, naming by content hash, deduplication, the orphan sweep, and the authenticated retrieval route the client already caches offline. The note points at it through notes.pdf_attachment_id. Raw request body rather than the base64 JSON images travel in. A scanned book is tens of megabytes and base64 adds a third to that, on a path that carries nothing but the file. The bytes are checked for %PDF- before anything is written, so the declared content type is never trusted. Images and PDFs are limited separately — INKNOTE_MAX_IMAGE_MB (25) and INKNOTE_MAX_PDF_MB (200) — because a 25 MB picture is nearly always a mistake and a 25 MB document is not. Both configurable; the limits exist so a runaway upload cannot fill the disk, not to ration anything. The JSON body limit now follows the image limit instead of being a second number that could drift away from it. Verified against a real PDF: uploaded, stored with the INKENC01 header, returned byte-identical, deduplicated on a second upload, a GIF renamed to .pdf refused with 415, unauthenticated refused with 401. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
915856e1a4
commit
53965281b4
5 files changed
+101
-8
No files matched your search
@@ -29,6 +29,8 @@ services:
|
||||
- NODE_ENV=production
|
||||
# Optional tuning; unset means the server's own defaults apply.
|
||||
- ALLOWED_ORIGINS=${ALLOWED_ORIGINS:-}
|
||||
- INKNOTE_MAX_IMAGE_MB=${INKNOTE_MAX_IMAGE_MB:-}
|
||||
- INKNOTE_MAX_PDF_MB=${INKNOTE_MAX_PDF_MB:-}
|
||||
- MAX_VERSIONS_PER_NOTE=${MAX_VERSIONS_PER_NOTE:-}
|
||||
- VERSION_RETENTION_DAYS=${VERSION_RETENTION_DAYS:-}
|
||||
- VERSION_COALESCE_MINUTES=${VERSION_COALESCE_MINUTES:-}
|
||||
|
||||
Reference in new issue
Block a user