## Summary - productize the customer review workspace as a workspace-wide customer-safe review hub - add customer-safe latest review, decision summary, accepted risks, evidence basis, and review-pack presentation updates - update localized copy, focused feature coverage, browser smoke coverage, and Spec 312 artifacts ## Testing - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php` - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - `git diff --check` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #367
48 KiB
Feature Specification: Customer Review Workspace v1 Completion
Feature Branch: 312-customer-review-workspace-v1-completion
Created: 2026-05-15
Status: Draft
Input: User-provided full Spec 312 draft plus repo-backed candidate Customer Review Workspace v1 Completion.
Spec Candidate Check (mandatory - SPEC-GATE-001)
- Problem: Customer Review Workspace has repo-real foundations, but the customer-facing review consumption experience is still too list-like and technical. Stakeholders do not immediately understand the latest released review, customer-safe decision summary, accepted risks, evidence basis, review-pack status, and next action in one coherent surface.
- Today's failure: A workspace can have released reviews, review packs, decision summaries, accepted-risk data, and evidence truth, yet the customer-safe surface can still require operator translation. Filtered empty states and legacy reviews without Spec 308 summary content can also imply the wrong state or expose too much technical detail if not handled deliberately.
- User-visible improvement: Customer Review Workspace becomes a calm workspace-wide review hub that makes the current released review, decisions requiring awareness, accepted risks, evidence basis, review-pack availability, and one primary next action visible without exposing raw diagnostics or operator lifecycle actions.
- Smallest enterprise-capable version: Productize only the existing Customer Review Workspace read surface and its existing review/detail/pack handoffs. Use existing
EnvironmentReview.summary,governance_package.decision_summary,ReviewPackstatus truth, existing route helpers, existing RBAC, and focused rendered-HTML tests. No shell, sidebar, topbar, RBAC, persistence, OperationRun, provider, billing, AI, or artifact-lifecycle work. - Explicit non-goals: No changes to
OperateHubShell,TenantPageCategory,NavigationScope,WorkspaceSidebarNavigation, route-scope contract, RBAC, policies, migrations, tables, columns, models, persisted status families, OperationRun types, Review Pack generation semantics, provider connection scope, billing, AI summaries, artifact lifecycle, PSA handoff, broad localization, canonical query cleanup, or Environment Review / Review Pack resource redesign. - Permanent complexity imported: Feature-local page payload shaping, localized copy keys where surrounding code already uses localization, focused feature/browser coverage, and an implementation close-out entry. No new persisted truth, public framework, enum/status family, model, table, asset bundle, or OperationRun type.
- Why now:
docs/product/spec-candidates.mdlists Customer Review Workspace v1 Completion as the first post-Spec-311 P1 manual-promotion candidate. Spec 308 made customer-safe decision summaries available, and Spec 311 completed the workspace/environment shell-scope contract. The next narrow step can now focus on productizing customer-safe consumption. - Why not local: A one-off table label or a detail-only tweak would not solve the review-consumption workflow. A portal rewrite or shell fix would be too broad. The narrow correct slice is to shape and render existing released-review, decision-summary, accepted-risk, evidence, and pack truth on the existing workspace hub.
- Approval class: Workflow Compression.
- Red flags triggered: Customer-safe disclosure across review, pack, and evidence presentation. Defense: scope is bounded to existing surfaces and existing truth, with explicit no-new-persistence, no-new-status, no-new-RBAC, no-new-shell, and no-new-lifecycle constraints.
- Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 2 | Produktnaehe: 2 | Wiederverwendung: 2 | Gesamt: 12/12
- Decision: approve.
Spec Scope Fields (mandatory)
- Scope: workspace-wide customer-safe review consumption surface, with environment selection only as a page-level data filter.
- Primary Routes:
- Customer Review Workspace: existing
CustomerReviewWorkspaceroute with slugreviews/workspace. - Environment Review detail: existing canonical environment-bound
EnvironmentReviewResourceview route. - Review Pack delivery: existing Review Pack view/download route or customer-safe signed download flow where already available.
- Customer Review Workspace: existing
- Data Ownership:
- Review truth remains
EnvironmentReview.status,EnvironmentReview.published_at, andEnvironmentReview.summary. - Decision truth remains
FindingException/FindingExceptionDecision, represented through existing released-review governance-package summary. - Evidence truth remains
EvidenceSnapshotand existing evidence summary fields. - Review Pack truth remains
ReviewPack.status, file path availability,ReviewPack.summary, and existing pack metadata. - Execution truth remains
OperationRunand must not be rendered as raw customer-safe detail.
- Review truth remains
- RBAC:
- Workspace membership remains required.
- Managed environment entitlement remains required for environment-filtered data and environment-bound detail routes.
- Existing review and review-pack policies/capabilities remain authoritative.
- Non-member / out-of-scope access remains deny-as-not-found according to existing semantics.
- Member missing capability remains denied according to existing policy semantics.
For canonical-view specs:
- Default filter behavior when tenant-context is active: Customer Review Workspace remains workspace-wide. Remembered environment or Filament tenant context must not become global shell context. Query parameters such as
tenantormanaged_environment_idmay set only the page-level environment filter when existing behavior supports them. - Explicit entitlement checks preventing cross-tenant leakage: Counts, latest-review selection, decision summaries, review-pack links, and empty-state distinction must be scoped to the current workspace and the actor's managed-environment entitlements.
Cross-Cutting / Shared Pattern Reuse (mandatory)
- Cross-cutting feature?: yes.
- Interaction class(es): customer-safe review consumption, status messaging, action links, empty states, evidence/report disclosure, review-pack availability.
- Systems touched:
CustomerReviewWorkspace,customer-review-workspace.blade.php, existingEnvironmentReviewResourcehandoff only if required, existing Review Pack view/download handoff only if required, existing review workspace feature tests, review-pack tests, and existing browser smoke. - Existing pattern(s) to extend: existing Customer Review Workspace table/page, existing
EnvironmentReviewRegisterService::customerWorkspaceTenantQuery(), existingEnvironmentReview::published()scope, existinggovernance_package.decision_summary, existingReviewPackStatus, existingCapabilities::REVIEW_PACK_VIEW, existing localization file structure, existingcustomer_workspace=1detail context. - Shared contract / presenter / builder / renderer to reuse: Reuse
EnvironmentReviewRegisterService,EnvironmentReviewResource::tenantScopedUrl(), existingReviewPackstatus enum/constant truth, existingArtifactTruthPresenterwhere already used, existing Filament/Blade page patterns, and existing localization keys. Do not create a public decision-summary presenter framework for v1. - Why the existing shared path is sufficient or insufficient: Existing services already provide authorized workspace/environment review queries and existing summaries contain Spec 308 decision content. The current page is insufficient as a customer-safe consumption surface because it does not yet present latest review, decision summary, accepted risks, evidence basis, pack status, and filter-aware empties as one coherent experience.
- Allowed deviation and why: A page-local private helper for derived display payloads is allowed if it keeps the implementation narrow and avoids business logic in Blade. New shared frameworks, new DTO families, and new persisted summaries are not allowed.
- Consistency impact: Wording and status mapping must stay aligned across Customer Review Workspace, Environment Review detail handoff, and Review Pack availability. Customer-safe labels must avoid raw IDs, fingerprints, raw payloads, OperationRun URLs, provider dumps, and internal reason families.
- Review focus: Verify no shell/sidebar/topbar regression, no raw leakage, no operator-only actions, no new persistence/status families, no policy/RBAC change, no Review Pack generation semantics change, and no
/admin/tlinks.
OperationRun UX Impact (mandatory)
- Touches OperationRun start/completion/link UX?: no.
- Shared OperationRun UX contract/layer reused: N/A. Existing Review Pack generation may have OperationRun behavior, but Spec 312 must not create, start, mutate, link, or expose OperationRun raw detail from the customer-safe workspace.
- Delegated start/completion UX behaviors: unchanged.
- Local surface-owned behavior that remains: Read-only review and pack availability presentation only.
- Queued DB-notification policy: N/A.
- Terminal notification path: unchanged.
- Exception required?: none.
Provider Boundary / Platform Core Check (mandatory)
- Shared provider/platform boundary touched?: no.
- Boundary classification: platform-core customer review consumption over existing governance artifacts.
- Seams affected: Existing review, evidence, decision, and review-pack summaries. No Graph contract, provider connection, provider credential, or provider dispatch seam changes.
- Neutral platform terms preserved or introduced: workspace, managed environment, customer review, released review, governance decisions requiring awareness, accepted risks, evidence basis, review pack, next action.
- Provider-specific semantics retained and why: Existing review/evidence titles may contain Microsoft/Intune terms when that is the existing customer-safe content. Spec 312 must not introduce new provider-specific platform-core vocabulary.
- Why this does not deepen provider coupling accidentally: The workspace derives display from TenantPilot review and governance artifact truth, not raw provider payloads or Graph endpoints.
- Follow-up path: provider connection scope hardening remains a separate follow-up candidate.
UI / Surface Guardrail Impact (mandatory)
| 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 overview | yes | Existing Filament page plus existing Blade view composition | customer-safe review consumption, status messaging, empty states, action links | page, table, URL query filter | no | Productize existing page only |
| Latest released review section | yes | Existing Filament/Blade page composition | review handoff, review-pack handoff | page payload | no | One dominant CTA only |
| Decision summary / accepted risks / evidence basis | yes | Existing summary payload rendered as customer-safe content | evidence/report disclosure | page payload | no | No raw payloads or diagnostics |
| Environment Review detail handoff | possible | Existing native Filament resource | released-review detail | detail query context | no | Only if canonical customer-safe handoff needs adjustment |
| Review Pack download/open handoff | possible | Existing resource/download route | artifact delivery | link/action visibility | no | No generation/regeneration/expire action |
| Shell/sidebar/topbar | no | N/A | route-scope contract | none | no | Must not change |
Implementation intent: use existing Filament-native components and the current Blade view. Do not add CSS, JS, images, icon packs, assets, or ad-hoc styling systems. Keep Filament v5 / Livewire v4.1.4+ compatible.
Decision-First Surface Role (mandatory)
| 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 | Primary customer-safe consumption surface | Stakeholder or MSP operator understands current released review status and next action | latest released review, customer-safe decision summary, accepted risks, evidence basis, review-pack state, primary CTA | Environment Review detail and Review Pack download/open | Primary because it is the workspace-wide customer hub | Follows released-review consumption, not operator lifecycle work | Removes manual translation across review, pack, evidence, and decision pages |
| Environment Review detail | Secondary detail surface | Reader inspects the selected released review | released review context and existing customer-safe summary | sections, evidence, package detail where allowed | Secondary because it deepens the chosen review | Existing owner of review detail | Prevents rebuilding review detail inside workspace |
| Review Pack delivery | Artifact delivery surface | Reader downloads or opens the prepared package | pack availability/download when authorized | package content | Delivery artifact, not a workspace dashboard | Existing pack owner remains authoritative | Avoids creating parallel artifact lifecycle |
Audience-Aware Disclosure (mandatory)
| 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 | customer-read-only, MSP operator | latest review, decisions requiring awareness, accepted risks, evidence basis, pack status, filter state | none by default | raw evidence JSON, fingerprints, OperationRun URLs, provider payloads hidden | Download/open review pack when available; otherwise open review; clear filter in filtered empty state | operator-only lifecycle actions and raw/internal metadata | Workspace states the decision once; detail/export provide evidence |
| Environment Review detail handoff | customer-read-only, MSP operator | selected released review summary and package availability | existing detail sections only where allowed | raw/support details not introduced here | existing detail action hierarchy | publish/refresh/archive hidden in customer workspace mode | Detail remains review owner |
| Review Pack handoff | customer-read-only, MSP operator | available/preparing/not available/expired/unavailable state and download/open when authorized | none from workspace | storage path, policy internals, exception internals hidden | download/open only when authorized | generate/regenerate/expire hidden from customer workspace | Pack status uses existing ReviewPack truth |
UI/UX Surface Classification (mandatory)
| 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 | List / Review Workspace | Customer-safe workspace hub | Download/open review pack or open latest review | Dedicated CTA/link, not full-row fake affordance | current no-row-click behavior preserved unless repo-real route/capability allows | secondary links neutral and contextual | none | existing /admin/reviews/workspace |
existing EnvironmentReviewResource view |
workspace plus optional environment filter label | Customer reviews | latest review, decision summary, accepted risks, evidence basis, pack state | none |
| Filtered empty state | Empty State | Filter-aware customer review empty | Clear environment filter | Single clear-filter CTA when applicable | N/A | none | none | existing workspace route | N/A | active page-level filter | Customer reviews | filter has no matches vs no released reviews exist | none |
| Review Pack handoff | Detail / Artifact delivery | Download/open existing pack | Download/open pack | Existing route/action | N/A | status explanation neutral | existing operator actions elsewhere only | existing ReviewPack route | existing ReviewPack route/download | environment and review context | Review pack | availability and authorization-safe status | none |
Operator Surface Contract (mandatory)
| 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 | Customer-safe reader / MSP operator | Consume released review and choose next safe action | Workspace review hub | What is the current released customer review and what needs attention? | latest review, environment filter, decision summary, accepted risks, evidence basis, review-pack availability, primary next action | none by default | review release status, decision awareness, evidence completeness, review-pack availability | none | Download/open review pack, Open review, Clear filter | none |
| Environment Review detail handoff | Customer-safe reader / MSP operator | Inspect selected released review | Existing detail page | What does this released review contain? | existing customer-safe review detail | existing diagnostics only where already allowed | review status, evidence completeness, pack availability | existing read/download only | Open review / Download pack where existing | no new dangerous actions |
| Review Pack handoff | Customer-safe reader / MSP operator | Receive prepared package | Existing artifact flow | Is the review pack available to download/open? | pack state, safe explanation, download/open when authorized | none from workspace | ready/preparing/not available/expired/unavailable/evidence incomplete | existing download only | Download/open pack | no generate/regenerate/expire in workspace |
Proportionality Review (mandatory when structural complexity is introduced)
- New source of truth?: no.
- New persisted entity/table/artifact?: no.
- New abstraction?: no public abstraction. Page-local private display helpers are allowed only if needed to avoid Blade logic.
- New enum/state/reason family?: no persisted or domain state. Customer-safe display labels are derived from existing
EnvironmentReviewStatus,EnvironmentReviewCompletenessState,ReviewPackStatus, and existing summary payloads. - New cross-domain UI framework/taxonomy?: no.
- Current operator problem: Customer-safe review consumption still requires operator translation and can confuse filtered absence, incomplete evidence, missing packs, and no decisions.
- Existing structure is insufficient because: Current workspace table and intro copy do not yet present the released-review story as latest review plus decision summary, accepted risks, evidence basis, pack state, and one next action.
- Narrowest correct implementation: Shape and render a derived page payload from existing review/pack/evidence truth, add localized copy where needed, and cover with focused tests.
- Ownership cost: Feature-local tests, localization keys, and page helper maintenance.
- Alternative intentionally rejected: New customer portal, new review-pack status machine, new summary persistence, new customer approval workflow, shell/sidebar route fix, and broad localization adoption.
- Release truth: Current-release productization over existing review and governance artifacts.
Compatibility posture
This feature assumes pre-production runtime posture but requires legacy customer-safe rendering for released reviews or Review Packs created before Spec 308. The compatibility behavior is display-only: show unavailable/incomplete decision/evidence states without failing or exposing raw payloads. No data backfill, migration shim, dual-write, or persisted legacy alias is allowed.
Summary
Spec 312 finalizes Customer Review Workspace as a customer-safe, workspace-wide review consumption surface for released environment reviews.
After Spec 308, customer-safe Decision Summary content exists in Environment Reviews and Review Packs. After Spec 311, route scope is separated from page-level environment filters. Spec 312 uses that foundation and productizes consumption only:
- latest released review visibility
- deterministic latest-review selection
- customer-safe Decision Summary
- accepted risks
- evidence basis
- Review Pack status and download/open handoff
- clear empty states
- no operator-only lifecycle actions
- no raw/internal/debug leakage
- robust legacy fallback for pre-Spec-308 review/pack content
This is not a shell, navigation, RBAC, provider, billing, AI, artifact-lifecycle, migration, or OperationRun spec.
User Scenarios & Testing (mandatory)
User Story 1 - See the current released review first (Priority: P1)
As a customer-safe reader, I want the workspace to show the latest released review prominently so I know which review is current.
Why this priority: Without a deterministic latest/current review, the workspace remains a list that still needs operator explanation.
Independent Test: Seed multiple published reviews with distinct and tied timestamps, open Customer Review Workspace, and assert the latest review section uses published_at desc, then generated_at or repo-real fallback, then id desc.
Acceptance Scenarios:
- Given multiple released reviews in the workspace, When the workspace renders, Then the latest/current review section shows the deterministic latest released review.
- Given an active environment filter, When matching released reviews exist, Then latest selection is scoped to that filter without changing shell/sidebar/topbar context.
- Given multiple released reviews with equal timestamps, When latest selection runs, Then the repo-real stable tie-breaker selects the same review every time.
User Story 2 - Understand decisions, risks, and evidence without raw data (Priority: P1)
As a stakeholder, I want the workspace to explain decisions requiring awareness, accepted risks, and evidence basis in customer-safe language so I can understand the review without internal diagnostics.
Why this priority: This is the core customer-safe productization value unlocked by Spec 308.
Independent Test: Render workspace HTML for released reviews with decision summary states requires_awareness, none, unavailable, and incomplete, and assert customer-safe copy appears while raw payloads, fingerprints, OperationRun URLs, provider dumps, and internal reason families do not.
Acceptance Scenarios:
- Given a released review with Spec 308
decision_summary, When the workspace renders, Then the customer-safe summary count, status, text, entries, and next action are visible. - Given no decisions require awareness, When the workspace renders, Then it says no decisions require awareness and does not imply incomplete evidence.
- Given missing or incomplete decision/evidence summary, When the workspace renders, Then it shows unavailable/incomplete evidence, not "No decisions".
- Given accepted risks in customer-safe released-review scope, When the workspace renders, Then it shows title/state/summary/due context without internal workflow details or mutation controls.
User Story 3 - Know whether a review pack can be consumed (Priority: P1)
As a customer-safe reader, I want Review Pack availability to be clear and actionable so I know whether to download/open the package or inspect the review.
Why this priority: Review Pack is the customer artifact, and ambiguity here makes the workspace not sellable.
Independent Test: Render ready, queued/generating, missing, expired, failed, evidence-incomplete, and unauthorized pack scenarios and assert the customer-safe status and CTA visibility.
Acceptance Scenarios:
- Given a ready downloadable pack and authorized actor, When the workspace renders, Then the primary CTA is download/open review pack.
- Given no downloadable pack, When the workspace renders, Then the primary CTA is open review.
- Given a pack exists but actor lacks download capability, When the workspace renders, Then no download URL appears and the status remains customer-safe.
- Given generating, expired, failed, or missing pack state, When the workspace renders, Then the page maps it to preparing, expired, unavailable, or not available yet.
User Story 4 - Empty states explain filter and availability (Priority: P2)
As an MSP operator, I want empty states to distinguish "no released reviews" from "active filter has no matching released reviews" so I do not misread workspace readiness.
Why this priority: The page is workspace-wide, and filter-aware empty states are required to preserve the Spec 311 scope contract.
Independent Test: Seed released reviews outside the active environment filter, render the workspace with filter query params, and assert the empty state says the filter has no matches and offers clear filter.
Acceptance Scenarios:
- Given no released reviews exist in the workspace, When the workspace renders, Then it says no released customer reviews exist.
- Given released reviews exist elsewhere in the workspace but the active environment filter matches none, When the workspace renders, Then it explains the active filter has no matches and offers clear filter.
- Given a missing, preparing, expired, unavailable, or evidence-incomplete pack, When the review row/section renders, Then the status explanation is specific and customer-safe.
Edge Cases
- No released reviews exist.
- Released reviews exist but active environment filter matches none.
- Released reviews exist globally but not for selected environment.
- Multiple released reviews share the same
published_at. - A published review has no
published_atand must use repo-real fallback ordering. - Review exists but
governance_package.decision_summaryis missing. - Decision summary exists with zero awareness-required decisions.
- Decision summary exists with decisions requiring awareness.
- Decision evidence is incomplete or unavailable.
- Accepted risks exist but are not customer-safe or are redacted.
- Review Pack is missing.
- Review Pack is queued/generating.
- Review Pack is expired.
- Review Pack is failed/blocked/unavailable.
- Review Pack exists but actor lacks download capability.
- Evidence snapshot is missing, restricted, expired, partial, stale, or incomplete.
- Customer-safe detail handoff must preserve
customer_workspace=1or repo-real equivalent. - Existing Review Pack generated before Spec 308 lacks decision summary.
- Query uses legacy
tenantalias. - Query uses canonical
managed_environment_id. - Canonical route contains technical IDs as route params, but visible labels stay customer-safe.
Requirements (mandatory)
Functional Requirements
- FR-001: Customer Review Workspace MUST remain a workspace-wide hub. Environment selection is a page-level filter only and MUST NOT alter shell, sidebar, topbar, breadcrumb, or global environment context.
- FR-002: The page MUST make the latest released review visible when available, including customer-safe review label/title, managed environment label, review status, published date, governance package availability, review-pack status, and primary next action.
- FR-003: Latest released review selection MUST be deterministic: current workspace, actor entitlement, optional page-level environment filter,
published_at desc, repo-real timestamp fallback if needed,created_at/generated_at descfallback where repo-real, and final stable identifier desc. - FR-004: Released reviews SHOULD be shown in a scanable customer-safe list/card/table format with status, environment, published date, decision awareness state, review-pack availability, and open/download action.
- FR-005: The page MUST surface customer-safe Decision Summary from released-review/governance-package truth, preferring Spec 308 content, then existing customer-safe summary fields, then unavailable/incomplete state.
- FR-006: The workspace MUST NOT recompute a second decision source of truth from raw evidence payloads.
- FR-007: Legacy released reviews or Review Packs without Spec 308 summary MUST render customer-safe unavailable/incomplete decision/evidence states instead of failing or exposing raw payloads.
- FR-008: Accepted risks MUST be shown only when customer-visible, accepted/approved according to existing decision truth, included in released review/governance-package scope, and not revoked/superseded/internal-only unless already marked customer-safe.
- FR-009: Evidence basis MUST be concise and customer-safe, using states
complete,no_awareness_required,incomplete,unavailable, ornot_generatedas derived display labels. - FR-010: Incomplete and unavailable evidence MUST NOT be rendered as "No decisions".
- FR-011: Review Pack availability MUST use existing
ReviewPackstatus truth and file availability. Ready/available maps to Available, queued/generating maps to Preparing, missing maps to Not available yet, expired maps to Expired, failed/blocked/inaccessible maps to Unavailable, and evidence-incomplete review context maps to Evidence incomplete. - FR-012: Each review context SHOULD have one dominant primary CTA: download/open pack when available and authorized; otherwise open review; in filtered empty state, clear environment filter.
- FR-013: Customer Review Workspace MUST NOT render generate, regenerate, expire, approve, reject, renew, revoke, close, delete, force delete, restore, rerun, or similar mutation/lifecycle actions.
- FR-014: Empty states MUST distinguish no released reviews, filtered no results, no awareness-required decisions, incomplete/unavailable decision evidence, pack missing, pack preparing, pack expired, and pack unavailable.
- FR-015: If active filter has no matching released reviews but workspace-wide released reviews exist for the actor, the empty state MUST explain that the filter has no matches and SHOULD show clear filter.
- FR-016: Rendered customer-safe HTML and hrefs MUST NOT contain visible raw IDs as labels, source fingerprints, raw OperationRun URLs, raw evidence JSON, provider payload dumps, debug details, internal reason families,
/admin/tURLs, storage paths, policy internals, exception internals, or raw provider/customer payloads. - FR-017: Canonical route parameters may contain repo-real IDs where existing routes require them, but those IDs MUST NOT appear as visible customer-facing labels, headings, badges, summaries, empty-state copy, or CTA text.
- FR-018: Existing authorization behavior MUST remain unchanged and server-side policies remain authoritative.
- FR-019: Existing Review Pack generation, status machine, storage contract, export format semantics, expire/regenerate behavior, and OperationRun lifecycle MUST remain unchanged.
- FR-020: New visible headings, badge labels, empty-state copy, and CTA labels SHOULD use localization keys where the surrounding files already use localization.
Non-Functional Requirements
- NFR-001: Scope MUST remain minimal to Customer Review Workspace productization.
- NFR-002: Rendering MUST be deterministic for the same actor, workspace, filter, review, and pack state.
- NFR-003: The page MUST avoid broad unbounded scans by scoping to workspace and actor-entitled environments, applying the optional page filter, using existing relationships, and using existence queries for filtered/global empty distinction.
- NFR-004: Implementation MUST use Filament v5 / Livewire v4 patterns and MUST NOT introduce a new design framework.
- NFR-005: No new CSS, JS, images, icon packs, assets, tables, columns, models, migrations, persisted status families, or OperationRun types are allowed.
- NFR-006: Runtime tests MUST stay in focused Pest feature lanes and the existing bounded browser smoke when rendered UI changes.
UX Requirements
- UX-001: Default view order SHOULD be latest review, Decision Summary, Review Pack availability / primary action, Accepted Risks, Evidence Basis, then secondary details.
- UX-002: The page MUST avoid button floods, raw diagnostic panels, equal-weight actions, noisy per-row technical links, and debug-like labels.
- UX-003: If environment filter is active, it MUST be visibly explained as a filter, not global context.
- UX-004: Customer-safe wording SHOULD prefer
Governance decisions requiring awareness,Accepted risks,Evidence basis,Review pack,Next action,No decisions require awareness,Decision evidence unavailable, andReview pack is being prepared. - UX-005: The latest/current review area SHOULD keep one visually dominant action.
Security / RBAC Requirements
- SEC-001: Workspace membership remains required.
- SEC-002: Managed environment access remains required for filtered data and environment-bound details.
- SEC-003: Review and Review Pack policies remain authoritative.
- SEC-004: Hiding links in the customer-safe UI is not a security boundary; direct route access must still be denied where policies deny access.
- SEC-005: No lifecycle mutation actions are introduced in the customer-safe workspace.
- SEC-006: No cross-workspace or cross-environment data influences counts, summaries, links, or empty states.
- SEC-007: If a Review Pack exists but the actor lacks download capability, no download URL is rendered.
- SEC-008: Rendered customer-safe workspace HTML MUST NOT contain legacy
/admin/tURLs.
Data / Truth Source Requirements
| Truth | Owner |
|---|---|
| Decision truth | FindingException, FindingExceptionDecision, represented through released review summary |
| Review truth | EnvironmentReview.summary, EnvironmentReview.status, published_at |
| Evidence truth | EvidenceSnapshot and existing evidence summary/completeness fields |
| Review Pack truth | ReviewPack.summary, ReviewPack.status, file path/status and existing metadata |
| Execution truth | OperationRun, not displayed as customer-safe raw detail |
Customer Review Workspace MUST derive display from existing review, pack, decision, and evidence truth and MUST NOT persist a second truth source.
Out of Scope
- Shell/sidebar/topbar/route-scope work.
- Changes to
OperateHubShell,TenantPageCategory,NavigationScope,WorkspaceSidebarNavigation. - RBAC or policy changes unless a repo-real inconsistency is proven and documented before implementation.
- Migrations, new tables, new columns, new models.
- New enum/status/reason families or persisted status families.
- New OperationRun types, lifecycle, start UX, notifications, or raw links.
- Provider connection scope hardening.
- Billing/entitlement/commercial lifecycle work.
- Artifact lifecycle/retention work.
- AI-generated summaries.
- PSA/support-desk handoff.
- Product truth/docs drift cleanup.
- Review-pack artifact family expansion.
- Customer approval workflow.
- Canonical link/query cleanup beyond preserving existing customer-safe handoff.
- Redesign of Environment Review Resource or Review Pack Resource.
Acceptance Criteria
- AC-001: Customer Review Workspace continues to render under the existing workspace-wide shell/sidebar/topbar contract from Spec 311.
- AC-002: Environment filter limits page data but does not change shell, sidebar, breadcrumb, or global context.
- AC-003: When a released review exists, a latest/current review section is visible.
- AC-004: Latest selection is deterministic by published timestamp and repo-real tie-breaker.
- AC-005: Decision Summary content is visible in customer-safe wording when present.
- AC-006: No-awareness state is distinct and calm.
- AC-007: Incomplete/unavailable evidence is not presented as "No decisions".
- AC-008: Accepted risks are visible in customer-safe form when available.
- AC-009: Evidence basis is visible without raw evidence payload.
- AC-010: Review Pack state is clear and customer-safe.
- AC-011: The primary next action is obvious and not competing with operator-only actions.
- AC-012: Rendered customer-safe page does not expose raw/internal/debug/OperationRun/fingerprint data.
- AC-013: Customer-safe surface does not introduce lifecycle mutation actions.
- AC-014: Existing customer review and review-pack authorization behavior remains green.
- AC-015: Opening a review uses canonical environment-bound detail route where applicable and preserves customer-safe origin.
- AC-016: Spec 311 shell/sidebar tests remain unaffected unless no shell/sidebar files are touched, in which case existing focused workspace assertions are sufficient.
- AC-017: Legacy pre-Spec-308 reviews/packs render customer-safe unavailable/incomplete states.
- AC-018: Pack access without capability renders no download URL and no policy/storage internals.
- AC-019: Visible labels use title/environment/published date/customer-safe labels rather than raw database identifiers.
- AC-020: Filtered empty state explains active environment filter and offers/shows clear-filter path when workspace-wide released reviews exist elsewhere.
- AC-021: Rendered customer-safe workspace HTML contains no
/admin/tlinks.
Success Criteria
- A stakeholder can identify the current released review and primary next action in one page.
- Decision Summary, accepted risks, evidence basis, and Review Pack status can be understood without raw diagnostics.
- Legacy reviews/packs without Spec 308 content remain safe and renderable.
- Focused tests cover latest selection, filter empties, decision states, accepted risks, evidence basis, pack states, authorization, leakage, links, and lifecycle-action absence.
- No application code outside the stated review workspace/handoff surfaces is required for implementation.
Test Strategy
Primary test files
Use or extend repo-real equivalents:
apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php
apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php
apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php
apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.php
apps/platform/tests/Feature/EnvironmentReview/EnvironmentReviewExecutivePackTest.php
apps/platform/tests/Feature/ReviewPack/EnvironmentReviewDerivedReviewPackTest.php
apps/platform/tests/Feature/ReviewPack/ReviewPackDownloadTest.php
apps/platform/tests/Feature/ReviewPack/ReviewPackRbacTest.php
Browser smoke is expected if rendered UI changes:
apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php
Planned validation commands
cd apps/platform && ./vendor/bin/sail artisan test --compact \
tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php \
tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php \
tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php \
tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.php
cd apps/platform && ./vendor/bin/sail artisan test --compact \
tests/Feature/EnvironmentReview/EnvironmentReviewExecutivePackTest.php \
tests/Feature/EnvironmentReview/EnvironmentReviewCreationTest.php
cd apps/platform && ./vendor/bin/sail artisan test --compact \
tests/Feature/ReviewPack/EnvironmentReviewDerivedReviewPackTest.php \
tests/Feature/ReviewPack/ReviewPackDownloadTest.php \
tests/Feature/ReviewPack/ReviewPackRbacTest.php
cd apps/platform && ./vendor/bin/sail artisan test --compact \
tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php
cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
git diff --check
Run Spec 311 regression lane only if shell/sidebar/topbar-adjacent files are unexpectedly touched:
cd apps/platform && ./vendor/bin/sail artisan test --compact \
tests/Feature/Filament/PanelNavigationSegregationTest.php \
tests/Feature/Workspaces/GlobalContextShellContractTest.php \
tests/Feature/Filament/WorkspaceContextTopbarAndTenantSelectionTest.php
Assumptions
- Spec 311 is completed and should be treated as a dependency, not reopened.
- Repo-real released status is
EnvironmentReviewStatus::Published/published(). - Repo-real latest ordering currently uses
published_at desc,generated_at desc,id desc; implementation may usecreated_at desconly if repo verification shows it is the correct fallback. - Current workspace query returns entitled
ManagedEnvironmentrows with latest published review relationship; implementation may refine query/payload but must not broaden access. - Spec 308
governance_package.decision_summaryis the preferred customer-safe decision source. - Review Pack downloadable state depends on existing
ReviewPackStatus::Ready, file path truth, expiry, and existing capability/policy checks. - Existing
customer_workspace=1andsource_surface=customer_review_workspaceare the repo-real customer-safe detail handoff indicators unless implementation verifies a different current contract.
Risks
- Old WIP patch could reintroduce shell/sidebar/topbar fixes. Mitigation: reject shell files and confirm no forbidden files changed.
- Customer-safe page could leak raw/internal data. Mitigation: rendered HTML and href leakage tests.
- Canonical route params could be confused with visible ID leakage. Mitigation: allow route params, forbid visible raw IDs as customer-facing meaning.
- Latest selection could be flaky. Mitigation: deterministic timestamp plus stable identifier tests.
- Page could become too busy. Mitigation: decision-first layout and one primary CTA.
- Review Pack states could drift from existing status truth. Mitigation: map from existing
ReviewPackStatusand file/capability truth only. - Authorization could accidentally change. Mitigation: existing RBAC/review-pack tests remain green.
- Legacy pre-Spec-308 summaries could fail or leak. Mitigation: unavailable/incomplete fallback tests.
- Browser smoke could be unavailable locally. Mitigation: document reason and compensate with rendered HTML assertions.
Current Customer Review Workspace Behavior
Repo inspection found:
CustomerReviewWorkspaceis an undiscovered Filament page with slugreviews/workspace, localized title/navigation, and table-based workspace rows.- Workspace rows are
ManagedEnvironmentrecords scoped throughEnvironmentReviewRegisterService::customerWorkspaceTenantQuery(). - The query scopes to current workspace and actor-entitled environments, requires at least one published environment review, and eager-loads one latest published review ordered by
published_at desc,generated_at desc,id desc. - Page-level filter supports
managed_environment_idand explicit query aliasestenant/managed_environment_id; remembered environment context is intentionally not defaulted. - Existing row columns include environment name, governance package availability, review status, evidence status, next step, and open review link.
- Existing customer-safe detail handoff uses
customer_workspace=1,source_surface=customer_review_workspace, and canonicalEnvironmentReviewResource::tenantScopedUrl(). - Existing intro Blade section provides customer-safe workspace intro, canonical note, and non-certification disclosure.
Missing Productization
Current page behavior does not yet fully satisfy the provided 312 target:
- No prominent latest/current review section above the list.
- No dedicated customer-safe Decision Summary section from Spec 308 summary truth.
- Accepted risks are mostly summarized for row logic and are not productized as a clear customer-safe section.
- Evidence basis is not yet explained as the required complete/no-awareness/incomplete/unavailable/not-generated state set.
- Review Pack status mapping needs clearer ready/preparing/missing/expired/unavailable/evidence-incomplete wording and CTA hierarchy.
- Filtered empty state still needs a workspace-wide existence distinction between no released reviews and active filter no matches.
- Legacy pre-Spec-308 summary fallback needs explicit unavailable/incomplete tests.
- Leakage guard needs broader rendered-HTML and href assertions.
Existing Safe Data Sources
- Released review truth:
EnvironmentReview::published()andEnvironmentReviewStatus::Published. - Latest review query:
EnvironmentReviewRegisterService::customerWorkspaceTenantQuery()andlatestPublishedQuery(). - Decision summary source:
EnvironmentReview.summary['governance_package']['decision_summary']. - Accepted risks source:
EnvironmentReview.summary['governance_package']['accepted_risks']and existing released-review/risk acceptance summary fields. - Evidence basis source:
EnvironmentReview.summary['governance_package']['evidence_basis_summary'],EnvironmentReview.summary['evidence_basis'],EvidenceSnapshot, and completeness fields. - Review Pack status source:
ReviewPackStatusenum andReviewPackfile/expiry fields. - Handoff source: existing
EnvironmentReviewResource,ReviewPackResource, andCustomerReviewWorkspace::DETAIL_CONTEXT_QUERY_KEY.
Existing Released Review Selection
Repo-real selection currently orders published reviews by:
published_at descgenerated_at descid desc
Spec 312 implementation should keep that repo-real fallback unless code verification proves created_at is the safer fallback for a specific query.
Existing Review Pack Status Mapping
Repo-real states:
queuedgeneratingreadyfailedexpired
Spec 312 display mapping:
| Repo-real state | Customer-safe state |
|---|---|
| ready with downloadable file and authorization | Available |
| queued / generating | Preparing |
| null pack or missing file | Not available yet |
| expired or past expiry | Expired |
| failed / blocked / inaccessible / unauthorized | Unavailable |
| review or governance package evidence incomplete | Evidence incomplete |
Proposed Minimal Changes
- Add/extend focused tests first in existing Customer Review Workspace, Review Pack, and Environment Review test families.
- Refine
CustomerReviewWorkspacedisplay payload and helpers only as needed. - Update
customer-review-workspace.blade.phpto render a decision-first latest review and summary layout using existing Filament/Blade conventions. - Add minimal localization keys in existing localization files.
- Preserve existing detail and pack handoffs; only touch
EnvironmentReviewResourceif customer-safe handoff cannot be preserved otherwise. - Do not change Review Pack generation/status/storage semantics.
- Do not change shell/sidebar/topbar/RBAC/policies/migrations/assets.
Follow-up Candidates
Not part of Spec 312:
- Provider Connection Scope Hardening
- Canonical Link / Query Cleanup
- Product Truth / Docs Drift Cleanup
- Environment Resource Context Follow-through
- Legacy Compatibility / Dead Code Retirement
- Tenant Helper Naming Cleanup
- Artifact Lifecycle & Retention
- Commercial Entitlements / Billing-State Maturity
- Customer-facing Localization Adoption v1
- Review Pack Backfill for pre-Spec-308 artifacts
- Customer Approval Workflow
- Review Pack Artifact Family Expansion
Done Definition
Spec 312 is done when:
- Customer Review Workspace provides a customer-safe released-review consumption experience.
- Latest review, decision summary, accepted risks, evidence basis, pack status, and one primary next action are visible.
- Latest released review selection is deterministic.
- Empty states are clear and filter-aware.
- Legacy reviews/packs without Spec 308 summary render safe unavailable/incomplete states.
- No raw/internal data leaks.
- No operator-only lifecycle actions appear.
- Existing authorization remains unchanged.
- Focused tests pass.
- Browser smoke passes if available; otherwise non-run reason is documented and rendered HTML assertions cover changed UI.
- Pint dirty passes.
git diff --checkpasses.- No shell/sidebar/topbar, RBAC, migration, OperationRun type, persisted status family, Review Pack generation semantics, or asset changes were introduced.