# Spec 379 Runtime Validation Evidence Date: 2026-06-14 ## Baseline - Branch: `379-management-report-pdf-runtime` - Starting HEAD: `d43ebcb4 feat(report): implement management report pdf v1 (#449)` - Initial dirty state: only `specs/379-management-report-pdf-runtime/` was untracked. - Spec 378 files verified: - `docker-compose.yml` - `apps/platform/config/tenantpilot.php` - `apps/platform/app/Services/Pdf/PdfRenderingGateway.php` - `apps/platform/tests/Unit/Pdf/Spec378PdfRenderingGatewayTest.php` ## Local Runtime Controls - Gotenberg image remains pinned to `gotenberg/gotenberg:8.34.0-chromium`. - No public Gotenberg port is exposed by the `gotenberg` service. - Runtime safeguards remain configured: - `API_DISABLE_DOWNLOAD_FROM=true` - `WEBHOOK_DISABLE=true` - `CHROMIUM_ALLOW_FILE_ACCESS_FROM_FILES=true` - `CHROMIUM_ALLOW_LIST=^file:///tmp/.*$` - `CHROMIUM_DENY_PRIVATE_IPS=true` - `CHROMIUM_DENY_PUBLIC_IPS=true` - timeout, body-limit, queue, and concurrency env controls remain present. - `docs/deployment-checklist.md` documents the pinned image, internal service URL, and renderer hardening controls. - Local validation on 2026-06-15 confirmed that `CHROMIUM_ALLOW_LIST=^$` makes `/forms/chromium/convert/html` return `403 Forbidden` because Chromium must navigate to Gotenberg's temporary `file:///tmp/.../index.html`. The allow-list remains restricted to that internal file path and external fetches remain disabled. ## Staging/Dokploy Validation Staging/Dokploy runtime validation was not executable from this local workspace. Generation therefore remains blocked by default through: - `TENANTPILOT_PDF_RENDERER_RUNTIME_VALIDATED=false` - `tenantpilot.pdf_renderer.runtime_validated` - `ManagementReportPdfRuntimeGate` To enable management PDF generation in Staging/Production, validate the deployed Gotenberg container/runtime path first, then set `TENANTPILOT_PDF_RENDERER_RUNTIME_VALIDATED=true` in the environment. ## Verification Commands - `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec379` - Result: 7 passed, 81 assertions. - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec379ManagementReportPdfSmokeTest.php --compact` - Result: 1 passed, 12 assertions. - `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec378` - Result: 11 passed, 44 assertions. - `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec357` - Result: 13 passed, 108 assertions. - `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec366` - Result: 9 passed, 181 assertions. - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/ReviewPackDownloadTest.php tests/Feature/ReviewPack/ReviewPackResourceTest.php tests/Unit/Pdf/Spec378PdfRenderingGatewayTest.php` - Result: 49 passed, 268 assertions. - `cd apps/platform && ./vendor/bin/sail pint ...` - Result: PASS on changed runtime/test files. - `git diff --check` - Result: PASS. ## Guard Notes The optional guard command below was run and produced two pre-existing failures unrelated to Spec 379: - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/OperationLifecycleOpsUxGuardTest.php tests/Feature/Guards/ActionSurfaceContractTest.php` - `ActionSurfaceContractTest`: operation registry URL assertion expects no navigation context, but current code returns an operations-index navigation context. - `ActionSurfaceContractTest`: required-permissions page assertion expects `Start verification`, which the current page no longer renders. Both failures reproduce in isolation and no Spec379 code path is involved.