Implemented the first version of the PDF and HTML renderer for review packs. Added ReviewPackRenderedReportController and related blade views to render reports. Updated EnvironmentReviewResource, ReviewPackResource, ReviewPackService, and routing. Added new tests for the renderer and download actions, and updated UI documentation. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #427
265 lines
18 KiB
Markdown
265 lines
18 KiB
Markdown
# Implementation Plan: Review Pack PDF/HTML Renderer v1
|
|
|
|
**Branch**: `356-review-pack-pdf-html-renderer-v1` | **Date**: 2026-06-05 | **Spec**: `specs/356-review-pack-pdf-html-renderer-v1/spec.md`
|
|
**Input**: Feature specification from `specs/356-review-pack-pdf-html-renderer-v1/spec.md`
|
|
|
|
## Summary
|
|
|
|
Implement a rendered review-output follow-up that reuses the current review-derived `ReviewPack` contract to provide one calm HTML report, surfaces that report through the current released-review/review-pack seams, and keeps PDF strictly conditional on current repo-supported capabilities. The slice must preserve the current `ReviewPackGenerate` authority path, current signed download seam, current customer-safe disclosure contract, and current audit boundaries without introducing a second artifact family or a new dependency.
|
|
|
|
Spec 263 remains the bundle-contract baseline and must not be reopened. Spec 355 is the gating proof that the operator/productization flow is coherent enough for this delivery-format follow-up.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4.15, Laravel 12.52, Filament 5.2.1, Livewire 4.1.4
|
|
**Primary Dependencies**: Filament admin panel, current `ReviewPackService`, `GenerateReviewPackJob`, `ReviewPackDownloadController`, current `EnvironmentReview` summary/composer truth, Blade views, Pest 4.3
|
|
**Storage**: PostgreSQL plus current `exports` disk; no schema change or new persistence family planned
|
|
**Testing**: Pest Feature tests plus one bounded Browser smoke
|
|
**Validation Lanes**: confidence, browser, `git diff --check`
|
|
**Target Platform**: Laravel monolith in `apps/platform`
|
|
**Project Type**: web application
|
|
**Performance Goals**: render from current stored review-pack/review truth only; no live provider calls; no new queue family; no wide per-request recomposition beyond one current pack/review
|
|
**Constraints**: no new package without approval, no new artifact family, no new `OperationRun`, no Graph calls during render, no customer portal, PDF conditional on current support only
|
|
**Scale/Scope**: one released review and one current review pack, surfaced through current admin/operator and customer-safe read-only paths
|
|
|
|
## UI / Surface Guardrail Plan
|
|
|
|
- **Guardrail scope**: new rendered delivery surface plus changed customer-safe and review-pack owner surfaces
|
|
- **Affected routes/pages/actions/states/navigation/panel/provider surfaces**:
|
|
- `CustomerReviewWorkspace`
|
|
- `ViewEnvironmentReview` in customer-workspace mode
|
|
- `ReviewPackResource` detail/download surface
|
|
- one new read-only rendered report route under `/admin/review-packs/{reviewPack}/...` for preview/print delivery
|
|
- **No-impact class, if applicable**: N/A
|
|
- **Native vs custom classification summary**: mixed; native Filament owner surfaces plus one bounded custom rendered report view
|
|
- **Shared-family relevance**: delivery-status messaging, review/report viewers, download actions, customer-safe disclosure
|
|
- **State layers in scope**: page, detail, URL/route
|
|
- **Audience modes in scope**: operator-MSP, customer-admin, customer-read-only, auditor-read-only where current review-pack access already allows it
|
|
- **Decision/diagnostic/raw hierarchy plan**: decision-first rendered report and owner-surface summary; appendix/raw ZIP detail stays secondary
|
|
- **Raw/support gating plan**: raw pack files, fingerprints, and technical context stay collapsed or secondary behind current authorized seams
|
|
- **One-primary-action / duplicate-truth control**: `CustomerReviewWorkspace` keeps `Open review` as the list inspect model; released-review detail gets one dominant rendered-output affordance; review-pack detail does not compete with the owner-surface summary
|
|
- **Handling modes by drift class or surface**: customer-safe overclaim and false PDF availability are hard-stop candidates; copy-only drift is review-mandatory
|
|
- **Repository-signal treatment**: review-mandatory for the new rendered route and for any changed customer-safe surface copy
|
|
- **Special surface test profiles**: shared-detail-family
|
|
- **Required tests or manual smoke**: focused Feature disclosure and authorization tests plus one bounded browser smoke through the current workspace/detail flow
|
|
- **Exception path and spread control**: if PDF support is absent without a package, record `document-in-feature` and keep HTML as the shipped floor instead of widening scope
|
|
- **Active feature PR close-out entry**: Smoke Coverage
|
|
- **UI/Productization coverage decision**: reachable UI changes require route inventory, design coverage, strategic-surface, unresolved-page, and page-report follow-through
|
|
- **Coverage artifacts to update**: `route-inventory.md`, `design-coverage-matrix.md`, `strategic-surfaces.md`, `unresolved-pages.md`, `page-reports/...`
|
|
- **No-impact rationale**: N/A
|
|
- **Navigation / Filament provider-panel handling**: no navigation or provider-panel change is planned
|
|
- **Screenshot or page-report need**: yes; the rendered report is a new reachable customer-facing surface
|
|
|
|
## Shared Pattern & System Fit
|
|
|
|
- **Cross-cutting feature marker**: yes
|
|
- **Systems touched**:
|
|
- `apps/platform/app/Services/ReviewPackService.php`
|
|
- `apps/platform/app/Jobs/GenerateReviewPackJob.php`
|
|
- `apps/platform/app/Http/Controllers/ReviewPackDownloadController.php`
|
|
- `apps/platform/routes/web.php`
|
|
- `apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php`
|
|
- `apps/platform/app/Filament/Resources/EnvironmentReviewResource/Pages/ViewEnvironmentReview.php`
|
|
- `apps/platform/app/Filament/Resources/ReviewPackResource.php`
|
|
- current localization files and current review summary/artifact-truth views
|
|
- **Shared abstractions reused**: current `ReviewPack` delivery contract, `ReviewPackOutputReadiness`, `ArtifactTruthPresenter`, current review summary and `EnvironmentReviewSection` truth, current export/dedupe/download seams
|
|
- **New abstraction introduced? why?**: none by default; any render helper should stay local to the renderer/view seam if needed to keep view logic thin
|
|
- **Why the existing abstraction was sufficient or insufficient**: current services and presenters already own truth and safe delivery semantics, but no current surface renders that truth as a calm human-readable report
|
|
- **Bounded deviation / spread control**: no second renderer stack, no second artifact family, no package-backed PDF engine
|
|
|
|
## OperationRun UX Impact
|
|
|
|
- **Touches OperationRun start/completion/link UX?**: yes, reuse-only
|
|
- **Central contract reused**: current `ReviewPackGenerate` path and current `OperationRunLinks` follow-up behavior
|
|
- **Delegated UX behaviors**: queued toast, already-available pack reuse, active-run dedupe, current operation link continuity, and current terminal notification behavior remain unchanged
|
|
- **Surface-owned behavior kept local**: preview/download of already-ready rendered output only
|
|
- **Queued DB-notification policy**: unchanged
|
|
- **Terminal notification path**: unchanged
|
|
- **Exception path**: none
|
|
|
|
## Provider Boundary & Portability Fit
|
|
|
|
- **Shared provider/platform boundary touched?**: no
|
|
- **Provider-owned seams**: N/A
|
|
- **Platform-core seams**: read-only report delivery over existing review-pack truth
|
|
- **Neutral platform terms / contracts preserved**: review pack, rendered report, evidence basis, accepted risk, governance decision, limitation state
|
|
- **Retained provider-specific semantics and why**: provider-specific appendix content may remain inside the structured appendix because it already exists in current stored truth; it does not become the primary rendered language
|
|
- **Bounded extraction or follow-up path**: none
|
|
|
|
## Constitution Check
|
|
|
|
- Inventory-first: no inventory truth changes; the renderer is a delivery view over current stored review/review-pack truth.
|
|
- Read/write separation: preview/download is read-only; current export initiation remains the only write/queue path.
|
|
- Graph contract path: no Graph calls.
|
|
- Deterministic capabilities: current capability and entitlement logic remains authoritative.
|
|
- RBAC-UX: non-members remain `404`; in-scope viewers stay on current review/review-pack permission paths.
|
|
- Workspace isolation: current workspace membership remains the first boundary.
|
|
- Tenant isolation: rendered access stays environment-scoped through current review-pack/review seams.
|
|
- Run observability: current `ReviewPackGenerate` remains the only `OperationRun`; no renderer-specific run is added.
|
|
- Automation: no new scheduled or queued work is added beyond the current export path.
|
|
- Data minimization: rendered output stays customer-safe by default and does not surface raw/debug detail.
|
|
- Test governance: Feature plus one bounded browser smoke is the narrowest honest proof.
|
|
- Proportionality: no new persistence, no new package, no second artifact family, and no new workflow engine.
|
|
- No premature abstraction: render helpers stay local; no generic reporting engine is allowed.
|
|
- Persisted truth: unchanged.
|
|
- Behavioral state: unchanged.
|
|
- UI semantics: direct domain-to-report mapping over current truth; no new status taxonomy.
|
|
- Shared pattern first: extend the current review/review-pack/report seams instead of adding a parallel delivery subsystem.
|
|
- Provider boundary: unchanged.
|
|
- V1 explicitness / few layers: HTML-first and current-contract-first.
|
|
- Spec discipline / bloat check: PDF stays conditional rather than forcing broad infrastructure.
|
|
- Filament-native UI: existing owner surfaces stay native; the custom report view remains a bounded read-only delivery surface.
|
|
|
|
## Test Governance Check
|
|
|
|
- **Test purpose / classification by changed surface**:
|
|
- Feature: rendered contract truth, authorization, audit continuity, action hierarchy, honest PDF handling
|
|
- Browser: open-path and customer-safe presentation smoke
|
|
- **Affected validation lanes**: confidence, browser
|
|
- **Why this lane mix is the narrowest sufficient proof**: the slice is a read-only delivery/report follow-up over existing runtime truth; broad PGSQL or heavy-governance lanes are unnecessary
|
|
- **Narrowest proving command(s)**:
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/EnvironmentReview/EnvironmentReviewExecutivePackTest.php tests/Feature/EnvironmentReview/EnvironmentReviewExplanationSurfaceTest.php tests/Feature/EnvironmentReview/EnvironmentReviewUiContractTest.php tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php tests/Feature/ReviewPack/EnvironmentReviewDerivedReviewPackTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/ReviewPackResourceTest.php`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php`
|
|
- `git diff --check`
|
|
- **Fixture / helper / factory / seed / context cost risks**: existing released-review, review-pack, and entitlement fixtures are sufficient; avoid adding expensive default support/provider setup
|
|
- **Expensive defaults or shared helper growth introduced?**: none expected
|
|
- **Heavy-family additions, promotions, or visibility changes**: none beyond one explicit browser smoke path
|
|
- **Surface-class relief / special coverage rule**: shared-detail-family coverage is required because the rendered report must stay customer-safe and non-duplicative
|
|
- **Closing validation and reviewer handoff**: reviewers should verify HTML is the guaranteed floor, PDF is not overclaimed, and no second artifact family or new package appears
|
|
- **Budget / baseline / trend follow-up**: none expected
|
|
- **Review-stop questions**: false PDF claims, duplicate summary drift, authorization leaks, second artifact family drift
|
|
- **Escalation path**: `document-in-feature` if PDF remains unavailable without a new package
|
|
- **Active feature PR close-out entry**: Smoke Coverage
|
|
- **Why no dedicated follow-up spec is needed**: the HTML rendered-report slice is already the bounded follow-up; PDF-only hardening becomes a follow-up only if the repo cannot support it inside this scope
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/356-review-pack-pdf-html-renderer-v1/
|
|
|-- spec.md
|
|
|-- plan.md
|
|
|-- tasks.md
|
|
`-- checklists/
|
|
`-- requirements.md
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
|
|
Likely runtime surfaces for later implementation:
|
|
|
|
```text
|
|
apps/platform/app/
|
|
|-- Services/
|
|
| `-- ReviewPackService.php
|
|
|-- Jobs/
|
|
| `-- GenerateReviewPackJob.php
|
|
|-- Http/Controllers/
|
|
| |-- ReviewPackDownloadController.php
|
|
| `-- ... rendered-report controller for the new read-only preview/print seam
|
|
|-- Filament/
|
|
| |-- Pages/Reviews/CustomerReviewWorkspace.php
|
|
| |-- Resources/EnvironmentReviewResource/Pages/ViewEnvironmentReview.php
|
|
| `-- Resources/ReviewPackResource.php
|
|
`-- Support/
|
|
`-- existing artifact-truth and review-output readiness helpers
|
|
|
|
apps/platform/resources/
|
|
|-- views/
|
|
| |-- filament/pages/reviews/customer-review-workspace.blade.php
|
|
| |-- filament/infolists/entries/environment-review-summary.blade.php
|
|
| |-- filament/infolists/entries/environment-review-section.blade.php
|
|
| |-- filament/infolists/entries/review-pack-output-guidance.blade.php
|
|
| `-- review-packs/... for the rendered-report preview/print view
|
|
`-- lang/
|
|
|-- en/localization.php
|
|
`-- de/localization.php
|
|
|
|
apps/platform/routes/
|
|
`-- web.php
|
|
```
|
|
|
|
Likely tests for later implementation:
|
|
|
|
```text
|
|
apps/platform/tests/
|
|
|-- Feature/EnvironmentReview/
|
|
| |-- EnvironmentReviewExecutivePackTest.php
|
|
| |-- EnvironmentReviewExplanationSurfaceTest.php
|
|
| `-- EnvironmentReviewUiContractTest.php
|
|
|-- Feature/ReviewPack/
|
|
| |-- EnvironmentReviewDerivedReviewPackTest.php
|
|
| |-- ReviewPackDownloadTest.php
|
|
| `-- ReviewPackResourceTest.php
|
|
|-- Feature/Reviews/
|
|
| `-- CustomerReviewWorkspacePackAccessTest.php
|
|
`-- Browser/Reviews/
|
|
`-- CustomerReviewWorkspaceSmokeTest.php
|
|
```
|
|
|
|
**Structure Decision**: stay inside the current review/review-pack seams. Add exactly one new read-only controller and rendered-report view under the existing review-pack route family so preview/print delivery stays separate from the current signed ZIP download seam.
|
|
|
|
## Complexity Tracking
|
|
|
|
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
|
|---|---|---|
|
|
| One bounded rendered-report surface | The current ZIP plus Markdown entrypoint still feels internal to a stakeholder | Another Markdown-only adjustment would not remove unzip-first friction |
|
|
| Conditional PDF handling | The user value includes printable output, but the repo shows no clear PDF stack | Forcing a new PDF package or second renderer would overshoot current release truth |
|
|
|
|
## Proportionality Review
|
|
|
|
- **Current operator problem**: the current review pack is accurate but not immediately consumable as a calm stakeholder report.
|
|
- **Existing structure is insufficient because**: a ZIP plus Markdown entrypoint still requires explanation and creates productization friction.
|
|
- **Narrowest correct implementation**: one HTML report over current review-pack truth and PDF only when the repo can support it from the same contract.
|
|
- **Ownership cost created**: maintain a render view, owner-surface launch affordances, and focused customer-safe regression coverage.
|
|
- **Alternative intentionally rejected**: a new `AuditorPack` family, a new package-backed PDF engine, or a customer portal.
|
|
- **Release truth**: current-release productization follow-through.
|
|
|
|
## Technical Approach
|
|
|
|
1. Reconfirm the current review-derived delivery contract.
|
|
- Treat Spec 263's runtime as authoritative for `executive-summary.md`, delivery metadata, current review-pack anchoring, and current signed download continuity.
|
|
- Keep current review-output readiness truth from Specs 347, 349, 351, and 355.
|
|
|
|
2. Add one deterministic rendered-report contract over existing truth.
|
|
- Render from current stored review, `EnvironmentReviewSection`, and review-pack data only.
|
|
- Reuse current executive summary, section ordering/content semantics, evidence basis, readiness, accepted-risk, decision-summary, and non-certification disclosure truth instead of re-parsing archived ZIP contents as the primary source.
|
|
- Avoid live provider calls, new persistence, or a second composition engine.
|
|
|
|
3. Surface the rendered report through current owner seams.
|
|
- Keep `CustomerReviewWorkspace` as the first decision surface.
|
|
- Add one dominant rendered-output affordance on released-review detail and/or review-pack detail.
|
|
- Keep operator export initiation on the current `export_executive_pack` path.
|
|
- Keep report chrome outside the report canvas and make rendered/download labels readiness-aware.
|
|
- Add controlled repo-backed co-branding slots from existing workspace/environment names only.
|
|
- Keep limitations, PII/internal warnings, evidence basis, operation proof, disclosure, and generated metadata visible regardless of branding.
|
|
|
|
4. Keep printable delivery honest.
|
|
- If current repo support can produce PDF from the same rendered contract, allow it without a new package or second renderer.
|
|
- If not, keep the slice HTML-first and record the bounded PDF follow-up rather than widening scope.
|
|
- Hide toolbar/app actions from print output so the printed report stands alone.
|
|
|
|
5. Preserve audit and entitlement continuity.
|
|
- Reuse current review-pack view/download permissions and current audit events.
|
|
- Do not add a new panel, global search surface, asset strategy, package, or queue family.
|
|
- Render only from stored review/review-pack/evidence data; no live provider, Graph, operation, refresh, or AI calls during render.
|
|
|
|
## Implementation Phases
|
|
|
|
1. Lock the current contract and dependency truth, including current PDF-support reality.
|
|
2. Add failing tests for rendered HTML disclosure, authorization, and audit continuity.
|
|
3. Implement the bounded HTML report and owner-surface launch affordances.
|
|
4. Implement honest PDF handling from the same contract only if current repo support allows it.
|
|
5. Re-run focused Feature and Browser proof plus `git diff --check`.
|
|
|
|
## Rollout And Deployment Impact
|
|
|
|
- No migrations planned.
|
|
- No new env vars planned.
|
|
- No new queue family or scheduler change planned.
|
|
- No new storage volume or persistence family planned.
|
|
- No new Filament asset strategy is planned; `filament:assets` should remain unchanged unless implementation later proves otherwise.
|
|
- If implementation stays HTML-first because no PDF support exists, deployment impact remains route/view-only.
|