# Implementation Plan: Spec 366 - Management Report Layout & Branded Report Themes v1 **Branch**: `366-management-report-layout-branded-report-themes-v1` | **Date**: 2026-06-08 | **Spec**: [spec.md](./spec.md) **Input**: Feature specification from `/specs/366-management-report-layout-branded-report-themes-v1/spec.md` **Note**: This plan is a preparation artifact only. It defines the implementation path and validation gate; it does not implement application code. ## Summary Spec 366 productizes the existing authenticated Review Pack rendered-report route into a management-ready, profile-aware, print-friendly report with bounded text co-branding. It builds on the repo-real Spec 356 HTML report renderer and Spec 357 static profile/disclosure policy. The implementation should improve the existing rendered-report family, not create a new report engine, PDF stack, delivery workflow, customer portal, or theme persistence layer. The narrow technical approach is: 1. Verify current report truth and capture a small current-layout audit. 2. Add tests first for derived theme/layout behavior, rendered output, disclosure preservation, print toolbar behavior, and browser screenshots. 3. Add a bounded derived report theme/layout contract only where it reduces controller/view duplication and improves testability. 4. Refactor the existing rendered-report Blade into profile-aware sections/partials only if that makes the report safer to review. 5. Keep all report truth derived from existing Review Pack, Environment Review, Evidence Snapshot, profile, and disclosure policy data. ## 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, Laravel Sail 1.x, Tailwind CSS 4.2.2 through the existing platform build **Storage**: PostgreSQL via existing models only. No new table, migration, persisted report theme, or upload storage is planned. **Testing**: Pest 4 Unit, Feature, and one bounded Browser smoke. Browser tests use Pest 4 browser testing and should assert no JavaScript errors/console logs. **Validation Lanes**: fast-feedback, confidence, browser. **Target Platform**: Laravel web application under `apps/platform`. **Project Type**: Laravel + Filament app with a custom authenticated Blade report view under the existing Review Pack route family. **Performance Goals**: Rendered report remains stored-data-only. No Graph/provider calls during report render. **Constraints**: Disclosure policy is authoritative; branding cannot hide readiness/limitations; no raw JSON/secrets/default diagnostics; no new asset registration unless implementation proves it necessary. **Scale/Scope**: One existing rendered-report route/view family and existing owner-surface links. No new IA, panel, or navigation. ## Repo Truth Captured During Prep - Current branch after Spec Kit scaffold: `366-management-report-layout-branded-report-themes-v1` - Baseline HEAD before prep edits: `6ac0913f feat: implement operations UI operator actions regression gate (#436)` - Starting worktree: clean on `platform-dev`; after scaffold only the new Spec 366 artifacts are intended to change. - No existing `specs/366-management-report-layout-branded-report-themes-v1/` directory or branch existed before preparation. - Spec 356 and Spec 357 packages contain completed-task and validation signals and are treated as historical context only. - Current package baseline from Laravel Boost: - PHP 8.4.15 - Laravel 12.52.0 - Filament 5.2.1 - Livewire 4.1.4 - Pest 4.3.1 - PostgreSQL Relevant implementation files discovered: ```text apps/platform/app/Http/Controllers/ReviewPackRenderedReportController.php apps/platform/app/Services/ReviewPackService.php apps/platform/app/Support/ReviewPacks/ReportProfileRegistry.php apps/platform/app/Support/ReviewPacks/ReportDisclosurePolicy.php apps/platform/app/Support/ReviewPacks/ReviewPackOutputReadiness.php apps/platform/app/Support/ReviewPacks/ReviewPackOutputResolutionGuidance.php apps/platform/app/Filament/Resources/EnvironmentReviewResource.php apps/platform/app/Filament/Resources/EnvironmentReviewResource/Pages/ViewEnvironmentReview.php apps/platform/app/Filament/Resources/ReviewPackResource.php apps/platform/app/Filament/Resources/ReviewPackResource/Pages/ViewReviewPack.php apps/platform/resources/views/review-packs/rendered-report.blade.php apps/platform/lang/en/localization.php apps/platform/lang/de/localization.php apps/platform/tests/Feature/ReviewPack/ReviewPackDownloadTest.php apps/platform/tests/Feature/ReviewPack/Spec357RenderedReportProfileTest.php apps/platform/tests/Browser/Spec357ReportProfilesSmokeTest.php apps/platform/tests/Unit/Support/ReviewPacks/Spec357ReportProfileRegistryTest.php apps/platform/tests/Unit/Support/ReviewPacks/Spec357ReportDisclosurePolicyTest.php ``` Repo-specific baseline decisions: - `ReviewPackRenderedReportController` already builds the rendered-report payload and currently owns base branding, hero, management summary, source metadata, and profile/disclosure integration. - `ReportProfileRegistry` already defines `customer_executive`, `customer_technical`, `internal_msp_review`, `auditor_appendix`, and placeholder `framework_readiness`. - `ReportDisclosurePolicy` already emits mandatory disclosures, warnings, blocking reasons, proof states, and appendix/technical-detail visibility decisions. - `rendered-report.blade.php` already has a report toolbar outside `main.report-canvas`, print CSS that hides toolbar/screen-only controls, a cover/hero section, management summary, profile, limitations, evidence basis, appendix, and disclosure areas. - Existing tests already prove some Spec 366-adjacent behavior, so implementation must avoid duplicating broad Spec 356/357 proof and instead add the missing layout/theme/productization checks. ## Candidate Selection Gate - **Selected candidate**: Management Report Layout & Branded Report Themes v1. - **Source**: Direct user-provided Spec 366 draft. - **Why selected**: It is a bounded follow-through after the report renderer and profile/disclosure policy are repo-real. - **Deferred alternatives**: scheduled delivery, compliance framework profiles, customer portal report consumption, native PDF, and AI/HITL report review are deferred because they depend on a stable management-ready report layout. - **Completed-spec guardrail**: Specs 356 and 357 are completed/validated context only; they are not rewritten. No completed Spec 366 package existed. - **Result**: PASS. ## UI / Surface Guardrail Plan - **Guardrail scope**: changed customer-facing report surface. - **Affected routes/pages/actions/states/navigation/panel/provider surfaces**: - existing rendered Review Pack report URL generated by `ReviewPackService::generateRenderedReportUrl()` - `ReviewPackRenderedReportController` - `resources/views/review-packs/rendered-report.blade.php` - existing report launch links on Environment Review and Review Pack detail surfaces - **No-impact class, if applicable**: N/A. - **Native vs custom classification summary**: existing custom Blade report view inside an authenticated Laravel/Filament app. Keep owner surfaces Filament-native; report canvas may stay custom because it is a print artifact. - **Custom surface exception**: `UI-EX-001: Legitimate Custom Surface Exception` applies to the rendered-report canvas and toolbar/print treatment. The product reason is that the customer-facing governance report requires cover identity, readiness, KPI/decision strip, profile-aware appendix hierarchy, disclosure, and print behavior that ordinary CRUD/detail/table primitives do not express cleanly. - **Smallest custom behavior**: one local Blade report canvas with bounded toolbar/print CSS, profile-aware section ordering, and text-only co-branding. No second renderer, general design system, native PDF stack, customer portal, theme editor, upload UI, or report-layout framework. - **Standardized behavior retained**: authorization, workspace/environment entitlement, Review Pack launch links, owner surfaces, profile registry, disclosure policy, localization, and read-only action semantics remain on existing Laravel/Filament/Review Pack paths. - **Custom surface proof**: Feature/Browser tasks must prove report hierarchy, disclosure visibility, toolbar-hidden print behavior, screenshots, accessibility/focus basics, no text overlap, no JavaScript/console errors, and UI coverage update or no-update rationale. - **Shared-family relevance**: evidence/report viewer, status/readiness messaging, report toolbar, customer-safe disclosure, source metadata. - **State layers in scope**: report payload, report view, print CSS, profile-specific section ordering, derived theme/co-branding slots. - **Audience modes in scope**: customer executive, customer technical, internal MSP review, controlled auditor appendix. - **Decision/diagnostic/raw hierarchy plan**: management decision content first; evidence/technical appendix second; raw/support data absent by default. - **Raw/support gating plan**: no raw JSON or support payload in default report output. If existing technical details are rendered for internal/auditor profiles, keep them structured and non-secret. - **One-primary-action / duplicate-truth control**: report toolbar remains outside canvas; report content itself stands alone with a single readable management story. - **Handling modes by drift class or surface**: review-mandatory for any customer-facing disclosure, print CSS, appendix hierarchy, or branding change. - **Repository-signal treatment**: update `ui-099-rendered-review-report.md` and/or coverage matrix if the implemented visual hierarchy materially changes the page contract; otherwise record a no-update rationale. - **Special surface test profiles**: report-viewer / customer-facing artifact surface. - **Required tests or manual smoke**: Feature route/output tests plus one bounded Browser smoke with screenshots. - **Exception path and spread control**: custom report CSS remains local to the rendered report unless implementation proves a shared asset is required. No new Filament asset registration is planned. - **Active feature PR close-out entry**: Guardrail + Smoke Coverage. - **UI/Productization coverage decision**: material existing-page/report-surface change; coverage docs must be updated or explicitly closed out. - **Coverage artifacts to update**: likely `docs/ui-ux-enterprise-audit/page-reports/ui-099-rendered-review-report.md`; maybe design coverage matrix if the surface classification changes. - **No-impact rationale**: N/A. - **Navigation / Filament provider-panel handling**: no panel provider or navigation change planned. Laravel 12 Filament providers remain in `apps/platform/bootstrap/providers.php`. - **Screenshot or page-report need**: yes, screenshots under `specs/366-management-report-layout-branded-report-themes-v1/artifacts/screenshots/`. ## Shared Pattern & System Fit - **Cross-cutting feature marker**: yes. - **Systems touched**: existing Review Pack rendered report, profile registry, disclosure policy, Review Pack service URL generation, Environment Review/Review Pack owner-surface report links, localization. - **Shared abstractions reused**: `ReportProfileRegistry`, `ReportDisclosurePolicy`, `ReviewPackOutputReadiness`, `ReviewPackOutputResolutionGuidance`, `ReviewPackService`. - **New abstraction introduced? why?**: One bounded derived report theme/layout contract is planned because Spec 366 needs a testable contract for text co-branding, layout mode, KPI strip, and print/report section metadata. The concrete implementation may be a `ReportThemeResolver` or a controller-local view-model if that is narrower. - **Why the existing abstraction was sufficient or insufficient**: Existing profile/disclosure abstractions are sufficient for audience and safety. They do not define theme/co-branding slots, profile-specific section ordering, or KPI strip composition. - **Bounded deviation / spread control**: The new shape must live inside `App\Support\ReviewPacks` or the existing controller payload; it must not become a cross-domain theme engine. ## OperationRun UX Impact - **Touches OperationRun start/completion/link UX?**: no. - **Central contract reused**: N/A. - **Delegated UX behaviors**: N/A. - **Surface-owned behavior kept local**: N/A. - **Queued DB-notification policy**: N/A. - **Terminal notification path**: N/A. - **Exception path**: none. Existing Review Pack generation OperationRun behavior is out of scope. ## Provider Boundary & Portability Fit - **Shared provider/platform boundary touched?**: no. - **Provider-owned seams**: none. - **Platform-core seams**: report profile/audience, rendered report source metadata, evidence/readiness truth. - **Neutral platform terms / contracts preserved**: workspace, managed environment, report, profile, audience, readiness, evidence basis, review pack. - **Retained provider-specific semantics and why**: Existing stored report/pack sections may contain provider-specific evidence summaries where already allowed by profile/disclosure policy; no new provider coupling is added. - **Bounded extraction or follow-up path**: none. ## Constitution Check *GATE: Must pass before implementation. Re-check after design and before code merge.* - Inventory-first: PASS. Report rendering consumes existing last-observed/released review and Review Pack truth. - Read/write separation: PASS. Report route remains read-only. No restore/remediation/provider write action is introduced. - Graph contract path: PASS. No Graph/provider calls during report render. - Deterministic capabilities: PASS. Existing `REVIEW_PACK_VIEW` capability and policies remain authoritative. - RBAC-UX: PASS. Existing cross-workspace/environment not-found semantics and missing-capability 403 stay in place. - Workspace isolation: PASS. Existing Review Pack/Environment Review workspace/environment scope must remain. - Destructive-like actions: PASS. No destructive or high-impact action is introduced. - Global search: PASS. No resource global-search behavior changes. - Run observability: PASS. No new OperationRun type or queue path. - OperationRun start UX: PASS / N/A. No OperationRun start/link UX touched. - Ops-UX lifecycle and summary counts: PASS / N/A. - Data minimization: PASS. No secrets/raw provider payloads/default raw JSON in report output. - Test governance: PASS. Unit, Feature, and Browser lanes are explicit and bounded. - Proportionality: PASS. Bounded report theme/layout resolver is justified only for current report productization and remains derived/non-persisted. - No premature abstraction: PASS with constraint. Do not create theme persistence, editor, or generalized rendering framework. - Persisted truth: PASS. No new persisted truth. - Behavioral state: PASS. No new status/state family. - UI semantics: PASS. Directly map report profile/readiness/disclosure truth into layout. - Shared pattern first: PASS. Use existing report profile/disclosure services first. - Provider boundary: PASS. No provider-specific theme or platform-core leakage. - V1 explicitness / few layers: PASS. Keep local and derived. - Spec discipline / bloat check: PASS. Proportionality review is complete. - Badge semantics: PASS. If status-like badges are changed, use existing safe report/status presentation rather than ad-hoc truth. - Filament-native UI: PASS. Owner surfaces remain Filament-native; custom report canvas is covered by `UI-EX-001: Legitimate Custom Surface Exception` and remains bounded to the existing print/report artifact. - UI/UX surface taxonomy: PASS. Rendered report surface classified. - Decision-first operating model: PASS. Report first screen supports management decision. - Audience-aware disclosure: PASS. Customer/internal/auditor profile hierarchy is explicit. - Filament UI Action Surface Contract: PASS. No new Filament mutating actions; report toolbar actions are navigation/download/print only. - UI/Productization coverage: PASS. Coverage update/no-update rationale required. ## Test Governance Check - **Test purpose / classification by changed surface**: - Unit: derived theme/layout/profile mapping. - Feature: rendered-report route authorization, content, disclosure, ZIP invariance, print CSS, no provider calls. - Browser: visual/smoke proof for profile variants, print view, and screenshot artifacts. - **Affected validation lanes**: fast-feedback, confidence, browser. - **Why this lane mix is the narrowest sufficient proof**: Most safety is server-rendered HTML/content and deterministic derived data. Browser proof is required only for real report hierarchy, print toolbar behavior, JS/console smoke, and screenshots. - **Narrowest proving command(s)**: - `cd apps/platform && ./vendor/bin/sail artisan test tests/Unit/Support/ReviewPacks/Spec366ReportThemeContractTest.php --compact` - `cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/ReviewPack/Spec366RenderedReportLayoutTest.php --compact` - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec366ManagementReportLayoutSmokeTest.php --compact` - **Fixture / helper / factory / seed / context cost risks**: Reuse Spec357 rendered-report fixtures and helpers where possible. New helpers must be local to Spec366 files. - **Expensive defaults or shared helper growth introduced?**: no. - **Heavy-family additions, promotions, or visibility changes**: one explicit Browser smoke file only. - **Surface-class relief / special coverage rule**: customer-facing report surface requires browser screenshots and no raw leakage checks. - **Closing validation and reviewer handoff**: Re-run Spec356/Spec357/ReviewPack/EnvironmentReview regressions and verify no ZIP/download/authorization behavior changed. - **Budget / baseline / trend follow-up**: none expected beyond one browser file. - **Review-stop questions**: - Does branding hide or weaken disclosure/readiness truth? - Does any metric lack a repo-backed source? - Does customer executive layout still show appendix too prominently? - Does print hide toolbar and keep disclosure visible? - Did implementation add persistence/upload/theme editor/native PDF/delivery scope? - **Escalation path**: document-in-feature for deferred optional logo/accent; follow-up-spec for scheduled delivery, theme CRUD, PDF, portal, AI, or compliance reports. - **Active feature PR close-out entry**: Guardrail + Smoke Coverage. - **Why no dedicated follow-up spec is needed**: This is the dedicated layout/theme productization slice. Larger delivery/compliance/portal/AI items stay separate follow-ups. ## Project Structure ### Documentation (this feature) ```text specs/366-management-report-layout-branded-report-themes-v1/ ├── spec.md ├── plan.md ├── tasks.md ├── checklists/ │ └── requirements.md └── artifacts/ └── screenshots/ # created during implementation/browser smoke ``` Implementation tasks will create a repo-truth map and may create a current-layout audit: ```text specs/366-management-report-layout-branded-report-themes-v1/repo-truth-map.md specs/366-management-report-layout-branded-report-themes-v1/current-report-layout-audit.md ``` `repo-truth-map.md` is required by the implementation task list to lock the current report fields, repo-backed metrics, baseline commit, and any narrower controller-local theme decision. `current-report-layout-audit.md` is optional and should only be created when screenshots or manual review reveal concrete layout problems that guide implementation. Neither artifact is runtime code. ### Source Code (repository root) Expected implementation paths: ```text apps/platform/app/ ├── Http/Controllers/ReviewPackRenderedReportController.php ├── Services/ReviewPackService.php ├── Support/ReviewPacks/ │ ├── ReportProfileRegistry.php │ ├── ReportDisclosurePolicy.php │ ├── ReviewPackOutputReadiness.php │ ├── ReviewPackOutputResolutionGuidance.php │ └── ReportThemeResolver.php # only if justified during implementation └── Filament/Resources/ ├── EnvironmentReviewResource.php └── ReviewPackResource.php apps/platform/resources/views/review-packs/ ├── rendered-report.blade.php └── partials/ # only if splitting reduces review risk ├── report-toolbar.blade.php ├── report-cover.blade.php ├── report-state-hero.blade.php ├── report-kpi-strip.blade.php ├── report-executive-summary.blade.php ├── report-appendix.blade.php └── report-disclosure-footer.blade.php apps/platform/lang/ ├── en/localization.php └── de/localization.php apps/platform/tests/ ├── Unit/Support/ReviewPacks/Spec366ReportThemeContractTest.php ├── Feature/ReviewPack/Spec366RenderedReportLayoutTest.php └── Browser/Spec366ManagementReportLayoutSmokeTest.php ``` **Structure Decision**: Stay inside the existing Review Pack rendered-report family. Add no new app module, no new base folder outside existing conventions, and no new package. ## Data / Domain Model Implications - No new persisted entity, table, enum, lifecycle state, queue family, or independent report artifact. - Derived theme/layout data may include: - `prepared_by` - `prepared_for` - `generated_by` - `generated_at` - `accent` - `logo` - `layout_mode` - `kpi_strip` - `section_order` - `logo` and `accent` must stay null/default unless existing safe repo-backed fields are verified. - KPI strip values must be derived only from existing report/review/evidence payloads. ## Implementation Phases ### Phase 0 - Repo Verification and Current Layout Audit - Confirm Specs 356 and 357 are stable in the current branch. - Re-read current controller/view/tests. - Create `repo-truth-map.md` to record current fields, gaps, repo-backed metrics, optional branding fields, baseline commit, and any narrower controller-local theme decision. - Create `current-report-layout-audit.md` only if browser screenshots or manual review reveal concrete layout problems that guide implementation. - Stop if Spec 357 profile/disclosure behavior is absent or failing. ### Phase 1 - Tests First - Add Unit tests for derived theme/layout contract or verify current controller payload if no new class is justified. - Add Feature tests for route output, profile layout, co-branding, print CSS, disclosure preservation, no ZIP change, no provider call, no raw/localization leakage. - Add Browser smoke for profile variants, print class/print behavior, screenshots, and no JS/console errors. ### Phase 2 - Theme/Layout Contract - Add `ReportThemeResolver` or equivalent controller-local view-model shape only if justified by tests and current code. - Use workspace and managed-environment names for text co-branding. - Keep optional logo/accent null/default unless repo-backed fields already exist. - Add layout-mode and section-order data derived from `ReportProfileRegistry`. ### Phase 3 - Rendered Report Layout Productization - Update `ReviewPackRenderedReportController` to provide stable theme/layout/KPI data. - Update or split `rendered-report.blade.php` into partials only where reviewability improves. - Render management-ready first screen: cover, state hero, KPI strip, executive summary, key risks/decisions, evidence basis, accepted risks, next action, disclosure. - Ensure appendix is secondary for `customer_executive` and more prominent for `auditor_appendix`. - Keep toolbar outside report canvas and hidden in print. ### Phase 4 - Localization and Report Copy - Add EN/DE keys for new dominant report copy only. - Avoid raw localization keys in output. - Keep action labels and source metadata consistent with existing Review Pack/report vocabulary. ### Phase 5 - UI Coverage, Browser Smoke, and Close-Out - Run focused validation commands. - Save screenshots under the Spec 366 artifact directory. - Update UI audit coverage or record no-update rationale. - Record no migrations/packages/env/queues/scheduler/storage/asset changes. ## Rollout and Deployment Considerations - **Staging**: Validate rendered report profile variants, print behavior, and review-pack download unchanged. - **Production**: No schema change expected. Deploy as ordinary app/view/test change. - **Migrations**: none planned. - **Environment variables**: none planned. - **Queues / scheduler**: none planned. - **Storage**: no new storage path except test/browser screenshot artifacts in the repo during implementation. - **Filament assets**: no new registered Filament assets expected. If implementation registers assets unexpectedly, deployment must include `cd apps/platform && php artisan filament:assets`; otherwise existing deployment asset handling is unchanged. - **Reverse proxy / SSL**: no impact. - **Rollback/forward**: revert code/view/localization changes; no data migration rollback. ## Complexity Tracking | Violation | Why Needed | Simpler Alternative Rejected Because | |---|---|---| | Bounded derived report theme/layout resolver or equivalent view-model | Current-release report productization needs deterministic co-branding, layout, KPI, and profile ordering proof | Scattered controller/view variables would be harder to test and could let profile/disclosure/branding drift | ## Proportionality Review - **Current operator problem**: MSPs need a professional, customer-safe, print-ready report artifact over existing Review Pack truth. - **Existing structure is insufficient because**: It proves a report can render, but not yet that the report has a stable management layout/theme contract across profiles and print states. - **Narrowest correct implementation**: Local derived theme/layout contract inside the Review Pack report family, rendered by the existing route/view. - **Ownership cost created**: One small Unit test family, one Feature test file, one Browser smoke, localization keys, and optional partial files. - **Alternative intentionally rejected**: persisted themes, logo upload, a generic report engine, native PDF, scheduled delivery, AI, or compliance report framework. - **Release truth**: Current-release report productization. ## Filament v5 / Livewire v4 Output Contract - **Livewire v4.0+ compliance**: The application uses Livewire 4.1.4; this spec does not introduce Livewire v3 APIs. - **Provider registration location**: No panel provider change planned. Laravel 12 Filament providers remain registered in `apps/platform/bootstrap/providers.php`. - **Global search**: No globally searchable resource is changed or enabled. If implementation unexpectedly touches `ReviewPackResource` or `EnvironmentReviewResource` global search, it must verify safe View/Edit pages or keep global search disabled. - **Destructive/high-impact actions**: None introduced. Existing Review Pack download/render/print actions remain read-only. Any unexpected mutating action must stop implementation and update spec/plan first. - **Asset strategy**: No new registered Filament assets planned; no new `filament:assets` deployment requirement unless implementation proves otherwise. - **Testing plan**: Pest Unit/Feature/Browser tests as listed above, plus Spec356/Spec357/ReviewPack/EnvironmentReview regressions. ## Stop Conditions Stop and update spec/plan before code implementation continues if: - Spec 357 profile/disclosure policy is not present or not stable. - A native PDF package, new dependency, persisted theme table, upload UI, or theme editor appears necessary. - Report metrics require new data collection or a new source of truth. - A customer portal, public link, scheduled delivery, approval workflow, or AI narrative becomes necessary. - Branding cannot be implemented from existing workspace/managed-environment truth without new persisted fields. - Any write/mutation action is proposed inside the report surface.