280 lines
26 KiB
Markdown
280 lines
26 KiB
Markdown
# Implementation Plan: Monitoring Page-State Contract
|
|
|
|
**Branch**: `198-monitoring-page-state` | **Date**: 2026-04-15 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/198-monitoring-page-state/spec.md`
|
|
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/198-monitoring-page-state/spec.md`
|
|
|
|
**Note**: This plan keeps the work inside the existing Filament v5 / Livewire v4 page layer, current query and session helpers, and the current monitoring pages. It explicitly avoids a new global page-state framework, new persistence, or a shell-context refactor.
|
|
|
|
## Summary
|
|
|
|
Codify one bounded monitoring page-state contract for Operations, Audit Log, Finding Exceptions Queue, Evidence Overview, Baseline Compare Landing, and Baseline Compare Matrix, with Baseline Compare Landing remaining the compare launch-context support surface. Reuse existing Livewire page properties, `CanonicalAdminTenantFilterState`, `CanonicalNavigationContext`, existing session-backed table persistence, and the current compare draft/apply pattern to make contextual prefilter state, active state, inspect state, draft state, and shareable or restorable state explicit and consistent without adding a new runtime state engine.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4.15
|
|
**Primary Dependencies**: Laravel 12, Filament v5, Livewire v4, Pest v4, Tailwind CSS v4, existing `CanonicalAdminTenantFilterState`, `CanonicalNavigationContext`, `OperateHubShell`, Filament `InteractsWithTable`, and page-local Livewire state on the affected Filament pages
|
|
**Storage**: PostgreSQL plus existing Laravel session-backed table filter, search, and sort persistence; no schema change planned
|
|
**Testing**: Pest feature tests, Filament or Livewire page tests, existing table-state persistence tests, and focused Pest browser smoke tests run through Laravel Sail
|
|
**Target Platform**: Laravel monolith web application under `apps/platform`, with canonical monitoring routes under `/admin` and tenant-bound compare routes under `/admin/t/{tenant}` or active tenant context
|
|
**Project Type**: web application
|
|
**Performance Goals**: Keep monitoring pages DB-only at render time, preserve current session-backed table persistence, avoid new outbound HTTP or queued work during state hydration, avoid N+1 query regressions, and keep first-mount state hydration deterministic and cheap
|
|
**Constraints**: No new global page-state framework, no new persistence, no panel or route-family changes, no shell or context refactor that belongs in Spec 199, no authorization-plane changes, no new Graph calls, no new badge taxonomy, and no forced flattening of Baseline Compare Matrix into a generic table contract
|
|
**Scale/Scope**: 5 primary in-scope page-state surfaces, 1 compare launch-context support surface, 6 page classes, 7 existing focused test files, likely 1 new cross-surface contract test, and 1 focused browser smoke suite or extension of existing smoke coverage
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Passed before Phase 0 research. Re-checked after Phase 1 design and still passing.*
|
|
|
|
| Principle | Pre-Research | Post-Design | Notes |
|
|
|-----------|--------------|-------------|-------|
|
|
| Inventory-first / snapshots-second | PASS | PASS | The feature does not alter inventory, snapshot, or backup truth. It standardizes page-state semantics only. |
|
|
| Read/write separation | PASS | PASS | Existing writes such as exception approval or rejection keep their current confirmation, audit, and authorization behavior. No new write workflow is introduced. |
|
|
| Graph contract path | N/A | N/A | No Microsoft Graph calls or contract-registry changes are planned. |
|
|
| Deterministic capabilities | PASS | PASS | Capability checks stay in the existing registries and page actions. The work does not add new raw capability strings or new auth planes. |
|
|
| Workspace + tenant isolation | PASS | PASS | Requested tenant filters, selected-record deeplinks, and compare focus state remain subject to existing workspace and tenant entitlement checks. |
|
|
| RBAC-UX authorization semantics | PASS | PASS | Non-members remain `404`, members without capability remain `403`, and server-side authorization remains authoritative for mutations and restricted drilldowns. |
|
|
| Run observability / Ops-UX | PASS | PASS | No new `OperationRun` is introduced. Monitoring pages remain DB-only at render, and no start surface behavior is changed. |
|
|
| Data minimization | PASS | PASS | No new persistence, caches, or derived artifacts are introduced. The contract remains derived from existing page and query state. |
|
|
| Proportionality / anti-bloat | PASS WITH JUSTIFIED TAXONOMY | PASS WITH JUSTIFIED TAXONOMY | The feature introduces a bounded page-state taxonomy because five primary monitoring surfaces plus the compare launch surface already need the same explicit contract. It avoids a runtime framework or registry unless implementation proves one tiny helper is truly unavoidable. |
|
|
| UI semantics / few layers | PASS | PASS | The design uses direct page-state declarations and existing helpers, not a presenter or explanation framework. |
|
|
| Filament-native UI | PASS | PASS | Existing Filament pages, tables, actions, and Blade views remain the implementation path. No custom status system or new UI framework is needed. |
|
|
| Shell boundary / Spec 199 separation | PASS | PASS | Global workspace or tenant shell concerns remain out of scope. Any discovered shell drift is documented for Spec 199 instead of solved here. |
|
|
| Filament v5 / Livewire v4 compliance | PASS | PASS | All touched surfaces remain on Filament v5 and Livewire v4 page patterns. |
|
|
| Provider registration location | PASS | PASS | No panel or provider change is required; Laravel 11+ provider registration remains in `bootstrap/providers.php`. |
|
|
| Global search hard rule | PASS | PASS | No globally searchable resource is added or modified. Existing search behavior remains unchanged. |
|
|
| Destructive action safety | PASS | PASS | Existing destructive-like governance actions in Finding Exceptions Queue keep `->requiresConfirmation()` and current authorization and audit semantics. |
|
|
| Asset strategy | PASS | PASS | No new global or lazy-loaded assets are planned. Existing deployment handling of `cd apps/platform && php artisan filament:assets` remains sufficient. |
|
|
|
|
## Filament-Specific Compliance Notes
|
|
|
|
- **Livewire v4.0+ compliance**: The implementation stays on Filament v5 + Livewire v4 page, table, and action APIs. No legacy Livewire or Filament APIs are introduced.
|
|
- **Provider registration location**: No provider or panel registration changes are planned. Laravel 11+ provider registration remains in `bootstrap/providers.php`.
|
|
- **Global search**: No in-scope page is a globally searchable resource surface, and this plan does not change global search visibility for any existing resource.
|
|
- **Destructive actions**: `Approve exception` and `Reject exception` remain the only destructive-like actions directly affected by state-contract cleanup. They continue to execute via `Action::make(...)->action(...)` with `->requiresConfirmation()`, existing server-side authorization, and existing audit behavior. Operations, Audit Log, Evidence Overview, and Baseline Compare Matrix do not gain new destructive actions.
|
|
- **Asset strategy**: No new assets or build steps are planned. Existing deployment handling of `cd apps/platform && php artisan filament:assets` remains unchanged.
|
|
- **Testing plan**: Extend the current Operations, Audit Log, Finding Exceptions Queue, Evidence Overview, Baseline Compare Landing, Baseline Compare Matrix, `ActionSurfaceRbacSemanticsTest`, `BaselineCompareMatrixAuthorizationTest`, and table-persistence suites, and add one narrow cross-surface contract test plus focused browser smoke coverage for refresh, back, deeplink, share behavior, and unauthorized requested-state fallback.
|
|
|
|
## Phase 0 Research
|
|
|
|
Research outcomes are captured in `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/198-monitoring-page-state/research.md`.
|
|
|
|
Key decisions:
|
|
|
|
- Reuse `CanonicalAdminTenantFilterState`, `CanonicalNavigationContext`, existing session-backed table persistence, and page-local Livewire state instead of introducing a global page-state framework.
|
|
- Make state precedence explicit: supported query or deeplink input hydrates first on mount, session provides baseline only for explicitly persisted filter/search/sort state, and active local state becomes authoritative after hydration.
|
|
- Unify selected-record inspect on Audit Log and Finding Exceptions Queue so action-based inspect and deeplinked selected IDs express the same inspect state.
|
|
- Keep Baseline Compare Matrix as the only explicit draft/apply special case, with draft state remaining local-only and unapplied draft state never being shareable or restorable.
|
|
- Treat Baseline Compare Landing as a launch-context broker for matrix state, not as a competing owner of compare state.
|
|
- Extend existing Pest and Livewire test seams rather than leaning on browser-only validation or adding a new guard framework.
|
|
|
|
## Phase 1 Design
|
|
|
|
Design artifacts are created under `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/198-monitoring-page-state/`:
|
|
|
|
- `research.md`: page-state decisions, rationale, and rejected alternatives
|
|
- `data-model.md`: derived page-state contract model, state-field descriptors, hydration rules, and inspect-state descriptors
|
|
- `contracts/monitoring-page-state.logical.openapi.yaml`: internal logical contract for the bounded page-state model and per-surface expectations
|
|
- `quickstart.md`: implementation and verification workflow for Spec 198
|
|
|
|
Design highlights:
|
|
|
|
- Keep the contract derived and page-local. No new persisted truth or generalized runtime registry is planned.
|
|
- Reuse existing helpers for tenant-sensitive session state and navigation context rather than adding a second helper layer.
|
|
- Make the role of each state field explicit per surface: contextual prefilter, active, draft, inspect, and shareable/restorable.
|
|
- Keep Operations and Evidence Overview in the simple query or session plus active-state pattern, keep Audit Log and Finding Exceptions Queue in the unified selected-record inspect pattern, and keep Baseline Compare Matrix in the explicit draft/applied/focus special-case pattern.
|
|
- Add cross-surface regression protection through focused feature tests instead of a new runtime state validator.
|
|
|
|
## Phase 1 — Agent Context Update
|
|
|
|
Planned command:
|
|
|
|
- `.specify/scripts/bash/update-agent-context.sh copilot`
|
|
|
|
This feature does not introduce a new language or framework, but the required agent-context refresh still runs after the design artifacts are complete.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/198-monitoring-page-state/
|
|
├── spec.md
|
|
├── plan.md
|
|
├── research.md
|
|
├── data-model.md
|
|
├── quickstart.md
|
|
├── contracts/
|
|
│ └── monitoring-page-state.logical.openapi.yaml
|
|
├── checklists/
|
|
│ └── requirements.md
|
|
└── tasks.md
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
|
|
```text
|
|
apps/platform/
|
|
├── app/
|
|
│ ├── Filament/
|
|
│ │ └── Pages/
|
|
│ │ ├── Monitoring/
|
|
│ │ │ ├── Operations.php # MODIFY
|
|
│ │ │ ├── AuditLog.php # MODIFY
|
|
│ │ │ ├── FindingExceptionsQueue.php # MODIFY
|
|
│ │ │ └── EvidenceOverview.php # MODIFY
|
|
│ │ ├── BaselineCompareLanding.php # MODIFY
|
|
│ │ └── BaselineCompareMatrix.php # MODIFY
|
|
│ └── Support/
|
|
│ ├── Filament/
|
|
│ │ └── CanonicalAdminTenantFilterState.php # REUSE / possible small extend
|
|
│ ├── Navigation/
|
|
│ │ └── CanonicalNavigationContext.php # REUSE / possible small extend
|
|
│ └── OperateHub/
|
|
│ └── OperateHubShell.php # REUSE
|
|
├── resources/
|
|
│ └── views/
|
|
│ └── filament/
|
|
│ └── pages/
|
|
│ ├── monitoring/
|
|
│ │ ├── operations.blade.php # MODIFY
|
|
│ │ ├── audit-log.blade.php # MODIFY
|
|
│ │ ├── partials/
|
|
│ │ │ └── audit-log-inspect-event.blade.php # MODIFY
|
|
│ │ ├── finding-exceptions-queue.blade.php # MODIFY
|
|
│ │ └── evidence-overview.blade.php # MODIFY
|
|
│ ├── baseline-compare-landing.blade.php # MODIFY
|
|
│ └── baseline-compare-matrix.blade.php # MODIFY
|
|
└── tests/
|
|
├── Feature/
|
|
│ ├── Monitoring/
|
|
│ │ ├── OperationsDashboardDrillthroughTest.php # MODIFY
|
|
│ │ ├── AuditLogInspectFlowTest.php # MODIFY
|
|
│ │ ├── FindingExceptionsQueueHierarchyTest.php # MODIFY
|
|
│ │ └── MonitoringPageStateContractTest.php # NEW
|
|
│ ├── Evidence/
|
|
│ │ └── EvidenceOverviewPageTest.php # MODIFY
|
|
│ ├── Filament/
|
|
│ │ ├── BaselineCompareMatrixPageTest.php # MODIFY
|
|
│ │ ├── BaselineCompareLandingStartSurfaceTest.php # MODIFY
|
|
│ │ └── TableStatePersistenceTest.php # MODIFY
|
|
│ └── Rbac/
|
|
│ ├── BaselineCompareMatrixAuthorizationTest.php # REUSE / possible extend
|
|
│ └── ActionSurfaceRbacSemanticsTest.php # REUSE / possible extend
|
|
└── Browser/
|
|
├── Spec190BaselineCompareMatrixSmokeTest.php # REUSE / possible extend
|
|
├── Spec194GovernanceFrictionSmokeTest.php # REUSE / possible extend
|
|
└── Spec198MonitoringPageStateSmokeTest.php # NEW
|
|
```
|
|
|
|
**Structure Decision**: Keep the work entirely inside the existing Laravel/Filament monolith under `apps/platform`. Modify the affected page classes, their existing Blade views, and focused test suites. Reuse current support helpers and extract a new support helper only if repeated implementation proves that at least three pages share the same normalization code in a way that cannot stay page-local.
|
|
|
|
## Complexity Tracking
|
|
|
|
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
|
|-----------|------------|-------------------------------------|
|
|
| Cross-surface monitoring page-state taxonomy and per-surface contract documentation (BLOAT-001 trigger) | Five primary monitoring surfaces plus the compare launch surface already have overlapping but divergent page-state behavior, and the product needs explicit hydration, inspect, and restore rules now. | Pure page-by-page local cleanup would reduce individual bugs but would not produce a shared operator contract or durable regression coverage across the monitoring family. |
|
|
|
|
## Proportionality Review
|
|
|
|
- **Current operator problem**: Similar monitoring pages currently give different answers about what a deeplink sets, what refresh restores, when a selected record is authoritative, and whether draft state exists.
|
|
- **Existing structure is insufficient because**: The current page-local implementations contain the behavior, but not a consistent or documented contract. Without an explicit shared model, the same drift will continue page by page.
|
|
- **Narrowest correct implementation**: Reuse current helpers and page-local Livewire state, add explicit per-surface state declarations and targeted tests, and keep Compare Matrix as one documented special case. Do not add persistence or a global runtime framework.
|
|
- **Ownership cost created**: Reviewers must maintain one bounded page-state taxonomy, a small set of per-surface declarations, and focused regression coverage for deeplink, inspect, and restoration behavior.
|
|
- **Alternative intentionally rejected**: A global page-state engine or shell-level state resolver was rejected because the affected surfaces can be standardized with existing helpers and local state.
|
|
- **Release truth**: current-release operator predictability and monitoring-family consistency
|
|
|
|
## Implementation Strategy
|
|
|
|
### Phase A — Declare the bounded page-state contract per surface
|
|
|
|
**Goal**: Make the state classes, query roles, and shareable or restorable subset explicit without adding a global framework.
|
|
|
|
| Step | File | Change |
|
|
|------|------|--------|
|
|
| A.1 | `apps/platform/app/Filament/Pages/Monitoring/Operations.php`, `AuditLog.php`, `FindingExceptionsQueue.php`, `EvidenceOverview.php`, `BaselineCompareMatrix.php`, `BaselineCompareLanding.php` | Add or align explicit page-local contract declarations for contextual prefilter, active, draft, inspect, and shareable or restorable state, plus invalid-state fallback behavior |
|
|
| A.2 | Existing page-local mount and hydrate methods | Make first-mount precedence explicit between query input, session state, and page-local defaults |
|
|
| A.3 | `apps/platform/tests/Feature/Monitoring/MonitoringPageStateContractTest.php` | Add one cross-surface contract test that asserts every in-scope page exposes the expected state classes, query roles, shareable or restorable semantics, and Audit Log/Finding Exceptions inspect-vocabulary compatibility |
|
|
|
|
### Phase B — Standardize the simple monitoring pattern on Operations and Evidence Overview
|
|
|
|
**Goal**: Align the surfaces that should behave like query or session plus active-state pages, not special-case workbenches.
|
|
|
|
| Step | File | Change |
|
|
|------|------|--------|
|
|
| B.1 | `apps/platform/app/Filament/Pages/Monitoring/Operations.php` | Make requested dashboard prefilter, requested tenant scope, active tab, and persisted table state follow one deterministic precedence rule |
|
|
| B.2 | `apps/platform/app/Filament/Pages/Monitoring/EvidenceOverview.php` | Align query hydration, session persistence, clear-filter behavior, and shareable filter semantics with the shared simple monitoring contract |
|
|
| B.3 | `apps/platform/tests/Feature/Monitoring/OperationsDashboardDrillthroughTest.php`, `apps/platform/tests/Feature/Filament/TableStatePersistenceTest.php`, and `apps/platform/tests/Feature/Rbac/ActionSurfaceRbacSemanticsTest.php` | Cover query-first hydration, tenant-sensitive reset behavior, active tab restoration, persistence boundaries, and unauthorized requested-tenant fallback |
|
|
| B.4 | `apps/platform/tests/Feature/Evidence/EvidenceOverviewPageTest.php` | Extend multi-filter hydration, clear-filter, and refresh or reopen scenarios |
|
|
|
|
### Phase C — Unify inspect-state semantics on Audit Log and Finding Exceptions Queue
|
|
|
|
**Goal**: Ensure action-based inspect and deeplinked selected-record entry use one primary inspect model on each surface.
|
|
|
|
| Step | File | Change |
|
|
|------|------|--------|
|
|
| C.1 | `apps/platform/app/Filament/Pages/Monitoring/AuditLog.php` and `apps/platform/resources/views/filament/pages/monitoring/audit-log.blade.php` | Make `selectedAuditLogId` the only inspect contract, with consistent open, close, refresh, and invalid-selection fallback behavior |
|
|
| C.2 | `apps/platform/app/Filament/Pages/Monitoring/FindingExceptionsQueue.php` and `apps/platform/resources/views/filament/pages/monitoring/finding-exceptions-queue.blade.php` | Make `selectedFindingExceptionId` the only inspect and decision state, with summary and action lanes deriving from that single selection |
|
|
| C.3 | `apps/platform/resources/views/filament/pages/monitoring/partials/audit-log-inspect-event.blade.php` | Align inline inspect rendering with the single selected-event contract |
|
|
| C.4 | `apps/platform/tests/Feature/Monitoring/AuditLogInspectFlowTest.php`, `apps/platform/tests/Feature/Monitoring/FindingExceptionsQueueHierarchyTest.php`, and `apps/platform/tests/Feature/Rbac/ActionSurfaceRbacSemanticsTest.php` | Add positive and negative cases for query-selected inspect, invalid or unauthorized IDs, close-detail behavior, refresh behavior, selection clearing when filters no longer match, and compatible selected-record vocabulary across both surfaces |
|
|
|
|
### Phase D — Preserve the Compare Matrix special case while making it explicit
|
|
|
|
**Goal**: Keep Baseline Compare Matrix powerful while making draft, applied, focus, and launch-context semantics predictable.
|
|
|
|
| Step | File | Change |
|
|
|------|------|--------|
|
|
| D.1 | `apps/platform/app/Filament/Pages/BaselineCompareLanding.php` and `apps/platform/resources/views/filament/pages/baseline-compare-landing.blade.php` | Treat landing state as launch context only, and make matrix launch parameters explicit and non-competing |
|
|
| D.2 | `apps/platform/app/Filament/Pages/BaselineCompareMatrix.php` and `apps/platform/resources/views/filament/pages/baseline-compare-matrix.blade.php` | Make applied filter state, draft filter state, presentation mode, focus state, and shareable slices explicit; keep draft state local-only until apply |
|
|
| D.3 | `apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php` | Extend draft-versus-applied, focus restoration, refresh behavior, and non-shareable draft discard coverage |
|
|
| D.4 | `apps/platform/tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php` and `apps/platform/tests/Feature/Rbac/BaselineCompareMatrixAuthorizationTest.php` | Cover launch-context hydration, focus handoff, and invalid or unauthorized requested compare context |
|
|
|
|
### Phase E — Browser verification and closure documentation
|
|
|
|
**Goal**: Prove the contract through UI-level flows and leave a clear handoff boundary for shell-context concerns.
|
|
|
|
| Step | File | Change |
|
|
|------|------|--------|
|
|
| E.1 | `apps/platform/tests/Browser/Spec198MonitoringPageStateSmokeTest.php` | Add a focused browser smoke suite for deeplink, refresh, back, close-detail, and share behavior across the in-scope surfaces |
|
|
| E.2 | Existing browser suites | Reuse or extend `Spec190BaselineCompareMatrixSmokeTest.php` and `Spec194GovernanceFrictionSmokeTest.php` where they already cover relevant state flows |
|
|
| E.3 | `specs/198-monitoring-page-state/quickstart.md` and final implementation notes | Record the final state-class mapping, shareable/restorable subset, and any shell or context handoff that remains for Spec 199 |
|
|
|
|
## Key Design Decisions
|
|
|
|
### D-001 — Reuse current helpers and keep the contract page-local
|
|
|
|
`CanonicalAdminTenantFilterState`, `CanonicalNavigationContext`, and current page-local Livewire properties already cover most of the needed mechanics. The narrowest implementation is to make the contract explicit on the pages that already own the state.
|
|
|
|
### D-002 — Query or deeplink input wins on first hydration, session only persists the state the page already owns
|
|
|
|
The consistent precedence rule is: supported query or deeplink input hydrates first, session supplies only explicitly persisted table filter, search, or sort state, and page-local active state becomes authoritative after mount.
|
|
|
|
### D-003 — Selected-record inspect is the authoritative inspect model on Audit Log and Finding Exceptions Queue
|
|
|
|
The inspect action, the selected summary, and the deeplinked selected ID must all express the same state. There must be no second inspect world beside the selected-record contract.
|
|
|
|
### D-004 — Baseline Compare Matrix keeps explicit draft, applied, and focus slices
|
|
|
|
Compare Matrix already has a genuine draft/apply interaction model. The right move is to document and tighten it, not to flatten it into a direct-active table pattern.
|
|
|
|
### D-005 — Regression protection belongs in focused tests, not a new runtime state engine
|
|
|
|
The contract is enforceable through page-local declarations and focused Pest coverage. That keeps the implementation surface small and avoids importing a new state registry or framework.
|
|
|
|
## Risk Assessment
|
|
|
|
| Risk | Impact | Likelihood | Mitigation |
|
|
|------|--------|------------|------------|
|
|
| Query and session precedence regressions change what first mount restores | High | Medium | Make precedence explicit per page, extend query-param and table-persistence tests, and cover tenant-sensitive filter resets |
|
|
| Invalid deeplinks leave phantom selected state or stale action lanes | High | Medium | Add invalid-ID fallback rules and test them on Audit Log, Finding Exceptions Queue, and Baseline Compare launch context |
|
|
| Compare Matrix accidentally persists or shares draft state | High | Medium | Keep draft and applied state separate in code and tests, and assert that shared links restore only applied and focused state |
|
|
| Shell-context concerns leak into Spec 198 and widen scope | Medium | Medium | Keep workspace or tenant shell concerns documented only as handoff items for Spec 199 |
|
|
| Implementation drifts into a generic page-state framework | Medium | Medium | Keep helpers page-local by default and extract only a tiny shared helper if duplication across multiple pages proves it necessary during implementation |
|
|
|
|
## Test Strategy
|
|
|
|
- Extend Operations, Audit Log, Finding Exceptions Queue, Evidence Overview, Baseline Compare Landing, Baseline Compare Matrix, and `TableStatePersistenceTest` with deterministic query, session, refresh, back, and restore coverage.
|
|
- Add one focused cross-surface contract test for the explicit page-state declarations on the in-scope pages.
|
|
- Reuse current RBAC suites where requested state can become unauthorized or cross-tenant.
|
|
- Add one browser smoke suite for the top user journeys: Operations deeplink and refresh, Audit Log selected-event open and close, Finding Exceptions selected-exception review state, Evidence Overview filter clear behavior, and Baseline Compare draft/apply plus focus restoration.
|
|
- Run focused verification through Sail and format only touched files with Pint.
|