TenantAtlas/specs/379-management-report-pdf-runtime/plan.md
ahmido dbff2a0a90 feat(report): implement management report pdf runtime (#450)
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
2026-06-15 11:36:29 +00:00

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.yml includes pinned internal gotenberg/gotenberg:8.34.0-chromium.
  • apps/platform/config/tenantpilot.php exposes PDF renderer config.
  • apps/platform/app/Services/Pdf/PdfRenderRequest.php
  • apps/platform/app/Services/Pdf/PdfRenderResult.php
  • apps/platform/app/Services/Pdf/PdfRendererClient.php
  • apps/platform/app/Services/Pdf/PdfRenderingGateway.php
  • apps/platform/tests/Unit/Pdf/Spec378PdfRenderingGatewayTest.php
  • docs/package-governance.md approves Gotenberg with controls.
  • docs/deployment-checklist.md records Dokploy/runtime controls.

Report/profile foundations:

  • apps/platform/app/Http/Controllers/ReviewPackRenderedReportController.php
  • apps/platform/resources/views/review-packs/rendered-report.blade.php
  • apps/platform/app/Support/ReviewPacks/ReportProfileRegistry.php
  • apps/platform/app/Support/ReviewPacks/ReportDisclosurePolicy.php
  • apps/platform/app/Support/ReviewPacks/ReportThemeResolver.php
  • apps/platform/app/Services/ReviewPackService.php
  • apps/platform/app/Jobs/GenerateReviewPackJob.php
  • apps/platform/app/Models/ReviewPack.php
  • apps/platform/app/Models/EnvironmentReview.php
  • apps/platform/app/Models/StoredReport.php

Execution/audit foundations:

  • apps/platform/app/Services/OperationRunService.php
  • apps/platform/app/Support/OperationRunType.php
  • apps/platform/app/Support/OperationCatalog.php
  • apps/platform/app/Support/OperationRunLinks.php
  • apps/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

  1. 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.
  2. 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.
  3. Operation type: Reuse an existing canonical type only if it honestly represents management PDF generation. Otherwise add a narrow report.management.generate type/catalog mapping and tests.
  4. UI coverage: Update route inventory/page reports/design matrix only for material surface changes, or record an explicit checked no-update rationale.
  5. Capabilities: Generation uses Capabilities::ENVIRONMENT_REVIEW_MANAGE on an Environment Review owner surface or Capabilities::REVIEW_PACK_MANAGE on a Review Pack owner surface. Download uses Capabilities::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:
    • ReviewPackResource detail page and/or EnvironmentReviewResource detail page
    • existing rendered report source route
    • optional generated PDF download route/controller
    • StoredReportResource only 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, OperationRunType if 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=Spec379
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec379ManagementReportPdfSmokeTest.php --compact
    • cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec378
    • cd apps/platform && ./vendor/bin/sail pint --dirty
    • git 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-feature for local decisions; follow-up-spec for 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:assets remains 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; StoredReportResource remains non-globally-searchable unless a future spec updates it with safe View/Edit semantics.
  • Destructive/high-impact actions: Generate management PDF is high-impact artifact creation, must use Action::make(...)->action(...), explicit confirmation, server authorization through ENVIRONMENT_REVIEW_MANAGE or REVIEW_PACK_MANAGE according to selected owner surface, readiness gate, audit, and tests. PDF download requires REVIEW_PACK_VIEW.
  • Asset strategy: no new panel/shared assets expected; deploy uses existing filament:assets requirement 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.