# 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. - [X] T001 [P] Create the aggregate runtime scaffolding in `app/Support/Baselines/TenantGovernanceAggregate.php` and `app/Support/Baselines/TenantGovernanceAggregateResolver.php` - [X] T002 [P] Create the focused regression scaffolding in `tests/Feature/Baselines/TenantGovernanceAggregateResolverTest.php` and `tests/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. - [X] T003 [P] Extend source-truth regression coverage for aggregate input counts and summary assessment mapping in `tests/Feature/Baselines/BaselineCompareStatsTest.php` and `tests/Feature/Baselines/BaselineCompareSummaryAssessmentTest.php` - [X] T004 Implement the derived tenant summary contract fields in `app/Support/Baselines/TenantGovernanceAggregate.php` - [X] T005 Implement aggregate resolution and request-scoped reuse from `BaselineCompareStats` and `BaselineCompareSummaryAssessment` in `app/Support/Baselines/TenantGovernanceAggregateResolver.php` and `app/Support/Baselines/BaselineCompareStats.php` - [X] 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`, and `tests/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 - [X] 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` - [X] 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`, and `tests/Feature/Filament/BaselineCompareLandingDuplicateNamesBannerTest.php` ### Implementation for User Story 1 - [X] T009 [US1] Route the tenant dashboard `Baseline Governance` summary card through the shared aggregate in `app/Filament/Widgets/Dashboard/BaselineCompareNow.php` - [X] T010 [US1] Drive the tenant governance banner from the shared aggregate in `app/Filament/Widgets/Tenant/BaselineCompareCoverageBanner.php` - [X] T011 [US1] Replace the Baseline Compare landing default-visible posture summary with the shared aggregate while keeping diagnostics on `BaselineCompareStats`, preserving existing `Compare now` confirmation and capability semantics, and keeping diagnostics secondary in `app/Filament/Pages/BaselineCompareLanding.php` - [X] T012 [US1] Keep aggregate posture, tone, and supporting-message semantics aligned to existing compare-summary rules in `app/Support/Baselines/BaselineCompareSummaryAssessor.php` and `app/Support/Baselines/BaselineCompareSummaryAssessment.php` - [X] 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`, and `tests/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 - [X] 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`, and `tests/Feature/Filament/BaselineCompareLandingAdminTenantParityTest.php` - [X] 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.php` and `tests/Feature/Filament/BaselineCompareCoverageBannerTest.php` ### Implementation for User Story 2 - [X] T016 [US2] Add next-action label and target ownership to the aggregate contract in `app/Support/Baselines/TenantGovernanceAggregate.php` and `app/Support/Baselines/TenantGovernanceAggregateResolver.php` - [X] T017 [US2] Map shared next-action intent to findings, run, and landing destinations in `app/Filament/Widgets/Dashboard/BaselineCompareNow.php` - [X] T018 [US2] Align banner and landing next-action presentation to the shared intent in `app/Filament/Widgets/Tenant/BaselineCompareCoverageBanner.php` and `app/Filament/Pages/BaselineCompareLanding.php` - [X] 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`, and `tests/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 - [X] T020 [P] [US3] Add request-local reuse, tenant-switch, and no-tenant safety coverage in `tests/Feature/Filament/TenantGovernanceAggregateMemoizationTest.php` - [X] T021 [P] [US3] Extend multi-card dashboard stability and no-local-requery coverage in `tests/Feature/Filament/NeedsAttentionWidgetTest.php` and `tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php` ### Implementation for User Story 3 - [X] T022 [US3] Harden tenant-switch, workspace-scope, and no-tenant key behavior for the second dashboard summary consumer in `app/Support/Ui/DerivedState/DerivedStateFamily.php` and `app/Support/Baselines/TenantGovernanceAggregateResolver.php` - [X] T023 [US3] Replace local overdue, expiring, lapsed, and high-severity findings ownership with the shared aggregate in `app/Filament/Widgets/Dashboard/NeedsAttention.php` - [X] T024 [US3] Extend governance aggregate consumer declarations and no-local-requery guard coverage to include `NeedsAttention` in `specs/167-derived-state-memoization/contracts/request-scoped-derived-state.logical.openapi.yaml` and `tests/Feature/Guards/DerivedStateConsumerAdoptionGuardTest.php` - [X] T025 [US3] Run the focused memoization and guard pack in `tests/Feature/Filament/TenantGovernanceAggregateMemoizationTest.php`, `tests/Feature/Filament/NeedsAttentionWidgetTest.php`, and `tests/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. - [X] 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`, and `app/Filament/Pages/BaselineCompareLanding.php` - [X] T027 Run formatting for touched implementation files with `vendor/bin/sail bin pint --dirty --format agent` using `specs/168-tenant-governance-aggregate-contract/quickstart.md` - [X] T028 Run the final focused verification pack from `specs/168-tenant-governance-aggregate-contract/quickstart.md` against `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` --- ## 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 - `T001` and `T002` can run in parallel during Setup. - `T003` and `T006` can run in parallel during Foundational work. - `T007` and `T008` can run in parallel for User Story 1. - `T014` and `T015` can run in parallel for User Story 2. - `T020` and `T021` can run in parallel for User Story 3. - After `T022`, `T023` and `T024` can run in parallel because they change different files. --- ## Parallel Example: User Story 1 ```bash # 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 ```bash # 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 ```bash # 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 1. Complete Phase 1: Setup. 2. Complete Phase 2: Foundational. 3. Complete Phase 3: User Story 1. 4. Validate that the dashboard governance card, tenant banner, and landing summary now share one posture and count contract. ### Incremental Delivery 1. Add User Story 2 to align next-action guidance once shared posture parity is proven. 2. Add User Story 3 to bring the second dashboard card onto the same contract and lock in request-local stability. 3. Finish with copy alignment, formatting, and the focused verification pack. ### Parallel Team Strategy 1. One developer can complete Phase 1 and Phase 2 while another prepares the story tests. 2. 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. 3. 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.