Implements platform feature branch `259-compliance-evidence-mapping`. Target branch: `platform-dev`. Follow-up integration path after merge: `platform-dev` -> `dev`. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #312
14 KiB
Data Model — Compliance Evidence Mapping v1
Spec: 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_idtenant_id- workspace membership existence
- tenant membership role
- capability grants derived from ../../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
404and 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 loaded through ../../apps/platform/app/Support/Governance/Controls/CanonicalControlCatalog.php
Relevant fields:
control_keynamedomain_keysubdomain_keysummarycontrol_classevaluation_strategyevidence_archetypeshistorical_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
Relevant fields / payload:
EvidenceSnapshot.idEvidenceSnapshot.generated_atEvidenceSnapshot.expires_atEvidenceSnapshotItem.dimension_key = findings_summarysummary_payload.entries[].idsummary_payload.entries[].statussummary_payload.entries[].severitysummary_payload.entries[].terminal_outcomesummary_payload.entries[].canonical_control_resolutionsummary_payload.entries[].governance_statesummary_payload.entries[].governance_warningsummary_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
Relevant fields / relationships:
statuscurrent_validity_stateowner_user_idapproved_by_user_idrequest_reasonreview_due_ateffective_fromexpires_atownerapprovercurrentDecision
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
Relevant fields / relationships:
idworkspace_idtenant_idstatusgenerated_atpublished_atsummaryevidence_snapshot_idcurrent_export_review_pack_idoperation_run_idtenantevidenceSnapshotsections
Planned embedded summary additions inside the existing summary JSON:
control_interpretation.versioncontrol_interpretation.display_labelcontrol_interpretation.non_certification_disclosurecontrol_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
Relevant fields:
section_keytitlesort_ordercompleteness_statesummary_payloadrender_payloadmeasured_at
Planned usage:
- add one new v1 interpretation section inside the existing section family with the canonical
control_interpretationsection 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.versionsummary_payload.mapped_control_countsummary_payload.follow_up_required_countsummary_payload.limitation_countsrender_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
Relevant fields / relationships:
idworkspace_idtenant_idstatuscompleteness_stategenerated_atexpires_atsummaryitems
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
Relevant current action IDs:
customer_review_workspace.openedtenant_review.openedevidence_snapshot.opened
Planned shared metadata additions:
source_surfaceinterpretation_versionreview_idwhen a released review is opened from the workspacetenant_filter_idwhen 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_labelnon_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_keycontrol_namedomain_keyreadiness_bucketlimitation_flags[]customer_summaryevidence_basis_summaryaccepted_risk_summary(nullable)recommended_next_actiondetail_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_keycontrol_namereadiness_bucketlimitation_flags[]explanation_textevidence_basis_items[]accepted_risk_context(nullable)recommended_next_actionproof_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_idtenant_idtenant_namelatest_published_review_idlatest_review_published_atinterpretation_versioncontrol_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_idtenant_idcustomer_workspace_context(boolean)interpretation_versioncontrols[]non_certification_disclosureoperator_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_requiredreview_recommendedevidence_on_record
Limitation flags
accepted_risk_influencedpartial_mappingstale_evidencesupporting_evidence_unavailableunmapped
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