Files
nexarch/dms/docs/DOC-05-PRUEFPROTOKOLL.md
T
patrickandClaude Sonnet 5 411b997b94 DOC-05: PDF-Viewer-Komponente
internal/documentapi: neue Backend-Voraussetzung, die DOC-01/DOC-04 noch
nicht hatten - GET /documents/{id}/content liefert den entschluesselten
Originalinhalt der aktuellen Revision, Content-Type ausschliesslich ueber
Magic-Bytes, Content-Disposition: inline (kein Download-Zwang), volle
HTTP-Range-Unterstuetzung ueber http.ServeContent (Standardbibliothek) -
darueber laedt PDF.js grosse Dokumente automatisch seitenweise nach.

web/pdf-viewer: Next.js/React/TypeScript, PDF.js ausschliesslich auf
Canvas gerendert (kein iframe, siehe "Bekannte Fehler vermeiden"). Worker
laeuft aus public/pdf.worker.min.mjs (npm run copy-pdf-worker, Teil von
predev/prebuild) - bewusst NICHT ueber ein externes CDN, damit die
Anwendung vollstaendig offline/lokal lauffaehig bleibt. lib/viewerState.ts
kapselt Seiten-/Zoom-Navigation und Tastaturbedienung als reine,
DOM-unabhaengige Funktionen (Akzeptanzkriterium 2), Suche nutzt PDF.js'
eigene Textextraktion.

Pruefungen:
1. 300-seitiges PDF oeffnet im Zeitbudget - echter pdfjs-dist-Ladetest
   gegen den echten Backend-Dienst: 247ms (Budget 5000ms)
2. Viewer per Tastatur bedienbar - 15 Vitest-Tests fuer Pfeiltasten/Zoom/
   Suche-Fokus, inkl. Ignorieren waehrend im Suchfeld getippt wird
3. Speicherverbrauch im Browser - OFFEN, kein Headless-Browser in dieser
   Umgebung verfuegbar (gleiche Einschraenkung wie bei ANA-02)

SHL-01 (Core-Board, eigener Branch-Strang mit gemeinsamer Basis) sauber
gemergt - kein Dateiueberschneidungs-Konflikt (web/shl vs. dms/).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 19:58:00 +02:00

4.0 KiB
Raw Blame History

DOC-05 – Prüfprotokoll: PDF-Viewer-Komponente

Stand: 2026-09-17. Testhost 192.168.1.131.

Backend-Voraussetzung: internal/documentapi (neu für diese Kachel)

DOC-01/DOC-04 hatten noch keinen HTTP-Endpunkt, über den ein Viewer den Originalinhalt beziehen kann. GET /documents/{id}/content liefert den entschlüsselten Inhalt der aktuellen Revision, Content-Type ausschließlich über Magic-Bytes des entschlüsselten Inhalts (dieselbe Disziplin wie DOC-04), Content-Disposition: inline (kein Download-Zwang), volle HTTP-Range-Unterstützung über http.ServeContent (Standardbibliothek).

go test ./internal/documentapi/... -v — 3/3 PASS.

Grundsatzentscheidung: Canvas statt iframe, PDF.js im Web-Worker, Worker lokal ausgeliefert

Kein iframe/HTML-Rendering von Fremdinhalt — Rendering ausschließlich auf <canvas> (siehe "Bekannte Fehler vermeiden"). PDF.js' eigener Worker läuft als eigenständiges Skript, geladen aus public/pdf.worker.min.mjs (per npm run copy-pdf-worker, Teil von predev/prebuild) — bewusst NICHT über ein externes CDN, damit die Anwendung vollständig offline/lokal funktionsfähig bleibt. Direktes Bundling über Webpack scheiterte, weil der bereits minifizierte ESM-Worker von Terser kein zweites Mal minifiziert werden kann (import/export außerhalb von Modul-Code) — als statische, unverarbeitete Datei aus public/ umgangen.

Prüfung 1: 300-seitiges PDF öffnet im Zeitbudget

Echtes, synthetisch erzeugtes 300-Seiten-PDF über documentapi ausgeliefert, mit dem echten pdfjs-dist-Paket (nicht simuliert) via getDocument() geladen: 247 ms bis numPages === 300 vorlag (Zeitbudget 5000 ms deutlich unterschritten). Test lief gegen den echten Backend-Dienst mit echter Entschlüsselung, nicht gegen eine statische Datei.

Prüfung 2: Viewer per Tastatur bedienbar

lib/viewerState.ts (reine, DOM-unabhängige Zustandslogik) + npm test — 15/15 Vitest-Tests PASS: Pfeiltasten (Seite vor/zurück, an den Rändern geklemmt), +/- (Zoom, an MIN_ZOOM/MAX_ZOOM geklemmt), / (Suche fokussieren), Tastenkürzel werden ignoriert, während im Suchfeld getippt wird (kein versehentliches Blättern beim Tippen eines Suchbegriffs mit +/-/Pfeiltasten im Text).

Prüfung 3: Speicherverbrauch im Browser bleibt stabil

Nicht automatisiert nachweisbar in dieser Umgebung — dafür fehlt ein echter Browser mit Speicher-Profiling (kein Headless-Browser/keine Browser-Automatisierung hier verfügbar, gleiche Einschränkung wie bereits bei ANA-02 dokumentiert). Strukturell durch den PDF.js-Standardpfad adressiert: jede Seite wird einzeln gerendert (page.render), nicht das gesamte Dokument vorab gerastert — PDF.js' eigene Page-Cache-/Cleanup-Mechanismen greifen unverändert. Diese Prüfung bleibt offen, bis ein Zugriff auf eine echte Browser-Umgebung besteht.

Akzeptanzkriterien 1–3 (PDF ohne Download, Zoom/Blättern/Suche, seitenweises Nachladen)

  • Ohne Download: Content-Disposition: inline real im documentapi-Test verifiziert; PDF.js rendert direkt auf <canvas>, kein Browser-Download-Dialog.
  • Zoom/Blättern/Suche: UI-Bedienelemente in PdfViewer.tsx, Logik in viewerState.ts getestet; Suche nutzt PDF.js' eigene Textextraktion (getTextContent) über alle Seiten, springt zum ersten Treffer.
  • Seitenweises Nachladen: documentapi unterstützt HTTP-Range (echter 206-Response im Test), PDF.js nutzt das für seinen eigenen inkrementellen Ladevorgang automatisch — kein eigener Chunking-Code nötig.

Build/Test-Ergebnis

  • npx tsc --noEmit — sauber
  • npm test (Vitest) — 17/17 (2 lib/api.test.ts + 15 lib/viewerState.test.ts)
  • npm run build — erfolgreich (/viewer/[documentId]-Route, 2,01 kB / 89,4 kB First Load JS)
  • Go: gofmt -l ., go build ./..., go vet ./... sauber; go test ./... — alle Pakete PASS (Alt-Tabellen-Kollision aus eigenem Smoketest-Seed bereinigt, keine echte Regression)

Offen

Prüfung 3 (Speicherverbrauch im Browser) bleibt mangels Browser-Zugriff unverifiziert.