# Data Model — Customer Review Workspace v1 **Spec**: [spec.md](spec.md) No new persisted tables or customer-review entities are required for v1. The feature reuses existing tenant-owned review, review-pack, evidence, findings, and audit truth, then derives one workspace-scoped read model for page presentation. ## Persisted Truth Reused ### Workspace / Tenant Entitlement Context **Purpose**: Establish the current workspace boundary and the entitled tenant set before any review rows are composed. **Persisted carriers**: - existing workspace membership records - existing tenant membership pivot records and tenant role assignments - existing capability registry and role-capability map **Relevant fields / contracts**: - `workspace_id` - `tenant_id` - tenant membership role - capability grants derived from [../../apps/platform/app/Support/Auth/Capabilities.php](../../apps/platform/app/Support/Auth/Capabilities.php) **Validation rules**: - current actor must be a member of the current workspace or the page resolves as not found - tenant rows may only be composed for tenants in the current workspace where the actor is entitled through the canonical role-capability map - no cross-workspace or cross-tenant fallback lookups are allowed ### TenantReview **Purpose**: Canonical source for the latest customer-safe review posture, summary text, findings summary, accepted-risk summary, and primary inspect target. **Persisted carrier**: existing `tenant_reviews` rows via `TenantReview` **Relevant fields / relationships**: - `id` - `workspace_id` - `tenant_id` - `status` - `generated_at` - `published_at` - `summary` - `evidence_snapshot_id` - `current_export_review_pack_id` - `tenant` - `evidenceSnapshot` - `currentExportReviewPack` - `sections` **Validation / usage rules**: - the default customer-safe path uses the latest published review per entitled tenant - draft, ready, failed, archived, and superseded reviews stay off the default-visible page summary unless explicitly reused as internal proof elsewhere - summary data already shaped into the review artifact remains the preferred source for findings and review-level posture messaging ### TenantReviewSection **Purpose**: Supporting persisted proof for accepted-risk and section-level disclosure without introducing a new workspace summary store. **Persisted carrier**: existing `tenant_review_sections` rows **Relevant fields / relationships**: - `tenant_review_id` - `section_key` - `title` - `completeness_state` - `summary_payload` - `render_payload` **Validation / usage rules**: - accepted-risk summaries should come from the existing review section payloads that were already composed for the review artifact - section payload reuse must remain read-only and redaction-safe ### ReviewPack **Purpose**: Canonical packaged artifact for customer-safe review consumption and download. **Persisted carrier**: existing `review_packs` rows via `ReviewPack` **Relevant fields / relationships**: - `id` - `workspace_id` - `tenant_id` - `tenant_review_id` - `status` - `generated_at` - `expires_at` - `summary` - `file_path` - `file_disk` - `sha256` - `tenantReview` - `evidenceSnapshot` **Validation / usage rules**: - download is available only when the current pack is ready and not expired - the workspace page may surface availability and a signed download path only when `REVIEW_PACK_VIEW` applies - the workspace page must not start generation, regeneration, or recovery flows ### EvidenceSnapshot **Purpose**: Existing proof artifact for freshness and evidence completeness when the actor explicitly asks for supporting detail. **Persisted carrier**: existing `evidence_snapshots` rows via `EvidenceSnapshot` **Relevant fields / relationships**: - `id` - `workspace_id` - `tenant_id` - `status` - `completeness_state` - `generated_at` - `expires_at` - `summary` - `items` **Validation / usage rules**: - evidence detail is not part of the default-visible customer path - drilldown remains explicit and capability-gated by `EVIDENCE_VIEW` - evidence truth remains tenant-owned and derived from the existing snapshot lifecycle ### Audit Log Event Family **Purpose**: Existing audit truth for explicit review-artifact access and download actions. **Persisted carrier**: existing `audit_logs` rows via `WorkspaceAuditLogger` **Relevant fields / contracts**: - stable `AuditActionId` - `workspace_id` - optional `tenant_id` - actor metadata - target resource type / id / label - action context metadata **Validation / usage rules**: - no new audit store is introduced - explicit artifact open/download events should reuse the current audit pipeline - page render itself should not become a noisy new audit family ## Derived Read Model ### CustomerReviewWorkspaceEntry **Purpose**: Derived page row or card summarizing the latest customer-safe review state for one entitled tenant. **Persistence**: none; computed at request time **Fields**: - `workspace_id` - `tenant_id` - `tenant_name` - `latest_published_review_id` (nullable) - `latest_review_generated_at` (nullable) - `latest_review_published_at` (nullable) - `review_outcome_label` (nullable, derived from existing artifact truth) - `review_outcome_explanation` (nullable) - `key_findings_summary` (nullable, derived from existing review summary) - `accepted_risk_summary` (nullable, derived from existing review section payloads) - `review_pack_id` (nullable) - `review_pack_available` (boolean) - `review_pack_status_note` (nullable derived string) - `evidence_snapshot_id` (nullable) - `primary_review_url` (nullable) - `review_pack_download_url` (nullable) - `evidence_detail_url` (nullable) - `redaction_note` (nullable) - `absence_note` (nullable derived string) **Derivation rules**: - exactly one entry exists per entitled tenant visible in the current workspace scope - when a published review exists, the entry derives customer-safe posture from that latest published review only - when no published review exists for an entitled tenant, the entry may carry a derived absence note such as `No published review available yet`; this remains view logic, not domain state - raw JSON, raw provider payloads, unrestricted audit metadata, fingerprints, and debug-only context are never part of the entry **Validation rules**: - entries may only be built for tenants in the current workspace and current entitlement scope - `review_pack_download_url` is present only when a current pack exists and the actor can view it - `evidence_detail_url` is present only when the actor can view evidence detail - absence or unavailable wording must not hint at hidden drafts or hidden operator-only artifacts ## Request-Scoped Page State ### CustomerReviewWorkspaceState **Purpose**: Livewire-safe page state carrying tenant launch context and remembered filters. **Persistence**: request, query, and session-backed page state only **Fields**: - `tenant_id` (nullable requested prefilter) - `highlight_tenant_id` (nullable) - `launch_source` (nullable string such as review, review_pack, evidence, or dashboard) - `search` (nullable) - `tableFilters` (session-backed when the implementation uses table filters) **Validation rules**: - requested tenant filters must resolve to an entitled tenant or the page should respond as not found for explicit tenant targeting - state that needs to survive Livewire interactions must remain hydrated public or query/session-backed state - if implementation adds a secondary status filter, it must operate on customer-safe derived labels only, not raw internal lifecycle states ## State Transition Summary This slice introduces no new persisted lifecycle or status family. Only derived page-state transitions are expected: - default workspace view -> tenant-prefiltered view - tenant-prefiltered view -> cleared workspace view - published review available -> inspect or download action available subject to capability checks - no published review available -> truthful absence message only No queue, publish, generate, regenerate, remediate, or archive transition belongs to this page.