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
42 KiB
Feature Specification: Review Pack PDF/HTML Renderer v1
Feature Branch: 356-review-pack-pdf-html-renderer-v1
Created: 2026-06-05
Status: Implemented - close-ready after validation
Type: Productization / rendered review output / customer-safe report delivery
Depends on: Specs 263, 347, 349, 351, 355
Runtime posture: Reuse the current review-derived ReviewPack delivery contract. HTML rendering is required. PDF is allowed only if the repo already supports it from the same contract without adding a new package, a new OperationRun, or a second artifact family.
Input: Direct user-provided Spec 356 draft plus repo truth from the current review-pack export surfaces and Spec 355's documented follow-up queue.
Dependencies And Repo-Truth Adjustments
- Spec 263 already introduced the current executive entrypoint (
executive-summary.md) and delivery metadata inside the current review-derived pack. This spec must not reopen or duplicate that bundle-contract work. - Current customer-safe detail surfaces already direct the reader to start with
executive-summary.md, and the current review-derived pack is tenant-safe, auditable, and backed by the current signed-download seam. - Current repo truth before this slice required a ZIP download and Markdown/JSON inspection. This branch adds the calm rendered HTML/print report while preserving the existing ZIP artifact.
- Spec 355 explicitly deferred this renderer until the operator/productization flow was browser-verified as coherent. Spec 355 is now commit-backed on
platform-dev, so that prerequisite gate is satisfied. - No dedicated repo-supported report PDF stack is present in the current application dependencies. PDF therefore remains deferred for this slice; the implementation stays HTML-first with browser print support and does not add a package or second rendering subsystem.
Spec Candidate Check (mandatory — SPEC-GATE-001)
- Problem: TenantPilot can now produce customer-safe review packs and an executive-first Markdown entrypoint, but the externally deliverable output still feels like an internal ZIP artifact rather than a calm report a customer, executive, or demo stakeholder can open immediately.
- Today's failure: Even after Spec 263 and Spec 355, an operator still has to explain that the stakeholder should download a ZIP, open
executive-summary.md, and ignore the structured JSON appendix unless deeper inspection is needed. That adds friction and weakens the product's demo- and handoff-quality story. - User-visible improvement: An entitled user can open one rendered report from the current released review/current pack context, read the executive story first, understand evidence basis and limitations, and download a printable version when the repo can support it honestly.
- Smallest enterprise-capable version: Keep one released-review-bound
ReviewPackartifact and the current export/download authority model. Add one deterministic HTML report over the existing contract, surface it through the current review/customer-workspace seams, and allow PDF only when it comes from the same render contract without new dependencies. - Explicit non-goals: No new
AuditorPackmodel or table, no new customer portal, no public share links, no email delivery, no AI summary generation, no branding or white-label system, no batch multi-review export, no second report engine, and no new review publication workflow. - Permanent complexity imported: One bounded render layer, one or more read-only preview/download surfaces, localized copy updates, and focused Feature/Browser coverage. No new persistence family, no new queue family, no new capability family, and no second artifact taxonomy are allowed.
- Why now: Spec 355 explicitly named this as the next narrow follow-up once sellable-flow coherence was proven. The remaining gap is not another operator workflow foundation; it is the presentable customer/demo artifact.
- Why not local: A copy-only change or another Markdown file does not remove the ZIP-first friction. A customer portal or generic reporting engine overshoots the current repo truth.
- Approval class: Core Enterprise
- Red flags triggered: New rendered delivery surface and a conditional PDF branch. Defense: the slice stays derived from the current
ReviewPacktruth, forbids a new package or artifact family, and keeps PDF honest instead of forcing infrastructure. - Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 1 | Gesamt: 10/12
- Decision: approve
Candidate Source And Completed-Spec Guardrail
- Candidate source:
- direct user-provided Spec 356 draft
- explicit deferred follow-up in
specs/355-platform-sellable-smoke-matrix/spec.md - current review-pack runtime truth in
ReviewPackService,GenerateReviewPackJob, customer-review surfaces, and their tests
- Completed-spec guardrail result:
specs/263-auditor-pack-executive-export/is treated as completed historical/runtime context because its task checklist is fully checked and its runtime/test traces are present; it must not be rewritten.specs/347-*,349-*,351-*, and355-*are dependency and proof context only and must not be normalized back into preparation wording.- no
specs/1000-*package existed before this Spec 356 run.
- Close alternatives deferred:
customer-review-workspace-v1-completion: broader workspace productization lane; this renderer is the smaller output-first slice.localization-v1-customer-facing-surfaces: important follow-through, but it should not hide the output-format gap.customer-portal-boundary-contract: premature before the current output artifact is rendered and trustworthy.decision-based-governance-inbox-v1: separate operator-workbench lane, not delivery-format work.
- Smallest viable implementation slice: one current-review-bound HTML report plus truthful preview/download affordances on existing review/report surfaces; PDF only when the same render contract can produce it without new infrastructure.
Spec Scope Fields (mandatory)
- Scope: canonical-view
- Primary Routes:
- existing workspace customer review registry at
/admin/reviews/workspace - existing environment review detail route under
EnvironmentReviewResource - existing review-pack detail route under
ReviewPackResource - existing signed review-pack download route
/admin/review-packs/{reviewPack}/download - one new read-only rendered-report route under the current
/admin/review-packs/{reviewPack}/...family for preview/print delivery, while the current signed route remains ZIP-download-only
- existing workspace customer review registry at
- Data Ownership:
EnvironmentReview,EnvironmentReviewSection,ReviewPack,EvidenceSnapshot,StoredReport,Finding,FindingException, andAuditLogremain the only persisted truth used by this slice- rendered HTML and any optional PDF remain derived from current review-pack/review truth; if implementation requires a new table, a new stored artifact family, or new DB columns, the scope must stop and split
- RBAC:
- workspace membership remains the first isolation boundary and stays
404for non-members or out-of-scope environment/review targets - current operator export initiation on published review detail continues to require the existing review-manage capability path used by
export_executive_pack - current in-scope review/review-pack view permissions remain authoritative for rendered preview/download
- this slice must not invent a new capability family for rendered delivery
- workspace membership remains the first isolation boundary and stays
For canonical-view specs, the spec MUST define:
- Default filter behavior when tenant-context is active:
CustomerReviewWorkspacekeeps the current managed-environment prefilter launch behavior. The rendered report remains anchored to the selected released review/current pack rather than any hidden shell/session state. - Explicit entitlement checks preventing cross-tenant leakage: rendered preview/download is available only for entitled workspace and managed-environment scope through the current review/review-pack seams; inaccessible targets are omitted from aggregate lists and direct targeting resolves as not found.
UI Surface Impact (mandatory — UI-COV-001)
Does this spec add, remove, rename, or materially change any reachable UI surface?
- No UI surface impact
- Existing page changed
- New page/route added
- Navigation changed
- Filament panel/provider surface changed
- New modal/drawer/wizard/action added
- New table/form/state added
- Customer-facing surface changed
- Dangerous action changed
- Status/evidence/review presentation changed
- Workspace/environment context presentation changed
UI/Productization Coverage (mandatory when UI Surface Impact is not "No UI surface impact"; otherwise write N/A - no reachable UI surface impact plus rationale)
- Route/page/surface:
CustomerReviewWorkspacegovernance-package areaViewEnvironmentReviewin customer-workspace modeReviewPackResourcedetail/download surface- one new read-only rendered report preview/print route under
/admin/review-packs/{reviewPack}/...
- Current or new page archetype: existing customer-safe detail/report surfaces plus one rendered-report viewer route
- Design depth: Strategic Surface for customer-review workspace follow-through, released-review detail, review-pack detail, and rendered report preview
- Repo-truth level: repo-verified existing surfaces plus one new spec-backed rendered-report route in the current review-pack family
- Existing pattern reused: current governance-package truth,
ArtifactTruthPresenter, current review-pack delivery contract, current customer-safe detail disclosure - New pattern required: one bounded report-view pattern over the existing review-pack truth; no portal, dashboard, or second delivery family
- Screenshot required: yes; the rendered report and its launch path need browser-proof screenshots during implementation
- Page audit required: yes; the rendered report is a new reachable customer-facing surface
- Customer-safe review required: yes; this slice exists to improve customer/demo delivery without leaking internal detail
- Dangerous-action review required: no; the slice adds read-only delivery surfaces only
- Coverage files updated or explicitly not needed:
docs/ui-ux-enterprise-audit/route-inventory.mddocs/ui-ux-enterprise-audit/design-coverage-matrix.mddocs/ui-ux-enterprise-audit/page-reports/...docs/ui-ux-enterprise-audit/strategic-surfaces.mddocs/ui-ux-enterprise-audit/grouped-follow-up-candidates.mddocs/ui-ux-enterprise-audit/unresolved-pages.mdN/A - no reachable UI surface impact
- No-impact rationale when applicable: N/A
- Audit follow-through note: implementation must update the Review Pack detail/page coverage so the current
UI-042unresolved ledger entry no longer conflicts with the changed review-pack/report surfaces.
Cross-Cutting / Shared Pattern Reuse (mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write N/A - no shared interaction family touched)
- Cross-cutting feature?: yes
- Interaction class(es): download actions, preview/report viewers, delivery-status messaging, customer-safe disclosure, review-output guidance
- Systems touched:
CustomerReviewWorkspace,EnvironmentReviewResource,ViewEnvironmentReview,ReviewPackResource,ReviewPackService,GenerateReviewPackJob,ReviewPackDownloadController, localization files, and the current review-pack/report truth presenters - Existing pattern(s) to extend: current
ReviewPackdelivery contract, currentexport_executive_packpath, current signed download route, current customer-safe released-review detail block - Shared contract / presenter / builder / renderer to reuse:
ReviewPackService,GenerateReviewPackJob,ReviewPackOutputReadiness,ArtifactTruthPresenter,EnvironmentReviewsummary truth, current review-pack authorization/download seams - Why the existing shared path is sufficient or insufficient: the existing path is sufficient for review anchoring, entitlement, export dedupe, audit continuity, and executive-summary truth. It is insufficient only because the current externally consumable output is still ZIP-first and Markdown-first.
- Allowed deviation and why: none. The slice must extend the current
ReviewPackfamily and current review/report seams instead of creating a new report subsystem. - Consistency impact: rendered copy, package-readiness wording, evidence-basis language, non-certification disclosure, and dominant next-action semantics must stay aligned across workspace rows, released-review detail, review-pack detail, and the rendered report.
- Review focus: reviewers must block any second artifact family, any live provider-data render path, any false PDF claim, or any duplicated summary language that competes with the current owner surfaces.
OperationRun UX Impact (mandatory when the feature creates, queues, deduplicates, resumes, blocks, completes, or deep-links to an OperationRun; otherwise write N/A - no OperationRun start or link semantics touched)
- Touches OperationRun start/completion/link UX?: yes, reuse-only
- Shared OperationRun UX contract/layer reused: the existing
ReviewPackGeneratestart and completion flow reused byexport_executive_packremains the only run path - Delegated start/completion UX behaviors: queued toast, already-available pack reuse, active-run dedupe messaging, current operation link continuity, and current terminal notification behavior remain on the shared review-pack export path
- Local surface-owned behavior that remains: preview/download of already-ready rendered output only; the renderer must not invent its own queued/run semantics
- Queued DB-notification policy: unchanged from the current review-pack export contract
- Terminal notification path: unchanged; the current
OperationRunCompletedpath remains authoritative - Exception required?: none
Provider Boundary / Platform Core Check (mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write N/A - no shared provider/platform boundary touched)
N/A - no shared provider/platform boundary is widened. Provider-specific appendix content remains secondary and does not become the primary rendered language.
UI / Surface Guardrail Impact (mandatory when operator-facing surfaces are changed; otherwise write N/A)
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / N/A Note |
|---|---|---|---|---|---|---|
| Customer Review Workspace governance-package area | yes | Native Filament page plus shared review-package primitives | delivery status, launch actions, customer-safe disclosure | page, URL | no | Existing row-level Open review remains the list inspect model |
| Released review detail in customer-workspace mode | yes | Native Filament detail surface plus shared summary/artifact-truth primitives | package meaning, evidence basis, rendered output action hierarchy | detail, URL | no | One rendered-output action must not compete with diagnostics or proof links |
| Review Pack detail and rendered report preview/print surface | yes | Mixed native detail plus bounded custom report surface | evidence/report viewer, read-only output delivery | detail, route | no | The rendered report is read-only and derived from the current pack |
| Published review detail in operator mode | yes | Native Filament detail surface | current pack reuse, export/read-only follow-through | detail | no | Operator export remains current source-owned initiation path |
Decision-First Surface Role (mandatory when operator-facing surfaces are changed)
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Customer Review Workspace governance-package area | Primary Decision Surface | Decide whether the current released review is ready for stakeholder consumption | release/readiness state, limitations, dominant next step | deeper review detail and rendered report after explicit open | Primary because it remains the calm workspace handoff surface | stays on the existing review-consumption workflow | removes the need to explain ZIP mechanics first |
| Released review detail in customer-workspace mode | Secondary Context | Confirm what the rendered report will say and whether it is safe to open/download | executive-ready summary, evidence basis, current readiness, dominant output action | appendix detail, proof links, deeper governance sections | Secondary because the workspace owns the first selection decision | keeps delivery anchored to one released review | avoids duplicate workspace- and detail-level summaries |
| Review Pack detail and rendered report preview | Secondary Context | Inspect or download the current artifact in a presentable format | rendered report, limitation disclosure, appendix relationship | raw ZIP contents and technical metadata stay secondary | Secondary because the report is a delivery artifact, not the primary decision queue | stays on the current review-pack/report flow | removes unzip-plus-Markdown explanation work |
| Published review detail in operator mode | Secondary Context | Prepare or reuse the current pack before external handoff | export readiness and pack reuse status | run detail and review-pack detail after follow-up | Secondary because it is operator-only preparation, not customer-safe consumption | preserves current operator initiation flow | avoids adding a second operator export path |
Audience-Aware Disclosure (mandatory when operator-facing surfaces are changed)
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|---|---|---|---|---|---|---|---|
| Customer Review Workspace | operator-MSP, customer-admin, customer-read-only | release state, package readiness, rendered-report availability, next step | none beyond current review state | raw pack files, fingerprints, internal reasoning | Open review |
raw/support detail stays off the list surface | workspace rows say whether the handoff is ready; detail owns the explanation |
| Released review detail in customer-workspace mode | operator-MSP, customer-admin, customer-read-only | rendered summary, evidence basis, limitation state, one output action | review lineage and deeper governance detail in secondary sections | raw payloads, fingerprints, platform reason family, internal reason ownership | Open rendered report or equivalent safe output action |
appendix/raw detail stays secondary | the report intent is stated once and later sections add evidence |
| Review Pack detail and rendered report | operator-MSP, customer-admin, auditor-read-only | rendered story first, appendix relationship second, truthful availability | technical metadata and ZIP details remain secondary | raw JSON files, fingerprints, support-only interpretation | Open rendered report or Download rendered report |
raw bundle detail remains lower priority | the rendered report explains the human-readable path once; ZIP metadata stays supportive only |
| Published review detail in operator mode | operator-MSP | export readiness, reuse truth, current pack availability | run detail and pack metadata after explicit follow-up | raw appendix files remain on the pack/resource seam | Export executive pack |
customer-safe rendered copy stays off blocked/draft operator states | operator initiation does not duplicate customer-facing delivery text |
UI/UX Surface Classification (mandatory when operator-facing surfaces are changed)
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Customer Review Workspace governance-package area | Dashboard / Workbench | Customer-safe workspace review hub | Open the released review that is ready for delivery | existing review-open inspect path | existing | supporting output actions stay off the list row | none | /admin/reviews/workspace |
existing review detail route | workspace plus optional managed-environment filter | Customer review | whether the current released review is ready for a rendered handoff | none |
| Released review detail in customer-workspace mode | Detail / Report | Read-only detail report | Open the rendered report | sectioned detail with one dominant safe action | forbidden | appendix/proof links remain in-body secondary | none | /admin/reviews/workspace |
existing review detail route | workspace, managed environment, released review | Governance package | what the rendered handoff means and whether it is available | none |
| Review Pack detail and rendered report | Detail / Report / Export Viewer | Read-only artifact viewer | Inspect or download the presentable output | detail then explicit report open | existing detail row click on pack list stays current | ZIP diagnostics and raw metadata stay secondary | none | current review-pack collection route | current review-pack detail and render route | workspace, managed environment, artifact state | Review pack / rendered report | rendered output readiness and appendix relationship | none |
| Published review detail in operator mode | Detail / Report / Export initiation | Operator export surface | Generate or reuse the current pack | existing detail/open model | existing | pack detail and run links remain secondary | none | existing review collection route | existing review detail route | managed environment, review status, pack status | Executive pack export | whether the current output can be prepared or reused now | none |
Operator Surface Contract (mandatory when operator-facing surfaces are changed)
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Customer Review Workspace | MSP operator | Decide whether a released review is ready to hand over | Read-only workspace report | Is there a presentable current review I can share now? | release state, rendered-output availability, next step | none beyond secondary detail | release readiness, evidence sufficiency, package availability | none | Open review | none |
| Released review detail in customer-workspace mode | MSP operator or entitled customer reader | Understand and open the presentable report | Read-only detail report | What will the stakeholder read first, and what are the limitations? | executive summary, evidence basis, limitations, one output action | deeper governance detail, lineage, proof links | delivery readiness, evidence sufficiency, review status | none | Open rendered report / Download rendered report | none |
| Review Pack detail and rendered report | MSP operator or entitled reviewer | Inspect the current artifact in human-readable form | Read-only artifact viewer | Can I open a calm report from the current pack without unpacking it? | rendered report, appendix explanation, availability | ZIP metadata, fingerprints, technical context | artifact readiness, delivery status | none | Open rendered report | none |
| Published review detail in operator mode | MSP operator | Prepare or reuse the current pack | Export-initiation detail surface | Can I prepare the presentable output now, or is a current pack already available? | review status, reuse truth, pack availability | run detail and pack metadata | review status, pack availability | current ReviewPackGenerate only |
Export executive pack | none |
Proportionality Review (mandatory when structural complexity is introduced)
- New source of truth?: no
- New persisted entity/table/artifact?: no new persistence family; current
ReviewPackremains the source artifact - New abstraction?: no new cross-domain abstraction by default; any helper must stay local to current review-pack/report rendering
- New enum/state/reason family?: no
- New cross-domain UI framework/taxonomy?: no
- Current operator problem: the current output still requires ZIP-first explanation, which weakens customer/demo consumption even though the underlying review truth is already repo-real.
- Existing structure is insufficient because: the current Markdown entrypoint and JSON appendix are accurate but not directly consumable as a calm rendered report.
- Narrowest correct implementation: render one HTML report from current review-pack/review truth and only allow PDF when the same contract can produce it without new infrastructure.
- Ownership cost: maintain one bounded report view, one or more read-only routes/actions, and focused customer-safe regression coverage.
- Alternative intentionally rejected: a customer portal, a second report engine, or a new PDF dependency were rejected as broader than current-release truth requires.
- Release truth: current-release sellability follow-through, not future delivery automation.
Compatibility posture
This feature assumes a pre-production environment.
Backward compatibility, legacy aliases, migration shims, historical fixture support, and compatibility-specific tests are out of scope unless explicitly required by this spec.
Current review-pack extension is preferred over a new delivery artifact family.
Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)
- Test purpose / classification: Feature, Browser
- Validation lane(s): confidence, browser,
git diff --check - Why this classification and these lanes are sufficient: focused Feature tests can prove rendered contract truth, authorization, audit continuity, and honest PDF handling. One bounded browser smoke is justified because the rendered report is a customer-facing delivery surface.
- New or expanded test families: extend existing
apps/platform/tests/Feature/EnvironmentReview/,apps/platform/tests/Feature/ReviewPack/includingReviewPackResourceTest.php,apps/platform/tests/Feature/Reviews/, and current customer-review browser smoke coverage - Fixture / helper cost impact: low to moderate; reuse current released-review, review-pack, evidence-snapshot, and entitlement fixtures. No provider-sync, no new queue family, and no heavy-governance lane are needed.
- Heavy-family visibility / justification: none beyond one explicit browser smoke or an existing browser family extension
- Special surface test profile: shared-detail-family
- Standard-native relief or required special coverage: customer-workspace detail plus rendered report need explicit disclosure and action-hierarchy coverage; ordinary review-pack CRUD smoke is not sufficient
- Reviewer handoff: reviewers must confirm HTML is the mandatory floor, PDF is not falsely claimed, the renderer stays on the current
ReviewPackfamily, and no second artifact family or new package appears - Budget / baseline / trend impact: low feature-local increase only
- Escalation needed:
document-in-featureif the repo cannot support PDF without a package and the slice lands HTML-only - Active feature PR close-out entry: Smoke Coverage
- Planned validation commands:
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && 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 tests/Feature/ReviewPack/ReviewPackResourceTest.phpexport PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php
User Scenarios & Testing (mandatory)
User Story 1 - Open A Calm Rendered Review Report (Priority: P1)
As an entitled operator or customer-safe reviewer, I want to open one calm rendered report from the current released review/current pack context so I do not have to unzip a package and explain Markdown/JSON files first.
Why this priority: This is the core productization gap. Without a rendered report, the output still feels like an internal artifact.
Independent Test: From the current customer-review/review-pack flow, open the rendered report and verify that executive story, evidence basis, limitations, findings, accepted risks, and non-certification disclosure are visible without raw diagnostics by default.
Acceptance Scenarios:
- Given a released review with a ready current pack, When an entitled user opens the rendered output, Then the report shows the executive story, evidence basis, limitations, key findings, accepted risks, and appendix relationship from current stored truth.
- Given a current pack whose output readiness is
partial,blocked, orexpired, When the user opens the owner surfaces, Then the product explains the limitation truthfully and does not overclaim a customer-ready rendered report.
User Story 2 - Keep Printable Delivery Honest And Bounded (Priority: P1)
As an MSP operator, I want the same rendered contract to support a printable handoff path when the repo can do so honestly, but I do not want the product to promise PDF when current dependencies cannot support it safely.
Why this priority: A printable artifact is part of the draft's user value, but false PDF claims or a second rendering engine would create more debt than value.
Independent Test: Verify that the current review/review-pack flow exposes one rendered output contract, that HTML is always available, and that PDF is either supported from the same contract or truthfully unavailable without a dependency addition.
Acceptance Scenarios:
- Given the repo can render PDF from the same contract without a new package, When an entitled user requests a printable version, Then the product serves PDF from the same underlying rendered report and does not introduce a second artifact family.
- Given the repo cannot render PDF without adding a package, When an entitled user uses the output surfaces, Then the product still serves the HTML report and does not label PDF as available.
User Story 3 - Keep Delivery Tenant-Safe, Auditable, And Derived (Priority: P2)
As a platform owner, I want rendered delivery to stay on the current entitlement, audit, and review-pack truth seams so the presentable report does not become a second uncontrolled export surface.
Why this priority: The sellability gain matters only if it stays on the current authorization and audit model.
Independent Test: Verify non-members receive 404, in-scope viewers stay on the current read-only permission paths, and export/download/render actions keep the current audit and OperationRun boundaries.
Acceptance Scenarios:
- Given a non-member or wrong-environment target, When they try to open the rendered report or current pack route, Then the response remains deny-as-not-found.
- Given an entitled viewer, When they open the rendered report, Then the content is derived from existing review-pack/review truth and does not trigger live provider calls or a new queue/run path.
Edge Cases
- A released review exists but no ready current pack exists yet: the owner surfaces stay truthful about unavailability and do not fabricate a rendered handoff action.
- The current pack is expired: the owner surfaces show
expired, and the user must rely on the current operator export path rather than a stale rendered link. - Evidence is partial or stale: the rendered report must carry the limitation state explicitly instead of reading as customer-safe ready.
- Workspace lifecycle blocks new pack generation but an existing ready pack remains readable: export stays blocked while current read-only access remains governed by existing entitlement rules.
- PDF support is absent in current repo dependencies: the feature must still ship HTML cleanly or stop at the documented HTML-only boundary without adding a package.
Requirements (mandatory)
Constitution alignment: This feature reuses the current ReviewPackGenerate OperationRun path and current review-pack authorization/download seams. It must not introduce a second run type, a second artifact family, or live provider calls during render.
Constitution alignment (PROP-001 / PERSIST-001 / BLOAT-001): The rendered output must remain derived from current review/review-pack truth. If implementation requires a new table, a second persisted artifact family, or a new dependency-backed rendering engine, the scope fails and must split.
Constitution alignment (XCUT-001): Delivery status messaging, rendered report actions, and customer-safe disclosure must extend the current review/review-pack/report seams rather than introducing a parallel local UX language.
Functional Requirements
- FR-356-001: The current review-derived
ReviewPackremains the source artifact for this slice; no second artifact family may be introduced. - FR-356-002: Operator-side export initiation for published reviews must continue to reuse the current
export_executive_packaction and currentReviewPackGenerateOperationRunsemantics. - FR-356-003: The renderer must consume the current review-derived runtime truth exposed by
EnvironmentReview,EnvironmentReviewSection,ReviewPack, current readiness semantics, and current governance-package summary truth. It must stay semantically consistent with the existing ZIP contract, including the currentexecutive-summary.mdand section ordering/content, without requiring archive re-parsing as the primary runtime source. - FR-356-004: V1 must provide one rendered HTML report suitable for customer-safe and demo-ready consumption without requiring JSON inspection by default.
- FR-356-005: The HTML report must present executive story, evidence basis, limitation state, key findings, accepted risks, governance decisions requiring awareness, next actions, and explicit non-certification disclosure.
- FR-356-006: The rendered report must not expose raw provider payloads, fingerprints, internal reason ownership, platform reason families, or operator-only diagnostics by default.
- FR-356-007: The rendered output must remain anchored to one released review and one current review pack. No batch, portfolio, or multi-review delivery is allowed in v1.
- FR-356-008:
CustomerReviewWorkspace, released-review detail, review-pack detail, and any render/download actions must keep readiness states truthful and must not imply rendered or PDF readiness when the current truth does not support it. - FR-356-009: PDF is allowed only if the repo can generate it from the same rendered contract without a new package, a second render subsystem, or a second artifact family. Otherwise HTML remains the v1 floor and the product must stay honest about PDF unavailability.
- FR-356-010: Existing export/download audit events and metadata must be reused or minimally extended. A new renderer-specific audit family is out of scope.
- FR-356-011: This slice must not add a new panel, a new global-search surface, or a new Filament asset strategy.
- FR-356-012: This slice must not require live provider calls or Graph calls during render.
- FR-356-013: Report chrome and app actions must render outside the report canvas and must be hidden from print output so printed reports contain no operator/admin controls.
- FR-356-014: The rendered report must show a readiness-aware hero state at the top. Customer-safe labels may appear only when the stored review/pack readiness supports them; limited, internal, PII, blocked, or not-ready outputs must show an external-sharing warning.
- FR-356-015: The report must include a management-readable Executive Summary that explains overall state, reason, impact, recommended next action, and top limitations without making raw state keys the dominant copy.
- FR-356-016: Output limitations and evidence-basis copy must be human-readable, early in the report, and honest about shareability. Technical state fields may appear only in the supporting appendix.
- FR-356-017: Report localization must not leak raw
localization.*keys in EN or DE, including the non-certification disclosure. - FR-356-018: Empty or zero-heavy sections must collapse to compact empty-state copy instead of large KPI/card grids.
- FR-356-019: The appendix must appear after the management/readiness/risk/evidence sections, be clearly marked as supporting/auditor context, and avoid raw JSON dump presentation.
- FR-356-020: Accepted-risk content must use customer-safe summaries when available, must not expose internal rationale as customer-safe copy, and must honestly show expired/expiring/incomplete state without legal or approval claims.
- FR-356-021: Controlled MSP co-branding is limited to repo-backed existing workspace/environment names plus TenantPilot generated-by copy. No branding settings, upload UI, theme engine, or new persistence may be added.
- FR-356-022: Report/download labels must be readiness-aware and must not use forbidden terms such as customer-ready, certified, approved compliance report, or share-with-customer for limited/internal/blocked output.
- FR-356-023: The existing ZIP review-pack download/export contract must continue to work unchanged alongside the rendered HTML/print report.
Scope Boundaries
In Scope
- one rendered HTML report over the current review-derived
ReviewPackcontract - truthful preview/download affordances on the current review/customer-workspace/report seams
- honest PDF handling from the same contract when current repo support exists
- localized copy required to explain rendered output, appendix relationship, and PDF availability truthfully
- focused authorization, audit, disclosure, and browser smoke follow-through for the rendered report
- bounded productization of report presentation, readiness copy, print chrome, localization, compact empty sections, supporting appendix, accepted-risk display, evidence-basis explanation, and repo-backed MSP co-branding slots
Out Of Scope
- a customer portal
- a standalone
AuditorPackorRenderedReportpersistence family - a new PDF dependency or rendering package
- email delivery, scheduled delivery, public sharing, or branding/white-label systems
- multi-review or multi-tenant bundles
- a second review composition engine
- AI-generated report narratives
- a branding admin UI, logo upload, accent/theme engine, customer-specific templates, public links, customer accounts, or customer portal
Success Criteria
- Entitled users can open one rendered HTML report from current released-review/current-pack context without unzipping JSON first.
- The rendered output stays customer-safe, limitation-aware, and derived from current stored truth.
- PDF is either served from the same contract without new infrastructure or explicitly and honestly unavailable.
- No second artifact family, new package, new queue family, or live provider render path is introduced.
Risks
- Risk 1 - PDF support gap: current repo dependencies do not provide an approved native report PDF stack for this slice. Mitigation: HTML and browser print are mandatory; native PDF remains a documented follow-up behind the hard no-new-package boundary.
- Risk 2 - Scope creep into portal/reporting engine work: presentable output can tempt broader document-delivery ambitions. Mitigation: stay on the current review-pack family and existing routes/surfaces only.
- Risk 3 - Duplicate truth drift: rendered copy could diverge from current review detail or executive-summary truth. Mitigation: keep one render contract sourced from current stored review-pack/review data.
- Risk 4 - Customer-safe overclaim: a rendered report can look more final than the underlying evidence state deserves. Mitigation: render limitation state and non-certification disclosure explicitly.
Follow-Up Candidates
- PDF-only delivery hardening if HTML lands and the repo later gains an approved PDF stack
- richer customer-facing localization adoption over rendered delivery surfaces
- customer portal boundary work only after current rendered delivery is proven
Assumptions
- Spec 355's browser-verified readiness gate is sufficient proof that the current review/output flow is coherent enough for a rendered delivery follow-up.
- Current
ReviewPackandEnvironmentReviewsummary truth is rich enough to drive an HTML report without live provider calls. - Implementation and productization changes are included in this branch; close readiness is based on completed validation, screenshots, and reviewer acceptance rather than additional preparation-only work.
Open Questions
No blocking implementation questions remain.
Runtime constraint result:
- the current repo does not provide an approved native report PDF stack from the same render contract without a new dependency; the slice remains HTML-first with browser print and records native PDF as a bounded follow-up instead of widening scope