Files
paliad/internal/services
mAi 8ccf64cf83 feat(submissions): t-paliad-370 S4 — truthful base-preview render (code)
docforge UX slice S4 (PRD §2.3). Extends the S3 /api/submission-preview
endpoint with a truthful page-image render behind the SAME modal+endpoint
shape (the swappable body region). Resolves the S3 caveat: anchors-only
Composer/Gitea bases now render their REAL letterhead/Rubrum styling instead
of falling back to a base-agnostic structural view.

Pipeline (PRD §2.3): build the .docx via the EXISTING export pipeline
(byte-faithful) → Gotenberg sidecar (.docx→PDF over HTTP, keeps the Go image
lean) → poppler pdftoppm (PDF→PNG-per-page) → cache + single-flight.

Code only — NO Dokploy/compose change (head provisions the sidecar + fonts).
When GOTENBERG_URL is unset or poppler is absent, Available()=false and the
endpoint gracefully falls back to S3 structural HTML, so merging this is safe
before the infra lands.

Backend:
- internal/services/preview_render.go: PreviewImageRenderer interface +
  GotenbergRenderer (.docx→PDF→PNG) + PreviewImageCache (bounded FIFO,
  single-flight per key, serialised conversions) + NewPreviewImageCacheFromEnv
  (GOTENBERG_URL / PREVIEW_DPI). The PNG cache is regenerable, not a retained
  document (no disk/DB persistence; rebuildable from inputs).
- /api/submission-preview gains fidelity=truthful: builds the truthful .docx
  (editor = clone draft + base override → full export pipeline incl. Composer;
  catalog = context bag → render), caches by (draft id+updated_at | code+
  project) × base × lang × data-mode, returns page data-URIs. Structural
  responses now carry truthful:false.
- exportSubmissionDraft + Export gain a pluggable missing-marker (nil = default,
  so every existing export path is byte-identical); enables sample-data truthful
  render. New SubmissionDraftService.{ExportWithMarker,RenderContextPreviewDocx}.
- Unit tests: cache hit/miss, single-flight, eviction, availability, gotenberg
  multipart request shape (httptest, no poppler needed).

Frontend:
- base-preview-modal.ts requests fidelity=truthful; renders <img> page(s) with
  a ‹ n/N › prev/next pager (instant — pages held client-side); falls back to
  the S3 structural sheet when truthful:false. CSS for .base-preview-img +
  page-nav.

bun build (i18n scan clean) + go vet ./... + go test ./... (15 ok, 0 fail;
+6 new service tests).
2026-06-01 18:54:41 +02:00
..