Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
## [Unreleased]
- Proposed: accept manual PDF uploads up to 64MiB after the required processing
service release is verified and pinned. Larger files are rejected before
storage or processing with HTTP 413; split the file and upload it again.
This limit is not yet a released capability.
- Proposed: repair fresh-install and upgrade failures while retaining existing
mail and its read state. Real database smoke tests preserve the complete
historical upgrade path and verify the repaired installation.
Expand Down
10 changes: 5 additions & 5 deletions backend/api/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@
router = APIRouter(prefix="/api/data", tags=["data"])

DATA_VECTOR_DIMENSIONS = 1536
# Upper bound for the binary PDF DOM recognition upload variant. Kept in step
# with the NewsDOM sidecar's own MAX_PARSE_UPLOAD_BYTES (20 MiB): accepting more
# would let a caller stash a pending document the configured sidecar will always
# reject while the base64 copy inflates the database.
_MAX_PDF_DOM_UPLOAD_BYTES = 20 * 1024 * 1024
# Upper bound for the binary PDF DOM recognition upload variant. Keep this in
# step with NewsDOM's MAX_PARSE_UPLOAD_BYTES and the signed email-import
# transport ceiling so large customer PDFs are not accepted by one path and
# rejected by the next.
_MAX_PDF_DOM_UPLOAD_BYTES = 64 * 1024 * 1024
Comment thread
seonghobae marked this conversation as resolved.
ATTACHMENT_PARSE_BREAKDOWN_EVIDENCE_SOURCE = (
"email_attachments.content_type, "
"email_attachments.parse_content_type, "
Expand Down
4 changes: 4 additions & 0 deletions backend/tests/test_data_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2993,6 +2993,10 @@ def test_data_pdf_dom_upload_persists_signed_organization_scope(mock_db):
assert stored_document.document_status == "pdf_dom_recognition_pending"


def test_data_pdf_dom_upload_budget_matches_newsdom_transport_contract():
assert data_api._MAX_PDF_DOM_UPLOAD_BYTES == 64 * 1024 * 1024


def test_data_pdf_dom_upload_rejects_invalid_signature_and_size(mock_db, monkeypatch):
token = _signed_session_token(_valid_session_payload())
client, previous_secret, original_overrides = _with_signed_auth(mock_db, token)
Expand Down
66 changes: 66 additions & 0 deletions docs/adr/0021-bounded-pdf-dom-upload-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# ADR-0021: Bounded PDF DOM upload contract

**Status:** Proposed
**Date:** 2026-08-20
**Decision owner:** Naruon maintainers
**Scope:** Signed `POST /api/data/documents/pdf-dom-recognition` uploads
**Figma File ID:** N/A — backend upload contract; no visual surface.
**Former proposal ID:** ADR-0005 in #1427. Renumbered after the 2026-09-05
open-PR inventory found unrelated 0005 proposals; the decision content and
immutable-release prerequisite are retained. Existing #1469 inherits this
proposal and must take the rename by ancestry, not publish a second decision.

## Context

Naruon email imports and the NewsDOM sidecar are being aligned to a 64MiB
bounded PDF transport budget. The direct Data workspace upload still used an
independent 20MiB limit, so a customer could upload a large PDF through email
but receive an avoidable `413` when using the equivalent manual workflow.

## Decision

After NewsDOM publishes an immutable 64MiB transport release and Naruon pins
that exact release, set the direct PDF DOM upload and its pending-payload
decoder to 64MiB. Keep the signed-session boundary, PDF signature validation,
one-byte-over-limit read, base64 persistence contract, and `413` response
unchanged. Until then this consumer change remains Draft and must not be merged.

## Consequences

- After the owner release is pinned, email and manual PDF ingestion present the
same bounded size expectation to customers.
- The endpoint can persist more temporary database content, so existing
workspace quotas, background worker limits, and database capacity monitoring
remain required.
- No unbounded upload is introduced, and malformed or non-PDF payloads continue
to fail closed before recognition.

## Alternatives rejected

### Keep a separate 20MiB manual-upload limit

Rejected because it creates a customer-visible workflow inconsistency without a
different safety property after the sidecar contract is raised.

### Remove the upload limit

Rejected because request and database resource use must remain bounded at the
authenticated trust boundary.

## References (APA 7th)

Internet Engineering Task Force. (2022). *HTTP semantics (RFC 9110).* RFC
Editor. https://www.rfc-editor.org/rfc/rfc9110

RFC 9110 supports retaining an explicit `413 Payload Too Large` response when a
request exceeds the server's permitted content size.

National Institute of Standards and Technology. (2025). *Secure software
development framework (SSDF) version 1.2* (NIST Special Publication 800-218
Rev. 1, Initial Public Draft). https://doi.org/10.6028/NIST.SP.800-218r1.ipd

The SSDF supports auditable input bounds, regression tests, and operational
controls for untrusted-input boundary changes.

No customer data or source PDF is included; the standards remain linked to their
authoritative publishers.
1 change: 1 addition & 0 deletions docs/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ govern implementation.
| [ADR-0003](0003-separate-topic-measurement-from-agenda-generation.md) | Keep statistical measurement separate from agenda generation | Proposed | Target and future capability `PLANNED`; no implementation authorization |
| [ADR-0004](0004-status-weighted-calendar-conflicts.md) | Evaluate CalDAV VEVENT overlaps by occupying status; cancelled does not occupy | Accepted | `ACCEPTED-NARUON-POLICY`; advisory evaluate API only |
| [ADR-0020](0020-full-document-trigram-storage.md) | Repair whole-document trigram persistence without changing ranking; measure latency before rollout | Proposed | Storage candidate; no protected integration or performance acceptance |
| [ADR-0021](0021-bounded-pdf-dom-upload-contract.md) | Propose 64MiB direct PDF admission only after the required NewsDOM release is pinned | Proposed | `BLOCKED-UPSTREAM`; requires an immutable NewsDOM 64MiB release and exact Naruon pin |

The complete topic-intelligence requirements, architecture, contract, UML,
conceptual ERD, security, test, and operability graph is indexed at
Expand Down
31 changes: 31 additions & 0 deletions docs/doctoring/bounded-pdf-dom-upload-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Doctoring record: bounded PDF DOM upload contract

**Observed gap:** The signed Data workspace PDF upload rejected files above
20MiB while Naruon's planned shared admission bound is 64MiB. The current
NewsDOM immutable release and an exact Naruon pin proving 64MiB support have
not been verified; this record must not present that proposal as provider runtime.

**Proposed correction:** After NewsDOM publishes an immutable 64MiB release and
Naruon pins it exactly, the upload endpoint and pending-payload decoder will
share a 64MiB bound. Signature validation, signed-session authorization, base64
storage, worker deferral, and `413` rejection remain fail-closed. The Naruon PR
stays Draft until that owner evidence exists.

**Evidence:** `backend/tests/test_data_api.py` asserts the 64MiB contract and
keeps the over-limit test monkeypatched to a small fixture. The NewsDOM sidecar
alignment is tracked separately in its own ADR and PR.
The four existing focused PDF tests use mocks and reduced over-limit fixtures;
they do not prove a real 64MiB PDF processed by a released NewsDOM service.
[ADR-0021](../adr/0021-bounded-pdf-dom-upload-contract.md) preserves the
proposal formerly numbered 0005, whose number collided with unrelated PRs.

**References (APA 7th):**

- Internet Engineering Task Force. (2022). *HTTP semantics (RFC 9110).* RFC
Editor. https://www.rfc-editor.org/rfc/rfc9110
- National Institute of Standards and Technology. (2025). *Secure software
development framework (SSDF) version 1.2* (NIST SP 800-218 Rev. 1, Initial
Public Draft). https://doi.org/10.6028/NIST.SP.800-218r1.ipd

No customer or private reference data was read, and no source PDF is
redistributed.