## Summary - add the tenant review domain with tenant-scoped review library, canonical workspace review register, lifecycle actions, and review-derived executive pack export - extend review pack, operations, audit, capability, and badge infrastructure to support review composition, publication, export, and recurring review cycles - add product backlog and audit documentation updates for tenant review and semantic-clarity follow-up candidates ## Testing - `vendor/bin/sail bin pint --dirty --format agent` - `vendor/bin/sail artisan test --compact --filter="TenantReview"` - `CI=1 vendor/bin/sail artisan test --compact` ## Notes - Livewire v4+ compliant via existing Filament v5 stack - panel providers remain in `bootstrap/providers.php` via existing Laravel 12 structure; no provider registration moved to `bootstrap/app.php` - `TenantReviewResource` is not globally searchable, so the Filament edit/view global-search constraint does not apply - destructive review actions use action handlers with confirmation and policy enforcement Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #185
5.2 KiB
5.2 KiB
Data Model: Tenant Review Layer
Overview
The first slice introduces a new tenant-owned review aggregate that consumes existing evidence-domain and governance outputs without replacing them.
Entities
TenantReview
- Purpose: The primary recurring governance review record for one tenant, anchored to one chosen evidence basis.
- Ownership: Tenant-owned (
workspace_id,tenant_idrequired). - Core fields:
idworkspace_idtenant_idevidence_snapshot_idcurrent_export_review_pack_idnullableoperation_run_idnullable for async composition/refreshinitiated_by_user_idpublished_by_user_idnullablesuperseded_by_review_idnullable self-referencefingerprintnullable, deterministic for dedupe of unchanged draft compositionstatusenum:draft,ready,published,archived,superseded,failedcompleteness_stateenum:complete,partial,missing,stalesummaryJSONB for aggregate executive metadata and publish blockerspublished_atnullable timestamparchived_atnullable timestampgenerated_atnullable timestampcreated_at,updated_at
- Derived presentation states:
- publication state is derived from
statuspluspublished_at; no separate persisted publication enum is introduced in this slice - export readiness is derived from
current_export_review_pack_id, review completeness/readiness rules, and the latest related review-pack state; no separate persisted export-readiness enum is introduced in this slice
- publication state is derived from
- Relationships:
- belongs to
Tenant - belongs to
Workspace - belongs to
EvidenceSnapshot - belongs to
Useras initiator - belongs to
Useras publisher - belongs to
OperationRunfor async generation/refresh only - has many
TenantReviewSection - has many
ReviewPackexport artifacts if export history is retained per review
- belongs to
- Validation rules:
workspace_idandtenant_idmust match the anchored evidence snapshot- exactly one active evidence basis per review
- published reviews cannot be mutated in place
- archived reviews cannot return to draft/ready
- State transitions:
draft -> readydraft -> failedready -> publishedready -> failedpublished -> supersededpublished -> archivedready -> archived- terminal:
archived,superseded
TenantReviewSection
- Purpose: Ordered section-level composition for one tenant review.
- Ownership: Tenant-owned through
tenant_review_id; redundantly storesworkspace_idandtenant_idfor isolation and query simplicity. - Core fields:
idtenant_review_idworkspace_idtenant_idsection_keyenum-like string such asexecutive_summary,open_risks,accepted_risks,permission_posture,baseline_drift_posture,operations_healthtitlesort_orderrequiredbooleancompleteness_statesource_snapshot_fingerprintnullablesummary_payloadJSONBrender_payloadJSONBmeasured_atnullable timestampcreated_at,updated_at
- Relationships:
- belongs to
TenantReview
- belongs to
- Validation rules:
- unique per
tenant_review_id + section_key sort_ordermust be stable and non-negativesummary_payloadandrender_payloadmust be sanitized, summary-first, and secret-free
- unique per
ReviewPack (existing, extended)
- Purpose: Existing export artifact reused as the stakeholder-facing executive pack output.
- Change in this feature:
- add
tenant_review_idnullable foreign key - treat executive-pack exports as review-derived artifacts when
tenant_review_idis present
- add
- Important existing fields reused:
workspace_id,tenant_idoperation_run_idevidence_snapshot_idstatusfingerprintoptionsfile_disk,file_path,file_size,sha256generated_at,expires_at
- State transitions:
- existing
queued -> generating -> ready|failed -> expired - derived from review export pipeline, not from review publication state itself
- existing
Derived Views
Workspace Review Register Row
- Purpose: Canonical
/admin/reviewsrow projection for entitled tenants only. - Fields:
tenant_idtenant_namereview_idreview_statuscompleteness_statepublished_atgenerated_atevidence_snapshot_idhas_ready_exportpublish_blockers_count
Indexing / Constraints
tenant_reviews(workspace_id, tenant_id, created_at desc)tenant_reviews(tenant_id, status, published_at desc)- partial unique index for one current mutable review per
tenant_idif desired:status in ('draft','ready') - unique
tenant_review_sections(tenant_review_id, section_key) review_packs(tenant_review_id, generated_at desc)
Invariants
- Tenant-owned review tables always include both
workspace_idandtenant_id. - A published review is immutable.
- A review always points to exactly one anchored evidence snapshot.
- Review completeness is explicit and never inferred from pack readiness alone.
- Export artifacts never become the source of truth for review content; they remain derived from
TenantReview.