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
22 KiB
Tasks: Spec 378 - Management Report PDF v1
Input: specs/378-management-report-pdf-v1/spec.md, specs/378-management-report-pdf-v1/plan.md
Prerequisites: Spec and plan are complete. Renderer governance is approved with controls for Gotenberg 8 Chromium. Renderer runtime/gateway work must complete and be staging-validated before report generation work.
Tests: Required. Use Pest 4 Unit, Feature/Filament action, and Browser/content smoke. PostgreSQL lane is required if migrations/indexes are introduced.
Implementation note: Renderer governance and the first runtime/gateway boundary are implemented. Downstream report generation tasks remain pending for later /spec-kit-implementation-loop passes.
Phase 1: Repo Verification And Hard Gates
Purpose: Confirm current repo truth before runtime edits.
- Gate stop note (2026-06-14): branch
378-management-report-pdf-v1, HEADf1eadadf docs: add spec 377 post-productization browser reaudit closeout gate (#448), dirty baseline was the untracked active spec directoryspecs/378-management-report-pdf-v1/. Runtime implementation stopped before code edits because T008 initially found no approved production-safe PDF renderer inapps/platform/composer.json, Playwright is dev/browser tooling only inapps/platform/package.json, anddocs/package-governance.mddid not yet approve a production PDF renderer. - Renderer governance update (2026-06-14): T008 has been reviewed and updated through package/runtime governance. Gotenberg 8 Chromium is approved with controls as an internal Docker service, documented in
artifacts/spec378-pdf-renderer-decision-matrix.md,artifacts/spec378-gotenberg-security-controls.md,artifacts/spec378-constitution-renderer-gate-review.md,spec.md,plan.md, anddocs/package-governance.md. No runtime service, app code, report generation, or tests were implemented by this governance update. - Runtime/gateway update (2026-06-14): Sail/local runtime target is root
docker-compose.yml; no Dokploy config file is present in the repo, sodocs/deployment-checklist.mdrecords staging/production controls.apps/platform/.env.example,apps/platform/config/tenantpilot.php, andapps/platform/app/Services/Pdf/*now define the Gotenberg app config and gateway/client boundary. Report payload, storage, OperationRun, UI action, download route, PDF template, and browser smoke remain pending. - T001 Re-read
specs/378-management-report-pdf-v1/spec.md,plan.md,tasks.md, andchecklists/requirements.md. - T002 Record branch, HEAD, dirty state, and touched-file baseline in the active implementation close-out notes before runtime edits.
- T003 Verify the existing rendered report source paths:
ReviewPackRenderedReportController,rendered-report.blade.php,ReportProfileRegistry,ReportDisclosurePolicy,ReportThemeResolver, andReviewPackService. - T004 Verify current Review Pack source readiness/current-pack rules in
ReviewPackService,ReviewPackDownloadController,EnvironmentReviewResource,ReviewPackResource, and related tests. - T005 Verify current
StoredReportschema/model/resource capability map and decide whether a narrow extension can represent a management PDF artifact. - T006 Verify current
OperationRunType,OperationCatalog,OperationRunService, and Operations UI/actionability rules before adding or mappingreport.management.generate. - T007 Verify current audit action IDs and audit logger usage for review exports/downloads; identify whether distinct management PDF generation/download action IDs are required.
- T008 Hard gate: verify an approved production-safe PDF renderer path. If no approved path exists, stop before runtime edits, run package-governance review, and update
spec.md/plan.md. - T009 Confirm no live Graph/provider call is required for payload, render, generation, or download.
- T010 Decide the first owner surface for v1 generation: Environment Review detail, Review Pack detail, or Customer Review Workspace. Prefer Environment Review or Review Pack detail unless repo verification proves otherwise.
Phase 1A: Renderer Governance Decision Completed
Purpose: Document the renderer/package/runtime decision without implementing report generation.
- G001 Review the renderer/package gate after the manual
gate stop validdecision. - G002 Evaluate renderer candidates: Gotenberg 8 Chromium, Spatie Browsershot / Spatie Laravel PDF, dompdf / laravel-dompdf, wkhtmltopdf / Snappy, and PrinceXML.
- G003 Create
specs/378-management-report-pdf-v1/artifacts/spec378-pdf-renderer-decision-matrix.md. - G004 Document required Gotenberg security controls in
specs/378-management-report-pdf-v1/artifacts/spec378-gotenberg-security-controls.md. - G005 Document invoice/billing/e-invoice boundary in
spec.md,plan.md, andspecs/378-management-report-pdf-v1/artifacts/spec378-constitution-renderer-gate-review.md. - G006 Update
docs/package-governance.mdwith Gotenberg 8 Chromium approved-with-controls runtime service entry. - G007 Update
spec.mdandplan.mdwith the selected renderer and pending runtime-config boundary. - G008 Identify exact runtime config targets before editing: root
docker-compose.ymlfor Sail/local service wiring, Dokploy/deployment config or documentation location if present, and explicitnot presentnotes for missing deployment config files. - G009 Add the Gotenberg runtime service to the identified Sail/Dokploy config target(s) with a pinned image, no public port, health check, timeouts, request/output limits, and outbound/file-access controls.
- G010 Add renderer app config for base URL, timeout, body/output limits, unavailable behavior, and correlation id handling.
- G011 Add failing renderer gateway/client tests for health check, renderer unavailable, timeout, invalid response, size-limit rejection, and safe error mapping before completing the gateway/client.
- G012 Implement the Laravel
PdfRenderingGateway/PdfRendererClientas the only production renderer integration boundary. - G013 Confirm Gotenberg runtime controls in staging before enabling report PDF generation.
- Remaining validation note:
docker compose config --quietpasses locally, but a direct pull/probe ofgotenberg/gotenberg:8.34.0-chromiumwas cancelled after staying silent and returning a Docker credential interruption. Staging/Dokploy must verify the configured/healthhealthcheck command runs inside the pinned image.
- Remaining validation note:
Phase 2: Test Design First
Purpose: Add failing or pending proof for the core behavior before implementation.
- T011 Add Unit coverage for management report payload sections: cover, executive summary, governance posture, key decisions, top findings, accepted risks, evidence readiness, limitations, next actions, provenance, and method summary.
- T012 Add Unit coverage proving
customer_executiveprofile and disclosure policy hide technical appendix, raw provider payloads, internal MSP fields, signed URLs, and raw operation context. - T013 Add Unit coverage for readiness decisions: missing review, non-current pack, expired pack, not-ready pack, invalid/unimplemented profile, disclosure blocker, missing evidence limitation, and unauthorized actor.
- T014 Add Unit or Feature coverage for Gotenberg gateway renderer failure mapping to safe failed/blocked result without stack trace leakage.
- T015 Add Feature coverage for authorized generation from a ready current Review Pack or Environment Review source.
- T016 Add Feature coverage for artifact storage or canonical artifact reference with workspace, tenant scope, managed environment, source review, source pack, profile, format, generated-by, generated-at, and operation-run provenance.
- T017 Add Feature coverage for generation audit metadata and failed generation audit/OperationRun evidence.
- T018 Add Feature coverage for successful download audit metadata.
- T019 Add authorization coverage for no workspace membership, wrong tenant, and wrong managed environment returning 404.
- T020 Add authorization coverage for scoped member without generation/download capability returning 403 after scope is established.
- T021 Add Feature coverage proving denied generation creates no artifact and exposes no download.
- T022 Add Feature coverage proving download route re-resolves artifact/source scope and rejects stale, expired, cross-workspace, cross-tenant, or cross-environment access.
- T023 Add Filament/Livewire action coverage for visibility, disabled reason, notification, and operation/download link behavior on the chosen owner surface.
- T024 Add Browser/content smoke coverage for generate or download flow when local fixtures support it.
- T025 Add Browser/content smoke assertions that PDF text includes required management chapters and excludes forbidden strings:
SQLSTATE,access token,client secret,raw Graph payload,internal_msp_review, serialized job markers, and signed URLs.
Phase 3: Payload, Readiness, And Disclosure
Purpose: Build deterministic report content from existing source truth only.
- T026 Implement a bounded management report payload builder or equivalent under the existing report/review-pack support namespace.
- T027 Build payload only from existing
ReviewPack,EnvironmentReview,EvidenceSnapshot, findings summary, accepted risk/exception, decision summary, and rendered-report support truth. - T028 Ensure the payload builder does not query from Blade/PDF templates and does not call Graph/provider services.
- T029 Resolve the effective profile through
ReportProfileRegistryand default tocustomer_executive. - T030 Apply
ReportDisclosurePolicybefore rendering and fail closed for unknown/unimplemented profile input. - T031 Implement readiness/blocked reason mapping for source missing, not current, not ready, expired, evidence limitation, disclosure blocker, Gotenberg renderer unavailable, storage unavailable, and authorization failure.
- T032 Ensure missing evidence either blocks generation or appears as a management-visible limitation according to existing review/report policy; document the chosen behavior in code/tests.
- T033 Keep next actions derived from existing report/review/finding/evidence data; do not invent AI or unsupported recommendations.
Phase 4: Artifact Storage And Idempotency
Purpose: Store or reference the generated PDF without inventing a report center.
- T034 If current fields are insufficient, add a narrow reversible migration for the existing report/artifact substrate rather than a new table.
- T035 If extending
StoredReport, add only fields required for PDF artifact identity, tenant scope, source environment, source review/pack, profile, format, status, file disk/path, generated by, generated at, and operation run provenance; newly persisted tenant-owned artifact truth must include NOT NULLtenant_idunless a constitution-compliant exception is added before implementation. - T036 Add or update
StoredReportconstants/casts/relationships for management PDF only ifStoredReportis the chosen substrate. - T037 Update
StoredReportResourcecapability/report type handling only if management PDFs are listed/viewed there; keep global search disabled. - T038 Store PDF artifacts on a private disk/path and avoid public filenames or secret-bearing paths.
- T039 Implement source/profile/fingerprint idempotency or document why repeated generation intentionally creates separate artifacts.
- T040 Ensure no ready/downloadable artifact is exposed when generation fails before storage commit.
- T041 If any schema/index behavior is PostgreSQL-specific, add PostgreSQL lane proof.
Phase 5: OperationRun And Audit
Purpose: Make generation observable and accountable.
- T042 Add or map canonical operation type
report.management.generateonly if no existing type fits; updateOperationRunType,OperationCatalog, labels, guards, and tests consistently. - T043 Start/queue generation through
OperationRunServiceunless a spec/plan update explicitly approves a synchronous no-run path. - T044 Route queued toast/link/artifact-link/start-failure behavior through existing OperationRun UX patterns.
- T045 Mark successful generation completed/succeeded with safe results metadata.
- T046 Mark renderer/storage/source blocked cases completed/failed or completed/blocked with safe reason codes according to existing OperationRun outcome semantics.
- T047 Do not write
context.reconciliationunless an actual reconciliation adapter runs. - T048 Record generation audit with actor, workspace, tenant scope, managed environment, source review, source pack, stored artifact/report id, operation run id, profile, format, generated at, and safe metadata.
- T049 Record download audit with actor, workspace, tenant scope, managed environment, artifact/report id, source review/pack, profile, format, downloaded at, and safe request metadata if available.
- T050 Confirm audit metadata excludes secrets, signed URLs, raw provider payloads, raw operation context, stack traces, and SQL errors.
Phase 6: UI Action And Download Route
Purpose: Expose one clear, safe generation/download flow.
- T051 Add the
Generate management PDFaction to the selected owner surface usingAction::make(...)->action(...). - T052 Gate the action with server-side authorization, readiness, and scope checks; UI state is not security.
- T053 Implement explicit Filament confirmation for high-impact artifact creation using
->requiresConfirmation()or the repo-approved equivalent before generation starts. - T054 Show disabled/blocked reason when source review/pack is not ready, expired, not current, profile-blocked, disclosure-blocked, unauthorized, or renderer unavailable.
- T055 If a matching ready PDF artifact already exists, prefer a
Download management PDForOpen management PDFaffordance over duplicate generation. - T056 If generation is queued/running, show a single canonical
View operationor equivalent operation link through existing link helpers. - T057 Implement a signed and/or server-authorized PDF download route if existing routes cannot safely represent management PDF format/profile/artifact identity.
- T058 In the download route/controller, re-resolve workspace, tenant scope, managed environment, source review/pack, artifact status, and actor capability before returning file bytes.
- T059 Set safe PDF download filename and headers without exposing internal IDs as the primary label.
- T060 Keep Review Pack ZIP download behavior unchanged.
Phase 7: PDF Rendering
Purpose: Render the management PDF from prepared payload only.
- T061 Implement the PDF renderer through the approved Gotenberg 8 Chromium path via
PdfRenderingGateway/PdfRendererClient. - T062 Render cover, executive summary, governance posture, key decisions, top risks/findings, accepted risks, evidence readiness, scope/limitations, next actions, provenance, and method summary.
- T063 Include generated timestamp, source review/pack metadata, profile, and classification/confidentiality marker.
- T064 Include header/footer and page numbering when supported by the approved renderer.
- T065 Avoid remote fonts, external assets, public images, or network-dependent resources.
- T066 Avoid huge raw tables; limit top findings to a management-safe count and route full details to deferred technical/auditor reports.
- T067 Ensure PDF output does not include hidden technical appendix content for
customer_executive. - T068 Ensure Gotenberg renderer errors produce safe exceptions/results that can be mapped to OperationRun failed/blocked.
Phase 8: Localization
Purpose: Make the report labels and actions DE/EN-ready through existing seams.
- T069 Add EN localization keys for action labels, notifications, blocked reasons, PDF chapter titles, profile labels, limitation labels, and provenance labels.
- T070 Add DE localization keys for the same user-facing labels.
- T071 Ensure date/time/number formatting uses existing locale-aware conventions where available.
- T072 Add tests for central labels or rendered content in EN and DE where feasible.
Phase 9: UI Coverage And Documentation-In-Feature
Purpose: Satisfy UI-COV without broad docs churn.
- T073 Apply the UI coverage rule: update route inventory for any new signed/authorized PDF route,
ui-099-rendered-review-report.mdfor rendered-report/PDF source or customer-facing report presentation changes,ui-042-review-pack-detail.mdfor Review Pack detail action/download changes,ui-048-stored-report-detail.mdfor StoredReport registry/detail exposure, and the design coverage matrix for material action hierarchy, artifact state, or surface classification changes. - T074 If materially changed, update the relevant UI coverage artifact(s) with screenshot/reference/status.
- T075 If not materially changed, record the checked no-update rationale in the implementation close-out.
- T076 Store browser screenshots/content evidence under
specs/378-management-report-pdf-v1/artifacts/if captured. - T077 Record renderer/package decision in the governance artifacts.
- T092 Record the storage substrate decision in implementation close-out after
StoredReportversus alternate canonical artifact representation is resolved. - T093 Record the OperationRun type decision in implementation close-out after confirming whether
report.management.generateor an existing canonical type is used. - T094 Record the UI coverage decision in implementation close-out after owner surface, download route, and StoredReport exposure are known.
Phase 10: Validation
Purpose: Prove the feature and prevent adjacent report regressions.
- T078 Run
cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec378. - T079 Run
cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec357. - T080 Run
cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec366. - T081 Run focused Review Pack regressions selected from current touched surfaces, including rendered-report/profile/download/resource tests as applicable.
- T082 Run focused Customer Review Workspace regression if the implementation touches customer workspace action/state copy.
- T083 Run focused OperationRun regression if a new operation type or OperationCatalog mapping is added.
- T084 Run
cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec378ManagementReportPdfSmokeTest.php --compactif browser/content smoke was added. - T085 Run PostgreSQL lane if migrations, JSONB indexes, or artifact storage constraints require it.
- T086 Run
cd apps/platform && ./vendor/bin/sail pint --dirty. - T087 Run
git diff --check. - T088 Static scan changed runtime files for Livewire v3 API names (
emit,emitTo,dispatchBrowserEvent) and confirm none were introduced. - T089 Review changed runtime files for Graph/provider calls during render/generation/download and confirm none were introduced.
- T090 Review final implementation diff for new packages, env vars, migrations, queues, scheduler, storage, panel providers, global search, Filament assets, native PDF runtime, customer portal, scheduled delivery, AI, and auditor/technical report scope.
- T091 Complete final close-out with Livewire v4 compliance, provider registration location, global search status, destructive/high-impact action status, asset strategy, tests, and deployment impact.
Non-Goals
- NT001 Do not build a Technical Evidence Report PDF.
- NT002 Do not build an Auditor Evidence Report PDF.
- NT003 Do not build a Report Delivery Center.
- NT004 Do not add scheduled/email/Teams delivery.
- NT005 Do not add public links or a customer portal.
- NT006 Do not add Word/DOCX, PowerPoint, Excel, or raw JSON customer appendix export.
- NT007 Do not add AI-generated summaries or AI review workflow.
- NT008 Do not create a second report taxonomy or generic report engine.
- NT009 Do not change Review Pack ZIP download contract.
- NT010 Do not add a new artifact lifecycle/retention framework.
- NT011 Do not call Microsoft Graph/provider APIs during render, generation, or download.
- NT012 Do not rewrite completed historical specs or remove close-out/validation evidence from related specs.
Dependencies And Ordering
- Phase 1 gates must complete before runtime edits.
- Phase 1A governance is complete, but G008-G013 must complete before management report payload/storage/OperationRun/UI/PDF generation implementation.
- T010 must complete before T023 and T051-T060, but it is not a prerequisite for G008-G013 runtime/gateway work.
- Tests in Phase 2 should be added before or alongside implementation.
- Payload/readiness/disclosure must complete before PDF rendering.
- Artifact storage and OperationRun/audit must complete before exposing download.
- Browser/content smoke runs after the owner surface and download route are usable.
- Validation and close-out run last.
Parallel Opportunities
- T003-T007 can run in parallel during verification.
- T011-T014 can be developed in parallel with T015-T023 after fixtures are agreed.
- T069-T072 can run after visible labels are known.
- T078-T083 can run in parallel once implementation is stable.
Implementation Strategy
- Resolve the renderer/package gate first. Completed decision: Gotenberg 8 Chromium internal service approved with controls.
- Add the Gotenberg runtime service/config and Laravel gateway before report generation work.
- Keep content/payload derived from existing rendered-report truth.
- Prefer narrow StoredReport/canonical artifact extension over new persistence.
- Use OperationRun/audit as generation truth.
- Add the smallest owner-surface action and signed/authorized download path.
- Prove customer-safe content and leakage boundaries with tests and browser/content smoke.
Expected Task Count
- Implementation tasks: 94 plus 13 renderer-governance/runtime-boundary tasks
- Non-goal guardrails: 12
- MVP path: T001-T068 plus validation subset T078, T081, T083 if operation type changed, T084, T086-T091