TenantAtlas/specs/378-management-report-pdf-v1/artifacts/spec378-gotenberg-security-controls.md
ahmido d43ebcb4ee feat(report): implement management report pdf v1 (#449)
Added PDF generation service for management reports as per Spec 378, including Gotenberg integration in docker-compose and configuration updates.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #449
2026-06-14 18:36:07 +00:00

88 lines
5.4 KiB
Markdown

# Spec 378 Gotenberg Security Controls
Date: 2026-06-14
Decision: Gotenberg 8 Chromium is approved with controls as an internal production PDF rendering service for report-style documents.
These are required future implementation controls. This artifact does not add runtime config and does not claim that Gotenberg is already deployed in the repo.
## Required Runtime Boundary
- Gotenberg runs as a separate internal Docker service.
- The Laravel app and queue containers do not install or execute Node, Puppeteer, Chrome, Chromium, or a browser binary for production PDF rendering.
- Laravel accesses the service only through a narrow `PdfRenderingGateway` / `PdfRendererClient`.
- The gateway exposes only server-generated HTML-to-PDF rendering required by report generators.
- No user-provided URL rendering is allowed in Spec 378 v1.
- No public port is exposed for the renderer in Sail or Dokploy.
- The service is reachable only over the internal Docker/Dokploy network.
## Required Image And Deployment Controls
- Use a pinned Gotenberg 8 Chromium image version or immutable digest; never `latest`.
- Prefer the Chromium-only Gotenberg 8 image variant for v1 unless office conversion is explicitly approved later.
- Record the exact image tag/digest in the implementation PR.
- Add a health check using Gotenberg `/health`.
- Configure startup/readiness behavior so unavailable renderer state fails generation before artifact exposure.
- Configure resource limits appropriate for PDF generation workers.
- Configure request timeout (`API_TIMEOUT`) and Chromium startup timeout (`CHROMIUM_START_TIMEOUT`) explicitly.
- Configure multipart request size limit (`API_BODY_LIMIT`) explicitly.
- Configure Chromium queue/concurrency limits (`CHROMIUM_MAX_QUEUE_SIZE`, `CHROMIUM_MAX_CONCURRENCY`) explicitly.
- Disable unused webhook behavior unless a future spec explicitly approves it.
- Disable or do not use `downloadFrom` in v1.
## Required Request Controls
- Send HTML as a server-generated `index.html` multipart payload.
- Send only local bundled assets alongside the HTML payload.
- Reference assets by relative filename only.
- Do not send signed URLs inside HTML.
- Do not send access tokens, refresh tokens, client secrets, provider credentials, raw provider payloads, SQL errors, stack traces, serialized job context, or internal MSP-only notes inside HTML.
- Do not render arbitrary operator-provided HTML.
- Do not render arbitrary user-provided remote URLs.
- Apply max HTML payload size, max asset size, and max PDF output size in the Laravel gateway before calling Gotenberg.
- Add a correlation id / OperationRun id to request metadata, using the configured Gotenberg correlation header.
## Required Network And File-Access Controls
- Keep Gotenberg internal-only with no public listener.
- No direct user-provided URL rendering in v1.
- Deny or tightly restrict outbound URL access.
- For Spec 378, default to no external outbound fetches: use bundled local assets only.
- Set Chromium outbound restrictions to reject public and private external HTTP destinations unless a later approved asset host allow-list is introduced.
- Do not enable file access beyond Gotenberg's per-request working directory defaults.
- Keep Chromium file access from files disabled.
- Do not mount application storage, secrets, `.env`, or host paths into the Gotenberg container.
- If custom fonts are required later, use a dedicated reviewed font image or readonly font mount with no secrets.
## Required Error And Audit Controls
- Renderer unavailable must map to OperationRun failed/blocked with safe reason.
- Renderer timeout must map to OperationRun failed/blocked with safe reason.
- Renderer 400/503 responses must map to structured internal error classes.
- Do not expose raw renderer errors to customers.
- No ghost report: failed generation must not expose a ready artifact, stale download URL, or partially written PDF.
- Renderer logs must not contain secrets because request HTML and metadata must be pre-sanitized.
- Audit generation attempts and successful downloads with safe metadata only.
- Log correlation id, source review/pack id, operation run id, profile, format, status, and safe renderer outcome.
## Required Testing And Validation Controls
- Unit coverage for renderer client request building and size-limit rejection.
- Feature coverage for renderer unavailable, timeout, invalid payload, and successful artifact response mapping.
- Feature coverage proving no ready artifact is exposed on renderer/storage failure.
- Feature coverage proving denied generation never calls the renderer.
- Browser/content smoke only after runtime service and generation flow are implemented.
- Deployment validation must include health check behavior and queue worker failure handling.
## Explicit Non-Approval
Gotenberg is approved as shared internal PDF rendering infrastructure for report-style documents.
This approval does not approve legal invoice generation, German B2B e-invoicing, XRechnung, ZUGFeRD/Factur-X, GoBD archival, tax calculation, invoice numbering, or billing compliance.
## Source Notes
- Gotenberg supports Docker and Docker Compose service use, with other services able to reach it on the compose network.
- Gotenberg exposes a Chromium HTML-to-PDF route accepting `index.html` plus optional assets.
- Gotenberg exposes `/health` for liveness/monitoring.
- Gotenberg has timeout, body limit, correlation id, Chromium concurrency, queue, file access, and outbound URL filtering settings that must be set deliberately.