# Data Model — Compliance Evidence Mapping v1 **Spec**: [spec.md](spec.md) No new persisted table, report artifact family, or projection store is required for this feature. The implementation reuses current review, section, evidence, finding, accepted-risk, membership, and audit truth, then embeds one bounded interpretation contract inside the existing review payloads. ## Source Truth Reused ### Workspace / Tenant Entitlement Context **Purpose**: Establish the active workspace boundary and entitled tenant set before any workspace row, released-review detail, or supporting evidence route is resolved. **Persisted carriers**: - existing workspace membership rows - existing tenant membership pivot rows and role assignments - existing capability registry and role-capability map **Relevant fields / contracts**: - `workspace_id` - `tenant_id` - workspace membership existence - tenant membership role - capability grants derived from [../../apps/platform/app/Support/Auth/Capabilities.php](../../apps/platform/app/Support/Auth/Capabilities.php) - remembered tenant context from the existing workspace session model **Validation rules**: - the actor must be a member of the current workspace or the request resolves as not found - workspace rows and explicit tenant filters may only resolve for entitled tenants in that workspace - out-of-scope tenant targets remain `404` and must not leak review or evidence presence ### CanonicalControlDefinition **Purpose**: Existing provider-neutral control identity used as the anchor for every mapped customer-safe control summary. **Carrier**: existing [../../apps/platform/config/canonical_controls.php](../../apps/platform/config/canonical_controls.php) loaded through [../../apps/platform/app/Support/Governance/Controls/CanonicalControlCatalog.php](../../apps/platform/app/Support/Governance/Controls/CanonicalControlCatalog.php) **Relevant fields**: - `control_key` - `name` - `domain_key` - `subdomain_key` - `summary` - `control_class` - `evaluation_strategy` - `evidence_archetypes` - `historical_status` **Validation / usage rules**: - canonical controls remain provider-neutral and customer-facing labels must continue to use the catalog's neutral names - provider-specific Microsoft bindings stay internal resolution inputs only - the interpretation overlay may add customer-safe readiness meaning, but it must not create a second control taxonomy ### Findings Summary Evidence Input **Purpose**: Existing per-finding evidence basis that already resolves canonical control references and accepted-risk governance state. **Persisted carriers**: - existing `evidence_snapshots` - existing `evidence_snapshot_items` - existing `findings` **Primary producer**: [../../apps/platform/app/Services/Evidence/Sources/FindingsSummarySource.php](../../apps/platform/app/Services/Evidence/Sources/FindingsSummarySource.php) **Relevant fields / payload**: - `EvidenceSnapshot.id` - `EvidenceSnapshot.generated_at` - `EvidenceSnapshot.expires_at` - `EvidenceSnapshotItem.dimension_key = findings_summary` - `summary_payload.entries[].id` - `summary_payload.entries[].status` - `summary_payload.entries[].severity` - `summary_payload.entries[].terminal_outcome` - `summary_payload.entries[].canonical_control_resolution` - `summary_payload.entries[].governance_state` - `summary_payload.entries[].governance_warning` - `summary_payload.canonical_controls[]` - `summary_payload.risk_acceptance` **Validation / usage rules**: - canonical control identity continues to come from the current upstream resolution path only - the interpretation overlay should consume current governance-state and terminal-outcome values rather than inventing a second status source - if the current payload is sufficient, upstream evidence collection remains unchanged ### FindingException / Accepted Risk Decision **Purpose**: Existing accepted-risk and accountability truth that can weaken or qualify a customer-safe control interpretation. **Persisted carrier**: existing `finding_exceptions` rows via [../../apps/platform/app/Models/FindingException.php](../../apps/platform/app/Models/FindingException.php) **Relevant fields / relationships**: - `status` - `current_validity_state` - `owner_user_id` - `approved_by_user_id` - `request_reason` - `review_due_at` - `effective_from` - `expires_at` - `owner` - `approver` - `currentDecision` **Validation / usage rules**: - accepted-risk truth may qualify a control interpretation but must not collapse into a fully positive readiness claim - missing owner, approver, or review-due truth must surface as explicit partial disclosure rather than fabricated certainty - this slice remains read-only and does not introduce approval, renewal, or revocation actions ### TenantReview **Purpose**: Existing released review artifact that anchors the shared interpretation contract for both workspace and detail surfaces. **Persisted carrier**: existing `tenant_reviews` rows via [../../apps/platform/app/Models/TenantReview.php](../../apps/platform/app/Models/TenantReview.php) **Relevant fields / relationships**: - `id` - `workspace_id` - `tenant_id` - `status` - `generated_at` - `published_at` - `summary` - `evidence_snapshot_id` - `current_export_review_pack_id` - `operation_run_id` - `tenant` - `evidenceSnapshot` - `sections` **Planned embedded summary additions inside the existing `summary` JSON**: - `control_interpretation.version` - `control_interpretation.display_label` - `control_interpretation.non_certification_disclosure` - `control_interpretation.controls[]` - `control_interpretation.limitations[]` **Validation / usage rules**: - only released reviews feed the default customer-safe workspace path - the shared interpretation version must be carried at compose time so older released reviews preserve the meaning shown at publication time - the workspace must read the embedded summary contract instead of recomputing the interpretation locally ### TenantReviewSection **Purpose**: Existing detailed review section carrier used for the per-control explanation surface on the released review detail page. **Persisted carrier**: existing `tenant_review_sections` rows via [../../apps/platform/app/Models/TenantReviewSection.php](../../apps/platform/app/Models/TenantReviewSection.php) **Relevant fields**: - `section_key` - `title` - `sort_order` - `completeness_state` - `summary_payload` - `render_payload` - `measured_at` **Planned usage**: - add one new v1 interpretation section inside the existing section family with the canonical `control_interpretation` section key - keep the section near the top of the customer-workspace detail disclosure so mapped-control explanation precedes rawer supporting sections **Planned embedded payload shape**: - `summary_payload.version` - `summary_payload.mapped_control_count` - `summary_payload.follow_up_required_count` - `summary_payload.limitation_counts` - `render_payload.entries[]` containing detailed per-control explanations **Validation / usage rules**: - exactly one interpretation section should exist per review for v1 - the detail surface should read this section instead of deriving a second explanation contract in-page - this remains part of the existing review artifact and does not create a new section table or entity family ### EvidenceSnapshot **Purpose**: Existing supporting proof artifact that informs evidence-basis summaries and explicit deeper drilldown. **Persisted carrier**: existing `evidence_snapshots` rows via [../../apps/platform/app/Models/EvidenceSnapshot.php](../../apps/platform/app/Models/EvidenceSnapshot.php) **Relevant fields / relationships**: - `id` - `workspace_id` - `tenant_id` - `status` - `completeness_state` - `generated_at` - `expires_at` - `summary` - `items` **Validation / usage rules**: - supporting proof remains optional, lower-priority, and capability-gated - the overlay may summarize the evidence basis, but raw payloads and unrestricted diagnostics remain outside the default customer-safe path - supporting evidence access should reuse the existing evidence route and audit action ### Audit Log Event Family **Purpose**: Existing audit trail used to keep the displayed interpretation and access path traceable. **Persisted carrier**: existing `audit_logs` rows via [../../apps/platform/app/Services/Audit/WorkspaceAuditLogger.php](../../apps/platform/app/Services/Audit/WorkspaceAuditLogger.php) **Relevant current action IDs**: - `customer_review_workspace.opened` - `tenant_review.opened` - `evidence_snapshot.opened` **Planned shared metadata additions**: - `source_surface` - `interpretation_version` - `review_id` when a released review is opened from the workspace - `tenant_filter_id` when the workspace is entered with a safe prefilter **Validation / usage rules**: - no new audit store or audit event family is justified - interpretation-version traceability should be added to shared metadata before introducing any new event concept ## Embedded Interpretation Contracts ### ControlInterpretationOverlayVersion **Purpose**: The explicit version label that states which customer-safe interpretation rules produced the displayed control/readiness summaries. **Persistence**: embedded in existing `TenantReview.summary` and the existing interpretation section payload; echoed in shared audit metadata when relevant **Fields**: - `version_key` (planned baseline: `compliance_evidence_mapping.v1`) - `display_label` - `non_certification_disclosure` **Validation rules**: - exactly one version key is carried for a given released review - the version must be visible on workspace and detail surfaces whenever mapped control summaries are shown ### CustomerControlSummary **Purpose**: Compact per-control summary reused by the workspace and as the top-level contract for the detail surface. **Persistence**: embedded inside `TenantReview.summary['control_interpretation']['controls']` **Fields**: - `control_key` - `control_name` - `domain_key` - `readiness_bucket` - `limitation_flags[]` - `customer_summary` - `evidence_basis_summary` - `accepted_risk_summary` (nullable) - `recommended_next_action` - `detail_anchor` (nullable) - `supporting_finding_ids[]` **Validation rules**: - one summary exists per mapped canonical control for the released review - the summary must stay customer-safe and must not expose provider IDs, raw JSON, or support-only diagnostics - the same summary meaning must appear on the workspace and detail surfaces for the same released review ### CustomerControlExplanation **Purpose**: Detailed per-control explanation rendered on the released-review detail surface. **Persistence**: embedded inside the interpretation `TenantReviewSection.render_payload.entries[]` **Fields**: - `control_key` - `control_name` - `readiness_bucket` - `limitation_flags[]` - `explanation_text` - `evidence_basis_items[]` - `accepted_risk_context` (nullable) - `recommended_next_action` - `proof_access_state` **Validation rules**: - the detail explanation must be a denser expansion of the compact summary, not a second source of truth - supporting evidence remains explicit drilldown, not default-visible raw detail - the explanation must keep non-certification language visible and must not claim legal or framework attestation ### CustomerReviewWorkspaceEntry **Purpose**: Derived row-level presentation contract for one entitled tenant with a released review on the workspace page. **Persistence**: none; derived at request time from the latest released `TenantReview` and its embedded interpretation contract **Fields**: - `workspace_id` - `tenant_id` - `tenant_name` - `latest_published_review_id` - `latest_review_published_at` - `interpretation_version` - `control_summaries[]` - `follow_up_summary` **Validation rules**: - exactly one derived entry exists per entitled tenant with a released review visible in the current workspace scope - when no entitled tenant has a released review, the workspace falls back to a page-level empty state rather than emitting partial row contracts without a review - the one dominant row action remains opening the released review; supporting proof stays secondary and is not a peer primary action on the row ### CustomerReviewDetailContext **Purpose**: Derived detail-page contract for the existing released-review surface when launched from the workspace. **Persistence**: none; derived from the released `TenantReview`, its interpretation section, and the current `customer_workspace` query flag **Fields**: - `review_id` - `tenant_id` - `customer_workspace_context` (boolean) - `interpretation_version` - `controls[]` - `non_certification_disclosure` - `operator_actions_hidden` (boolean) - `supporting_evidence_collapsed_by_default` (boolean) **Validation rules**: - the detail page must stay read-only in customer-workspace context - the same interpretation version and control meaning shown on the workspace must be visible here - supporting evidence should remain explicit in-body drilldown rather than a new dominant header action ## Derived Disclosure States This feature introduces no new platform-wide lifecycle family. It does require one bounded overlay-local readiness contract and explicit limitation flags. ### Primary readiness buckets - `follow_up_required` - `review_recommended` - `evidence_on_record` ### Limitation flags - `accepted_risk_influenced` - `partial_mapping` - `stale_evidence` - `supporting_evidence_unavailable` - `unmapped` **Validation rules**: - limitation flags qualify the customer-safe interpretation and must never be silently collapsed into `evidence_on_record` - accepted risk remains a qualifier, not a passing state - these values stay embedded in the interpretation contract only and do not become a broader platform taxonomy or standalone persistence family