TenantAtlas/specs/330-environment-dashboard-baseline-compare-productization/plan.md
ahmido 0c7adefe5b Spec 330: environment dashboard baseline compare productization (#392)
## Summary
- add the baseline compare landing experience for the environment dashboard productization flow
- expand the environment dashboard overview and summary-building logic to support richer baseline comparison states and assessments
- update the supporting Blade templates for the new compare and overview presentation
- add English and German translations for the baseline compare surface
- include the Spec 330 planning and task artifacts alongside the implementation

## Tests
- touched browser, feature, and unit coverage for the new baseline compare flow
- updated test files include `Spec330EnvironmentDashboardBaselineCompareSmokeTest`, `BaselineCompareLandingWhyNoFindingsTest`, `Spec330EnvironmentDashboardBaselineCompareProductizationTest`, `HeaderContextBarTest`, and `ManagedEnvironmentModelTest`
- no additional test run was performed as part of this commit/push/PR workflow

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #392
2026-05-20 20:32:39 +00:00

357 lines
25 KiB
Markdown

# Implementation Plan: Spec 330 - Environment Dashboard / Baseline Compare Productization
**Branch**: `330-environment-dashboard-baseline-compare-productization` | **Date**: 2026-05-19 | **Spec**: `specs/330-environment-dashboard-baseline-compare-productization/spec.md`
**Input**: User-provided Spec 330 and repo inspection.
## Summary
Productize two existing environment-owned strategic surfaces into decision-first governance pages:
```text
Is this environment ready, blocked, stale, or requiring review?
Which baseline drift requires action?
```
The implementation must keep current routes, source truth, RBAC, environment-owned scope, and OperationRun semantics. It must not add new backend readiness/drift/proof engines. Environment Dashboard should elevate status, reason, impact, proof, and one primary next action before technical detail. Baseline Compare should elevate assignment, compare trust, drift impact, evidence/proof, and one primary next action before findings detail, raw diff, or diagnostics.
## Technical Context
**Language/Version**: PHP 8.4.15, Laravel 12.52.0.
**Primary Dependencies**: Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, Tailwind CSS 4.2.2.
**Storage**: PostgreSQL; no schema change expected.
**Testing**: Pest 4 Feature/Livewire/Browser tests.
**Validation Lanes**: confidence and browser; targeted navigation/context guard filters.
**Target Platform**: Laravel Sail locally; Dokploy/container deployment posture unchanged.
**Project Type**: Laravel monolith under `apps/platform`.
**Performance Goals**: DB-only page render; no Graph/provider API calls during render; no broad new query families.
**Constraints**: No new persisted truth, migration, package, queue, scheduler, storage, env var, deployment asset, compatibility route, or legacy alias support.
**Scale/Scope**: Two existing environment-owned Filament pages, existing widget/view structures, feature-local payload helpers if needed, focused tests, and browser smoke.
## UI / Surface Guardrail Plan
- **Guardrail scope**: changed existing operator-facing strategic environment-owned surfaces.
- **Affected routes/pages/actions/states/navigation/panel/provider surfaces**:
- `/admin/workspaces/{workspace}/environments/{environment}`
- `/admin/workspaces/{workspace}/environments/{environment}/baseline-compare`
- `apps/platform/app/Filament/Pages/EnvironmentDashboard.php`
- `apps/platform/app/Filament/Widgets/Dashboard/EnvironmentDashboardOverview.php`
- `apps/platform/resources/views/filament/widgets/dashboard/environment-dashboard-overview.blade.php`
- `apps/platform/resources/views/filament/widgets/dashboard/environment-dashboard-context-chips.blade.php`
- `apps/platform/app/Support/EnvironmentDashboard/EnvironmentDashboardSummaryBuilder.php`
- `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`
- `apps/platform/resources/views/filament/pages/baseline-compare-landing.blade.php`
- **No-impact class, if applicable**: N/A.
- **Native vs custom classification summary**: Native Filament Dashboard/Page/Widget plus existing Blade composition; no new UI framework.
- **Shared-family relevance**: dashboard signals, status messaging, action links, proof links, OperationRun links, baseline compare state, diagnostics disclosure.
- **State layers in scope**: route-owned environment, page payload, widget payload, Baseline Compare launch query state (`baseline_profile_id`, `subject_key`, `nav`), and existing session/context guard behavior.
- **Audience modes in scope**: operator-MSP, manager, governance operator, support reviewer where authorized.
- **Decision/diagnostic/raw hierarchy plan**: decision first, proof path visible, diagnostics collapsed, raw/support hidden or gated.
- **Raw/support gating plan**: collapsed by default and capability-gated through existing support diagnostics/raw capabilities where exposed.
- **One-primary-action / duplicate-truth control**: one dominant next action per page; secondary links/cards support the decision rather than repeat the same verdict.
- **Handling modes by drift class or surface**: review-mandatory for UI-002 and UI-061 strategic surfaces; document-in-feature for any UI coverage registry no-change decision.
- **Repository-signal treatment**: Spec 325 target images are direction only; runtime claims must be repo-verified, derived, unavailable, or deferred.
- **Special surface test profiles**: `global-context-shell`, `monitoring-state-page`, `shared-detail-family`.
- **Required tests or manual smoke**: Feature/Livewire tests for decision layout, false-green guard, RBAC/scope/disclosure plus Pest Browser smoke for explicit environment routes, no-baseline/action-needed/drift states, diagnostics collapsed, raw detail hidden, cross-workspace denial, and static tenant copy guard.
- **Exception path and spread control**: none expected. Any new dangerous action, schema, capability, backend proof source, or route family requires spec/plan/tasks update first.
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.
- **UI/Productization coverage decision**: active spec package carries productization proof. Update UI coverage registry only if route/archetype/coverage classification changes; otherwise document why UI-002/UI-061 plus Spec 325 artifacts are sufficient.
- **Coverage artifacts to update**: none expected unless implementation changes route/archetype state.
- **Navigation / Filament provider-panel handling**: no panel provider registration changes expected. Laravel 12 panel providers remain in `apps/platform/bootstrap/providers.php`.
- **Screenshot or page-report need**: screenshots required; full page report optional unless implementation materially changes coverage classification.
## Shared Pattern & System Fit
- **Cross-cutting feature marker**: yes.
- **Systems touched**: Environment Dashboard page, dashboard widgets, dashboard summary builder, Baseline Compare Landing page/view, baseline stats/aggregate helpers, backup/recovery helpers, provider permission view models, OperationRun links, resource policies, `UiEnforcement`, and browser fixtures/tests.
- **Shared abstractions reused**: `EnvironmentDashboardSummaryBuilder`, `EnvironmentDashboardSummary`, `BaselineCompareStats`, `TenantGovernanceAggregateResolver`, `OperationRunLinks`, `ManagedEnvironmentLinks`, `OperationUxPresenter`, `OpsUxBrowserEvents`, `BadgeRenderer`, `UiEnforcement`, policies/capability resolvers.
- **New abstraction introduced? why?**: none. Page-local private helpers may be added only to reduce Blade complexity or duplicate payload calculation.
- **Why the existing abstraction was sufficient or insufficient**: Existing paths provide source truth, authorization, links, compare state, backup/recovery/readiness signals, and OperationRun proof. They do not fully enforce the first-read decision hierarchy and collapsed diagnostics disclosure.
- **Bounded deviation / spread control**: no public readiness/proof/disclosure framework; keep composition local to the two surfaces.
## OperationRun UX Impact
- **Touches OperationRun start/completion/link UX?**: yes, through existing Baseline Compare start action and proof links. No new OperationRun type or lifecycle behavior.
- **Central contract reused**: `OperationRunLinks`, `OperationUxPresenter`, `OpsUxBrowserEvents`, existing `OperationRunPolicy`, existing operation detail routes, and `BaselineCompareService::startCompare()`.
- **Delegated UX behaviors**: compare queued toast, run-enqueued browser event, open operation link, blocked/cannot-start messaging, and tenant/workspace-safe URLs stay on the existing Ops UX path.
- **Surface-owned behavior kept local**: display-only proof availability labels and next-action hierarchy.
- **Queued DB-notification policy**: unchanged / N/A.
- **Terminal notification path**: unchanged.
- **Exception path**: none.
## Provider Boundary & Portability Fit
- **Shared provider/platform boundary touched?**: display-only provider readiness/permissions and static copy guard.
- **Provider-owned seams**: existing provider connection, Microsoft/Entra/Intune required permissions, provider tenant ID where source records require it.
- **Platform-core seams**: workspace, environment, readiness, proof, baseline, drift, evidence, operation, review, diagnostics.
- **Neutral platform terms / contracts preserved**: workspace, environment, provider, required permissions, operation proof, evidence, review, baseline, drift, diagnostics.
- **Retained provider-specific semantics and why**: Microsoft/Entra/Intune can remain at source/provider-boundary labels only.
- **Bounded extraction or follow-up path**: Provider Readiness Productization remains a separate follow-up spec.
## Constitution Check
- **Inventory-first, snapshots-second**: Environment and compare surfaces derive from last-observed inventory, explicit snapshots, backups, evidence, reviews, and operations; no new source truth is created.
- **Read/write separation by default**: Pages remain read/decision-first. Existing compare start is the only high-impact operation start and already requires confirmation/authorization/OperationRun.
- **Single Contract Path to Graph**: No Graph/provider API calls may be added to page render.
- **Deterministic Capabilities**: Reuse existing `Capabilities`, `CapabilityResolver`, resource policies, `UiEnforcement`, and route authorization.
- **RBAC-UX**: UI visibility is not security. Server-side policies/gates remain authoritative for operations, evidence, review packs, backup/restore, provider permissions, and diagnostics.
- **Workspace/environment isolation**: Both pages require explicit route-bound environment. Non-member or mismatched workspace/environment access is 404.
- **OperationRun UX**: Existing compare start and operation links reuse shared OperationRun UX helpers; no local lifecycle/notification behavior.
- **UI-COV-001**: Existing strategic surfaces UI-002 and UI-061 materially change. Active spec package must carry repo-truth map, tests, screenshots, and coverage close-out decision.
- **TEST-GOV-001**: Targeted Feature and Browser lanes are explicit. Browser cost is named and scoped.
- **PROP-001 / BLOAT-001**: No new source of truth, persisted entity, enum/status family, public abstraction, proof engine, or cross-domain UI framework.
- **UI-FIL-001**: Use native Filament components/shared primitives first; custom Blade must preserve Filament semantics, accessibility, dark mode, and one-primary-action hierarchy.
- **Filament v5 / Livewire v4**: Livewire v4.0+ compliance required. No Livewire v3 or Filament v3/v4 APIs.
- **Panel provider location**: panel providers remain in `apps/platform/bootstrap/providers.php`; no provider registration change expected.
- **Global search**: no resource global search change expected. If a resource is touched, it must retain safe View/Edit pages or disable global search.
- **Destructive/high-impact actions**: no destructive action introduced. Existing compare start remains confirmed/capability-gated/OperationRun-backed.
- **Assets**: no Filament asset registration expected; `filament:assets` deployment posture unchanged.
## Current Repo Truth Summary
Existing verified Environment Dashboard surfaces:
- `EnvironmentDashboard` extends Filament `Dashboard` and renders `EnvironmentDashboardContextChips`, `ManagedEnvironmentTriageArrivalContinuity`, `DashboardKpis`, and `EnvironmentDashboardOverview`.
- `EnvironmentDashboard::getUrl()` resolves route-owned `ManagedEnvironment` and strips workspace/environment parameters into `ManagedEnvironmentLinks::viewUrl()`.
- `EnvironmentDashboardSummaryBuilder` already derives context, posture, KPIs, recommended actions, governance status, readiness cards, active operation summary, and recent operations from existing models/services.
- Current dashboard view renders recommended actions, governance status, active operations requiring attention, and right-side readiness cards.
- Existing browser tests already assert dashboard context chips, KPI cards, readiness cards, ranked actions, and no table-first layout.
Existing verified Baseline Compare surfaces:
- `BaselineCompareLanding` is environment-owned at slug `workspaces/{workspace}/environments/{environment}/baseline-compare`.
- It rejects old workspace-style `/admin/baseline-compare-landing?environment_id=` URLs and remembered environment fallback.
- It strips legacy scope keys from generated URLs while preserving `baseline_profile_id`, `subject_key`, and `nav`.
- `BaselineCompareStats::forTenant()` derives states including `no_tenant`, `no_assignment`, `no_snapshot`, `invalid_scope`, `comparing`, `failed`, `idle`, and `ready`.
- Existing compare start action uses `Action::make('compareNow')->requiresConfirmation()->action(...)`, `BaselineCompareService::startCompare()`, `UiEnforcement`, `OperationUxPresenter`, and `OpsUxBrowserEvents`.
- Current Blade already has explanation/stats, no-assignment/no-snapshot empty states, coverage warnings, evidence gap details, findings summaries, and diagnostics section; diagnostics are currently rendered when present and must become collapsed/default-secondary.
Known productization gaps:
- Environment Dashboard needs a more explicit decision card/question and proof/action panel instead of equal-weight dashboard sections.
- Environment Dashboard readiness dimensions should map to source truth and unavailable states in the spec map before implementation.
- Baseline Compare needs a first-read drift/action decision card, no-baseline actionable unavailable state, proof/disclosure panel, and raw diff/diagnostics collapsed by default.
- Baseline Compare must avoid false all-clear copy when zero findings coexist with evidence/coverage/trust gaps.
## Existing Repository Surfaces Likely Affected
Runtime files, only during later implementation:
- `apps/platform/app/Filament/Pages/EnvironmentDashboard.php`
- `apps/platform/app/Filament/Widgets/Dashboard/EnvironmentDashboardOverview.php`
- `apps/platform/resources/views/filament/widgets/dashboard/environment-dashboard-overview.blade.php`
- `apps/platform/resources/views/filament/widgets/dashboard/environment-dashboard-context-chips.blade.php`
- `apps/platform/app/Support/EnvironmentDashboard/EnvironmentDashboardSummaryBuilder.php`
- `apps/platform/app/Support/EnvironmentDashboard/EnvironmentDashboardSummary.php`
- `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`
- `apps/platform/resources/views/filament/pages/baseline-compare-landing.blade.php`
- `apps/platform/resources/lang/en/*` and `apps/platform/resources/lang/de/*` only where touched copy follows existing localization conventions.
Tests, only during later implementation:
- `apps/platform/tests/Feature/Filament/TenantDashboardTenantScopeTest.php`
- `apps/platform/tests/Feature/Filament/TenantDashboardDbOnlyTest.php`
- `apps/platform/tests/Feature/Rbac/DashboardRecoveryPostureVisibilityTest.php`
- `apps/platform/tests/Feature/Rbac/TenantDashboardArrivalContextVisibilityTest.php`
- `apps/platform/tests/Feature/Filament/BaselineCompareEnvironmentRouteContractTest.php`
- `apps/platform/tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php`
- `apps/platform/tests/Feature/Filament/BaselineCompareExplanationSurfaceTest.php`
- `apps/platform/tests/Feature/Rbac/DriftLandingUiEnforcementTest.php`
- `apps/platform/tests/Feature/Navigation/Spec322AdminSurfaceScopeContractTest.php`
- `apps/platform/tests/Feature/Navigation/Spec322EnvironmentCtaUrlContractTest.php`
- `apps/platform/tests/Feature/ManagedEnvironment/ManagedEnvironmentCopyNeutralizationGuardTest.php`
- `apps/platform/tests/Browser/Spec330EnvironmentDashboardBaselineCompareSmokeTest.php`
Spec/UI artifacts:
- `specs/330-environment-dashboard-baseline-compare-productization/repo-truth-map.md`
- screenshot artifacts under `specs/330-environment-dashboard-baseline-compare-productization/artifacts/screenshots/`
- optional UI coverage registry updates only if implementation materially changes route/archetype/coverage state.
## Domain / Model Implications
- No new model, table, migration, enum, status family, persisted display state, or public service contract.
- Environment readiness must derive from:
- `ManagedEnvironment` and workspace relation.
- `ProviderConnection` status/health/consent/readiness fields.
- `ManagedEnvironmentPermission` and required permissions view model.
- `TenantBackupHealthResolver`, `TenantBackupHealthAssessment`, backup sets/schedules.
- `RestoreSafetyResolver` and restore/recovery evidence presentation.
- `TenantGovernanceAggregateResolver`, `Finding`, `FindingException`, and baseline compare stats.
- `EvidenceSnapshot`, `EnvironmentReview`, `ReviewPack`, and related links.
- `OperationRun` attention/freshness/outcome and `OperationRunLinks`.
- Baseline drift/action state must derive from:
- `BaselineTenantAssignment`, `BaselineProfile`, `BaselineSnapshot`, `BaselineSnapshotTruthResolver`.
- `BaselineCompareStats`, `TenantGovernanceAggregate`, `BaselineCompareSummaryAssessment`, `operatorExplanation`.
- `Finding` drift findings/severity counts.
- Evidence gap summaries/details and compare diagnostics only as secondary/collapsed context.
- Existing compare OperationRun relation and links.
## UI / Filament Implications
- Filament v5 and Livewire v4.0+ compliance must be preserved.
- Keep panel provider registration unchanged.
- Use Filament sections/buttons/badges/actions and existing shared primitives where suitable.
- Avoid fake charts, fake health, fake compliance, fake customer-safe, fake restore confidence, or generic KPI dashboard expansion.
- Environment Dashboard target order:
- header/scope
- main readiness decision card
- readiness dimensions
- right-side proof/action/disclosure panel
- ranked next actions
- operations/reviews/evidence/backup/provider details as secondary context
- diagnostics collapsed
- Baseline Compare target order:
- header/scope
- main drift/action decision card
- no-baseline visual Compare readiness stepper/pipeline and compact available inputs when compare is blocked by missing assignment
- assignment / compare trust / drift summary only when a baseline-backed compare state exists
- right-side evidence/proof/disclosure panel
- findings/evidence-gap summary
- raw diff/details collapsed or secondary
## Livewire / Page State Implications
- Environment Dashboard and Baseline Compare must rely on route-owned environment context.
- Baseline Compare launch context (`baseline_profile_id`, `subject_key`, `nav`) remains initialization/query state only; it must not override environment ownership.
- Existing `BaselineCompareLanding::monitoringPageStateContract()` should remain consistent with Spec 198/319 contracts.
- Clean old workspace-style URLs and legacy query aliases must not establish environment context.
- Cross-workspace route mismatches stay 404.
## RBAC / Policy Implications
Reuse existing authorization:
- Environment page visibility: environment membership and `TENANT_VIEW`.
- Provider permissions/readiness: required permissions routes and existing provider/permission capabilities.
- Backup posture: backup-set/schedule capabilities and policies.
- Restore/recovery proof: restore-run/backup capabilities and policies.
- Baseline compare view: environment access and `TENANT_VIEW`.
- Compare start: `TENANT_SYNC` through existing `UiEnforcement`.
- Baseline profile links: `BaselineProfileResource` authorization/policies.
- Drift findings: `FindingResource` / finding capabilities.
- Evidence snapshots: `EvidenceSnapshotPolicy` / evidence capability.
- Review and review packs: `EnvironmentReviewResource`, `ReviewPackResource`, policies.
- Operation proof: `OperationRunPolicy` and link helpers.
- Diagnostics/raw detail: `SUPPORT_DIAGNOSTICS_VIEW` or stricter existing raw/support capability.
No new permission semantics should be added unless implementation proves existing capabilities cannot express the action and spec/plan/tasks are updated first.
## Audit / Observability Implications
- No new audit events are expected for read-only productization.
- Existing support diagnostics modal on Environment Dashboard already writes audit/telemetry and must remain authorized/redacted.
- Existing Baseline Compare start audit/OperationRun behavior remains unchanged.
- Do not imply OperationRun completion proves environment health or compare acceptability.
## Test Strategy
Feature/Livewire tests:
- Repo truth map existence and required sections.
- Environment Dashboard decision layout.
- Environment Dashboard no false green when proof is missing.
- Environment Dashboard ranked next actions.
- Baseline Compare decision layout.
- Baseline Compare no-baseline actionable unavailable state.
- Baseline Compare drift/evidence state with raw details hidden by default.
- Diagnostics hidden/collapsed by default across both pages.
- Environment-owned route contract and legacy alias rejection.
- Static `tenant` platform-copy guard.
- RBAC for visible/hidden actions and raw diagnostics.
Browser tests:
- Explicit Environment Dashboard route non-empty/action-needed state.
- Explicit Baseline Compare route no-baseline state.
- Baseline Compare compare/drift state if fixtures support it.
- Diagnostics collapsed and raw details absent by default.
- Cross-workspace/invalid environment safe denial.
- Dynamic display name containing `Tenant` allowed, static tenant copy absent.
- Required screenshots under the Spec 330 artifacts path.
Validation:
- Targeted Feature/Livewire tests.
- Targeted Browser smoke.
- Context/route guard filter for EnvironmentDashboard, BaselineCompare, AdminSurfaceScope, EnvironmentOwned, LegacyTenant, and Spec322.
- `pint --dirty`.
- `git diff --check`.
## Implementation Phases
### Phase 1 - Repo Truth And Current UI Audit
- Inspect Environment Dashboard page/widget/summary builder/tests.
- Inspect Baseline Compare Landing page/view/stats/tests.
- Inspect Spec 325 target images/briefs and UI audit reports.
- Create/update `repo-truth-map.md`.
- Confirm exact source/capability/fallback for every visible element.
- Stop if a desired visible element requires new backend truth.
### Phase 2 - Environment Dashboard Productization
- Add a first-read readiness question and decision card.
- Refine existing summary builder/widget payloads to expose status/reason/impact/proof/next-action without new state persistence.
- Add/right-size proof/action panel and ranked actions.
- Keep useful existing cards/details as secondary context.
- Collapse diagnostics/raw support by default.
### Phase 3 - Baseline Compare Productization
- Add a first-read drift/action question and decision card.
- Render no-baseline/no-snapshot/no-compare states as actionable unavailable states.
- Show assignment, compare trust, drift impact, evidence/proof, and operation proof before findings/raw details.
- Collapse raw diff/diagnostics by default.
- Preserve existing compare start action semantics and matrix/detail links.
### Phase 4 - Route, RBAC, Copy, And Disclosure Guards
- Verify route-owned environment context.
- Reject remembered fallback and legacy aliases.
- Guard cross-workspace mismatches.
- Gate/hide unavailable actions.
- Preserve dynamic names containing `Tenant`; remove static platform `tenant` copy.
- Ensure no false green claims.
### Phase 5 - Browser Smoke And Screenshots
- Add browser smoke file.
- Create required screenshots where generated.
- Confirm diagnostics collapsed and raw details absent by default.
- Confirm no context drift.
### Phase 6 - Validation And Close-Out
- Run focused Feature/Livewire/browser tests.
- Run targeted Spec 314-322 context guards.
- Run Pint and diff check.
- Report full suite status honestly.
- Record no migrations/packages/env/queues/storage/deployment assets/backcompat/legacy aliases.
## Risk Controls
- Treat Spec 325 images as direction only; map every visible element to repo truth.
- Use unavailable/deferred states instead of inventing proof.
- Do not broaden Baseline Compare Matrix scope.
- Do not turn Environment Dashboard into a generic M365/admin-center status page.
- Keep OperationRun as execution proof, not health proof.
- Keep raw diagnostics collapsed/capability-gated.
## Rollout / Deployment Considerations
- No migration expected.
- No seeders expected.
- No env var expected.
- No queue/scheduler/storage change expected.
- No package change expected.
- No deployment asset change expected unless implementation unexpectedly registers Filament assets; current expectation is no `filament:assets` change beyond existing deployment posture.
- Staging validation should focus on route-owned environment behavior, no-baseline/action-needed states, diagnostics collapsed, and no static `tenant` copy.
## Candidate Selection Gate
Passed. Spec 330 was directly user-provided, is aligned with Spec 325 strategic target surfaces and post-Spec 329 follow-up sequencing, is not already present as an active/completed package, preserves completed Specs 314-329, and is scoped to two existing environment-owned pages.
## Spec Readiness Gate
Expected pass after `spec.md`, `plan.md`, `tasks.md`, `repo-truth-map.md`, and `checklists/requirements.md` are generated and preparation analysis finds no blocking consistency issues.