## Summary - amend the operator UI constitution and related SpecKit templates for the new UI/UX governance rules - add Spec 168 artifacts plus the tenant governance aggregate implementation used by the tenant dashboard, banner, and baseline compare landing surfaces - normalize Filament action surfaces around clickable-row inspection, grouped secondary actions, and explicit action-surface declarations across enrolled resources and pages - fix post-suite regressions in membership cache priming, finding workflow state refresh, tenant review derived-state invalidation, and tenant-bound backup-set related navigation ## Commit Series - `docs: amend operator UI constitution` - `spec: add tenant governance aggregate contract` - `feat: add tenant governance aggregate contract` - `refactor: normalize filament action surfaces` - `fix: resolve post-suite state regressions` ## Testing - `vendor/bin/sail artisan test --compact` - Result: `3176 passed, 8 skipped (17384 assertions)` ## Notes - Livewire v4 / Filament v5 stack remains unchanged - no provider registration changes; `bootstrap/providers.php` remains the relevant location - no new global-search resources or asset-registration changes in this branch Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #199
25 KiB
Feature Specification: Tenant Governance Aggregate Contract
Feature Branch: 168-tenant-governance-aggregate-contract
Created: 2026-03-28
Status: Draft
Input: User description: "Spec 168 — Tenant Governance Aggregate Contract"
Spec Scope Fields (mandatory)
- Scope: tenant
- Primary Routes:
/admin/t/{tenant}as the tenant dashboard where Baseline Governance and Needs Attention currently surface overlapping governance posture/admin/t/{tenant}/baseline-compare-landingas the tenant baseline-compare hub that owns compare posture, next action, and supporting diagnostics- tenant-context governance banners and summary cards that surface baseline posture or governance attention inside the tenant panel
- Data Ownership:
- Tenant-owned: findings, finding-exception validity, overdue workflow state, and tenant-scoped compare-run visibility that together describe the tenant's current governance attention posture
- Workspace-owned but tenant-resolved: baseline assignment, baseline profile, effective baseline snapshot availability, and workspace-level prerequisites that shape tenant compare posture
- This feature introduces no new persisted tenant-governance record; the shared aggregate remains derived for one tenant at a time
- RBAC:
- Existing workspace membership and tenant entitlement remain required for every surface that consumes the aggregate
- Existing tenant inspection capabilities remain the gate for opening findings, baseline compare detail, and other drill-down destinations reached from the aggregate
- Existing compare-start authorization and confirmation rules remain unchanged for the Baseline Compare landing action
Operator Surface Contract (mandatory when operator-facing surfaces are changed)
| Surface | Primary Persona | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|
Tenant dashboard Needs Attention |
Tenant operator | Summary widget | What needs action right now across governance and baseline posture? | Overdue findings, lapsed governance, expiring governance, high-severity active findings, baseline-posture summary | Deep reason codes, raw compare diagnostics, low-level evidence gaps, run internals | governance attention, due urgency, compare posture, severity urgency | Read-only summary with drill-down navigation | Review dashboard attention items, open related destination | None |
Tenant dashboard Baseline Governance card |
Tenant operator | Summary card | Can I trust the latest baseline posture, and what should I do next? | Aggregate headline, supporting message, next action, visible drift count, high-severity count, last compared label | Deep coverage details, duplicate-name stats, evidence-gap drill-down, run diagnostics | compare freshness, compare outcome, governance attention, trustworthiness | Read-only summary with drill-down navigation | Open findings, open run, open Baseline Compare | None |
| Baseline Compare landing | Tenant operator | Landing page | What is the tenant's current baseline governance posture, and should I compare now or investigate detail? | Aggregate posture, assignment or snapshot availability, findings attention, next action, compare availability | Coverage detail, evidence-gap detail, duplicate-name diagnostics, low-level run reason detail | compare availability, compare freshness, compare outcome, governance attention, coverage limits | Existing compare action unchanged; page state itself is read-focused | Review posture, open findings, start Compare now, open run detail |
No new dangerous action; existing Compare now remains confirmation-gated and capability-gated |
| Tenant governance banner | Tenant operator | Inline warning banner | Is there a governance or compare limitation I should not miss on this screen? | Shared aggregate headline, supporting message, next action intent, warning tone | Full compare diagnostics and detailed count breakdowns | compare caution or stale state, governance attention, next action intent | Read-only summary with drill-down navigation | Follow next action to findings, run detail, or Baseline Compare | None |
Proportionality Review (mandatory when structural complexity is introduced)
- New source of truth?: No. Findings, exception validity, baseline assignment, snapshot availability, and compare-run truth remain the source data.
- New persisted entity/table/artifact?: No. The aggregate is derived and request-scoped.
- New abstraction?: Yes. This feature introduces one explicit tenant-scoped aggregate contract for governance summary state that multiple surfaces share.
- New enum/state/reason family?: No. Existing compare posture, governance validity, and attention semantics remain the source vocabulary.
- New cross-domain UI framework/taxonomy?: No. The work consolidates one summary family; it does not create a new presentation framework.
- Current operator problem: Operators can see overlapping tenant-governance cards and pages that recompute similar facts independently, which makes counts, headlines, and next-action guidance harder to trust and more expensive to keep aligned.
- Existing structure is insufficient because: The current structure lets baseline compare posture live in one shared path while overdue, expiring, and lapsed governance attention can still be owned locally by individual widgets or banners. That fragmentation means no single contract is accountable for the tenant's shared governance summary.
- Narrowest correct implementation: Introduce one derived tenant-scoped governance aggregate that absorbs the overlapping summary facts already reused across landing, dashboard, and banner surfaces, while leaving presentation mapping local to each surface.
- Ownership cost: The codebase takes on one explicit shared contract plus cross-surface regression tests and request-reuse guarantees, but removes duplicated query ownership and semantic drift from each consuming surface.
- Alternative intentionally rejected: Continuing to harden each widget or page independently was rejected because it preserves duplicate ownership. Adding a persisted summary record or cross-request cache was rejected because current-release needs do not require a new durable truth source.
- Release truth: Current-release truth. The overlap already exists on shipped tenant-governance surfaces and is growing with ongoing governance work.
User Scenarios & Testing (mandatory)
User Story 1 - One Tenant, One Governance Posture (Priority: P1)
As a tenant operator, I want the dashboard, banner, and baseline-compare landing to agree on what needs action, so that I do not have to reconcile conflicting counts or messages before deciding what to do next.
Why this priority: Trust in the product's governance posture depends on cross-surface consistency. Conflicting summary signals create operator hesitation and support debt.
Independent Test: Can be fully tested by seeding one tenant with baseline-compare posture and governance-attention states, then rendering at least three covered surfaces and verifying that the same tenant state produces the same underlying counts, posture family, and next-action intent.
Acceptance Scenarios:
- Given a tenant has no visible drift findings but has lapsed accepted-risk governance, When an authorized operator opens the dashboard and the baseline-compare landing, Then both surfaces present the tenant as needing attention rather than as an all-clear.
- Given a tenant has overdue open findings and expiring governance, When multiple tenant-governance surfaces render in the same session, Then they expose consistent overdue and governance-attention meaning for that tenant.
- Given a tenant has a trustworthy compare result with no findings and no governance-attention conditions, When the operator opens covered summary surfaces, Then those surfaces consistently present a healthy posture rather than mixed healthy and warning states.
User Story 2 - Consistent Next Action Across Summary Surfaces (Priority: P1)
As a tenant operator, I want each governance summary surface to point me toward the same next step for the same tenant state, so that I can act quickly without guessing which surface is authoritative.
Why this priority: A shared aggregate is only useful if it produces not just aligned counts, but aligned operator action.
Independent Test: Can be fully tested by exercising compare-in-progress, failed-compare, overdue-findings, and governance-lapsed scenarios and verifying that each covered surface routes the operator toward the same class of next action for the same state.
Acceptance Scenarios:
- Given a baseline compare is currently running, When the operator opens the dashboard card, banner, and landing page, Then each surface points to progress-aware follow-up instead of mixing stale completion guidance with active-run guidance.
- Given a tenant needs attention because overdue or lapsed governance states remain, When the operator opens any aggregate-consuming summary surface, Then the primary follow-up action remains aligned with reviewing findings rather than presenting unrelated compare guidance.
- Given a tenant lacks a usable baseline compare result because no assignment or no snapshot is available, When summary surfaces render, Then they consistently communicate availability or prerequisite guidance instead of one surface appearing healthy while another appears unavailable.
User Story 3 - Stable Multi-Card Tenant Summary (Priority: P2)
As a tenant operator, I want a page that shows multiple governance cards to stay stable for my current tenant, so that repeated summary cards do not disagree or flicker between different tenant-governance interpretations.
Why this priority: The immediate product problem is not only semantic drift over time but duplicate ownership inside one page render.
Independent Test: Can be fully tested by rendering a tenant page that includes more than one aggregate-consuming governance surface and verifying that the same tenant request produces one stable posture family and one stable set of governance-attention counts.
Acceptance Scenarios:
- Given a tenant dashboard renders both a governance card and a needs-attention summary, When the page loads, Then both surfaces reflect the same tenant posture and compatible next-step guidance.
- Given the operator switches from one tenant to another, When the new tenant page renders, Then the summary state resets to the new tenant and does not reuse the previous tenant's governance posture.
- Given no tenant is selected, When a tenant-governance surface is reached indirectly, Then it shows the appropriate empty or unavailable state and does not leak another tenant's summary.
Edge Cases
- A tenant has zero open drift findings, but overdue findings, expiring governance, or lapsed governance still exist; all aggregate-consuming attention surfaces must continue to present action-needed posture.
- A tenant has baseline assignment but no consumable snapshot or no completed compare result yet; covered surfaces must stay consistent about availability and prerequisites.
- A compare run is queued or running while older compare-derived counts still exist; summary surfaces must present progress-aware posture instead of mixing active-run and completed-run claims.
- A single request renders multiple governance summary surfaces for one tenant; the request must not produce contradictory counts or posture labels because different surfaces recomputed the same attention family separately.
- A tenant switch or no-tenant context occurs between requests; request-local reuse must not carry governance summary state across tenant boundaries.
- A surface still needs local diagnostics beyond the shared aggregate; those diagnostics must remain secondary and must not redefine the shared attention semantics.
Requirements (mandatory)
Constitution alignment (required): This feature introduces no new Microsoft Graph contract, no new long-running job type, and no new persisted artifact. It consolidates existing tenant-governance summary truth from current compare posture, findings attention, and governance validity into one shared derived contract. Existing compare operations and Monitoring observability remain unchanged.
Constitution alignment (PROP-001 / ABSTR-001 / PERSIST-001 / STATE-001 / BLOAT-001): This feature introduces one narrow abstraction: a shared tenant-governance aggregate contract. It does so because existing tenant surfaces already duplicate overlapping summary state and a narrower per-surface hardening would preserve split ownership. The contract remains derived, current-release, and intentionally avoids new persistence, new state families, or a cross-domain semantic framework.
Constitution alignment (OPS-UX): No new OperationRun type is introduced. Existing baseline-compare runs remain the only operational execution path involved, and their queued, running, failed, or completed visibility remains governed by the existing Ops-UX contract.
Constitution alignment (RBAC-UX): The feature stays entirely in the tenant/admin plane on tenant-context surfaces. It does not introduce new authorization behavior. Non-members remain deny-as-not-found, in-scope members without the required capability remain forbidden for existing compare-start or drill-down actions, and shared aggregate reuse must remain tenant-scoped so no cross-tenant summary leakage is possible.
Constitution alignment (OPS-EX-AUTH-001): Not applicable. No authentication flow is changed.
Constitution alignment (BADGE-001): Existing centralized badge and tone semantics for findings severity, governance validity, and compare posture remain the semantic source. This feature may make those semantics appear on more than one surface through the aggregate, but it must not introduce ad hoc per-surface status vocabularies.
Constitution alignment (UI-FIL-001): The feature reuses native Filament widgets, sections, links, and badges already present on the dashboard, landing page, and banner surfaces. It should consolidate the shared semantic source rather than introducing page-local markup or a new local visual language for warning states.
Constitution alignment (UI-NAMING-001): Operator-facing terms remain baseline governance, needs attention, baseline compare, compare now, and open findings. The feature must preserve the same domain vocabulary across dashboard cards, landing copy, banner messaging, and drill-down affordances so operators do not see one surface talk about attention while another describes the same state as healthy posture.
Constitution alignment (OPSURF-001): This feature materially refactors operator-facing summary surfaces. Default-visible information must remain operator-first: posture, urgency, and next action appear first, while diagnostics remain secondary. Mutation scope remains unchanged: read-only summary surfaces stay read-only, and the existing Compare now action continues to communicate its existing compare execution scope.
Constitution alignment (UI-SEM-001 / LAYER-001 / TEST-TRUTH-001): A shared aggregate is justified because direct per-surface mapping has already produced redundant truth and semantic drift. The aggregate must replace duplicate per-surface summary ownership rather than layering yet another presenter or wrapper on top of it. Tests must assert business truth across surfaces and request scope, not only thin adapter wiring.
Constitution alignment (Filament Action Surfaces): This feature modifies Filament pages and widgets in the tenant panel. The Action Surface Contract remains satisfied because the summary surfaces are read-only and the only existing mutation surface involved, Baseline Compare landing, keeps explicit confirmation and capability gating for compare start. UI-FIL-001 is satisfied because no exception to native Filament summary or action primitives is required.
Constitution alignment (UX-001 — Layout & Information Architecture): The feature does not add new create or edit screens. It changes summary and landing semantics on existing tenant surfaces. The landing page must keep operator posture and next-action messaging above diagnostics, and widgets or banners must keep attention content concise, explicit, and drill-down oriented rather than becoming diagnostic walls.
Functional Requirements
- FR-168-001: The system MUST provide one tenant-scoped governance aggregate for the currently selected tenant that combines the summary state already shared across tenant governance cards, banners, and baseline-compare summary surfaces.
- FR-168-002: The tenant-governance aggregate MUST include, at minimum, compare availability or progress state, compare outcome or freshness posture, compare trust-limiting signals relevant to summary posture, visible drift findings count, overdue open findings count, expiring governance count, lapsed governance count, active non-new findings count, and high-severity active findings count.
- FR-168-003: At least three existing tenant-facing summary surfaces MUST consume the same tenant-governance aggregate contract.
- FR-168-004: Aggregate-consuming surfaces MUST treat the shared aggregate as the semantic owner for overdue findings, expiring governance, lapsed governance, and tenant-level baseline posture, and MUST NOT define conflicting local business rules for those states.
- FR-168-005: Aggregate-consuming surfaces MAY keep local layout, wording emphasis, and navigation affordances appropriate to their context, but they MUST preserve the same underlying posture family, counts, and next-action intent for the same tenant state.
- FR-168-006: A tenant with zero visible drift findings but any overdue open findings, expiring governance, or lapsed governance MUST still render as needing attention on every aggregate-consuming attention surface.
- FR-168-007: A tenant with no baseline assignment, no usable snapshot, no current compare result, an in-progress compare, a failed compare, a stale compare result, or a trustworthy all-clear result MUST resolve to one consistent tenant-governance posture across all aggregate-consuming surfaces.
- FR-168-008: Repeated reads of the same tenant-governance aggregate during one request MUST reuse the same derived result instead of recomputing aggregate-owned counts separately for each consuming surface.
- FR-168-009: Request-local aggregate reuse MUST remain scoped to the current tenant context and MUST NOT leak summary state across tenants, workspaces, or no-tenant states.
- FR-168-010: The initial implementation MUST remain derived-only and MUST NOT require a new persisted summary record, a new cross-request cache, or a new dashboard setup step.
- FR-168-011: Existing compare-start actions, findings drill-downs, and baseline-compare navigation destinations MUST remain available, and this feature MUST NOT broaden or weaken their existing RBAC and confirmation behavior.
- FR-168-012: If a covered surface needs diagnostics beyond the shared aggregate, those diagnostics MUST remain secondary and MUST NOT redefine the shared attention semantics already owned by the aggregate.
- FR-168-013: The feature MUST stay bounded to one tenant at a time and MUST NOT expand this aggregate into cross-tenant portfolio posture, new governance workflow semantics, or a full dashboard redesign.
- FR-168-014: Regression coverage MUST verify semantic consistency across aggregate-consuming surfaces for at least these tenant states: unavailable prerequisites, compare in progress, compare failed, open findings requiring action, overdue findings without new drift, lapsed governance without new drift, caution or stale compare posture, and trustworthy all-clear.
- FR-168-015: Regression coverage MUST verify that a single page render containing multiple aggregate-consuming surfaces does not re-own overdue, expiring, or lapsed counts in parallel and remains stable for the current tenant context.
UI Action Matrix (mandatory when Filament is changed)
| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| Baseline Compare landing | app/Filament/Pages/BaselineCompareLanding.php |
Existing Compare now action remains in the header |
Not a record list surface | None | None | Existing prerequisite and unavailable messaging remains | Compare now only |
N/A | Existing compare start remains observable through OperationRun; no new audit surface added here |
This spec changes posture ownership and copy consistency, not the action inventory |
Tenant dashboard Needs Attention widget |
app/Filament/Widgets/Dashboard/NeedsAttention.php |
None | N/A | None | None | Healthy state remains a read-only reassurance surface | N/A | N/A | No | Read-only summary widget; covered because it currently owns overlapping attention counts |
Tenant dashboard Baseline Governance card |
app/Filament/Widgets/Dashboard/BaselineCompareNow.php |
None | N/A | None | None | Existing no-assignment state remains a read-only empty state | N/A | N/A | No | Read-only summary card; next-action links remain navigation only |
| Tenant governance banner | app/Filament/Widgets/Tenant/BaselineCompareCoverageBanner.php |
None | N/A | None | None | Banner simply hides when not relevant | N/A | N/A | No | Read-only warning banner; included because it must consume the shared aggregate family |
Key Entities (include if feature involves data)
- Tenant governance aggregate: A derived tenant-scoped summary that combines compare posture, governance-attention counts, and next-action intent for operator-facing summary surfaces.
- Baseline compare posture: The tenant's current compare availability, freshness, outcome, and trustworthiness summary.
- Governance attention summary: The tenant's actionable counts for overdue findings, expiring governance, lapsed governance, and other active finding pressure that should influence summary posture.
- Aggregate-consuming surface: Any tenant-facing card, widget, banner, or landing summary that reads the shared aggregate and applies only local presentation mapping.
Success Criteria (mandatory)
Measurable Outcomes
- SC-168-001: In seeded regression coverage, at least three tenant-governance summary surfaces display identical overdue, expiring, and lapsed-governance counts for the same tenant in 100% of tested scenarios.
- SC-168-002: In seeded regression coverage, tenants with zero visible drift findings but overdue or unhealthy governance still render as action-needed on every tested aggregate-consuming attention surface.
- SC-168-003: In operator acceptance review, a tenant operator can determine the current governance posture and next action from either the dashboard or baseline-compare landing within 10 seconds.
- SC-168-004: In regression coverage, a single page that renders multiple aggregate-consuming surfaces for one tenant shows no contradictory posture family, tone, or next-action combination within the same load.
- SC-168-005: The feature ships without requiring any new setup step, scheduled refresh step, or durable summary artifact for operators to see the shared tenant-governance posture.
Assumptions
- Existing findings workflow truth, finding-exception validity truth, and baseline-compare posture truth remain sufficient to derive the shared tenant-governance aggregate.
- Existing tenant dashboard and baseline-compare surfaces remain in place; this spec consolidates their summary contract rather than replacing the whole tenant-governance UI.
- Existing tenant-entitlement and compare-start authorization rules remain correct and do not need separate RBAC redesign in this slice.
Non-Goals
- Building a cross-tenant portfolio governance aggregate or workspace-wide control tower summary for this data family
- Introducing a new persisted summary table, cache artifact, or reporting export just to support shared summary posture
- Redefining findings workflow semantics, exception validity semantics, or compare reason-code semantics
- Redesigning the entire tenant dashboard or baseline-compare landing beyond the shared-governance summary family
Dependencies
- Existing baseline assignment, snapshot availability, and compare-run truth
- Existing findings and finding-exception governance-attention derivation
- Existing tenant dashboard widgets, baseline-compare landing surface, and tenant governance banner surfaces
- Existing tenant-context RBAC and drill-down destinations for findings and operation runs
Definition of Done
Spec 168 is complete when:
- one tenant-scoped governance aggregate owns the overlapping summary family used by at least three tenant-facing governance surfaces,
- dashboard, landing, and banner-style surfaces no longer contradict one another about overdue, expiring, lapsed, or compare-posture state for the same tenant,
- request-local reuse of the aggregate is testable and tenant-safe,
- no new persisted summary truth or cross-request cache is required,
- and the covered surfaces remain operator-first while keeping local presentation responsibility separate from shared business semantics.