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
435 lines
34 KiB
Markdown
435 lines
34 KiB
Markdown
# Implementation Plan: Spec 378 - Management Report PDF v1
|
|
|
|
**Branch**: `378-management-report-pdf-v1` | **Date**: 2026-06-14 | **Spec**: `specs/378-management-report-pdf-v1/spec.md`
|
|
**Input**: Feature specification from `specs/378-management-report-pdf-v1/spec.md`
|
|
|
|
## Summary
|
|
|
|
Implement the first durable customer-executive management PDF artifact over the existing Review Pack rendered-report family. The PDF must reuse the current `ReviewPackRenderedReportController` content/profile/disclosure truth where possible, produce a stored or canonically referenced private artifact, expose an authorized download path, and record OperationRun plus audit evidence for generation and download.
|
|
|
|
This is not a new report engine. It is the smallest PDF artifact productization slice after Specs 356, 357, and 366.
|
|
|
|
## 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 PDF rendering service (Sail/local service and Laravel gateway configured; staging/Dokploy controls pending), existing Playwright dev/browser tooling only
|
|
**Storage**: PostgreSQL plus private Laravel storage disk for generated PDF artifacts if stored file output is implemented
|
|
**Testing**: Pest Unit, Feature/Filament action, and Browser/content smoke
|
|
**Validation Lanes**: fast-feedback, confidence, browser; PostgreSQL lane if migrations/indexes are introduced
|
|
**Target Platform**: Laravel Sail locally, Dokploy container deployment for staging/production
|
|
**Project Type**: Laravel monolith under `apps/platform`
|
|
**Performance Goals**: PDF generation is queue-safe and idempotent; report render/download stays DB/storage-only with no live provider calls
|
|
**Constraints**: no Graph calls during render/generation/download; Gotenberg 8 Chromium only through a Laravel gateway/client; no direct browser runtime in Laravel app/queue containers; no new runtime package without package governance; workspace/managed-environment isolation; profile/disclosure fail-closed; private artifact storage; no raw technical leakage
|
|
**Scale/Scope**: one customer-executive PDF profile, one current ready Review Pack source, one artifact output path, focused report/audit/OperationRun tests
|
|
|
|
## Repo Truth Map
|
|
|
|
Current runtime/report foundations:
|
|
|
|
- `apps/platform/app/Http/Controllers/ReviewPackRenderedReportController.php` builds the existing rendered report state.
|
|
- `apps/platform/resources/views/review-packs/rendered-report.blade.php` renders the management-style HTML/print report.
|
|
- `apps/platform/app/Support/ReviewPacks/ReportProfileRegistry.php` defines `customer_executive`, technical, internal, auditor, and framework profiles.
|
|
- `apps/platform/app/Support/ReviewPacks/ReportDisclosurePolicy.php` evaluates mandatory disclosures and appendix/technical visibility.
|
|
- `apps/platform/app/Support/ReviewPacks/ReportThemeResolver.php` exists from Spec 366 for management layout/theme derivation.
|
|
- `apps/platform/app/Services/ReviewPackService.php` generates Review Packs, signed ZIP/download URLs, and signed rendered-report URLs.
|
|
- `apps/platform/app/Http/Controllers/ReviewPackDownloadController.php` owns current signed ZIP download access/audit.
|
|
- `apps/platform/app/Models/StoredReport.php` and `StoredReportResource` provide a narrow report substrate for permission posture and Entra admin roles.
|
|
- `apps/platform/app/Services/OperationRunService.php`, `OperationRunType`, `OperationCatalog`, and Operations UI/actionability specs provide run truth.
|
|
- `docs/ui-ux-enterprise-audit/page-reports/ui-099-rendered-review-report.md`, `ui-042-review-pack-detail.md`, and `ui-048-stored-report-detail.md` are the relevant UI coverage references.
|
|
|
|
Repo-truth constraints:
|
|
|
|
- No native PDF runtime dependency is present in `apps/platform/composer.json`.
|
|
- `apps/platform/package.json` includes Playwright for dev/browser tooling, not an approved production PDF runtime.
|
|
- Gotenberg 8 Chromium is approved with controls as an internal Docker PDF rendering service. Root `docker-compose.yml`, Laravel app config, and `PdfRenderingGateway` / `PdfRendererClient` now exist for Sail/local; no Dokploy config file exists in the repo, so `docs/deployment-checklist.md` records the required staging/production controls.
|
|
- Existing `StoredReport` has no file path, format, generated-by, status, source review, source review pack, or operation-run columns today.
|
|
- Existing Review Pack ZIP contract must remain unchanged.
|
|
|
|
## Renderer Governance Gate Result
|
|
|
|
- **Gate result**: approved with controls.
|
|
- **Selected renderer**: Gotenberg 8 Chromium internal service.
|
|
- **Decision matrix**: `specs/378-management-report-pdf-v1/artifacts/spec378-pdf-renderer-decision-matrix.md`.
|
|
- **Security controls**: `specs/378-management-report-pdf-v1/artifacts/spec378-gotenberg-security-controls.md`.
|
|
- **Constitution review**: `specs/378-management-report-pdf-v1/artifacts/spec378-constitution-renderer-gate-review.md`.
|
|
- **Package governance**: `docs/package-governance.md` records the approved runtime service scope and controls.
|
|
- **Runtime status**: Sail/local renderer service, Laravel config, health check, timeout/size controls, and gateway/client safe result mapping are implemented. Staging/Dokploy runtime validation remains pending before management report PDF generation is enabled.
|
|
- **Approved service boundary**: Laravel must call Gotenberg through `PdfRenderingGateway` / `PdfRendererClient`; production PDF rendering must not install or execute Chromium, Chrome, Puppeteer, Playwright, Node, or browser binaries in Laravel app/queue containers.
|
|
- **Invoice / billing boundary**: this approval is not approval for legal invoice generation, German B2B e-invoicing, XRechnung, ZUGFeRD/Factur-X, GoBD archival, tax calculation, invoice numbering, or billing compliance.
|
|
|
|
## PDF Rendering Layer Responsibilities
|
|
|
|
- `PdfRendererClient`: low-level HTTP transport to the internal Gotenberg service. It owns multipart request assembly, timeout handling, HTTP status mapping, response byte validation, configured body/output size limits, and correlation id headers.
|
|
- `PdfRenderingGateway`: shared application boundary for server-generated HTML-to-PDF rendering. It accepts sanitized HTML/assets/render options and returns typed success/failure results suitable for OperationRun and audit mapping. It does not know management-report domain rules.
|
|
- `ManagementReportPdfRenderer`: Spec 378 domain adapter. It converts a prepared management report payload into sanitized HTML/assets, calls `PdfRenderingGateway`, and maps returned renderer outcomes into management-report generation flow. It does not own HTTP transport, storage persistence, OperationRun lifecycle, or billing/invoice semantics.
|
|
|
|
## SaaS Invoice / Billing Boundary
|
|
|
|
The shared renderer is infrastructure only. Domain truth remains separate:
|
|
|
|
- PDF Rendering Infrastructure: shared.
|
|
- Report Domain: separate.
|
|
- Billing / Invoice Domain: separate.
|
|
- E-Invoice XML Compliance: separate.
|
|
|
|
Target separation:
|
|
|
|
```text
|
|
Shared PDF Rendering Infrastructure
|
|
-> Gotenberg / Chromium Renderer
|
|
-> PdfRenderingGateway
|
|
-> Storage
|
|
-> Audit
|
|
-> OperationRun
|
|
|
|
Domain-specific generators
|
|
-> ManagementReportGenerator
|
|
-> EvidenceReportGenerator
|
|
-> InvoiceDocumentGenerator
|
|
-> CreditNoteDocumentGenerator
|
|
```
|
|
|
|
Identity boundaries:
|
|
|
|
- `StoredReport` is not `BillingDocument`.
|
|
- `Report ID` is not `Invoice Number`.
|
|
- `OperationRun ID` is not `Invoice Number`.
|
|
- `StoredReport ID` is not `Invoice Number`.
|
|
|
|
Future billing specs must separately define `BillingDocument`, `InvoiceNumberAllocator`, `InvoiceTaxCalculator`, `EInvoiceXmlBuilder`, `ZugferdFacturXBuilder`, `XRechnungBuilder`, `InvoicePdfRenderer via PdfRenderingGateway`, `BillingDocumentArchive`, and `BillingAuditTrail`.
|
|
|
|
## Candidate Selection Gate
|
|
|
|
- **Selected candidate**: Spec 378 - Management Report PDF v1.
|
|
- **Source**: Direct user-provided Spec 378 draft.
|
|
- **Why selected**: It is the natural bounded follow-up after Specs 356/357/366 made the rendered report, profile/disclosure policy, and management layout repo-real.
|
|
- **Deferred alternatives**: Technical/Auditor Evidence Report, Delivery Center, scheduled delivery, Customer Review Workspace polish, compliance-framework reports, AI summaries.
|
|
- **Completed-spec guardrail**: Specs 356, 357, 365, 366, 367, 372, and 377 are context only. They contain completed task markers, validation, close-out, or browser evidence and must not be rewritten.
|
|
- **Result**: PASS.
|
|
|
|
## UI / Surface Guardrail Plan
|
|
|
|
- **Guardrail scope**: changed existing report/review artifact surfaces plus one possible new signed/authorized PDF download route.
|
|
- **Affected routes/pages/actions/states/navigation/panel/provider surfaces**:
|
|
- `ReviewPackRenderedReportController`
|
|
- rendered-report Blade template only if PDF payload generation requires shared partial/content extraction
|
|
- `EnvironmentReviewResource` and/or `ReviewPackResource` detail/header actions
|
|
- `StoredReportResource` only if generated management PDF artifacts appear there
|
|
- optional new management PDF download route
|
|
- **No-impact class, if applicable**: N/A.
|
|
- **Native vs custom classification summary**: owner surfaces remain native Filament actions; report canvas inherits Spec 366's legitimate custom report/print surface; stored report remains native Filament read-only registry.
|
|
- **Shared-family relevance**: report viewer, artifact download, status/readiness messaging, OperationRun start/link UX, audit.
|
|
- **State layers in scope**: detail header action state, source report payload, PDF artifact state, signed/download URL, OperationRun status/outcome, stored report/artifact lifecycle.
|
|
- **Audience modes in scope**: customer/read-only for PDF content; operator-MSP for generation/download/action state; support-platform only through existing OperationRun/log diagnostics.
|
|
- **Decision/diagnostic/raw hierarchy plan**: decision-first PDF; diagnostics only in OperationRun/logs; raw/support payload absent from PDF.
|
|
- **Raw/support gating plan**: no raw JSON/provider payload/support context in customer-executive PDF. Any failure detail remains safe summary in UI and deeper diagnostics in logs/OperationRun.
|
|
- **One-primary-action / duplicate-truth control**: source detail surfaces expose at most one dominant next step: generate if no current PDF and ready, download/open if generated, view operation if running/failed. The generate action must require explicit Filament confirmation before artifact creation starts.
|
|
- **Handling modes by drift class or surface**: hard-stop-candidate for raw leakage, unauthorized artifact access, unapproved PDF runtime package, second report engine, or historical/expired pack impersonation.
|
|
- **Repository-signal treatment**: update UI-099/UI-042/UI-048 only if action hierarchy or artifact presentation materially changes; otherwise record a no-update rationale in close-out.
|
|
- **Special surface test profiles**: report-viewer, high-impact artifact generation action, customer-facing artifact.
|
|
- **Required tests or manual smoke**: Unit payload/disclosure/readiness; Feature authorization/artifact/audit/run/download; Browser/content smoke for generate/download/PDF text.
|
|
- **Exception path and spread control**: custom PDF/report layout remains bounded to the existing rendered-report family. No generic report framework.
|
|
- **Active feature PR close-out entry**: Guardrail + Smoke Coverage.
|
|
- **UI/Productization coverage decision**: reachable report/action surfaces change; implementation must update or explicitly close out coverage docs.
|
|
- **Coverage artifacts to update**: update route inventory when a new signed/authorized PDF route is added; update `ui-099-rendered-review-report.md` when rendered-report/PDF source content or customer-facing report presentation materially changes; update `ui-042-review-pack-detail.md` when Review Pack detail owns the action/download state; update `ui-048-stored-report-detail.md` when StoredReport registry/detail exposes the artifact; update design coverage matrix when action hierarchy, artifact state, or customer-facing surface classification materially changes.
|
|
- **No-impact rationale**: N/A.
|
|
- **Navigation / Filament provider-panel handling**: no navigation or panel provider change planned. Laravel 12 Filament provider registration remains in `apps/platform/bootstrap/providers.php`.
|
|
- **Screenshot or page-report need**: yes, one bounded browser/content smoke with artifact evidence where local tooling permits it.
|
|
|
|
## Shared Pattern & System Fit
|
|
|
|
- **Cross-cutting feature marker**: yes.
|
|
- **Systems touched**: Review Pack rendered report, report profiles, disclosure policy, Review Pack service, stored report/artifact storage, OperationRun, audit, localization, Filament owner-surface actions.
|
|
- **Shared abstractions reused**:
|
|
- `ReportProfileRegistry`
|
|
- `ReportDisclosurePolicy`
|
|
- `ReportThemeResolver`
|
|
- `ReviewPackOutputReadiness`
|
|
- `ReviewPackOutputResolutionGuidance`
|
|
- `ReviewPackService`
|
|
- current signed route/download patterns
|
|
- `OperationRunService`
|
|
- current audit logger/action ID pattern
|
|
- **New abstraction introduced? why?**: likely one bounded generation service and one renderer adapter. This is justified because PDF generation must not live in Blade/controller code and must isolate rendering/storage failures.
|
|
- **Why the existing abstraction was sufficient or insufficient**: Existing abstractions are sufficient for HTML report content, profile/disclosure, source current-pack validation, and signed URL generation. They are insufficient for private PDF artifact storage, generation idempotency, OperationRun result metadata, and download audit.
|
|
- **Bounded deviation / spread control**: new code must live under existing report/review-pack/support namespaces and target only management PDF v1. No profile CRUD, delivery system, report engine, or artifact lifecycle framework.
|
|
|
|
## OperationRun UX Impact
|
|
|
|
- **Touches OperationRun start/completion/link UX?**: yes.
|
|
- **Central contract reused**: `OperationRunService`, `OperationRunLinks`, `OperationUxPresenter`, `OperationCatalog`, `OperationRunType` if a new type is needed.
|
|
- **Delegated UX behaviors**: queued toast/run link/artifact link/run-enqueued browser event/dedupe-or-blocked/start-failure messaging should use the shared OperationRun start UX path.
|
|
- **Surface-owned behavior kept local**: generation readiness explanation and source review/pack selection only.
|
|
- **Queued DB-notification policy**: no queued/running DB notification unless explicitly approved through the existing shared start UX contract.
|
|
- **Terminal notification path**: central lifecycle mechanism.
|
|
- **Exception path**: none expected. If implementation proposes synchronous no-run PDF generation, update spec/plan first and prove why OperationRun is unnecessary.
|
|
|
|
## Provider Boundary & Portability Fit
|
|
|
|
- **Shared provider/platform boundary touched?**: yes, indirectly through report/evidence content.
|
|
- **Provider-owned seams**: existing review/evidence summaries that may include Microsoft-specific evidence labels.
|
|
- **Platform-core seams**: report artifact identity, profile, disclosure, provenance, OperationRun type, StoredReport/source descriptor.
|
|
- **Neutral platform terms / contracts preserved**: management report, profile, evidence readiness, limitation, managed environment, workspace, generated artifact, source review, source pack, operation.
|
|
- **Retained provider-specific semantics and why**: only existing profile-safe evidence/finding summaries from stored review/pack truth. No new provider lookup or provider-specific renderer branch.
|
|
- **Bounded extraction or follow-up path**: Technical/Auditor Evidence Report follow-up if provider-specific detailed appendix becomes necessary.
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Must pass before implementation. Re-check after design and before code merge.*
|
|
|
|
- Inventory-first: PASS. Report consumes existing released review/Review Pack/evidence truth, not live provider state.
|
|
- Read/write separation: PASS. PDF generation mutates TenantPilot artifact storage only and requires explicit operator action, audit, and tests.
|
|
- Graph contract path: PASS. No Graph calls are allowed during render, generation, or download.
|
|
- Deterministic capabilities: PASS with task. Reuse existing capability registry paths or add a tested capability only after repo verification.
|
|
- RBAC-UX: REQUIRED. Non-member/wrong scope 404; member missing capability 403; server-side authorization required.
|
|
- Workspace isolation: REQUIRED. Artifact, source review, source pack, operation, and download all resolve workspace/environment scope.
|
|
- Destructive-like/high-impact action: REQUIRED. Generate PDF is high-impact artifact creation; it needs readiness gate, authorization, audit, and safe feedback. It is not destructive.
|
|
- Global search: PASS. No global-search enablement planned; `StoredReportResource` remains non-globally-searchable unless spec/plan are updated.
|
|
- Run observability: REQUIRED. Preferred path creates/reuses an OperationRun for generation.
|
|
- OperationRun start UX: REQUIRED if queued generation is used; central UX path only.
|
|
- Ops-UX lifecycle: REQUIRED. Status/outcome transitions through `OperationRunService`; summary counts flat numeric-only if used.
|
|
- Data minimization: REQUIRED. No secrets/raw provider payloads/signed URLs in PDF/audit metadata.
|
|
- Test governance: REQUIRED. Unit/Feature/Browser lanes and fixture costs explicit.
|
|
- Proportionality: PASS with constraint. Generated PDF artifact truth and renderer/generation service solve current customer artifact gap.
|
|
- No premature abstraction: PASS with constraint. Generation/renderer/payload components are bounded to one report family and must not become a generic framework.
|
|
- Persisted truth: PASS. Generated PDF is durable artifact truth with provenance.
|
|
- Behavioral state: PASS if new status/reason keys change artifact visibility, OperationRun outcome, or download behavior.
|
|
- UI semantics: PASS. Directly map existing profile/readiness/disclosure into the PDF; no new taxonomy.
|
|
- Shared pattern first: PASS. Reuse report/profile/disclosure/OperationRun/audit paths first.
|
|
- Provider boundary: PASS. Stored summaries only; no provider runtime calls.
|
|
- V1 explicitness / few layers: PASS. One profile, one artifact, one source family.
|
|
- BLOAT-001: REQUIRED and covered in `spec.md`.
|
|
- Badge/Filament-native UI: PASS. Owner surfaces stay native Filament. Custom report canvas remains bounded to report/print artifact.
|
|
- UI-COV-001: REQUIRED. Coverage update/no-update rationale required.
|
|
|
|
## Test Governance Check
|
|
|
|
- **Test purpose / classification by changed surface**:
|
|
- Unit: payload/readiness/disclosure/profile filtering and renderer adapter failure mapping.
|
|
- Feature: generation action, authorization, artifact storage, OperationRun outcomes, audit metadata, signed download, cross-scope denial.
|
|
- Filament/Livewire: owner-surface action visibility/disabled state where generation action lands.
|
|
- Browser/content smoke: generate/download path and PDF/text content proof.
|
|
- **Affected validation lanes**: fast-feedback, confidence, browser; pgsql if schema/index changes.
|
|
- **Why this lane mix is the narrowest sufficient proof**: Unit tests prove deterministic content and safety decisions; Feature tests prove server-side trust; Browser/content smoke proves the customer-facing artifact is usable and leakage-free.
|
|
- **Narrowest proving command(s)**:
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec378`
|
|
- `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec378ManagementReportPdfSmokeTest.php --compact`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec357`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec366`
|
|
- `cd apps/platform && ./vendor/bin/sail pint --dirty`
|
|
- `git diff --check`
|
|
- **Fixture / helper / factory / seed / context cost risks**: Reuse Spec357/Spec366 report fixtures and review-output seed command. Any new PDF fixture helpers must remain local to Spec378 unless reused by at least three current specs.
|
|
- **Expensive defaults or shared helper growth introduced?**: no by default.
|
|
- **Heavy-family additions, promotions, or visibility changes**: one explicit browser/content smoke only.
|
|
- **Surface-class relief / special coverage rule**: customer-facing document artifact requires special content/leakage smoke.
|
|
- **Closing validation and reviewer handoff**: reviewers verify package governance gate, no raw leakage, artifact/operation/audit agreement, scope-safe download, and no report-center/auditor scope.
|
|
- **Budget / baseline / trend follow-up**: record follow-up if PDF rendering adds material runtime to browser/confidence lanes or production queue requirements.
|
|
- **Review-stop questions**: renderer approved? artifact storage private? no raw leakage? no second report engine? OperationRun/audit consistent? correct 404/403?
|
|
- **Escalation path**: document-in-feature for approved renderer choice; follow-up-spec for delivery center, technical/auditor PDF, scheduled delivery, artifact lifecycle.
|
|
- **Active feature PR close-out entry**: Guardrail + Smoke Coverage.
|
|
- **Why no dedicated follow-up spec is needed**: The renderer/artifact choice belongs inside Spec 378 if it stays bounded; any broader delivery/auditor lifecycle work is explicitly deferred.
|
|
|
|
## Implementation Approach
|
|
|
|
### Phase 0 - Pre-Implementation Verification
|
|
|
|
1. Re-read current report/runtime files listed in the Repo Truth Map.
|
|
2. Renderer/package governance decision is complete: use Gotenberg 8 Chromium as an internal service with the controls in `artifacts/spec378-gotenberg-security-controls.md`.
|
|
3. Confirm the runtime config task has added the pinned Gotenberg service and app config before any report generation implementation starts.
|
|
4. Verify whether `StoredReport` can be extended narrowly to reference PDF artifacts.
|
|
5. Verify whether generation should land on Environment Review, Review Pack, or Customer Review Workspace first. Preferred v1 placement: Environment Review or Review Pack detail, because both already know source review/pack readiness.
|
|
|
|
### Phase 0.5 - PDF Rendering Infrastructure Runtime Config
|
|
|
|
This phase is the first allowed implementation phase after the governance gate. It must be completed before management report payload, storage, OperationRun, UI action, PDF templates, or report-generation work.
|
|
|
|
Required future implementation work:
|
|
|
|
- Identify exact runtime config targets before editing: root `docker-compose.yml` for Sail/local service wiring, the repo's Dokploy/deployment config or documentation location if present, and an explicit `not present` note if no Dokploy config file exists in the repo.
|
|
- Add a pinned Gotenberg 8 Chromium internal service to Sail/Dokploy runtime config.
|
|
- Keep the renderer internal-network only with no public port.
|
|
- Add renderer configuration for base URL, timeout, request body limit, asset size limit, PDF output size limit, queue/concurrency expectations, and disabled/unavailable behavior.
|
|
- Add health check verification using Gotenberg `/health`.
|
|
- Add failing gateway/client tests for health check, renderer unavailable, timeout, invalid response, size-limit rejection, and safe error mapping before completing `PdfRendererClient` / `PdfRenderingGateway`.
|
|
- Add `PdfRenderingGateway` / `PdfRendererClient` as the only Laravel integration boundary after the gateway/client tests are in place.
|
|
- Add request correlation using the OperationRun id or generation correlation id.
|
|
- Render server-generated HTML payloads only; do not use user-provided URL rendering.
|
|
- Apply the Gotenberg security controls before enabling report generation.
|
|
- Map renderer unavailable, timeout, invalid request, and output-size failures into safe internal result types for later OperationRun handling.
|
|
- Do not add Composer/npm PDF/browser packages unless this spec/plan and `docs/package-governance.md` are updated again.
|
|
|
|
### Phase 1 - Payload and Readiness
|
|
|
|
Create a deterministic management-report payload from existing report truth:
|
|
|
|
- Source: current ready non-expired Review Pack and linked Environment Review.
|
|
- Profile: `customer_executive`.
|
|
- Disclosure: `ReportDisclosurePolicy::evaluate(...)`.
|
|
- Sections: cover, executive summary, governance posture, decisions, top risks/findings, accepted risks, evidence readiness, limitations, next actions, provenance, method summary.
|
|
- Readiness: block or disable generation when source is missing/not ready/expired/not current/profile-blocked/disclosure-blocked/unauthorized.
|
|
- No direct database queries in Blade/PDF template.
|
|
|
|
Likely implementation surfaces:
|
|
|
|
```text
|
|
apps/platform/app/Support/ReviewPacks/ManagementReportPayloadBuilder.php
|
|
apps/platform/app/Support/ReviewPacks/ManagementReportReadiness.php
|
|
apps/platform/app/Support/ReviewPacks/ManagementReportPdfRenderer.php
|
|
```
|
|
|
|
Names may differ if existing repo conventions suggest a better home.
|
|
|
|
### Phase 2 - Artifact Storage
|
|
|
|
Preferred path:
|
|
|
|
- Use `StoredReport` if it can represent the generated PDF artifact with a narrow migration/addition.
|
|
- Add a management report type constant only if resource capability/report type maps are updated safely.
|
|
- Store private PDF file path/disk or artifact reference in the canonical substrate.
|
|
- Keep PDF payload/provenance in JSONB metadata without raw provider payloads.
|
|
- Do not create a new artifact table unless the spec/plan are updated and proportionality is re-approved.
|
|
|
|
Migration impact if needed:
|
|
|
|
- Safe incremental migration under `apps/platform/database/migrations`.
|
|
- Reversible where feasible.
|
|
- PostgreSQL lane if constraints/indexes/JSONB behavior are relevant.
|
|
- Staging validation required before production.
|
|
|
|
### Phase 3 - OperationRun and Audit
|
|
|
|
Preferred path:
|
|
|
|
- Add or map canonical operation type `report.management.generate` only if no existing type fits.
|
|
- Register the operation type in `OperationCatalog`/related guards as required.
|
|
- Use `OperationRunService` for queued/running/completed/failed/blocked transitions.
|
|
- Use safe `context.results` summary with artifact id, source review/pack ids, profile, format, and file metadata.
|
|
- Do not write adapter reconciliation metadata unless a reconciliation adapter actually runs.
|
|
- Record audit for generation and download with safe metadata.
|
|
|
|
### Phase 4 - UI Actions and Download
|
|
|
|
Owner surface behavior:
|
|
|
|
- Show or enable `Generate management PDF` only when source is ready and actor is authorized.
|
|
- If a current generated PDF exists for the same source/profile/fingerprint, prefer `Download management PDF` or `Open management PDF` rather than duplicate generation.
|
|
- When generation is running, show one clear operation link.
|
|
- When blocked/failed, show safe reason and operation link.
|
|
- Keep one primary action per focused area.
|
|
|
|
Download behavior:
|
|
|
|
- Use a signed route or server-authorized route with short-lived URL if signing is used.
|
|
- Re-resolve artifact/source scope server-side.
|
|
- Audit every successful download.
|
|
- Do not embed signed URLs in the PDF body.
|
|
|
|
### Phase 5 - PDF Rendering
|
|
|
|
Renderer requirements:
|
|
|
|
- Use the approved Gotenberg 8 Chromium renderer path through `PdfRenderingGateway` only.
|
|
- Render from prepared payload, not live controller/global request state.
|
|
- No remote fonts/assets.
|
|
- Header/footer, page metadata, generated timestamp, and page numbers when supported.
|
|
- Clean table/section breaks; no huge raw tables.
|
|
- No technical appendix in `customer_executive` PDF.
|
|
- EN/DE labels through localization.
|
|
|
|
### Phase 6 - Validation and Close-Out
|
|
|
|
- Run targeted Spec378 tests.
|
|
- Run Spec357/Spec366 regressions.
|
|
- Run Review Pack and Customer Review Workspace focused regressions as needed.
|
|
- Run browser/content smoke.
|
|
- Run Pint and `git diff --check`.
|
|
- Record Livewire v4 compliance, provider registration, global-search posture, destructive/high-impact action safety, asset strategy, tests, and deployment impact.
|
|
|
|
## Data Model / Persistence Impact
|
|
|
|
Expected possibilities:
|
|
|
|
1. **No schema change**: if current artifact storage can reference a PDF through existing fields. Unlikely based on current `StoredReport`.
|
|
2. **Narrow `StoredReport` extension**: likely path if adding `report_type=management_report_pdf`, artifact file metadata, tenant scope, source environment, source review/pack, operation run, generated by, generated at, status, and profile. This must stay tenant-owned with `workspace_id`, NOT NULL `tenant_id` where the table represents tenant-owned artifact truth, and source `managed_environment_id`.
|
|
3. **New artifact entity**: not approved by this plan. Stop and update spec/plan before implementation if this becomes necessary.
|
|
4. **Tenant-scope stop condition**: if the selected substrate cannot represent constitution-compliant tenant scope, stop before persistence changes and update spec/plan; do not rely on `managed_environment_id` alone for newly persisted tenant-owned artifact truth.
|
|
|
|
Retention/lifecycle:
|
|
|
|
- V1 may use existing stored report retention defaults or record "retained" semantics consistent with current StoredReportResource.
|
|
- Do not implement artifact lifecycle/hold/delete framework in this spec.
|
|
|
|
## RBAC / Policy Implications
|
|
|
|
- Generation requires workspace membership, tenant entitlement, managed-environment entitlement, and an existing review/export/manage capability unless a new capability is proven necessary.
|
|
- Download requires view/download permission for the generated artifact and same workspace/tenant/environment scope.
|
|
- Server handlers must call Gate/Policy/capability checks; UI disabled/hidden state is not security.
|
|
- Non-member/wrong workspace/wrong tenant/wrong environment gets 404.
|
|
- Member without capability gets 403 after scope is established.
|
|
- StoredReportResource capability map must include any new management report type or explicitly keep it out of the registry if a separate download route owns access.
|
|
|
|
## UI / Filament / Livewire Implications
|
|
|
|
- Filament v5 on Livewire 4.1.4 remains compliant; no Livewire v3 APIs.
|
|
- Panel providers remain registered in `apps/platform/bootstrap/providers.php`; no panel changes planned.
|
|
- `StoredReportResource` remains globally non-searchable unless spec/plan are updated. It has a View page today.
|
|
- Generate action is high-impact artifact creation and must use `Action::make(...)->action(...)`, `->requiresConfirmation()`, server-side authorization, readiness gate, explicit notification, and audit before artifact creation starts.
|
|
- No destructive action is added.
|
|
- No new Filament assets planned.
|
|
|
|
## Audit / Observability / Evidence Implications
|
|
|
|
- Generation audit must include actor, workspace, managed environment, source review id, source review pack id, stored report/artifact id, operation run id, profile, format, status, generated at, and safe metadata.
|
|
- Download audit must include actor, workspace, managed environment, artifact id, source review/pack ids, profile, format, downloaded at, and safe request metadata if existing audit captures it.
|
|
- OperationRun results should include artifact id/path hash/size/fingerprint only if safe; no signed URLs or secrets.
|
|
- Failed generation must be observable and safe.
|
|
|
|
## Deployment / Ops Impact
|
|
|
|
- **Env vars**: renderer base URL, timeout, body/output size limits, disabled/unavailable behavior, and matching Gotenberg timeout/body/concurrency controls are added to `apps/platform/.env.example`; no direct browser binary path is approved.
|
|
- **Migrations**: possible narrow `stored_reports` extension; staging migration validation required.
|
|
- **Queues**: likely uses queue worker for report generation. Dokploy worker command already includes `reports` queue in deployment guidance; implementation must confirm actual queue selection.
|
|
- **Scheduler/cron**: none.
|
|
- **Storage**: private PDF artifact storage required; production persistence/backup must include the disk/path.
|
|
- **Filament assets**: none planned; deployment already runs `php artisan filament:assets` when assets are registered.
|
|
- **Package/runtime**: Gotenberg 8 Chromium is approved with controls as an internal runtime service; no Composer/npm PDF/browser runtime package is approved. Any different renderer/runtime dependency requires package governance before code changes.
|
|
|
|
## Filament v5 Output Contract For Implementation Close-Out
|
|
|
|
Implementation response must explicitly state:
|
|
|
|
1. Livewire v4.0+ compliance.
|
|
2. Provider registration remains in `apps/platform/bootstrap/providers.php`.
|
|
3. Global search status: `StoredReportResource` is globally non-searchable today; any changed resource must keep View/Edit safety explicit.
|
|
4. Destructive/high-impact actions: no destructive action; generation is high-impact artifact creation with authorization, readiness, audit, and explicit confirmation implemented.
|
|
5. Asset strategy: no new Filament assets unless implementation changes plan; deploy `filament:assets` only if assets are registered.
|
|
6. Testing plan/results for payload, generation, access, audit, OperationRun, download, and browser/content smoke.
|
|
|
|
## Risks and Mitigations
|
|
|
|
- **Renderer config gap**: Sail/local renderer service/config and gateway/client boundary exist, but staging/Dokploy controls are not yet validated. Mitigate by confirming internal-only staging runtime, health check, queue behavior, and persistence before enabling report generation.
|
|
- **Storage mismatch**: StoredReport may need schema changes. Mitigate with narrow extension or stop/split.
|
|
- **Raw leakage**: PDF may include hidden/internal content. Mitigate with prebuilt payload and negative content tests.
|
|
- **Scope leakage**: signed URL could bypass context. Mitigate by server-side re-resolution and 404/403 tests.
|
|
- **Duplicate artifact churn**: repeated generation could create clutter. Mitigate with source/profile/fingerprint idempotency where practical.
|
|
- **Queue failures**: renderer/storage can fail. Mitigate OperationRun failed/blocked outcomes and no ready artifact exposure.
|
|
|
|
## Open Questions
|
|
|
|
Renderer governance decision is complete. Gotenberg 8 Chromium is approved with controls as the internal production PDF rendering service for report-style documents. Runtime/gateway implementation has started: Sail/local service, Laravel config, health check, timeout/size controls, and `PdfRenderingGateway` / `PdfRendererClient` now exist. Management report payload/storage/OperationRun/UI/PDF generation work must wait until staging/Dokploy controls are confirmed and the next implementation phase begins.
|
|
|
|
## Implementation Phases
|
|
|
|
1. Repo verification and renderer/package gate.
|
|
2. Runtime config target discovery and Gotenberg service/config.
|
|
3. Failing gateway/client tests, then `PdfRenderingGateway` / `PdfRendererClient`.
|
|
4. Failing tests for payload, readiness, disclosure, authorization, audit, storage, OperationRun, download, renderer failure mapping, and content leakage.
|
|
5. Payload/readiness/disclosure implementation.
|
|
6. Artifact storage and idempotency.
|
|
7. OperationRun and audit integration.
|
|
8. UI action and download route integration.
|
|
9. PDF rendering through the approved Gotenberg gateway.
|
|
10. Localization.
|
|
11. Browser/content smoke and UI coverage close-out.
|
|
12. Final validation and close-out.
|