TenantAtlas/specs/277-stored-reports-surface/data-model.md
Ahmed Darrazi db83112edc
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 6m41s
WIP: commit changes for PR to platform-dev
2026-05-06 01:50:13 +02:00

7.3 KiB

Data Model: Stored Reports Surface v1

Date: 2026-05-06
Branch: 277-stored-reports-surface

Overview

This slice introduces no new persisted entity. StoredReport remains the only stored-report source of truth. The new surface adds tenant-scoped, read-only view models over that truth and keeps downstream evidence, review, and review-pack consumers separate.

Existing Persisted Truth

1. Stored Report

Persistence: Existing stored_reports table
Ownership: Tenant-owned
Scope: Many retained rows per tenant and report family

Field Type Nullable Notes
id bigint no Internal stored-report id
workspace_id bigint no Required workspace isolation anchor
tenant_id bigint no Required tenant isolation anchor
report_type string no Current v1 supported values: permission_posture, entra.admin_roles
payload jsonb no Family-specific report payload
fingerprint string yes Integrity anchor for the current row
previous_fingerprint string yes Historical lineage anchor
created_at datetime yes Persisted creation time
updated_at datetime yes Standard timestamp

Behavior rules:

  • Stored reports are immutable retained artifacts after creation.
  • current versus historical is derived by comparing the row with the latest row for the same tenant_id and report_type.
  • retention_state stays derived as retained in this slice.
  • No new persisted lifecycle, publication, or browse metadata is introduced.

2. Evidence Snapshot Item Source Reference

Persistence: Existing evidence_snapshot_items.source_record_type and source_record_id fields
Ownership: Existing evidence domain

These fields remain downstream identity anchors when evidence items point to a stored report. They are context only in this slice and do not create an additional v1 launch seam.

3. Review Pack / Tenant Review Consumption

Persistence: Existing review-pack and tenant-review summaries
Ownership: Existing reporting domains

These consumers remain separate business truth. The stored-report surface may describe that stored reports are reused downstream, but it does not converge their operator routes in v1.

Derived Read Models

4. Stored Report Row Summary

Persistence: none, derived at runtime
Owner: stored-report register

Field Type Required Notes
report_id int yes Backed by stored_reports.id
display_reference string yes Stored report #{id} ({family label}) from existing artifact-truth wording
report_type string yes Raw family key
report_family_label string yes Headline-style label such as Permission posture report
lifecycle_state string yes current or historical from artifact truth
retention_state string yes retained
measured_at datetime yes Derived from payload timestamp when present, otherwise created_at
summary_highlights list yes Bounded, family-specific summary facts
history_visibility bool yes Whether the row is included only when history is revealed

5. Stored Report Detail View

Persistence: none, derived at runtime
Owner: stored-report detail page

Field Type Required Notes
artifact_truth array yes Reused ArtifactTruthPresenter::forStoredReport() envelope
display_reference string yes Stable stored-report reference
report_family_label string yes Headline family label
measured_at datetime yes Payload timestamp or created_at
integrity_anchor string no fingerprint, shown when present
previous_fingerprint string no Historical lineage anchor
current_report_id int no Latest same-family row when viewing a historical record
current_report_url string no Canonical detail URL for the current row
summary_branch object yes One of the two supported family-specific summary shapes below
raw_payload array yes Present but collapsed by default

6. Permission Posture Summary

Persistence: none, derived from StoredReport.payload

Payload anchors from current repo truth:

  • posture_score
  • required_count
  • granted_count
  • checked_at
  • permissions[] entries with key, type, status, and features

Derived summary fields:

Field Type Notes
posture_score int or null Primary posture score
required_count int Required permissions count
granted_count int Granted permissions count
missing_count int Derived as required_count - granted_count, never persisted
at_risk_permissions list First few non-granted permission entries for operator summary
checked_at datetime or null Preferred measurement timestamp when present

7. Entra Admin Roles Summary

Persistence: none, derived from StoredReport.payload

Payload anchors from current repo truth:

  • measured_at
  • totals.roles_total
  • totals.assignments_total
  • totals.high_privilege_assignments
  • high_privilege[] entries with role, principal, scope, and severity fields

Derived summary fields:

Field Type Notes
roles_total int Total role definitions captured
assignments_total int Total assignments captured
high_privilege_assignments int Count of privileged assignments
highest_risk_assignment array or null First highest-severity assignment for operator context
measured_at datetime or null Preferred measurement timestamp

8. Stored Report Launch Seam

Persistence: none, derived from existing operator routes

Field Type Required Notes
source_surface string yes Current v1 source surface name
target_url string yes Canonical stored-report detail URL

Current v1 seam:

  • AdminRolesSummaryWidget is the only confirmed canonical drilldown source in this slice.

Derived State Rules

Rule Derived Behavior
Current row selection Latest row by created_at desc, id desc for the same tenant_id and report_type
Lifecycle state current for the latest row, otherwise historical
Retention state retained for v1 stored-report browsing
Measured time payload.measured_at or payload.checked_at when available, otherwise created_at
Register visibility Only rows with an explicit family-to-capability mapping are listed
Detail authorization Family-aware capability check after workspace and tenant membership is established
Unexpected report family Outside v1 browse and detail scope until a follow-up spec adds support

Boundaries Explicitly Preserved

  • No new report-generation, export, or lifecycle-mutation truth is introduced.
  • Evidence snapshots, tenant reviews, review packs, and stored reports remain separate artifacts.
  • Current versus historical stays derived and is not persisted as a new domain state.
  • No generic report registry, schema catalog, or renderer framework is created.
  • Evidence, review, and review-pack routes remain context only and are not v1 convergence targets.