## Summary - add a workspace-scoped baseline compare matrix page under baseline profiles - derive matrix tenant summaries, subject rows, cell states, freshness, and trust from existing snapshots, compare runs, and findings - add confirmation-gated `Compare assigned tenants` actions on the baseline detail and matrix surfaces without introducing a workspace umbrella run - preserve matrix navigation context into tenant compare and finding drilldowns and add centralized matrix badge semantics - include spec, plan, data model, contracts, quickstart, tasks, and focused feature/browser coverage for Spec 190 ## Verification - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Badges/BaselineCompareMatrixBadgesTest.php tests/Feature/Baselines/BaselineCompareMatrixBuilderTest.php tests/Feature/Baselines/BaselineCompareMatrixCompareAllActionTest.php tests/Feature/Baselines/BaselineComparePerformanceGuardTest.php tests/Feature/Filament/BaselineCompareMatrixPageTest.php tests/Feature/Filament/BaselineProfileCompareStartSurfaceTest.php tests/Feature/Rbac/BaselineCompareMatrixAuthorizationTest.php tests/Feature/Guards/ActionSurfaceContractTest.php tests/Feature/Guards/NoAdHocStatusBadgesTest.php tests/Feature/Guards/NoDiagnosticWarningBadgesTest.php` - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - completed an integrated-browser smoke flow locally for matrix render, differ filter, finding drilldown round-trip, and `Compare assigned tenants` confirmation/action Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #221
23 KiB
Tasks: Workspace Baseline Compare Matrix V1
Input: Design documents from /specs/190-baseline-compare-matrix/
Prerequisites: plan.md, spec.md, research.md, data-model.md, contracts/baseline-compare-matrix.logical.openapi.yaml, quickstart.md
Tests: Tests are REQUIRED for this feature. Use Pest unit coverage for centralized matrix badge semantics, Pest feature coverage for matrix aggregation, page rendering, compare-all fan-out, and RBAC semantics, plus one browser smoke test for the rendered matrix surface and one core interaction.
Operations: This feature must reuse existing tenant-owned baseline_compare OperationRun semantics only. Tasks must preserve the Ops-UX 3-surface feedback contract, avoid any workspace umbrella run or shadow batch truth, keep OperationRun.status and OperationRun.outcome service-owned, keep reused summary_counts canonical via OperationSummaryKeys and numeric-only, prevent ad hoc queued, running, or completion database notifications, and keep compare-all feedback limited to canonical queued feedback plus existing Monitoring drilldowns.
RBAC: Existing workspace membership and tenant visibility remain authoritative. Tasks must preserve deny-as-not-found 404 behavior for non-members, 403 behavior for in-scope members missing WORKSPACE_BASELINES_VIEW, WORKSPACE_BASELINES_MANAGE, TENANT_VIEW, or TENANT_FINDINGS_VIEW, visible-disabled compare actions plus helper text for in-scope members missing capability where the surface contract requires it, and visible-set-only aggregation so hidden tenants never leak through counts, summaries, or drilldowns.
Operator Surfaces: The affected operator surfaces are baseline profile detail, the new workspace baseline compare matrix page, tenant compare landing, finding follow-up surfaces, and Monitoring run drilldowns.
Filament UI Action Surfaces: Baseline profile detail keeps its existing inspect model and gains Open compare matrix plus confirmation-gated Compare assigned tenants header actions. The matrix page exposes explicit tenant, subject, cell, and run drilldowns only, forbids row click, adds no destructive actions, and uses one narrow matrix-grid exception for the two-dimensional body.
Filament UI UX-001: The new page must keep Filament-native sections, summaries, legends, filters, and empty states. The grid body is the only approved UX-001 exception because a one-axis table cannot represent subject-by-tenant truth.
Badges: Matrix state, freshness, and trust surfaces must use centralized badge semantics through BadgeDomain, BadgeCatalog, and BadgeRenderer. No page-local status color or ad hoc legend mapping is allowed.
Organization: Tasks are grouped by user story so each story can be implemented and verified independently once the shared matrix foundation is in place.
Phase 1: Setup (Shared Matrix Harness)
Purpose: Prepare reusable fixtures and acceptance scaffolds for multi-tenant baseline matrix scenarios shared across all stories.
- T001 [P] Add reusable visible-set baseline matrix fixture builders in
apps/platform/tests/Feature/Concerns/BuildsBaselineCompareMatrixFixtures.php - T002 [P] Stage matrix acceptance scaffolds in
apps/platform/tests/Feature/Baselines/BaselineCompareMatrixBuilderTest.php,apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php,apps/platform/tests/Feature/Baselines/BaselineCompareMatrixCompareAllActionTest.php,apps/platform/tests/Feature/Rbac/BaselineCompareMatrixAuthorizationTest.php, andapps/platform/tests/Browser/Spec190BaselineCompareMatrixSmokeTest.php
Checkpoint: Shared matrix fixtures and empty acceptance seams exist for builder, page, compare-all, RBAC, and browser smoke coverage.
Phase 2: Foundational (Blocking Matrix Core)
Purpose: Establish centralized badge semantics, action-surface guards, and reusable query seams that every user story depends on.
⚠️ CRITICAL: No user story work should begin until this phase is complete.
- T003 [P] Add centralized matrix state and trust badge coverage in
apps/platform/tests/Unit/Badges/BaselineCompareMatrixBadgesTest.php - T004 [P] Add matrix header-action, visible-disabled compare-action helper-text, and grid-surface guard coverage in
apps/platform/tests/Feature/Guards/ActionSurfaceContractTest.php - T005 [P] Register matrix state and trust badge semantics in
apps/platform/app/Support/Badges/BadgeDomain.phpandapps/platform/app/Support/Badges/Domains/BaselineCompareMatrixStateBadge.php - T006 [P] Add visible-assignment and latest-compare query helpers for query-bounded matrix loading in
apps/platform/app/Models/BaselineTenantAssignment.php,apps/platform/app/Models/OperationRun.php, andapps/platform/app/Models/Finding.php - T007 Reuse reference snapshot, freshness, and explanation seams for matrix aggregation in
apps/platform/app/Support/Baselines/BaselineSnapshotTruthResolver.php,apps/platform/app/Support/Baselines/BaselineCompareSummaryAssessor.php,apps/platform/app/Support/Baselines/BaselineCompareEvidenceGapDetails.php, andapps/platform/app/Support/Baselines/BaselineCompareExplanationRegistry.php
Checkpoint: Central badge semantics and data-access seams are ready, so page, compare-all, drilldown, and degraded-state work can build on one authoritative matrix foundation.
Phase 3: User Story 1 - Scan Visible Drift Across Assigned Tenants (Priority: P1) 🎯 MVP
Goal: Let workspace operators open one baseline-scoped matrix and understand visible tenant drift, subject breadth, freshness, and trust from a single page.
Independent Test: Open the matrix for a baseline profile with mixed compare outcomes and verify that reference truth, visible tenant columns, subject rows, summaries, filters, and cell states are truthful without opening tenant pages first.
Tests for User Story 1
- T008 [P] [US1] Add matrix aggregation coverage for visible-set-only counts, subject-axis derivation, and cell precedence in
apps/platform/tests/Feature/Baselines/BaselineCompareMatrixBuilderTest.php - T009 [P] [US1] Add matrix page coverage for reference truth, summaries, filters, and grid rendering in
apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php
Implementation for User Story 1
- T010 [US1] Implement derived reference, tenant, subject, and cell bundle assembly in
apps/platform/app/Support/Baselines/BaselineCompareMatrixBuilder.php - T011 [US1] Add the workspace matrix page class, route state, and filter schema in
apps/platform/app/Filament/Pages/BaselineCompareMatrix.php - T012 [US1] Render reference sections, visible-set summaries, legends, and the subject-by-tenant grid in
apps/platform/resources/views/filament/pages/baseline-compare-matrix.blade.php - T013 [US1] Add
Open compare matrixheader navigation on baseline detail inapps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php - T014 [US1] Register the matrix page entry seam on the baseline resource in
apps/platform/app/Filament/Resources/BaselineProfileResource.phpandapps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php - T015 [US1] Run focused US1 verification from
specs/190-baseline-compare-matrix/quickstart.mdagainstapps/platform/tests/Unit/Badges/BaselineCompareMatrixBadgesTest.php,apps/platform/tests/Feature/Baselines/BaselineCompareMatrixBuilderTest.php, andapps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php
Checkpoint: Operators can scan one baseline-scoped visible-set matrix and identify the most divergent tenants and subjects without leaving the workspace surface.
Phase 4: User Story 2 - Refresh Compare Truth For The Visible Assigned Set (Priority: P1)
Goal: Let authorized operators trigger compare across all visible assigned tenants from the baseline detail or matrix surface without inventing a workspace umbrella run.
Independent Test: Start Compare assigned tenants from the baseline detail or matrix page and verify that eligible visible tenants reuse normal compare execution, blocked tenants stay explicit, and no second batch truth is created.
Tests for User Story 2
- T016 [P] [US2] Add compare-all fan-out and Ops-UX regression coverage for queued, already-queued, blocked, no-umbrella-run, service-owned run transitions, canonical
summary_counts, and no ad hoc non-terminal database notifications inapps/platform/tests/Feature/Baselines/BaselineCompareMatrixCompareAllActionTest.php - T017 [P] [US2] Extend compare-start surface, confirmation, and visible-disabled helper-text coverage for
Compare assigned tenantsinapps/platform/tests/Feature/Filament/BaselineProfileCompareStartSurfaceTest.phpandapps/platform/tests/Feature/Guards/ActionSurfaceContractTest.php
Implementation for User Story 2
- T018 [US2] Implement visible-tenant batch compare start reuse in
apps/platform/app/Services/Baselines/BaselineCompareService.php - T019 [US2] Add confirmation-gated
Compare assigned tenantsexecution, honest launch summaries, and visible-disabled helper text on the matrix page inapps/platform/app/Filament/Pages/BaselineCompareMatrix.phpandapps/platform/app/Support/Rbac/UiEnforcement.php - T020 [US2] Add confirmation-gated
Compare assigned tenantsexecution with capability-gated disabled state on baseline detail inapps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.phpandapps/platform/app/Support/Rbac/UiEnforcement.php - T021 [US2] Reuse canonical queued feedback, initiator-only run links, service-owned run transitions, canonical
summary_counts, and no ad hoc notification or status writes for compare-all outcomes inapps/platform/app/Support/OpsUx/OperationUxPresenter.php,apps/platform/app/Support/OpsUx/OpsUxBrowserEvents.php,apps/platform/app/Support/OperationRunLinks.php, andapps/platform/app/Services/OperationRunService.php - T022 [US2] Run focused US2 verification from
specs/190-baseline-compare-matrix/quickstart.mdagainstapps/platform/tests/Feature/Baselines/BaselineCompareMatrixCompareAllActionTest.phpandapps/platform/tests/Feature/Filament/BaselineProfileCompareStartSurfaceTest.php
Checkpoint: Authorized operators can refresh compare truth for the visible assigned set from one action while Monitoring and tenant compare runs remain the only execution truth.
Phase 5: User Story 3 - Drill From The Matrix Into Existing Follow-Up Surfaces (Priority: P2)
Goal: Let operators move from matrix cells, tenant summaries, and subject focus into existing compare, finding, and run detail surfaces without reconstructing context.
Independent Test: Open a differing, missing, or ambiguous matrix cell and confirm the product lands on the existing tenant compare or finding path with a bounded return path back to the matrix.
Tests for User Story 3
- T023 [P] [US3] Add subject-focus and drilldown continuity coverage in
apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php - T024 [P] [US3] Add matrix-to-tenant and matrix-to-finding authorization coverage for
404versus403semantics inapps/platform/tests/Feature/Rbac/BaselineCompareMatrixAuthorizationTest.php
Implementation for User Story 3
- T025 [US3] Add tenant, subject, finding, and run drilldown state handling in
apps/platform/app/Filament/Pages/BaselineCompareMatrix.php - T026 [US3] Reuse canonical matrix return-path context in
apps/platform/app/Support/Navigation/CanonicalNavigationContext.phpandapps/platform/app/Support/Navigation/RelatedNavigationResolver.php - T027 [US3] Accept matrix source context on tenant compare and finding follow-up surfaces in
apps/platform/app/Filament/Pages/BaselineCompareLanding.phpandapps/platform/app/Filament/Resources/FindingResource.php - T028 [US3] Expose bounded back-link and source-hint rendering for matrix arrivals in
apps/platform/app/Filament/Pages/BaselineCompareLanding.phpandapps/platform/app/Filament/Resources/OperationRunResource.php - T029 [US3] Run focused US3 verification from
specs/190-baseline-compare-matrix/quickstart.mdagainstapps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.phpandapps/platform/tests/Feature/Rbac/BaselineCompareMatrixAuthorizationTest.php
Checkpoint: The matrix becomes a decision surface instead of a dead-end report because operators can drill directly into existing follow-up workflows and return cleanly.
Phase 6: User Story 4 - Stay Honest In Degraded Or Low-Trust Conditions (Priority: P2)
Goal: Keep blocked, stale, ambiguous, not-compared, and low-trust states visibly distinct so the matrix never reads calmer than the underlying truth.
Independent Test: Open the matrix for a baseline profile with no usable snapshot, no visible tenants, stale results, ambiguous matches, and uncovered policy types, and verify that none of those states render as healthy matches.
Tests for User Story 4
- T030 [P] [US4] Add degraded-state page coverage for no usable snapshot, no assigned tenants, no visible tenants, and no compare results in
apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php - T031 [P] [US4] Add ambiguity, stale-result, uncovered-policy-type, policy-type filter honesty, and query-shape guard coverage in
apps/platform/tests/Feature/Baselines/BaselineCompareMatrixBuilderTest.phpandapps/platform/tests/Feature/Baselines/BaselineComparePerformanceGuardTest.php
Implementation for User Story 4
- T032 [US4] Reuse stale-result and evidence-gap semantics inside
apps/platform/app/Support/Baselines/BaselineCompareMatrixBuilder.php,apps/platform/app/Support/Baselines/BaselineCompareSummaryAssessor.php, andapps/platform/app/Support/Baselines/BaselineCompareEvidenceGapDetails.php - T033 [US4] Render explicit blocked, empty, stale, ambiguous, and low-trust states in
apps/platform/resources/views/filament/pages/baseline-compare-matrix.blade.php - T034 [US4] Add policy-type, state-group, severity, tenant-sort, subject-sort, and subject-focus state handling in
apps/platform/app/Filament/Pages/BaselineCompareMatrix.php - T035 [US4] Run focused US4 verification from
specs/190-baseline-compare-matrix/quickstart.mdagainstapps/platform/tests/Feature/Baselines/BaselineCompareMatrixBuilderTest.phpandapps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php
Checkpoint: The matrix stays honest when data is stale, missing, ambiguous, or invisible, so operators do not mistake degraded truth for clean posture.
Phase 7: Polish & Cross-Cutting Concerns
Purpose: Finalize guard coverage, browser confidence, copy review, formatting, and the focused verification pack across all stories.
- T036 [P] Add no-ad-hoc-badge and no-diagnostic-warning guard coverage for matrix state surfaces in
apps/platform/tests/Feature/Guards/NoAdHocStatusBadgesTest.phpandapps/platform/tests/Feature/Guards/NoDiagnosticWarningBadgesTest.php - T037 [P] Add browser smoke coverage for matrix render, one filter interaction, and one drilldown or compare affordance in
apps/platform/tests/Browser/Spec190BaselineCompareMatrixSmokeTest.php - T038 [P] Review
Verb + Object,visible-set only, andsimulation onlycopy inapps/platform/app/Filament/Pages/BaselineCompareMatrix.php,apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php, andapps/platform/resources/views/filament/pages/baseline-compare-matrix.blade.php - T039 [P] Run formatting with
cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agentusingspecs/190-baseline-compare-matrix/quickstart.md - T040 Run the focused verification pack from
specs/190-baseline-compare-matrix/quickstart.mdagainstapps/platform/tests/Unit/Badges/BaselineCompareMatrixBadgesTest.php,apps/platform/tests/Feature/Baselines/BaselineCompareMatrixBuilderTest.php,apps/platform/tests/Feature/Baselines/BaselineCompareMatrixCompareAllActionTest.php,apps/platform/tests/Feature/Baselines/BaselineCompareStatsTest.php,apps/platform/tests/Feature/Baselines/BaselineCompareFindingsTest.php,apps/platform/tests/Feature/Baselines/BaselineComparePerformanceGuardTest.php,apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php,apps/platform/tests/Feature/Filament/BaselineProfileCompareStartSurfaceTest.php,apps/platform/tests/Feature/Rbac/BaselineCompareMatrixAuthorizationTest.php,apps/platform/tests/Feature/Guards/ActionSurfaceContractTest.php,apps/platform/tests/Feature/Guards/NoAdHocStatusBadgesTest.php,apps/platform/tests/Feature/Guards/NoDiagnosticWarningBadgesTest.php, andapps/platform/tests/Browser/Spec190BaselineCompareMatrixSmokeTest.php
Dependencies & Execution Order
Phase Dependencies
- Setup (Phase 1): Starts immediately and prepares shared fixtures plus empty acceptance seams.
- Foundational (Phase 2): Depends on Setup and blocks all user-story work until centralized badge semantics, action-surface guards, and query seams exist.
- User Story 1 (Phase 3): Starts after Foundational and is the recommended engineering MVP because it delivers the first truthful read-only matrix.
- User Story 2 (Phase 4): Starts after User Story 1 because compare-all actions reuse the matrix page and baseline-detail seams established in the MVP.
- User Story 3 (Phase 5): Starts after User Story 1 because drilldown continuity depends on matrix page state and cell metadata.
- User Story 4 (Phase 6): Starts after User Story 1 and can proceed in parallel with User Story 2 or User Story 3 once the core matrix bundle and page exist.
- Polish (Phase 7): Starts after all desired user stories are complete.
User Story Dependencies
- US1: Depends only on the shared matrix foundation.
- US2: Depends on US1 for the matrix page, baseline-detail entry seams, and derived visible-set truth.
- US3: Depends on US1 for matrix page state and cell metadata used by drilldowns.
- US4: Depends on US1 for the matrix builder and page, then hardens degraded-state and filter honesty across the same surface.
Within Each User Story
- Write or extend the story tests first and confirm they fail before implementation is considered complete.
- Land shared service, builder, or navigation changes before view and copy wiring in the same story.
- Keep each story shippable on its own before moving to the next priority.
Parallel Opportunities
T001andT002can run in parallel during Setup.T003andT004can run in parallel before the shared badge and action-surface seams land.T005andT006can run in parallel once the corresponding tests exist.- Within US1,
T008andT009can run in parallel, thenT011andT012can split afterT010defines the matrix bundle. - Within US2,
T016andT017can run in parallel, thenT019andT020can split afterT018lands the batch compare seam. - Within US3,
T023andT024can run in parallel, thenT026,T027, andT028can split afterT025defines the page drilldown state. - Within US4,
T030andT031can run in parallel, thenT033andT034can split afterT032lands the degraded-state semantics. - Within Phase 7,
T036,T037, andT038can run in parallel before formatting and the final verification pack.
Parallel Example: User Story 1
# User Story 1 tests in parallel
T008 apps/platform/tests/Feature/Baselines/BaselineCompareMatrixBuilderTest.php
T009 apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php
# User Story 1 implementation split after the matrix bundle exists
T011 apps/platform/app/Filament/Pages/BaselineCompareMatrix.php
T012 apps/platform/resources/views/filament/pages/baseline-compare-matrix.blade.php
Parallel Example: User Story 2
# User Story 2 tests in parallel
T016 apps/platform/tests/Feature/Baselines/BaselineCompareMatrixCompareAllActionTest.php
T017 apps/platform/tests/Feature/Filament/BaselineProfileCompareStartSurfaceTest.php
# User Story 2 implementation split after the batch start seam lands
T019 apps/platform/app/Filament/Pages/BaselineCompareMatrix.php
T020 apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php
Parallel Example: User Story 3
# User Story 3 tests in parallel
T023 apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php
T024 apps/platform/tests/Feature/Rbac/BaselineCompareMatrixAuthorizationTest.php
# User Story 3 implementation split after drilldown state exists
T026 apps/platform/app/Support/Navigation/CanonicalNavigationContext.php
T027 apps/platform/app/Filament/Pages/BaselineCompareLanding.php
Parallel Example: User Story 4
# User Story 4 tests in parallel
T030 apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php
T031 apps/platform/tests/Feature/Baselines/BaselineCompareMatrixBuilderTest.php
# User Story 4 implementation split after degraded-state semantics land
T033 apps/platform/resources/views/filament/pages/baseline-compare-matrix.blade.php
T034 apps/platform/app/Filament/Pages/BaselineCompareMatrix.php
Implementation Strategy
MVP First
- Complete Phase 1: Setup.
- Complete Phase 2: Foundational.
- Complete Phase 3: User Story 1.
- STOP and VALIDATE: Confirm the read-only matrix answers the visible-set portfolio question honestly before adding refresh or drilldown behavior.
Incremental Delivery
- Deliver Setup plus Foundational to lock shared matrix fixtures, centralized badge semantics, action-surface guards, and query seams.
- Deliver User Story 1 so operators can scan one truthful cross-tenant baseline matrix.
- Deliver User Story 2 so operators can refresh visible-set compare truth from the same workflow.
- Deliver User Story 3 so the matrix becomes a decision surface with bounded follow-up continuity.
- Deliver User Story 4 so degraded and low-trust conditions remain explicit under the final filter set.
- Finish with browser confidence, copy review, formatting, and the focused verification pack.
Parallel Team Strategy
- One contributor can prepare fixture scaffolds and browser seams while another adds badge and action-surface guards.
- After the foundation lands, one contributor can own the matrix builder while another wires the page shell and Blade view.
- Once the matrix page exists, one contributor can take compare-all fan-out while another handles drilldown continuity.
- Degraded-state hardening can proceed in parallel with drilldown work once the base matrix bundle and page filters are stable.
- Rejoin for Polish so guard suites, browser smoke coverage, copy review, formatting, and the final verification pack land together.
Notes
[P]tasks target different files or safe concurrent work after prerequisite seams are in place.[US1],[US2],[US3], and[US4]map directly to the user stories inspec.md.- The recommended engineering MVP scope is Phase 1 through Phase 3. The product-complete P1 scope is Phase 1 through Phase 4.
- This task plan stays compliant with Filament v5 on Livewire v4, makes no panel-provider changes in
bootstrap/providers.php, introduces no new globally searchable resource, adds no destructive action, and requires no asset-strategy change beyond the existing deployment process.