Added jobs, controllers, and PDF generation logic for management report runtime as defined in Spec 379. Includes artifact migrations, payload builders, and testing coverage. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #450
22 KiB
Implementation Plan: Spec 379 - Management Report PDF Runtime Validation & Generation Completion
Branch: 379-management-report-pdf-runtime | Date: 2026-06-14 | Spec: specs/379-management-report-pdf-runtime/spec.md
Input: Feature specification from specs/379-management-report-pdf-runtime/spec.md
Summary
Validate the merged Spec 378 Gotenberg/PDF runtime in staging/Dokploy and complete the actual customer-safe Management Report PDF generation flow. The implementation must reuse PdfRenderingGateway / PdfRendererClient, existing Review Pack rendered-report truth, ReportProfileRegistry, ReportDisclosurePolicy, OperationRun, audit, and private storage patterns. It must not rebuild PDF infrastructure or expand into report delivery, auditor reports, billing PDFs, or a generic document engine.
Spec 379 is the sole active implementation package for post-G012 runtime validation and downstream Management Report PDF generation completion. Spec 378's unchecked downstream generation tasks are read-only historical baseline signals and must not be executed as a parallel work queue.
Technical Context
Language/Version: PHP 8.4.15, Laravel 12.52.0
Primary Dependencies: Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, PostgreSQL, approved Gotenberg 8 Chromium internal service from Spec 378
Storage: PostgreSQL plus private Laravel storage for generated PDF artifacts if file output is persisted
Testing: Pest Unit, Feature, Filament/Livewire action tests, Browser/content smoke
Validation Lanes: fast-feedback, confidence, browser, pgsql if schema/indexes are introduced
Target Platform: Laravel Sail locally; Dokploy container deployment for staging/production
Project Type: Laravel monolith under apps/platform
Performance Goals: generation is queue-safe and observable; render/download avoids live provider calls; failed runtime/storage cases fail closed
Constraints: no Graph calls during render/generation/download; only approved PDF gateway; private artifact storage; workspace/managed-environment isolation; confirmation-gated high-impact generation; customer-safe disclosure
Scale/Scope: one on-demand customer_executive Management Report PDF path over one ready current review/report source
Repo Truth Map
Renderer/runtime baseline from Spec 378:
docker-compose.ymlincludes pinned internalgotenberg/gotenberg:8.34.0-chromium.apps/platform/config/tenantpilot.phpexposes PDF renderer config.apps/platform/app/Services/Pdf/PdfRenderRequest.phpapps/platform/app/Services/Pdf/PdfRenderResult.phpapps/platform/app/Services/Pdf/PdfRendererClient.phpapps/platform/app/Services/Pdf/PdfRenderingGateway.phpapps/platform/tests/Unit/Pdf/Spec378PdfRenderingGatewayTest.phpdocs/package-governance.mdapproves Gotenberg with controls.docs/deployment-checklist.mdrecords Dokploy/runtime controls.
Report/profile foundations:
apps/platform/app/Http/Controllers/ReviewPackRenderedReportController.phpapps/platform/resources/views/review-packs/rendered-report.blade.phpapps/platform/app/Support/ReviewPacks/ReportProfileRegistry.phpapps/platform/app/Support/ReviewPacks/ReportDisclosurePolicy.phpapps/platform/app/Support/ReviewPacks/ReportThemeResolver.phpapps/platform/app/Services/ReviewPackService.phpapps/platform/app/Jobs/GenerateReviewPackJob.phpapps/platform/app/Models/ReviewPack.phpapps/platform/app/Models/EnvironmentReview.phpapps/platform/app/Models/StoredReport.php
Execution/audit foundations:
apps/platform/app/Services/OperationRunService.phpapps/platform/app/Support/OperationRunType.phpapps/platform/app/Support/OperationCatalog.phpapps/platform/app/Support/OperationRunLinks.phpapps/platform/app/Support/OpsUx/OperationUxPresenter.php- current audit logger/action ID paths used by Review Pack generation/download flows
Repo-Truth Decisions To Resolve During Implementation
- Owner surface: Prefer Review Pack detail or Environment Review detail. Do not add a new top-level page unless both existing surfaces are proven insufficient.
- Artifact substrate: Prefer a narrow extension of existing report/artifact storage if needed. If a new table/entity is required, stop and update spec/plan before implementation continues.
- Operation type: Reuse an existing canonical type only if it honestly represents management PDF generation. Otherwise add a narrow
report.management.generatetype/catalog mapping and tests. - UI coverage: Update route inventory/page reports/design matrix only for material surface changes, or record an explicit checked no-update rationale.
- Capabilities: Generation uses
Capabilities::ENVIRONMENT_REVIEW_MANAGEon an Environment Review owner surface orCapabilities::REVIEW_PACK_MANAGEon a Review Pack owner surface. Download usesCapabilities::REVIEW_PACK_VIEW. Any new capability requires spec/plan update and canonical registry tests.
UI / Surface Guardrail Plan
- Guardrail scope: changed existing report/review artifact owner surface plus possible new signed/server-authorized PDF download route.
- Affected routes/pages/actions/states/navigation/panel/provider surfaces:
ReviewPackResourcedetail page and/orEnvironmentReviewResourcedetail page- existing rendered report source route
- optional generated PDF download route/controller
StoredReportResourceonly if generated PDFs are listed/viewed there
- No-impact class, if applicable: N/A.
- Native vs custom classification summary: owner actions stay native Filament; PDF content inherits the bounded custom report artifact exception from Spec 366; artifact registry remains native if used.
- Shared-family relevance: report viewer, artifact download, status/readiness messaging, OperationRun UX, audit.
- State layers in scope: owner action state, modal confirmation, artifact state, OperationRun status/outcome, signed/download route, private storage.
- Audience modes in scope: customer-read-only PDF content; operator-MSP generation/download; support-platform diagnostics only through existing OperationRun/log surfaces.
- Decision/diagnostic/raw hierarchy plan: PDF is decision-first; OperationRun/logs carry diagnostics; raw/support evidence is absent from customer PDF.
- Raw/support gating plan: raw JSON, provider payloads, signed URLs, secrets, stack traces, SQL errors, and internal MSP/support fields are forbidden in PDF and audit metadata.
- One-primary-action / duplicate-truth control: owner surface shows one state-dependent action: generate, view operation, or download existing PDF.
- Handling modes by drift class or surface: hard-stop for renderer duplication, public artifact storage, raw leakage, wrong-scope download, or unvalidated runtime enablement.
- Repository-signal treatment: update UI coverage artifacts only when material; otherwise record no-update rationale in close-out.
- Special surface test profiles: report-viewer plus high-impact artifact-generation action.
- Required tests or manual smoke: Unit payload/readiness/disclosure; Feature authorization/storage/audit/run/download; Filament action state; Browser/content smoke.
- Exception path and spread control: any custom report/PDF rendering view remains bounded to management report output and consumes existing profile/disclosure truth.
- Active feature PR close-out entry: Guardrail + Smoke Coverage + Runtime Validation.
- UI/Productization coverage decision: reachable UI surfaces change.
- Coverage artifacts to update: route inventory for new route, UI-099 for report/PDF content change, UI-042 for Review Pack action/download changes, UI-048 for StoredReport exposure, design coverage matrix when action/artifact state materially changes.
- No-impact rationale: N/A.
- Navigation / Filament provider-panel handling: no navigation or panel-provider change planned. Laravel 12 panel providers remain in
apps/platform/bootstrap/providers.php. - Screenshot or page-report need: yes for bounded browser/content smoke if UI route/action/content changes are implemented.
Shared Pattern & System Fit
- Cross-cutting feature marker: yes.
- Systems touched: PDF gateway, Review Pack rendered report, report profile/disclosure policy, artifact storage, OperationRun, audit, localization, Filament owner actions.
- Shared abstractions reused:
PdfRenderingGateway,ReportProfileRegistry,ReportDisclosurePolicy,ReportThemeResolver,ReviewPackService,OperationRunService,OperationRunLinks,OperationUxPresenter, audit logger/action ID patterns. - New abstraction introduced? why?: one bounded generation service/payload builder/renderer adapter is allowed because PDF generation must be testable and must not live in Blade/controller code.
- Why the existing abstraction was sufficient or insufficient: existing abstractions provide renderer and report truth; they do not own generated artifact identity, OperationRun generation lifecycle, or download audit.
- Bounded deviation / spread control: implementation stays in existing report/review-pack/pdf namespaces; no generic document framework.
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: yes.
- Central contract reused:
OperationRunService,OperationRunLinks,OperationUxPresenter,OperationCatalog,OperationRunTypeif needed. - Delegated UX behaviors: queued toast,
View operation, artifact link, run-enqueued browser event, blocked/start-failure messaging, tenant/workspace-safe URL resolution. - Surface-owned behavior kept local: source readiness explanation, selected profile, and blocked reason.
- Queued DB-notification policy: no running DB notifications; queued DB notification only if already supported and explicitly opted in.
- Terminal notification path: central lifecycle mechanism.
- Exception path: none. Synchronous no-run generation is out of scope for Spec 379 and requires a future spec before implementation.
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: yes, only through existing stored report/evidence/review content.
- Provider-owned seams: existing Microsoft/provider labels inside allowed report summaries.
- Platform-core seams: artifact identity, profile, evidence basis, limitation, operation type, source review/pack provenance.
- Neutral platform terms / contracts preserved: management report, profile, evidence basis, limitation, managed environment, generated artifact, operation.
- Retained provider-specific semantics and why: existing profile-safe summaries only.
- Bounded extraction or follow-up path: Technical/Auditor report if deeper provider appendix is needed.
Constitution Check
GATE: Must pass before implementation. Re-check after runtime decisions and before code merge.
- Inventory-first: PASS. PDF consumes existing stored review/report truth, not live provider state.
- Read/write separation: PASS with controls. Generation is explicit TenantPilot artifact creation with confirmation, audit, and tests.
- Graph contract path: PASS. No Graph calls during render/generation/download.
- Deterministic capabilities: REQUIRED. Reuse capability registry or add tested capability only if necessary.
- RBAC-UX: REQUIRED. Non-member/wrong scope 404; scoped member missing capability 403; server-side authorization always.
- Workspace isolation: REQUIRED. Artifact, source, run, and download resolve workspace/environment scope.
- Destructive/high-impact actions: REQUIRED. Generate PDF is high-impact artifact creation and requires confirmation.
- Global search: PASS. No global-search enablement planned; if StoredReport is touched, keep disabled unless updated by spec.
- Run observability: REQUIRED. Queued/observable generation through OperationRun is mandatory.
- OperationRun start UX: REQUIRED. Central start/link/notification paths only.
- Ops-UX lifecycle: REQUIRED. Status/outcome transitions through
OperationRunService. - Data minimization: REQUIRED. No secrets/raw payloads/signed URLs in PDF or audit metadata.
- Test governance: REQUIRED. Unit/Feature/Filament/Browser lanes explicit.
- Proportionality: PASS with controls. Durable PDF artifact truth solves current report handoff gap.
- No premature abstraction: PASS with controls. Bounded generation components only.
- Persisted truth: PASS if generated artifact metadata is durable and source-bound.
- Behavioral state: PASS only for state/reason values that change generation/download behavior.
- UI semantics: PASS. Directly map existing profile/readiness/disclosure truth.
- Shared pattern first: PASS. Existing renderer/report/operation/audit paths first.
- Provider boundary: PASS. Stored summaries only; no provider runtime calls.
- UI-COV-001: REQUIRED. Coverage update or explicit no-update rationale required.
Test Governance Check
- Test purpose / classification by changed surface:
- Unit: runtime validation decision mapping, payload/readiness/disclosure, renderer adapter failure mapping.
- Feature: generation, private artifact storage, authorization, OperationRun, audit, download.
- Filament/Livewire: owner-surface action visible/disabled/confirmed/queued state.
- Browser/content smoke: generated/downloaded PDF content and leakage boundaries.
- Affected validation lanes: fast-feedback, confidence, browser, pgsql if schema/indexes are introduced.
- Why this lane mix is the narrowest sufficient proof: each lane proves one trust boundary and avoids broad surface discovery.
- Narrowest proving commands:
cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec379cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec379ManagementReportPdfSmokeTest.php --compactcd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec378cd apps/platform && ./vendor/bin/sail pint --dirtygit diff --check
- Fixture / helper / factory / seed / context cost risks: add explicit Spec379 fixtures only; do not widen global report fixtures.
- Expensive defaults or shared helper growth introduced?: no; browser smoke is explicit and feature-local.
- Heavy-family additions, promotions, or visibility changes: one explicit browser/content smoke.
- Surface-class relief / special coverage rule: high-impact artifact action and report-viewer.
- Closing validation and reviewer handoff: verify no duplicate renderer, no public artifact storage, no raw leakage, no wrong-scope download, no unvalidated runtime enablement.
- Budget / baseline / trend follow-up: record browser smoke runtime if materially slow.
- Review-stop questions: lane fit, fixture cost, runtime validation proof, artifact substrate proportionality, OperationRun truth.
- Escalation path:
document-in-featurefor local decisions;follow-up-specfor delivery center, retention/lifecycle framework, technical/auditor PDF, billing PDF. - Active feature PR close-out entry: Guardrail + Runtime Validation + Smoke Coverage.
- Why no dedicated follow-up spec is needed: v1 generation is the direct follow-through over Spec 378; broader delivery/lifecycle/report families stay deferred.
Project Structure
Documentation (this feature)
specs/379-management-report-pdf-runtime/
├── spec.md
├── plan.md
├── tasks.md
├── checklists/
│ └── requirements.md
└── artifacts/
├── runtime-validation.md # created during implementation
├── storage-operationrun-decision.md # created during implementation
└── screenshots/ # created during browser/content smoke if captured
Source Code (likely affected, implementation only)
apps/platform/app/Services/Pdf/
apps/platform/app/Support/ReviewPacks/
apps/platform/app/Services/ReviewPackService.php
apps/platform/app/Jobs/
apps/platform/app/Models/StoredReport.php
apps/platform/app/Filament/Resources/ReviewPackResource/
apps/platform/app/Filament/Resources/EnvironmentReviewResource/
apps/platform/app/Http/Controllers/
apps/platform/routes/
apps/platform/database/migrations/
apps/platform/tests/Unit/
apps/platform/tests/Feature/
apps/platform/tests/Browser/
apps/platform/resources/lang/
Structure Decision: Use the existing Laravel/Filament monolith. Add only feature-local report/PDF generation pieces under current report/PDF namespaces. Do not add new base folders or dependencies.
Implementation Phases
Phase 0 - Repo Verification And Runtime Gate
Re-read Spec 378 artifacts and current PDF runtime files. Validate staging/Dokploy runtime controls and record results in specs/379-management-report-pdf-runtime/artifacts/runtime-validation.md. If validation fails, block report generation and implement only safe disabled/blocked behavior.
Phase 1 - Tests First
Add failing Unit, Feature, Filament/Livewire, and Browser/content smoke coverage for payload, readiness, authorization, generation, OperationRun, audit, download, and leakage boundaries.
Phase 2 - Payload And Disclosure
Build a deterministic customer-executive management report payload from existing Review Pack/rendered-report/profile/disclosure truth. No Graph calls, no Blade queries, no duplicated renderer infrastructure.
Phase 3 - Artifact Storage And Idempotency
Choose the smallest artifact substrate. Prefer narrow existing substrate extension if needed; stop for spec/plan update if a new entity/table is required. Store PDFs privately and protect against partial-ready artifacts.
Phase 4 - OperationRun And Audit
Queue and track generation through OperationRun, map success/blocked/failed outcomes safely, and record generation/download audit metadata without secrets or raw payloads.
Phase 5 - Owner Action And Download Route
Add one confirmed high-impact owner-surface action, disabled/blocked reasons, canonical operation link, existing-artifact download state, and a signed/server-authorized route if needed.
Phase 6 - PDF Rendering And Localization
Render through PdfRenderingGateway, include required management chapters and provenance, use private/local assets only, and add EN/DE labels for action, blocked reasons, chapters, limitations, and provenance where needed.
Phase 7 - Coverage And Validation
Run focused tests, browser/content smoke, Spec378 regression, Pint dirty, git diff --check, and record deployment impact, UI coverage decision, and final no-duplication scan.
Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
| Durable generated artifact metadata | The PDF must be downloadable, auditable, and source-bound after generation | Browser print cannot provide artifact truth, authorization, or audit |
| Bounded generation service/payload builder | Generation needs tests, readiness, storage, audit, and OperationRun boundaries | Controller/Blade code would duplicate truth and hide failures |
| Possible operation type mapping | Management PDF generation is an operator-visible queued artifact operation | Reusing an unrelated type would mislabel monitoring/audit truth |
Proportionality Review
- Current operator problem: no real customer-ready Management Report PDF despite approved renderer infrastructure.
- Existing structure is insufficient because: Spec 378 gateway renders bytes but does not manage report payload, artifact identity, generation lifecycle, authorization, or audit.
- Narrowest correct implementation: validate runtime and implement one customer-executive generation/download path over existing review/report truth.
- Ownership cost created: tests, possible schema extension, operation/audit mapping, deployment validation artifact, one browser smoke.
- Alternative intentionally rejected: second renderer, generic document/report engine, public links, delivery center, technical/auditor report, billing PDF.
- Release truth: current-release follow-through over merged Spec 378.
Rollout And Deployment Considerations
- Environment variables: use existing Spec 378 PDF renderer env/config. Add only if implementation finds a missing bounded runtime switch.
- Migrations: possible only for narrow artifact metadata/storage fields; PostgreSQL lane required if added.
- Queues/workers: queued generation requires Dokploy workers and queue visibility.
- Storage: private persistent disk/object storage required for PDF artifacts.
- Scheduler: none expected.
- Filament assets: no new Filament assets expected;
filament:assetsremains part of deploy only if assets are registered. - Staging gate: staging/Dokploy runtime validation is mandatory before production promotion.
Filament v5 / Livewire v4 Output Contract
- Livewire v4.0+ compliance: target app uses Livewire 4.1.4; no Livewire v3 APIs are planned.
- Provider registration: no panel provider change planned; Laravel 12 panel providers remain in
apps/platform/bootstrap/providers.php. - Global search: no globally searchable resource is introduced;
StoredReportResourceremains non-globally-searchable unless a future spec updates it with safe View/Edit semantics. - Destructive/high-impact actions:
Generate management PDFis high-impact artifact creation, must useAction::make(...)->action(...), explicit confirmation, server authorization throughENVIRONMENT_REVIEW_MANAGEorREVIEW_PACK_MANAGEaccording to selected owner surface, readiness gate, audit, and tests. PDF download requiresREVIEW_PACK_VIEW. - Asset strategy: no new panel/shared assets expected; deploy uses existing
filament:assetsrequirement only if assets are registered. - Testing plan: Feature/Filament action tests cover owner action, authorization, OperationRun, audit, and download; Browser/content smoke covers customer-facing PDF.