TenantAtlas/specs/366-management-report-layout-branded-report-themes-v1/plan.md
ahmido f37056e1de feat: implement management report layout branded report themes (#437)
Implemented management report layout branded report themes as requested.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #437
2026-06-08 03:35:20 +00:00

27 KiB

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
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:

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)

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:

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:

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.