TenantAtlas/specs/392-customer-output-gating-review-pack-navigation/plan.md
ahmido dd7139ebe3 Spec392 customer output gating (#463)
Implements Spec392 customer output gating for review pack downloads, rendered reports, management PDFs, and customer workspace CTAs.

Validation:
- php vendor/bin/pest --filter=Spec392: 12 passed / 58 assertions
- php vendor/bin/pest --filter='ReviewPack|CustomerReviewWorkspace|StoredReport': 283 passed / 1 skipped / 2053 assertions
- affected browser matrix: 12 passed / 420 assertions
- php vendor/bin/pint --dirty: pass
- git diff --check: pass

Notes:
- Deprecated limited-download semantics remain removed.
- Unsafe customer-facing output returns 403/no output.
- Internal preview/report access is operator-only.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #463
2026-06-20 20:54:50 +00:00

21 KiB

Implementation Plan: Spec 392 - Customer Output Gating & Review Pack Navigation v1

Branch: 392-customer-output-gating-review-pack-navigation | Date: 2026-06-20 | Spec: specs/392-customer-output-gating-review-pack-navigation/spec.md Input: Feature specification from specs/392-customer-output-gating-review-pack-navigation/spec.md

Summary

Implement a route-enforced Customer Output Gate for existing customer-facing review output and correct misleading Review Pack / Customer Workspace navigation labels. The implementation should reuse existing review-pack readiness and disclosure truth first, then introduce one narrow gate/result adapter only if needed to make UI and direct routes consume the same decision.

The primary safety requirement is simple: customer output may be opened or downloaded only when the same canonical decision says it is ready and customer-safe. Internal preview remains separate, secondary, and permission-protected.

Technical Context

Language/Version: PHP 8.4.15 Primary Dependencies: Laravel 12.52, Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1 Storage: PostgreSQL; no new storage expected Testing: Pest 4, Laravel Feature/HTTP tests, Filament/Livewire tests, bounded Browser smoke Validation Lanes: fast-feedback, confidence, browser Target Platform: Laravel Sail local; Dokploy container deployment for staging/production Project Type: Laravel monolith under apps/platform Performance Goals: DB-only gate evaluation during render/download; no Graph or remote calls Constraints: no new persisted readiness truth; no broad Customer Review Workspace rebuild; no route bypass; no unsafe customer-facing download with limitations Scale/Scope: existing review, review-pack, stored-report, rendered-report, dashboard, evidence overview, and customer-workspace output surfaces only

Technical Approach

  1. Inventory existing customer-output actions and routes.
  2. Define a single customer-output gate decision shape over existing readiness/disclosure/policy truth.
  3. Enforce the gate at direct routes before any file stream, rendered report, signed URL, or customer-facing page output.
  4. Replace misleading customer-facing labels with truthful destination-specific labels.
  5. Separate customer output from internal preview in UI, authorization, route behavior, and tests.
  6. Keep internal proof, OperationRun links, raw metadata, and diagnostics secondary or capability-gated by default.

The first implementation choice should be:

Existing readiness/disclosure truth
    -> Customer output gate/result adapter
    -> UI action state and route enforcement

Do not create a new readiness engine. The gate may wrap current helpers such as ReviewPackOutputReadiness, ReviewPackOutputResolutionGuidance, and ReportDisclosurePolicy when they already express the needed truth.

Likely Affected Repository Surfaces

Implementation must re-verify exact current code before editing, but likely surfaces are:

  • apps/platform/app/Support/ReviewPacks/ReviewPackOutputReadiness.php
  • apps/platform/app/Support/ReviewPacks/ReviewPackOutputResolutionGuidance.php
  • apps/platform/app/Support/ReviewPacks/ReportDisclosurePolicy.php
  • apps/platform/app/Http/Controllers/ReviewPackDownloadController.php
  • apps/platform/app/Http/Controllers/ReviewPackRenderedReportController.php
  • apps/platform/app/Http/Controllers/ManagementReportPdfDownloadController.php
  • apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php
  • apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php
  • apps/platform/resources/views/review-packs/rendered-report.blade.php
  • apps/platform/app/Filament/Resources/ReviewPackResource.php
  • apps/platform/app/Filament/Resources/ReviewPackResource/Pages/ViewReviewPack.php
  • apps/platform/app/Filament/Resources/EnvironmentReviewResource.php
  • apps/platform/app/Filament/Resources/EnvironmentReviewResource/Pages/ViewEnvironmentReview.php
  • apps/platform/app/Support/EnvironmentDashboard/EnvironmentDashboardSummaryBuilder.php
  • apps/platform/app/Filament/Pages/Monitoring/EvidenceOverview.php
  • apps/platform/lang/en/localization.php
  • apps/platform/lang/de/localization.php
  • Focused tests under apps/platform/tests/Unit, apps/platform/tests/Feature, and apps/platform/tests/Browser

Implementation may remove a surface from the touched list if repo truth shows it is not customer-facing or already correct.

UI / Surface Guardrail Plan

  • Guardrail scope: changed existing customer-output actions, route access, labels, and customer/output states.
  • Affected routes/pages/actions/states/navigation/panel/provider surfaces: Customer Review Workspace output actions, Review Pack download/report actions, management-report download if customer-facing, Review Pack/Environment Review labels, Environment Dashboard customer-workspace CTA, Evidence Overview customer-workspace links.
  • No-impact class, if applicable: N/A.
  • Native vs custom classification summary: mixed existing native Filament resources/pages plus existing Blade report/workspace composition.
  • Shared-family relevance: status messaging, action links, dashboard signal links, artifact/report viewers, customer-safe disclosure.
  • State layers in scope: page, detail, route, URL-query.
  • Audience modes in scope: customer/read-only, operator-MSP, support-platform where authorized.
  • Decision/diagnostic/raw hierarchy plan: customer-output safety decision first; diagnostics and raw/support proof second or gated.
  • Raw/support gating plan: collapsed or capability-gated; no raw metadata by default on customer-facing surfaces.
  • One-primary-action / duplicate-truth control: show one top-level customer output state and one state-appropriate primary action; demote internal preview and proof links.
  • Handling modes by drift class or surface: route bypass is hard-stop; misleading CTA labels are review-mandatory; internal-preview exceptions must be documented in feature.
  • Repository-signal treatment: BUG-007 is a hard input; broad completed specs are context only.
  • Special surface test profiles: global-context-shell + customer-safe strategic review surface + artifact download route.
  • Required tests or manual smoke: Unit gate tests, HTTP route tests, Filament/Livewire action state tests, Browser smoke.
  • Exception path and spread control: no exception expected; any retained limitations-bearing internal preview must be named and permission-protected.
  • Active feature PR close-out entry: Guardrail / Exception / Smoke Coverage.
  • UI/Productization coverage decision: update existing page-report artifacts if implementation materially changes reachable page behavior; otherwise document no-count/no-archetype-change in active spec close-out.
  • Coverage artifacts to update: likely existing page reports under docs/ui-ux-enterprise-audit/page-reports/... for Customer Review Workspace / Review Pack / Environment Dashboard only if visible behavior materially changes.
  • No-impact rationale: N/A.
  • Navigation / Filament provider-panel handling: no provider registration or panel path change; verify provider registration remains apps/platform/bootstrap/providers.php.
  • Screenshot or page-report need: yes for browser proof of corrected CTA and safe/blocked output; page-report updates only if material page behavior changes.

Shared Pattern & System Fit

  • Cross-cutting feature marker: yes.
  • Systems touched: review-pack readiness/disclosure, output/download routes, Filament action labels, dashboard links, evidence/report viewers, localization, policy/capability checks.
  • Shared abstractions reused: ReviewPackOutputReadiness, ReviewPackOutputResolutionGuidance, ReportDisclosurePolicy, existing policies/capabilities, existing CustomerReviewWorkspace::environmentFilterUrl(), existing ReviewPackResource URLs, existing audit logger.
  • New abstraction introduced? why?: none by default; one narrow gate/result adapter only if needed to ensure route and UI consume the same customer-output decision.
  • Why the existing abstraction was sufficient or insufficient: current readiness helpers are sufficient for most derived safety signals, but they are not currently a route-enforced access boundary across every output path.
  • Bounded deviation / spread control: any new gate must stay scoped to customer-output open/download decisions and may not become a generic governance readiness framework.

OperationRun UX Impact

  • Touches OperationRun start/completion/link UX?: no new start/completion; existing proof links may remain secondary.
  • Central contract reused: existing OperationRun link helpers/routes.
  • Delegated UX behaviors: N/A for new starts.
  • Surface-owned behavior kept local: output safety copy and customer/internal action labels only.
  • Queued DB-notification policy: N/A.
  • Terminal notification path: unchanged.
  • Exception path: none.

Provider Boundary & Portability Fit

  • Shared provider/platform boundary touched?: no.
  • Provider-owned seams: N/A.
  • Platform-core seams: customer-output gating and artifact access labels.
  • Neutral platform terms / contracts preserved: customer output, customer workspace, review pack, internal preview, output state, blocking reason.
  • Retained provider-specific semantics and why: existing customer-safe review content may contain provider facts; gate labels should not.
  • Bounded extraction or follow-up path: none unless implementation finds provider-specific leakage requiring a separate follow-up.

Domain And Data Implications

  • No migration is expected.
  • No new model is expected.
  • No new persisted enum/status family is expected.
  • Gate state should be derived from existing records, summaries, readiness/disclosure payloads, file metadata, lifecycle timestamps, and authorization.
  • If existing data cannot represent a blocker required by the spec, implementation must stop and update spec.md / plan.md before adding persisted truth.

Expected gate result shape can be represented as array/value object fields:

state
can_open_customer_workspace
can_download_customer_output
can_download_internal_preview
primary_blocking_reason
blocking_reasons[]
is_customer_safe
is_internal_preview_only
customer_output_url
internal_preview_url
target_kind

Allowed visible states:

Ready
Needs attention
Blocked
Not configured
Expired
Unknown

These are derived presentation states, not persisted lifecycle truth.

Route And Authorization Plan

Route enforcement must run before output content is returned:

  • ReviewPackDownloadController: verify membership, capability, output gate, artifact status, expiry, file existence, audit, stream.
  • ReviewPackRenderedReportController: verify membership, capability, output gate/report profile before rendering a customer-facing report or showing a customer-safe download action.
  • ManagementReportPdfDownloadController: if customer-facing, apply equivalent output/report gate before PDF stream.
  • Any signed/stale route: stale or blocked customer output returns 403/404/safe redirect without file content.

Management-report PDF customer-facing criteria:

  • Customer-facing when labelled, linked, or positioned as customer/auditor review output from Customer Review Workspace, Review Pack, Environment Review, Environment Dashboard, Evidence Overview, or rendered-report flows.
  • Internal-only when reachable solely from operator/audit/technical surfaces and copy does not imply customer delivery.
  • Implementation must record the final include/exclude decision before editing or skipping this controller.

Authorization semantics:

  • Non-member or wrong workspace/environment: 404 deny-as-not-found.
  • Entitled member without capability: 403.
  • Entitled member with capability but unsafe customer-output gate: 403 or safe admin redirect with block reason.
  • Internal preview access: capability plus internal-preview gate; never customer-output permission alone.

Filament And Livewire Plan

  • Filament v5 / Livewire v4.0+ compliance is required; this app currently uses Livewire 4.1.4.
  • Panel provider registration remains apps/platform/bootstrap/providers.php; no provider changes are expected.
  • No global search behavior should be added or changed.
  • No destructive actions are introduced. Existing destructive/high-impact actions on related resources remain out of scope and must keep confirmation, authorization, audit, notifications, and tests.
  • UI labels must be route-truthful:
    • Open customer workspace -> actual Customer Review Workspace.
    • Open review pack -> internal Review Pack detail.
    • Download customer output -> customer-safe artifact only.
    • Download internal preview -> internal/operator artifact only.
    • View audit trail / View technical details -> internal detail only.
  • Hidden/disabled UI state is not a security boundary; route/controller checks are mandatory.

Audit And Observability Plan

  • Successful customer-output download must keep existing ReviewPackDownloaded or equivalent audit events.
  • Internal preview download, if introduced or relabelled, must be auditable with safe metadata and must not log secrets/raw payloads.
  • Blocked attempts may be logged only if current audit conventions support it without noise or sensitive data. If added, use stable action IDs and safe metadata.
  • No new OperationRun is expected because this is access/gating, not long-running execution.

Test Strategy

Unit tests

  • Gate returns Ready for published, safe, current output with artifact and permission.
  • Gate returns Blocked for PII/unredacted sensitive output.
  • Gate returns Needs attention or Blocked for limitations/not-ready output according to severity.
  • Gate returns Not configured for missing output/customer workspace.
  • Gate returns Expired for expired/superseded/archived/revoked output where repo-backed.
  • Gate returns Unknown when current safety cannot be determined.
  • Permission denial blocks even when output is otherwise safe.
  • Permission grant does not override unsafe output.

Feature / HTTP route tests

  • Safe customer-output download succeeds and audits.
  • PII/limited/not-ready output direct download is blocked.
  • Expired/superseded/missing output direct download is blocked.
  • Internal preview route/action requires internal/operator permission.
  • Customer/read-only user cannot access internal preview.
  • Rendered report does not expose customer download when gate blocks.
  • Management report PDF download, if customer-facing in implementation scope, respects the same gate.

Filament / Livewire tests

  • Unsafe customer output action is hidden/disabled/replaced with blocked state.
  • Blocking reason appears once.
  • Open customer workspace only appears when destination is actual Customer Review Workspace.
  • Open review pack is used for Review Pack detail.
  • Deprecated limited-download copy is absent from customer-facing surfaces.
  • Internal preview is secondary and permission-gated.

Browser smoke

  • Safe review pack: customer workspace opens and customer output downloads.
  • Unsafe review pack: customer output blocked and direct URL returns no file.
  • Internal preview, if present: labelled internal and secondary.
  • Dashboard CTA labelled Open customer workspace opens actual workspace.
  • Review Pack detail action is labelled Open review pack when destination is internal detail.

Rollout And Deployment Considerations

  • No env var changes expected.
  • No migrations expected.
  • No queue/scheduler changes expected.
  • No storage topology changes expected.
  • No Graph scopes or external API changes expected.
  • No Filament asset registration expected; filament:assets is not required unless implementation unexpectedly registers assets.
  • Staging validation should include safe and unsafe seeded review-output cases before production promotion.

Constitution Check

  • Inventory-first / snapshots-second: PASS. The gate reads existing observed/review/report/artifact truth and does not create new external truth.
  • Read/write separation: PASS. This is access/read/download gating; no Microsoft tenant mutation.
  • Graph contract path: PASS. No Graph calls are expected; render/download must remain DB/storage-only.
  • Deterministic capabilities: PASS. Existing capability registry remains authoritative.
  • RBAC-UX: PASS. Membership 404, capability 403, UI not a security boundary, route enforcement required.
  • Workspace/tenant isolation: PASS. All output records remain workspace/environment-scoped before access.
  • OperationRun UX: PASS. No new starts or lifecycle changes.
  • Test governance: PASS. Unit/Feature/Filament/Browser lanes are explicit and bounded.
  • Proportionality: PASS with condition. One narrow gate/result adapter is justified by security and route enforcement; no persistence/framework.
  • Persisted truth: PASS. No new tables/entities/artifacts expected.
  • State behavior: PASS. Derived visible states change route/action behavior, not persisted lifecycle.
  • UI semantics: PASS. One visible customer output state, no duplicated badges.
  • Shared pattern first: PASS. Reuse existing readiness/disclosure/action guidance before any new helper.
  • Provider boundary: PASS. No provider seam introduced.
  • Filament-native UI: PASS. Use native/action semantics and existing Blade composition; no new styling system.
  • UI/Productization coverage: PASS with condition. Update existing UI coverage/page-report artifacts only if runtime UI changes materially.

Test Governance Check

  • Test purpose / classification by changed surface: Unit for gate derivation; Feature/HTTP for direct routes; Filament/Livewire for action state; Browser for rendered workflow/CTA proof.
  • Affected validation lanes: fast-feedback, confidence, browser.
  • Why this lane mix is the narrowest sufficient proof: route bypass and CTA destination cannot be proven by unit tests alone; browser is needed only for final trust path.
  • Narrowest proving command(s):
    • cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec392
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec392CustomerOutputGatingSmokeTest.php --compact
    • git diff --check
  • Fixture / helper / factory / seed / context cost risks: use existing review-output fixtures; avoid new global seed defaults.
  • Expensive defaults or shared helper growth introduced?: no; any new fixture must be opt-in.
  • Heavy-family additions, promotions, or visibility changes: one explicit Browser smoke.
  • Surface-class relief / special coverage rule: no standard-native relief for the route gate; customer-output direct route proof is mandatory.
  • Closing validation and reviewer handoff: reviewers should verify safe/unsafe route behavior, CTA destinations, no limitations-bearing customer download, and no app-code scope expansion beyond listed surfaces.
  • Budget / baseline / trend follow-up: none.
  • Review-stop questions: Is the route gate shared? Is internal preview separate? Are completed specs untouched? Are broad report/workspace rewrites avoided?
  • Escalation path: document-in-feature for contained exceptions; follow-up-spec only for structural delivery gaps.
  • Active feature PR close-out entry: Guardrail / Exception / Smoke Coverage.
  • Why no dedicated follow-up spec is needed: this is the dedicated narrow follow-up for fresh customer-output safety evidence; future artifact lifecycle/report runtime/customer portal work is separate.

Implementation Phases

Phase 1 - Repo Truth And Action Inventory

Inventory all customer-output open/download actions and routes, classify each as customer-facing or internal, and record current label, destination, visibility condition, authorization, and direct-route behavior.

Phase 2 - Gate Contract And Tests

Add tests first for the gate states and route expectations. Choose the narrowest gate home after confirming current helper coverage.

Phase 3 - Route Enforcement

Apply the gate to customer-facing output routes before streaming/rendering output. Preserve membership/capability semantics and audit logging.

Phase 4 - UI Label And Action Correction

Update Customer Review Workspace, Review Pack, Environment Review, Environment Dashboard, Evidence Overview, and rendered report actions only where they are misleading or bypass the gate.

Phase 5 - Internal Preview Separation

If limited artifacts remain accessible, relabel as Download internal preview, demote to secondary, protect with internal permission, and remove from customer-facing/default surfaces.

Phase 6 - Customer-Safe Disclosure And Proof Demotion

Ensure internal proof links, OperationRun details, raw metadata, and diagnostics are secondary/capability-gated by default on customer-facing surfaces.

Phase 7 - Validation And Browser Evidence

Run targeted tests, browser smoke, pint --dirty, git diff --check, and update active spec/page-report artifacts as required by UI-COV.

Project Structure

specs/392-customer-output-gating-review-pack-navigation/
├── spec.md
├── plan.md
├── tasks.md
└── checklists/
    └── requirements.md

Likely runtime/test surfaces:

apps/platform/app/
├── Http/Controllers/
├── Filament/Pages/Reviews/
├── Filament/Pages/Monitoring/
├── Filament/Resources/
└── Support/

apps/platform/resources/views/
├── filament/pages/reviews/
└── review-packs/

apps/platform/tests/
├── Unit/
├── Feature/
└── Browser/

No new base folders are expected.