Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 5m7s
Added jobs, controllers, and PDF generation logic for management report runtime as defined in Spec 379. Includes artifact migrations, payload builders, and testing coverage.
284 lines
22 KiB
Markdown
284 lines
22 KiB
Markdown
# 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)
|
|
|
|
```text
|
|
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)
|
|
|
|
```text
|
|
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.
|