## 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
19 KiB
Tasks: Tenant Governance Aggregate Contract
Input: Design documents from /specs/168-tenant-governance-aggregate-contract/
Prerequisites: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/, quickstart.md
Tests: Tests are REQUIRED for this feature. Use Pest coverage in tests/Feature/Baselines/BaselineCompareStatsTest.php, tests/Feature/Baselines/BaselineCompareSummaryAssessmentTest.php, tests/Feature/Baselines/TenantGovernanceAggregateResolverTest.php, tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php, tests/Feature/Filament/BaselineCompareNowWidgetTest.php, tests/Feature/Filament/BaselineCompareCoverageBannerTest.php, tests/Feature/Filament/BaselineCompareLandingAdminTenantParityTest.php, tests/Feature/Filament/BaselineCompareLandingDuplicateNamesBannerTest.php, tests/Feature/Filament/BaselineCompareLandingRbacLabelsTest.php, tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php, tests/Feature/Filament/BaselineCompareLandingWhyNoFindingsTest.php, tests/Feature/Filament/NeedsAttentionWidgetTest.php, tests/Feature/Filament/TenantGovernanceAggregateMemoizationTest.php, and tests/Feature/Guards/DerivedStateConsumerAdoptionGuardTest.php.
Operations: This feature does not create a new OperationRun type or change run lifecycle ownership. Existing baseline-compare runs remain the only execution surface involved, and all work here is read-time summary consolidation.
RBAC: Existing tenant-context membership, entitlement, and 404 vs 403 semantics remain unchanged. Tasks must preserve current tenant-safe drill-down behavior and ensure request-local reuse never leaks summary state across tenants, workspaces, or no-tenant states.
Operator Surfaces: The tenant dashboard Baseline Governance card, tenant dashboard Needs Attention widget, tenant governance banner, and Baseline Compare landing must keep operator-first posture, urgency, and next-step guidance above diagnostics.
Filament UI Action Surfaces: No new action inventories are added. The existing Baseline Compare landing Compare now action remains confirmation-gated and capability-gated, and all other affected surfaces remain navigation-only summaries.
Filament UI UX-001: No new create, edit, or view layouts are introduced. Existing widget, banner, and landing layouts remain intact while shared summary ownership is refactored.
Badges: Existing compare-posture, severity, and governance-validity semantics must remain sourced from shared badge semantics; no new page-local mappings are introduced.
Organization: Tasks are grouped by user story so each story can be implemented and verified as an independent increment after the shared aggregate contract is in place.
Phase 1: Setup (Shared Aggregate Scaffolding)
Purpose: Create the narrow runtime and test scaffolding required for the tenant-governance aggregate.
- T001 [P] Create the aggregate runtime scaffolding in
app/Support/Baselines/TenantGovernanceAggregate.phpandapp/Support/Baselines/TenantGovernanceAggregateResolver.php - T002 [P] Create the focused regression scaffolding in
tests/Feature/Baselines/TenantGovernanceAggregateResolverTest.phpandtests/Feature/Filament/TenantGovernanceAggregateMemoizationTest.php
Phase 2: Foundational (Blocking Aggregate Contract)
Purpose: Build the shared aggregate runtime and request-scoped family contract that all user stories depend on.
⚠️ CRITICAL: No user story work should begin until this phase is complete.
- T003 [P] Extend source-truth regression coverage for aggregate input counts and summary assessment mapping in
tests/Feature/Baselines/BaselineCompareStatsTest.phpandtests/Feature/Baselines/BaselineCompareSummaryAssessmentTest.php - T004 Implement the derived tenant summary contract fields in
app/Support/Baselines/TenantGovernanceAggregate.php - T005 Implement aggregate resolution and request-scoped reuse from
BaselineCompareStatsandBaselineCompareSummaryAssessmentinapp/Support/Baselines/TenantGovernanceAggregateResolver.phpandapp/Support/Baselines/BaselineCompareStats.php - T006 [P] Declare the governance aggregate derived-state family, extend the first-slice supported consumer contract, and update the guard in
app/Support/Ui/DerivedState/DerivedStateFamily.php,specs/167-derived-state-memoization/contracts/request-scoped-derived-state.logical.openapi.yaml, andtests/Feature/Guards/DerivedStateConsumerAdoptionGuardTest.php
Checkpoint: The tenant-governance aggregate exists as one derived request-local contract that later surface work can consume.
Phase 3: User Story 1 - One Tenant, One Governance Posture (Priority: P1)
Goal: Make the dashboard governance card, tenant banner, and Baseline Compare landing agree on posture family and governance-attention counts for the same tenant.
Independent Test: Seed one tenant with unavailable prerequisites, compare in progress, compare failed, open findings requiring action, overdue without new drift, lapsed governance without new drift, caution, stale results, and trustworthy all-clear states, then verify the dashboard governance card, banner, and landing summary resolve the same posture family and count family while keeping landing diagnostics secondary.
Tests for User Story 1
- T007 [P] [US1] Add aggregate scenario coverage for unavailable, in-progress, failed, open-findings action-required, overdue-without-new-drift, lapsed-without-new-drift, caution, stale, and trustworthy-all-clear states in
tests/Feature/Baselines/TenantGovernanceAggregateResolverTest.php - T008 [P] [US1] Extend cross-surface posture and count parity assertions for the full FR-168-014 state matrix, landing diagnostics-secondary hierarchy, and unchanged compare-start authorization and confirmation semantics in
tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php,tests/Feature/Filament/BaselineCompareNowWidgetTest.php,tests/Feature/Filament/BaselineCompareCoverageBannerTest.php,tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php,tests/Feature/Filament/BaselineCompareLandingRbacLabelsTest.php,tests/Feature/Filament/BaselineCompareLandingWhyNoFindingsTest.php, andtests/Feature/Filament/BaselineCompareLandingDuplicateNamesBannerTest.php
Implementation for User Story 1
- T009 [US1] Route the tenant dashboard
Baseline Governancesummary card through the shared aggregate inapp/Filament/Widgets/Dashboard/BaselineCompareNow.php - T010 [US1] Drive the tenant governance banner from the shared aggregate in
app/Filament/Widgets/Tenant/BaselineCompareCoverageBanner.php - T011 [US1] Replace the Baseline Compare landing default-visible posture summary with the shared aggregate while keeping diagnostics on
BaselineCompareStats, preserving existingCompare nowconfirmation and capability semantics, and keeping diagnostics secondary inapp/Filament/Pages/BaselineCompareLanding.php - T012 [US1] Keep aggregate posture, tone, and supporting-message semantics aligned to existing compare-summary rules in
app/Support/Baselines/BaselineCompareSummaryAssessor.phpandapp/Support/Baselines/BaselineCompareSummaryAssessment.php - T013 [US1] Run the focused posture parity pack in
tests/Feature/Baselines/TenantGovernanceAggregateResolverTest.php,tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php,tests/Feature/Filament/BaselineCompareNowWidgetTest.php,tests/Feature/Filament/BaselineCompareCoverageBannerTest.php,tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php,tests/Feature/Filament/BaselineCompareLandingRbacLabelsTest.php,tests/Feature/Filament/BaselineCompareLandingWhyNoFindingsTest.php, andtests/Feature/Filament/BaselineCompareLandingDuplicateNamesBannerTest.php
Checkpoint: Three tenant-facing summary surfaces now share one governance posture and count contract for the same tenant state.
Phase 4: User Story 2 - Consistent Next Action Across Summary Surfaces (Priority: P1)
Goal: Make every covered summary surface point operators toward the same class of next step for the same tenant state.
Independent Test: Seed running-compare, failed-compare, unavailable-prerequisite, open-findings requiring action, overdue-without-new-drift, lapsed-governance without new drift, caution, and stale scenarios, then verify the dashboard governance card, banner, and landing summary expose the same next-action intent and matching operator-facing labels.
Tests for User Story 2
- T014 [P] [US2] Add next-action intent regressions for running, failed, unavailable, open-findings action-required, overdue-without-new-drift, lapsed-without-new-drift, caution, and stale scenarios in
tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php,tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php, andtests/Feature/Filament/BaselineCompareLandingAdminTenantParityTest.php - T015 [P] [US2] Add dashboard governance card and banner next-step assertions, including preserved findings drill-down and open-landing navigation availability, in
tests/Feature/Filament/BaselineCompareNowWidgetTest.phpandtests/Feature/Filament/BaselineCompareCoverageBannerTest.php
Implementation for User Story 2
- T016 [US2] Add next-action label and target ownership to the aggregate contract in
app/Support/Baselines/TenantGovernanceAggregate.phpandapp/Support/Baselines/TenantGovernanceAggregateResolver.php - T017 [US2] Map shared next-action intent to findings, run, and landing destinations in
app/Filament/Widgets/Dashboard/BaselineCompareNow.php - T018 [US2] Align banner and landing next-action presentation to the shared intent in
app/Filament/Widgets/Tenant/BaselineCompareCoverageBanner.phpandapp/Filament/Pages/BaselineCompareLanding.php - T019 [US2] Run the focused next-action pack in
tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php,tests/Feature/Filament/BaselineCompareNowWidgetTest.php,tests/Feature/Filament/BaselineCompareCoverageBannerTest.php,tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php, andtests/Feature/Filament/BaselineCompareLandingAdminTenantParityTest.php
Checkpoint: Covered summary surfaces no longer disagree about whether the operator should inspect findings, watch a run, open the landing page, or take no action.
Phase 5: User Story 3 - Stable Multi-Card Tenant Summary (Priority: P2)
Goal: Keep multiple governance cards on the same tenant page stable by reusing one request-local aggregate and removing duplicate local findings-count ownership.
Independent Test: Render the tenant dashboard with both Needs Attention and Baseline Governance visible, verify both surfaces stay consistent for the same tenant in one request, then switch tenants or remove tenant context and verify no stale summary leaks.
Tests for User Story 3
- T020 [P] [US3] Add request-local reuse, tenant-switch, and no-tenant safety coverage in
tests/Feature/Filament/TenantGovernanceAggregateMemoizationTest.php - T021 [P] [US3] Extend multi-card dashboard stability and no-local-requery coverage in
tests/Feature/Filament/NeedsAttentionWidgetTest.phpandtests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php
Implementation for User Story 3
- T022 [US3] Harden tenant-switch, workspace-scope, and no-tenant key behavior for the second dashboard summary consumer in
app/Support/Ui/DerivedState/DerivedStateFamily.phpandapp/Support/Baselines/TenantGovernanceAggregateResolver.php - T023 [US3] Replace local overdue, expiring, lapsed, and high-severity findings ownership with the shared aggregate in
app/Filament/Widgets/Dashboard/NeedsAttention.php - T024 [US3] Extend governance aggregate consumer declarations and no-local-requery guard coverage to include
NeedsAttentioninspecs/167-derived-state-memoization/contracts/request-scoped-derived-state.logical.openapi.yamlandtests/Feature/Guards/DerivedStateConsumerAdoptionGuardTest.php - T025 [US3] Run the focused memoization and guard pack in
tests/Feature/Filament/TenantGovernanceAggregateMemoizationTest.php,tests/Feature/Filament/NeedsAttentionWidgetTest.php, andtests/Feature/Guards/DerivedStateConsumerAdoptionGuardTest.php
Checkpoint: The tenant dashboard can render multiple governance summary surfaces in one request without contradictory counts, posture drift, or tenant leakage.
Phase 6: Polish & Cross-Cutting Concerns
Purpose: Final copy alignment, formatting, and focused verification across all stories.
- T026 [P] Align operator-facing copy and next-step labels in
app/Filament/Widgets/Dashboard/BaselineCompareNow.php,app/Filament/Widgets/Dashboard/NeedsAttention.php,app/Filament/Widgets/Tenant/BaselineCompareCoverageBanner.php, andapp/Filament/Pages/BaselineCompareLanding.php - T027 Run formatting for touched implementation files with
vendor/bin/sail bin pint --dirty --format agentusingspecs/168-tenant-governance-aggregate-contract/quickstart.md - T028 Run the final focused verification pack from
specs/168-tenant-governance-aggregate-contract/quickstart.mdagainsttests/Feature/Baselines/BaselineCompareStatsTest.php,tests/Feature/Baselines/BaselineCompareSummaryAssessmentTest.php,tests/Feature/Baselines/TenantGovernanceAggregateResolverTest.php,tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php,tests/Feature/Filament/BaselineCompareNowWidgetTest.php,tests/Feature/Filament/BaselineCompareCoverageBannerTest.php,tests/Feature/Filament/BaselineCompareLandingAdminTenantParityTest.php,tests/Feature/Filament/BaselineCompareLandingDuplicateNamesBannerTest.php,tests/Feature/Filament/BaselineCompareLandingRbacLabelsTest.php,tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php,tests/Feature/Filament/BaselineCompareLandingWhyNoFindingsTest.php,tests/Feature/Filament/NeedsAttentionWidgetTest.php,tests/Feature/Filament/TenantGovernanceAggregateMemoizationTest.php, andtests/Feature/Guards/DerivedStateConsumerAdoptionGuardTest.php
Dependencies & Execution Order
Phase Dependencies
- Setup (Phase 1): Starts immediately and creates the narrow aggregate runtime and test scaffolding.
- Foundational (Phase 2): Depends on Setup and blocks all user stories until the aggregate contract and request-scoped family are in place.
- User Story 1 (Phase 3): Starts after Foundational and delivers the MVP shared-posture slice across three surfaces.
- User Story 2 (Phase 4): Starts after User Story 1 because it refines the same summary surfaces with explicit next-action intent.
- User Story 3 (Phase 5): Starts after User Story 2 because it adopts the second dashboard summary surface only after shared next-action semantics and first-slice parity are settled.
- Polish (Phase 6): Starts after all desired user stories are complete and ends with focused verification.
User Story Dependencies
- User Story 1 (P1): Depends only on the aggregate contract and request-scoped family from Phase 2.
- User Story 2 (P1): Depends on User Story 1 because the same summary surfaces must already read the shared aggregate before their next-action mapping can be aligned.
- User Story 3 (P2): Depends on the aggregate contract from Phase 2 plus the settled shared posture and next-action semantics from User Stories 1 and 2 before the second dashboard consumer joins the shared contract.
Within Each User Story
- Story tests should be written before or alongside the relevant implementation tasks and must fail before the story is considered complete.
- Aggregate contract changes should land before surface adoption in the same story.
- Surface refactors should land before the focused story-level regression run.
Parallel Opportunities
T001andT002can run in parallel during Setup.T003andT006can run in parallel during Foundational work.T007andT008can run in parallel for User Story 1.T014andT015can run in parallel for User Story 2.T020andT021can run in parallel for User Story 3.- After
T022,T023andT024can run in parallel because they change different files.
Parallel Example: User Story 1
# User Story 1 tests in parallel:
Task: T007 tests/Feature/Baselines/TenantGovernanceAggregateResolverTest.php
Task: T008 tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php
# User Story 1 surface adoption split after aggregate semantics are fixed:
Task: T009 app/Filament/Widgets/Dashboard/BaselineCompareNow.php
Task: T010 app/Filament/Widgets/Tenant/BaselineCompareCoverageBanner.php
Parallel Example: User Story 2
# User Story 2 tests in parallel:
Task: T014 tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php
Task: T015 tests/Feature/Filament/BaselineCompareNowWidgetTest.php
# User Story 2 implementation split after next-action ownership lands:
Task: T017 app/Filament/Widgets/Dashboard/BaselineCompareNow.php
Task: T018 app/Filament/Widgets/Tenant/BaselineCompareCoverageBanner.php and app/Filament/Pages/BaselineCompareLanding.php
Parallel Example: User Story 3
# User Story 3 tests in parallel:
Task: T020 tests/Feature/Filament/TenantGovernanceAggregateMemoizationTest.php
Task: T021 tests/Feature/Filament/NeedsAttentionWidgetTest.php
# User Story 3 implementation split after request-scoped keying is settled:
Task: T023 app/Filament/Widgets/Dashboard/NeedsAttention.php
Task: T024 tests/Feature/Guards/DerivedStateConsumerAdoptionGuardTest.php and specs/167-derived-state-memoization/contracts/request-scoped-derived-state.logical.openapi.yaml
Implementation Strategy
MVP First
- Complete Phase 1: Setup.
- Complete Phase 2: Foundational.
- Complete Phase 3: User Story 1.
- Validate that the dashboard governance card, tenant banner, and landing summary now share one posture and count contract.
Incremental Delivery
- Add User Story 2 to align next-action guidance once shared posture parity is proven.
- Add User Story 3 to bring the second dashboard card onto the same contract and lock in request-local stability.
- Finish with copy alignment, formatting, and the focused verification pack.
Parallel Team Strategy
- One developer can complete Phase 1 and Phase 2 while another prepares the story tests.
- After User Story 1 lands, one developer can handle User Story 2 next-action adoption while another prepares User Story 3 memoization and guard coverage.
- Rejoin for Phase 6 to run Pint and the focused verification pack.
Notes
[P]tasks target different files with no direct dependency on unfinished code in the same phase.[US1],[US2], and[US3]labels map tasks directly to the feature specification user stories.- The suggested MVP scope is Phase 1 through Phase 3 only.
- No task in this plan introduces new persistence, a new Graph contract, a new Filament panel/provider registration, or a new destructive action.