Skip to content

Latest commit

 

History

History
90 lines (71 loc) · 2.73 KB

File metadata and controls

90 lines (71 loc) · 2.73 KB

Architecture — Simple PDF

High-level design of the self-hosted Simple PDF application.

Overview

Browser
    │  HTTP(S)
    ▼
Optional reverse proxy (TLS)
    │
    ▼
Gunicorn (2 workers typical) ── bind 0.0.0.0:8000 or 127.0.0.1:8000
    │
    ▼
Flask app factory (app/__init__.py)
    ├── auth.py          optional auth hook (off by default)
    ├── routes.py        UI + JSON API
    ├── validation.py    extension + magic bytes + sanitize
    ├── session_store.py on-disk sessions (multi-worker safe)
    ├── pdf_ops.py       combine / grayscale / edges / cleanup
    ├── edit_ops.py      post-combine page edits
    ├── ocr_ops.py       OCR via ocrmypdf / Tesseract
    ├── convert_ops.py   text / office → PDF
    ├── msg_ops.py       Outlook MSG → PDF
    └── cleanup.py       delete sessions older than N hours

Sessions without a database

There is no login database in the default configuration.

  1. A Flask session cookie identifies the browser session (sid).
  2. On disk: uploads/<sid>/
    • files/ originals
    • thumbs/ JPEG thumbnails
    • output/ combined / edited PDF
    • manifest.json item order

Shared disk state keeps multiple Gunicorn workers consistent.

Combine pipeline

ordered items (manifest)
        │
        ▼
each PDF/image → pages
        │
        ├─ cleanup? → drop near-blank pages
        ├─ edge_detect? → Canny / contour or margin trim
        └─ grayscale? → convert to gray
        │
        ▼
single PDF (garbage + deflate)
        │
        ▼
editor / download

Security model (baseline)

Control Implementation
Bind Configurable (PDF_EDITOR_HOST / PORT); prefer localhost + reverse proxy for public exposure
Upload Extension allow-list + magic-byte checks + size limits
Names Sanitized filenames + UUIDs
Auth Optional hook; PDF_EDITOR_AUTH_ENABLED=0 by default
Temporaries Startup cleanup (PDF_EDITOR_TEMP_HOURS, default 24) + clear-session API
Secrets PDF_EDITOR_SECRET_KEY or persisted .secret_key for stable cookies across workers

Auth hook

app/auth.py:

  • AUTH_ENABLED=False → allow all
  • AUTH_ENABLED=True → require session['authenticated'] or header X-PDF-Editor-Token matching PDF_EDITOR_AUTH_TOKEN

API routes go through the gate without per-endpoint auth wiring.

Configuration

Environment variables are documented in .env.example (prefix PDF_EDITOR_*). Runtime defaults live in app/config.py.

Out of scope (current design)

  • Multi-tenant user accounts / RBAC
  • Long-term document archive / search index
  • Guaranteeing OCR quality on handwriting or poor scans