TenantAtlas/specs/357-report-profiles-disclosure-policy-v1/plan.md
ahmido b7907bd69d feat: add report profile and disclosure policy to rendered review reports (#428)
Implementing report profiles and disclosure policy as per spec 357.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #428
2026-06-06 09:41:19 +00:00

12 KiB

Implementation Plan: Spec 357 - Report Profiles & Disclosure Policy v1

Branch: 357-report-profiles-disclosure-policy-v1 | Date: 2026-06-05 | Spec: /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/357-report-profiles-disclosure-policy-v1/spec.md
Input: Feature specification from /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/357-report-profiles-disclosure-policy-v1/spec.md

Summary

Add a bounded report-policy layer to the current rendered review-report flow. The implementation should keep the current ReviewPack artifact and rendered report route, but introduce:

  1. a static report-profile registry
  2. a disclosure-policy evaluator with explicit proof states
  3. profile-aware rendered-report composition and section filtering

The slice must stay static and read-only. It must not create new persistence, delivery flows, public links, PDF infrastructure, or AI/runtime expansion.

Technical Context

Language/Version: PHP 8.4.15
Primary Dependencies: Laravel 12.52, Filament 5.2.1, Livewire 4.1.4, Pest 4.3
Storage: Existing PostgreSQL truth plus existing exports disk-backed ReviewPack artifacts only
Testing: Pest Unit, Feature, Browser
Validation Lanes: confidence, browser
Target Platform: Laravel Sail local runtime and existing Filament admin panel
Project Type: Laravel monolith with Filament admin surfaces
Performance Goals: No measurable render slowdown beyond current rendered report; no new remote calls during render
Constraints: No Graph/provider calls during render, no new persistence, no public route contract widening, no second artifact family
Scale/Scope: One existing report route and its owner surfaces, one static registry, one policy evaluator, focused regressions

Repo Truth

Current repo-real seams:

  • apps/platform/app/Http/Controllers/ReviewPackRenderedReportController.php already builds the rendered report payload.
  • apps/platform/resources/views/review-packs/rendered-report.blade.php already renders HTML-first output.
  • apps/platform/app/Support/ReviewPacks/ReviewPackOutputReadiness.php and ReviewPackOutputResolutionGuidance.php already derive readiness and limitation semantics.
  • apps/platform/app/Services/ReviewPackService.php and GenerateReviewPackJob already anchor the current ReviewPack delivery contract.
  • docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.md, ui-042-review-pack-detail.md, and ui-099-rendered-review-report.md already document the affected strategic surfaces.

Current gap:

  • There is no static report-profile registry.
  • There is no first-class disclosure-policy result that distinguishes verified, assumed, missing, unknown, and not_applicable.
  • The current renderer cannot express different audience/detail policies without ad hoc branching.

Candidate Selection Gate

Result: PASS

  • The candidate was directly provided by the user as a concrete Spec 357 draft.
  • It aligns with current runtime truth after Spec 356 rather than reopening an older or completed foundation.
  • Related specs 347, 355, and 356 are treated as historical/runtime context only.
  • The scope is small and reviewable: static registry + disclosure policy + existing rendered-report integration.
  • Broader alternatives such as billing, localization, customer portal, or AI remain explicitly deferred.

UI / Surface Guardrail Plan

  • Guardrail scope: changed existing customer/report surfaces
  • Affected routes/pages/actions/states/navigation/panel/provider surfaces:
    • /admin/reviews/workspace
    • /admin/workspaces/{workspace}/environments/{environment}/environment-reviews/{record}
    • /admin/workspaces/{workspace}/environments/{environment}/review-packs/{record}
    • /admin/review-packs/{reviewPack}/report
  • No-impact class, if applicable: N/A
  • Native vs custom classification summary: mixed; existing native Filament owner surfaces plus the existing custom rendered-report Blade surface
  • Shared-family relevance: report viewer, status messaging, artifact truth, customer-safe disclosure
  • State layers in scope: detail route payload and existing owner-page derived payload; no shell or navigation contract change
  • Audience modes in scope: customer/read-only, operator-MSP, controlled auditor, support/internal
  • Decision-first contract: the rendered report must identify its audience, readiness, and limitations immediately before showing deeper section detail
  • Required tests or manual smoke:
    • explicit Unit tests for policy
    • explicit Feature coverage for rendered report
    • one bounded Browser smoke for profile variants and disclosure hierarchy
  • Active feature PR close-out entry: Guardrail / Exception / Smoke Coverage

Technical Approach

1. Keep everything inside the existing ReviewPack report family

Do not create:

  • a new report persistence model
  • a separate rendered artifact family
  • a profile CRUD resource
  • a delivery workflow

The current rendered report stays the single report route. The new logic should live inside App\Support\ReviewPacks and be consumed by the existing controller and owner surfaces.

2. Introduce a static report-profile registry

Preferred repo-aligned shape:

  • apps/platform/app/Support/ReviewPacks/ReportProfileRegistry.php
  • one static array-based contract or readonly value structure
  • no database/config mutation path

Required implemented profiles:

  • customer_executive
  • customer_technical
  • internal_msp_review
  • auditor_appendix

Required placeholder:

  • framework_readiness marked not implemented and not selectable for an implemented report

The registry must remain narrow and typed enough for tests, but must not become a generalized framework.

3. Introduce a disclosure-policy evaluator

Preferred repo-aligned shape:

  • apps/platform/app/Support/ReviewPacks/ReportDisclosurePolicy.php

Inputs:

  • selected effective profile
  • current readiness / limitation truth
  • evidence completeness state
  • PII/internal-only state
  • available source/disclosure metadata

Outputs:

  • mandatory disclosures
  • warnings
  • blocking reasons
  • proof states (verified, assumed, not_applicable, missing, unknown)

The evaluator must use stored truth only. No render-time provider or Graph calls.

4. Add one local rendered-report profile composition layer if needed

The current controller already builds a large report payload. If profile/disclosure integration makes that method unreviewable, introduce one local support layer under App\Support\ReviewPacks to compose:

  • effective profile metadata
  • filtered section list
  • disclosure result
  • appendix policy
  • audience labels

This must stay local to the current rendered report. No cross-domain reusable viewer framework.

5. Keep profile selection bounded and authenticated

V1 defaults:

  • default effective profile: internal_msp_review
  • customer-facing or auditor-oriented variants remain authenticated and capability-gated

Preferred surface policy:

  • the existing report route may accept a bounded authenticated profile selector only when the parameter is carried through the existing signed URL builders (ReviewPackService::generateRenderedReportUrl() and current owner-surface helper/action seams)
  • existing owner surfaces may add at most one small group of safe "view report as ..." actions if that remains reviewable
  • if action-surface growth is too large, keep selection route-local via those existing signed URL seams and test it directly

No unsigned query contract or share link may be introduced.

6. Mandatory truth overrides profile presentation

Profiles may influence:

  • section inclusion
  • appendix visibility
  • detail level
  • audience label

Profiles may not hide:

  • readiness state
  • evidence completeness / limitation state
  • internal-only or PII warning
  • non-certification disclosure
  • generated/source metadata

7. Preserve current owner-surface boundaries

  • CustomerReviewWorkspace remains the handoff surface
  • EnvironmentReviewResource remains the released-review detail seam
  • ReviewPackResource remains the artifact truth seam
  • the rendered report remains read-only delivery output

Do not turn any of these into a profile management surface.

Domain / Model Implications

  • No new table, column, enum, or persisted artifact family is expected.
  • ReviewPack, EnvironmentReview, EnvironmentReviewSection, and EvidenceSnapshot remain the only persisted truth used here.
  • Disclosure proof states remain derived-only and request-scoped.

Filament / Livewire Implications

  • Livewire v4.1.4 compliance is required; no Livewire v3 APIs.
  • Filament panel provider registration remains unchanged in apps/platform/bootstrap/providers.php.
  • No global-search changes are expected. ReviewPackResource and related review surfaces keep their current search posture.
  • Any new action affordances on owner surfaces must remain read-only and subordinate to the existing primary inspect/open model.

OperationRun / Observability Implications

  • No new OperationRun type is introduced.
  • Existing review-pack generation/run-link behavior remains authoritative.
  • Any profile or disclosure result should remain derivable from existing stored artifact truth and not require a new run or audit path.

Authorization / Security Implications

  • Existing workspace/environment entitlement and Capabilities::REVIEW_PACK_VIEW remain authoritative.
  • Customer-facing profiles must not bypass internal-only or current-export guards.
  • Invalid profile keys must fail closed.
  • Non-members and out-of-scope records remain 404, missing capability remains 403.

Data / Persistence Implications

  • No migrations
  • No new settings rows
  • No new config-write path
  • No new stored report or rendered artifact record

If implementation proves persistence is required, stop and split the scope.

Test Strategy

Unit

  • registry shape and implemented/placeholder behavior
  • disclosure proof-state evaluation
  • invalid-profile fail-closed behavior

Feature

  • rendered report profile selection and profile metadata
  • mandatory disclosures cannot be hidden
  • customer profiles remain visibly limited on limited/internal output
  • internal profile remains clearly internal when appropriate

Browser

One bounded smoke file covering:

  • internal MSP profile with limitations
  • customer executive profile on limited output
  • customer-safe profile on ready output
  • auditor appendix profile
  • invalid or placeholder profile behavior

Regression

Keep existing rendered-report and review-pack tests green, especially Spec 347 and Spec 356 coverage.

Rollout / Deployment

  • No env vars
  • No migrations
  • No queue changes
  • No scheduler changes
  • No storage contract changes
  • No filament:assets impact expected

Risks And Controls

  • Risk: profile system drifts into delivery or portal work
    • Control: static registry only; explicit non-goals in tasks and checklist
  • Risk: proof-state modeling becomes a fake certainty layer
    • Control: explicit assumed/verified distinction and tests
  • Risk: customer-facing profile hides limitations
    • Control: mandatory disclosure override plus feature/browser assertions
  • Risk: controller complexity grows too far
    • Control: allow one local report-profile payload layer only if needed

Implementation Phases

  1. Repo-truth recheck and failing tests first
  2. Static report-profile registry
  3. Disclosure-policy evaluator with proof states
  4. Rendered-report payload integration and section filtering
  5. Owner-surface handoff and localization updates
  6. UI-audit follow-through
  7. Focused validation, browser smoke, and screenshots

Spec Readiness Gate

Result: PASS

  • spec.md, plan.md, and tasks.md are present.
  • Scope is bounded to the current rendered report family.
  • No open question blocks safe implementation.
  • RBAC, isolation, disclosure truth, and customer-safe behavior are explicit.
  • No new persistence or delivery workflow is required.
  • Required checklist artifact is included in this spec package.

Assumptions

  • The current rendered report route remains the correct owner for profile-aware output.
  • A bounded authenticated selection mechanism is sufficient for v1.
  • Existing report/resource page reports can absorb the UI audit updates without inventing new page identities.

Open Questions

  • Whether owner-surface actions are necessary or whether the signed-URL-local profile selector is enough for v1
  • Whether auditor_appendix should render as internal-only by default until a later delivery workflow spec

These are safe implementation decisions, not product blockers.