## 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
49 lines
5.6 KiB
Markdown
49 lines
5.6 KiB
Markdown
# Research: Tenant Review Layer
|
|
|
|
## Decision 1: Model the review layer as a new tenant-owned aggregate
|
|
|
|
- **Decision**: Introduce a dedicated `TenantReview` aggregate as the primary recurring review record, separate from `EvidenceSnapshot` and separate from `ReviewPack` export artifacts.
|
|
- **Rationale**: The codebase already distinguishes evidence curation from stakeholder export. `EvidenceSnapshot` is a data-curation substrate with completeness/freshness semantics, while `ReviewPack` is an export artifact with file retention and download behavior. The missing concept is the recurring governance review itself: a curated, inspectable, publishable tenant review that can remain intelligible and historically stable over time.
|
|
- **Alternatives considered**:
|
|
- Reuse `EvidenceSnapshot` directly as the review record: rejected because evidence snapshots intentionally stop at curated inputs and do not own executive summary composition or review lifecycle.
|
|
- Reuse `ReviewPack` directly as the review record: rejected because `ReviewPack` is file/export-oriented and does not provide a durable, inspectable in-product review aggregate.
|
|
|
|
## Decision 2: Reuse the existing review-pack export pipeline instead of inventing a second export model
|
|
|
|
- **Decision**: Keep `ReviewPack` as the export/download artifact pattern and link it to `TenantReview` in the first slice instead of creating a second export model.
|
|
- **Rationale**: The current code already has deterministic fingerprinting, `OperationRun` integration, retention/expiry, signed downloads, and Filament surfaces for review-pack artifacts. Reusing that pipeline minimizes churn and lets the new review layer focus on composition, publication, and executive inspection rather than rebuilding artifact storage from scratch.
|
|
- **Alternatives considered**:
|
|
- New `ExecutiveReviewPack` table and controller: rejected because it duplicates status, file, retention, and async-export concerns that `ReviewPack` already solves.
|
|
- Inline synchronous file generation from review detail: rejected because it violates current Ops-UX and export-artifact patterns.
|
|
|
|
## Decision 3: Store ordered review sections as child records, not one opaque JSON blob
|
|
|
|
- **Decision**: Represent section-level review composition as `TenantReviewSection` child rows under `TenantReview`, each with a section key, ordering, completeness state, and summary payload.
|
|
- **Rationale**: Existing evidence uses `EvidenceSnapshotItem` child rows for ordered dimensions with their own metadata. The review layer has similar needs: ordered sections, per-section completeness, selective rendering, and future section-level evolution. Child rows keep section logic explicit and reduce coupling to one large JSON document.
|
|
- **Alternatives considered**:
|
|
- Single JSONB payload on `TenantReview`: rejected because it obscures section ordering and completeness as first-class data and makes future section-level evolution more brittle.
|
|
- One table per section type: rejected as over-modeled for the first slice.
|
|
|
|
## Decision 4: Keep publish and archive synchronous, but make composition and export asynchronous
|
|
|
|
- **Decision**: Review composition and executive-pack export may use `OperationRun`; publish and archive remain synchronous audited DB mutations.
|
|
- **Rationale**: Composition and export can involve section assembly, pack rendering, and file persistence, which fit the existing async pattern. Publish and archive are governance-state transitions and should behave like explicit DB-backed lifecycle mutations with immediate auditability.
|
|
- **Alternatives considered**:
|
|
- Make every lifecycle action asynchronous: rejected because publish/archive do not need background processing and would add unnecessary Monitoring noise.
|
|
- Make export synchronous: rejected because the repo already treats pack generation as an observable background operation.
|
|
|
|
## Decision 5: Canonical workspace review surface is a register, not a tenantless detail viewer
|
|
|
|
- **Decision**: In v1, `/admin/reviews` is a workspace-scoped canonical register with tenant-safe filtering and row-level drill-down back into tenant-scoped review detail.
|
|
- **Rationale**: This matches the current boundary used by other tenant-owned domains: canonical workspace context can safely summarize and list entitled tenant records, while authoritative inspection remains tenant-scoped. This lowers tenant-leak risk and aligns with the existing middleware and tenant-owned query-scoping model.
|
|
- **Alternatives considered**:
|
|
- Add a fully tenantless canonical review detail viewer under `/admin/reviews/{review}`: rejected for the first slice because it introduces extra tenant-resolution and wrong-tenant guard complexity before the domain proves its value.
|
|
- Keep everything tenant-only with no canonical register: rejected because recurring review management across multiple tenants is a core requirement.
|
|
|
|
## Decision 6: Treat review publication readiness as review completeness, not compliance readiness
|
|
|
|
- **Decision**: Publication/export gating is based on review completeness and required section presence, not on BSI, NIS2, or CIS mapping.
|
|
- **Rationale**: The spec explicitly defers Compliance Readiness. The first slice needs an internal readiness rule for “is this review good enough to publish/export?” without collapsing into framework-oriented compliance scoring.
|
|
- **Alternatives considered**:
|
|
- Add lightweight framework labels now: rejected because even “lightweight” framework mapping would blur the product boundary the spec intentionally separates.
|
|
- Allow publish/export regardless of completeness: rejected because it would undermine stakeholder trust in the executive pack. |