# Feature Specification: Monitoring Page-State Contract

**Feature Branch**: `198-monitoring-page-state`  
**Created**: 2026-04-15  
**Status**: Implemented  
**Input**: User description: "Spec 198 — Monitoring Page-State Contract"

## Spec Candidate Check *(mandatory — SPEC-GATE-001)*

- **Problem**: Monitoring and governance pages with tabs, filters, selected-record state, inspect panels, and deeplink entry currently behave like separate local state protocols instead of one product-level contract.
- **Today's failure**: Operators can open similar monitoring pages and get different answers to the same questions: what a link restores, whether a selected record is the real inspect state, whether a tab or filter is durable, and what refresh, back, or share will recreate. This increases drift, regressions, and review time.
- **User-visible improvement**: Operators learn one predictable model for how monitoring pages hydrate from links, keep active state, expose inspect state, and decide what is shareable or restorable.
- **Smallest enterprise-capable version**: Map the existing state behavior of the five named in-scope surfaces, define one shared monitoring page-state contract with one explicit special-case rule for Compare Matrix, align those surfaces to the contract, add regression coverage, and document what remains deferred to the shell/context spec.
- **Explicit non-goals**: No global shell/context refactor, no generic Filament purity cleanup, no shared detail family redesign, no visual unification for its own sake, no generic mega-state framework, and no forced reduction of Compare Matrix into a normal table contract.
- **Permanent complexity imported**: A bounded monitoring page-state taxonomy, a per-surface contract matrix, explicit shareable/restorable-state rules, and focused regression coverage for deeplink, inspect, tab/mode, and draft/apply behavior.
- **Why now**: The repo already has multiple important monitoring surfaces with divergent state behavior, and adjacent specs intentionally leave this page-state layer unresolved. Leaving the gap open will keep producing drift on future monitoring pages.
- **Why not local**: Local page-by-page fixes would reduce symptoms on individual surfaces but would not define the shared operator contract for hydration, inspect, draft/apply, or restoration semantics across the monitoring family.
- **Approval class**: Core Enterprise
- **Red flags triggered**: Cross-surface taxonomy risk and multi-surface remediation breadth. Defense: the scope is tightly bounded to named monitoring/governance pages, introduces no new persistence or runtime framework, and explicitly preserves one justified special-case surface.
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexität: 1 | Produktnähe: 2 | Wiederverwendung: 2 | **Gesamt: 11/12**
- **Decision**: approve

## Spec Scope Fields *(mandatory)*

- **Scope**: canonical-view
- **Primary Routes**:
  - `/admin/operations`
  - `/admin/audit-log`
  - `/admin/finding-exceptions/queue`
  - `/admin/evidence/overview`
  - Existing tenant-bound Baseline Compare landing route
  - Existing Baseline Compare Matrix route under the active baseline profile
- **Data Ownership**:
  - Operations, Audit Log, Finding Exceptions Queue, and Evidence Overview remain workspace-facing monitoring or governance views over workspace-visible records with tenant-scoped drilldowns.
  - Baseline Compare Matrix remains a tenant-bound analysis surface over tenant-visible compare evidence and profile context.
  - This feature introduces no new tables, persisted entities, or storage truth. It standardizes page-state behavior on existing surfaces.
- **RBAC**:
  - Existing workspace membership and workspace capability rules continue to govern Operations, Audit Log, Finding Exceptions Queue, and Evidence Overview.
  - Existing tenant membership and tenant capability rules continue to govern Baseline Compare routes and drilldowns.
  - State-contract changes do not weaken authorization: inaccessible routes or records remain deny-as-not-found for non-members and capability-gated for members.

For canonical-view specs, the spec MUST define:

- **Default filter behavior when tenant-context is active**: Workspace monitoring pages may accept a tenant prefilter from dashboard entry, remembered scope, or query state, but that prefilter must remain explicit and reversible. Tenant-bound compare pages stay bound to the active tenant and baseline profile; they do not silently broaden scope.
- **Explicit entitlement checks preventing cross-tenant leakage**: Requested tenant filters, selected-record deeplinks, compare focus state, and related drilldowns must resolve through existing entitled-tenant and record authorization checks. If a requested tenant, event, exception, or compare subject is not accessible, the page must discard that state predictably and expose no cross-tenant hints.

## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)*

| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Operations | Primary Decision Surface | Decide which run class or tenant scope needs inspection first | Active tab, current tenant scope, requested dashboard context, run health summary | Operation detail, related run context, deeper diagnostics | Primary because it is the canonical monitoring landing for deciding what run needs attention next | Aligns KPI-card entry and direct monitoring workflow under one tab/filter model | Removes guesswork about whether dashboard entry state, local tab state, and persisted filters are competing truths |
| Audit Log | Secondary Context Surface | Validate what happened after an operational or governance event | Active filters, whether an event is selected, concise actor/target summary | Full event body, related target navigation, evidence of what changed | Secondary because it explains and verifies decisions made elsewhere rather than being the first decision queue | Supports investigation after the operator already has a question | Removes ambiguity between action inspect, inline detail, and query-selected event state |
| Finding Exceptions Queue | Primary Decision Surface | Review one queued exception request and decide whether to approve or reject it | Queue scope, selected exception state, decision readiness, summary of what is under review | Full exception evidence, related finding detail, tenant context | Primary because it is the queue where governance work is actively decided and cleared | Aligns row selection, selected summary, and decision actions into one workbench flow | Prevents the queue from behaving like two inspect systems glued together |
| Evidence Overview | Primary Decision Surface | Decide whether evidence is current enough and which tenant needs follow-up | Current filters, evidence freshness, default-visible next-step signals | Snapshot detail after drilldown | Primary because it is the monitoring overview that tells operators where evidence is missing or stale | Aligns direct page use and prefiltered entry under one simple monitoring contract | Keeps the surface simple without a one-off hidden prefilter protocol |
| Baseline Compare Landing | Secondary Context Surface | Confirm which tenant/profile context should open the matrix next | Active tenant, baseline profile, launch context, and compare readiness cues | Matrix state, compare evidence, and downstream drilldowns after handoff | Secondary because it frames the compare launch and hands off to the matrix instead of owning the compare result state | Aligns tenant-bound entry and matrix launch without creating a second compare owner | Keeps launch context explicit so the matrix does not inherit hidden state |
| Baseline Compare Matrix | Primary Decision Surface | Decide what the current compare result means for one profile and subject | Applied compare state, visible distinction between draft and applied filters, focused subject if present | Cell-level evidence, finding drilldowns, supporting compare context | Primary because the matrix itself is the focused compare decision surface | Aligns landing deeplinks, focused subject entry, and in-page refinement without flattening compare behavior | Reduces hidden state shifts between draft controls, applied results, and shared links |

## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*

| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Operations | List / Table / Monitoring | Monitoring landing | Open the next run that needs inspection | Full-row click opens the canonical operation detail surface | required | Header utility and context strip only | none | `/admin/operations` | `/admin/operations/{run}` | Workspace scope, requested tenant prefilter, active tab | Operations / operation run | Whether the view is prefiltered and which run class is active | none |
| Audit Log | List / Table / History | History with inline inspect | Inspect an event and verify what happened | Explicit inspect action or matching deeplink opens the same inline event detail state | forbidden | Page utilities and selected-event detail header | none | `/admin/audit-log` | Same page with selected event state | Workspace or tenant prefilter, active audit filters, selected event | Audit log / audit event | Which event is selected and what filters define the visible history | none |
| Finding Exceptions Queue | Queue / Workbench / Review | Decision queue | Review the selected exception request and decide it | Explicit inspect or matching deeplink opens the same selected-exception workbench state | forbidden | Queue utility lane and related-links area | Selected-exception decision lane only | `/admin/finding-exceptions/queue` | Same page with selected exception state | Workspace scope, queue filters, selected exception | Finding exceptions queue / exception request | Whether a decision-ready exception is selected right now | none |
| Evidence Overview | Report / Monitoring / Registry | Read-only monitoring overview | Open the most relevant evidence snapshot | Full-row click opens the canonical evidence snapshot detail | required | Minimal page utility only | none | `/admin/evidence/overview` | Existing evidence snapshot detail route | Optional tenant prefilter and search state | Evidence overview / evidence snapshot | Evidence freshness and next step per tenant | none |
| Baseline Compare Landing | Report / Monitoring / Launch context | Tenant-bound compare launch surface | Open the compare matrix with the current tenant/profile context | Explicit open-matrix action or deeplink handoff is the only launch model | forbidden | Context strip and page header only | none | Existing Baseline Compare landing route | Existing Baseline Compare Matrix route under the active baseline profile | Active tenant, baseline profile, and launch context | Baseline compare landing / compare launch context | Which tenant/profile context will be used when the matrix opens | allowed support-surface exception: initialization-only launch context, with applied compare state owned by the matrix |
| Baseline Compare Matrix | Analysis / Focused Compare / Matrix | Tenant-bound compare analysis | Apply compare changes or drill into a focused subject | Focused subject/cell state on the current matrix page is the only primary inspect model | forbidden | Local matrix toolbar and downstream drilldown lane | none | Existing Baseline Compare landing route | Existing Baseline Compare Matrix route under the active baseline profile | Active tenant, baseline profile, applied compare state, focused subject | Baseline compare matrix / compare subject | Applied compare result for the current profile and subject | allowed special case for draft/applied state |

## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*

| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Operations | Workspace operator | Decide what run needs inspection next | Monitoring landing | Which run class needs attention, and am I looking at one tenant or all tenants? | KPI summary, active tab, current scope, filtered run list | Full run detail after drilldown, related context, deeper failure evidence | execution status, outcome, scope, freshness | read-only landing | Tab switch and open detail | none |
| Audit Log | Workspace operator or auditor | Inspect one event and understand what changed | History with inline inspect | What happened, in which scope, and which event should I inspect? | History list, current filters, selected-event summary when open | Event body, related target navigation, full change evidence | actor, target type, outcome, scope, time | read-only history | Inspect event and close detail | none |
| Finding Exceptions Queue | Workspace approver | Review one exception request and decide it | Decision queue | Is there a pending exception selected, and what decision is justified? | Queue filters, selected-exception summary, decision readiness | Full exception detail, related finding context, tenant drilldown | queue state, exception validity, selection state | `TenantPilot only` | Inspect exception, approve exception, reject exception | Approve exception and reject exception remain confirmation-gated |
| Evidence Overview | Workspace operator | Decide whether evidence is usable and where to drill down | Monitoring overview | Which tenants lack current evidence and what should I inspect next? | Tenant rows, freshness, completeness, next-step cues | Downstream evidence snapshot detail | freshness, completeness, scope | read-only landing | Clear filters and open snapshot | none |
| Baseline Compare Landing | Tenant operator | Confirm which compare context should open the matrix | Tenant-bound launch context | Which tenant/profile context am I about to compare, and what launch state is being handed off? | Active tenant, baseline profile, compare readiness, launch cues | Matrix-only evidence and focused compare analysis after handoff | tenant scope, profile readiness, launch context | read-only launch surface | Open compare matrix and return | none |
| Baseline Compare Matrix | Tenant operator | Decide how one baseline profile compares across subjects | Focused compare analysis | What does the current compare result show, and is my visible matrix based on draft or applied state? | Applied compare state, focused subject, matrix result summary | Cell-level evidence and follow-up drilldowns | compare coverage, state, severity, focus | read-only analysis | Apply filters, reset filters, focus subject | none |

## Proportionality Review *(mandatory when structural complexity is introduced)*

- **New source of truth?**: no
- **New persisted entity/table/artifact?**: no
- **New abstraction?**: no
- **New enum/state/reason family?**: yes
- **New cross-domain UI framework/taxonomy?**: yes
- **Current operator problem**: Similar monitoring pages currently hide different local rules for URL hydration, active state, inspect state, and restoration behavior, so operators cannot reliably predict how links, refresh, or selection will behave.
- **Existing structure is insufficient because**: Surface-local cleanup can fix a symptom on one page, but it cannot define whether query state is initialization-only or durable, whether selected record is the real inspect contract, or whether draft/apply is a deliberate exception instead of a private implementation accident.
- **Narrowest correct implementation**: Introduce only a bounded monitoring page-state taxonomy, a per-surface contract summary for the five primary monitoring surfaces plus Baseline Compare Landing as the compare launch-context support surface, and regression tests that enforce those rules. Do not add persistence, a runtime registry, or a generic global state framework.
- **Ownership cost**: The repo gains a contract reviewers must maintain, per-surface documentation/tests for shareable and restorable state, and explicit exception discipline for Compare Matrix and future monitoring surfaces.
- **Alternative intentionally rejected**: One-off local fixes were rejected because they would keep the operator mental model fragmented. A global shell state framework was rejected because it would import more complexity than the named surfaces require.
- **Release truth**: current-release operator clarity and monitoring-state consistency

## User Scenarios & Testing *(mandatory)*

### User Story 1 - Enter Operations Without Tab Drift (Priority: P1)

As a workspace operator, I want Operations to treat dashboard entry state, direct navigation, tabs, and filters as one coherent contract so I can predict what the page will show after navigation, refresh, or sharing.

**Why this priority**: Operations is the canonical monitoring landing. If its tab and prefilter behavior remains ambiguous, the monitoring family still lacks a reliable state model.

**Independent Test**: Open Operations directly and from a KPI/deeplink context, change tabs and filters, then verify that the documented active and shareable state behaves the same way after refresh and reopen.

**Acceptance Scenarios**:

1. **Given** an operator opens Operations from a KPI link with requested tenant or problem-class context, **When** the page hydrates, **Then** the documented initial tab and filter state becomes the active view without creating a second hidden local model.
2. **Given** an operator changes tabs or filters on Operations, **When** they refresh or reopen a shared link, **Then** only the documented restorable state is recreated and no stale local-only state reappears.

---

### User Story 2 - Inspect Audit Events Through One Model (Priority: P1)

As an operator investigating history, I want action-based inspect and deeplinked event selection on Audit Log to resolve to one inspect model so I do not have to infer which event state is authoritative.

**Why this priority**: Audit Log already mixes history browsing and selected-event detail. If inspect state is not unified here, similar history surfaces will continue to drift.

**Independent Test**: Open Audit Log with and without a selected event, inspect an event via the visible affordance, then refresh and back-navigate to verify that selected-event behavior follows one documented contract.

**Acceptance Scenarios**:

1. **Given** Audit Log is opened with a valid selected event entry state, **When** the page loads, **Then** the same inline detail state opens that would have opened from the normal inspect affordance.
2. **Given** the selected event becomes unavailable or inaccessible, **When** the page reloads, **Then** Audit Log falls back predictably to the unselected history state without leaving a phantom detail contract behind.

---

### User Story 3 - Review Finding Exceptions Through One Workbench State (Priority: P1)

As a workspace approver, I want row inspection, selected summary, header actions, and deeplink entry on Finding Exceptions Queue to behave as one selected-exception workbench state so I can review and decide requests without ambiguity.

**Why this priority**: Finding Exceptions Queue is the clearest governance decision surface in scope. If it still behaves like parallel inspect systems, the spec misses its highest-value target.

**Independent Test**: Open the queue with and without a selected exception, inspect one request, and confirm that decision actions, summary content, and shareable selected state all track the same selected-exception contract.

**Acceptance Scenarios**:

1. **Given** a valid exception is selected by deeplink or normal page interaction, **When** the queue renders, **Then** the same selected-exception state drives the summary, decision affordances, and refresh behavior.
2. **Given** no decision-ready exception is selected, **When** the queue renders, **Then** destructive-like decision actions are not promoted and the page returns to a calm queue state.

---

### User Story 4 - Keep Compare Matrix Explicitly Special (Priority: P1)

As a tenant operator using Compare Matrix, I want draft filters, applied results, focused subject state, and shared links to be explicitly separated so the page stays powerful without becoming unpredictable.

**Why this priority**: Compare Matrix is the intentional special case in scope. If its exception is not explicit, the rest of the contract will either over-normalize it or leave it undocumented.

**Independent Test**: Change draft filters without applying them, apply the new state, focus a subject, and validate what refresh, back, and a shared link restore.

**Acceptance Scenarios**:

1. **Given** draft compare controls differ from the applied matrix state, **When** the operator has not applied them yet, **Then** visible results remain tied to the applied state and the draft remains clearly local and pending.
2. **Given** a focused subject is part of the documented shareable state, **When** the matrix is reopened from a link, **Then** the same applied compare state and focused subject are restored without restoring abandoned draft state.

---

### User Story 5 - Preserve Simple Monitoring Pages Without One-Off Protocols (Priority: P2)

As a product reviewer, I want Evidence Overview and other simple monitoring pages to use the shared monitoring contract without unnecessary local exceptions so the product family feels consistent.

**Why this priority**: Simpler pages must benefit from the contract too; otherwise future monitoring pages will keep inventing unnecessary prefilter and restore behavior.

**Independent Test**: Apply and clear Evidence Overview filters, drill down into detail, and verify that refresh and shared-link behavior follow the documented simple monitoring pattern.

**Acceptance Scenarios**:

1. **Given** Evidence Overview is entered with a tenant prefilter or search state, **When** the page loads, **Then** the page clearly reflects whether that state is active and shareable.
2. **Given** filters are cleared on Evidence Overview, **When** the page refreshes or is reopened, **Then** the cleared or retained state matches the documented contract and no hidden second-layer filter state returns.

### Edge Cases

- A deeplink requests a tenant, audit event, exception, baseline profile, or focused subject that is no longer accessible.
- Session-persisted filter state and query-provided entry state disagree on first load.
- A user refreshes a page after changing local state that is intentionally not shareable or restorable.
- An operator uses browser back after clearing filters or closing inline inspect state.
- Compare Matrix has unapplied draft values when the page is refreshed, shared, or left and reopened.
- A selected audit event or exception disappears because the current filters no longer include it.
- A monitoring page is opened without tenant context, with remembered tenant context, and with explicit tenant-prefilter entry, and each path must stay distinguishable.

## Requirements *(mandatory)*

**Constitution alignment (required):** This feature introduces no new Microsoft Graph calls, no new persistence, and no new long-running or scheduled work. It standardizes operator-facing page-state semantics only. Existing destructive or approval mutations on in-scope surfaces retain their current confirmation, audit, and authorization obligations.

**Constitution alignment (PROP-001 / ABSTR-001 / PERSIST-001 / STATE-001 / BLOAT-001):** The feature introduces one bounded semantic taxonomy for monitoring page state. It does not create new storage truth or a runtime framework. The proportionality review above explains why one-off local cleanup is insufficient and why a broader global state layer is intentionally rejected.

**Constitution alignment (OPS-UX):** Existing `OperationRun` behavior remains unchanged. This spec does not introduce or rename run types, does not change service-owned run status transitions, and does not alter toast, progress-surface, or terminal-notification rules.

**Constitution alignment (RBAC-UX):** The feature spans workspace monitoring surfaces on `/admin` and tenant-bound compare surfaces under tenant context. Authorization behavior does not change: non-members remain deny-as-not-found, members still require existing capabilities for any mutation or restricted drilldown, and destructive-like actions keep confirmation. At least one positive and one negative authorization regression must confirm that state-contract cleanup does not loosen access.

**Constitution alignment (OPS-EX-AUTH-001):** Not applicable. Monitoring and operations pages in scope do not gain synchronous authentication-handshake behavior.

**Constitution alignment (BADGE-001):** The feature does not add a new badge language. Existing status, outcome, severity, and readiness badges remain centrally defined and must not be remapped ad hoc as part of the state-contract work.

**Constitution alignment (UI-FIL-001):** The feature must use native Filament pages, tables, actions, form state, and existing shared page primitives already present in the repo. It must avoid introducing page-local badge, button, or status frameworks. The approved exception is that Compare Matrix may keep richer local analysis controls because the contract is standardizing state semantics, not flattening the surface into generic Filament tables.

**Constitution alignment (UI-NAMING-001):** Operator vocabulary must stay domain-first and consistent across buttons, headers, notifications, and audit prose. Canonical terms include `Operations`, `Audit log`, `Finding exceptions queue`, `Evidence overview`, `Baseline compare matrix`, `Inspect event`, `Approve exception`, `Reject exception`, `Apply filters`, `Reset filters`, and `Show all tenants`. Implementation-first state labels must not leak into primary operator copy.

**Constitution alignment (DECIDE-001):** This spec classifies Operations, Finding Exceptions Queue, Evidence Overview, and Baseline Compare Matrix as primary decision surfaces and Audit Log as a secondary context surface. The tables above define the human-in-the-loop moment, what must be immediately visible, what stays on demand, and how the default experience becomes calmer and more predictable.

**Constitution alignment (UI-CONST-001 / UI-SURF-001 / ACTSURF-001 / UI-HARD-001 / UI-EX-001 / UI-REVIEW-001 / HDR-001):** Each in-scope surface has one broad action-surface class, one detailed surface type, one primary inspect/open model, explicit row-click rules, explicit secondary and destructive action placement, canonical routes, scope signals, and critical default-visible truth. Compare Matrix is the only explicit special-case exception and is justified by draft/applied analysis semantics rather than convenience.

**Constitution alignment (ACTSURF-001 - action hierarchy):** Navigation, context signals, mutation, and selection-bound work must remain separated on the affected pages. Queue decisions remain in the selected-object action lane, navigation and filter resets remain secondary, and no mixed catch-all action group should hide the contract.

**Constitution alignment (OPSURF-001):** Default-visible content must stay operator-first. Scope, active state, and the next meaningful inspect or review action must be visible without opening raw diagnostic detail. When a mutating action exists, its mutation scope stays explicit and its safety behavior remains unchanged.

**Constitution alignment (UI-SEM-001 / LAYER-001 / TEST-TRUTH-001):** The feature does not add a presenter or explanation layer. It documents and aligns direct page-state behavior on real surfaces. Tests must validate user-visible consequences such as restored filters, selected inspect state, and draft/apply separation rather than thin indirection alone.

**Constitution alignment (Filament Action Surfaces):** The Action Surface Contract is satisfied when each in-scope surface exposes exactly one primary inspect/open model, keeps redundant peer inspect actions out of the header, avoids empty `ActionGroup` or `BulkActionGroup` placeholders, and places destructive actions only where the chosen surface type permits them. Compare Matrix remains a documented exception because its primary interaction is focused in-page analysis rather than row-level list inspection.

**Constitution alignment (UX-001 — Layout & Information Architecture):** This feature changes page-state and interaction semantics, not form or infolist architecture. Existing tables and reports must keep meaningful empty states, filter/search affordances, and calm layout discipline while the contract becomes more predictable.

### Monitoring Page-State Taxonomy

- **Contextual Prefilter State**: State passed into a page from outside the page itself, such as requested tenant scope, requested tab, requested problem class, requested audit event, requested exception, or compare launch context.
- **Active Page State**: The current operative state of the page, such as active tab, active filters, applied compare state, presentation mode, or the current focused subject.
- **Draft Page State**: Local but not yet applied changes that intentionally differ from the active state. This is allowed only where the surface explicitly supports staged changes.
- **Inspect State**: The current selected record or focused subject that drives inline detail, decision controls, or focused analysis.
- **Shareable/Restorable State**: The subset of state the product intentionally recreates by reload, browser navigation, bookmark, or shared link.

### Per-Surface Contract Summary

| Surface | Contextual Prefilter State | Active Page State | Draft Page State | Inspect State | Shareable/Restorable State |
|---|---|---|---|---|---|
| Operations | Requested tenant scope, requested dashboard prefilter, requested navigation context | Active tab, active filters/search, visible run list scope | none | Inspect happens by leaving the page for canonical run detail, not by a second same-page inspect model | Supported tenant prefilter, active tab, compatible filter state, and any explicitly supported navigation context |
| Audit Log | Requested tenant context, requested navigation context, requested event id | Active filters/search and selected event when present | none | `selected event` is the only inline inspect model | Supported filters plus selected event when valid and accessible |
| Finding Exceptions Queue | Requested exception id and any allowed entry context | Active filters plus selected exception workbench state | none | `selected exception` is the only inspect and review model | Supported queue filters plus selected exception when valid and accessible |
| Evidence Overview | Requested tenant filter and search state | Active filters/search and computed overview rows | none | Inspect happens by opening snapshot detail, not by keeping a second same-page selected row state | Supported tenant/search filters only |
| Baseline Compare Landing | Active tenant, baseline profile, requested launch context, navigation context | Visible launch parameters and compare-readiness cues on the landing page | none | Inspect happens by opening the matrix, not by a second same-page compare model | Supported launch context only when valid and accessible |
| Baseline Compare Matrix | Baseline profile launch context, requested focus subject, navigation context, requested compare state from link | Applied compare filters, presentation mode, focused subject, visible matrix results | Pending filter or sort changes before apply | Focused subject or cell state on the matrix page | Applied compare state and documented focus state; unapplied draft state is never shareable |

### Functional Requirements

- **FR-198-001 Surface inventory**: The repo MUST maintain one explicit page-state contract for Operations, Audit Log, Finding Exceptions Queue, Evidence Overview, Baseline Compare Landing, and Baseline Compare Matrix.
- **FR-198-002 State-class declaration**: Each in-scope surface MUST declare which of the five state classes it uses.
- **FR-198-003 Query-role declaration**: Every state that can be provided by route or query input MUST be classified as initialization-only, durable/restorable, scoped deeplink state, or unsupported.
- **FR-198-004 Deterministic hydration**: Entry state from a deeplink, dashboard card, or upstream page MUST hydrate into page state by deterministic precedence rules when remembered or session state also exists.
- **FR-198-005 No competing primary models**: No in-scope surface MAY keep two competing primary models for the same operator function.
- **FR-198-006 Shared monitoring pattern**: Surfaces with comparable interaction shape MUST use compatible inspect, filter, and restoration semantics unless an explicit justified exception is documented.
- **FR-198-007 Operations tab contract**: Operations MUST use one canonical tab and prefilter contract across direct navigation, KPI entry, refresh, back, and share behavior.
- **FR-198-008 Operations entry-state continuity**: Requested tenant or problem-class state on Operations MUST either become the active state or be explicitly discarded; it may not silently drift into an undocumented local-only model.
- **FR-198-009 Audit Log inspect contract**: Audit Log MUST route explicit inspect and `event` deeplink entry through the same selected-event source of truth for open, close, refresh, restoration, and authorization fallback behavior.
- **FR-198-010 Finding Exceptions inspect contract**: Finding Exceptions Queue MUST route row inspection, selected summary, header decision state, and `exception` deeplink entry through one selected-exception source of truth for review, close, refresh, restoration, and authorization fallback behavior.
- **FR-198-011 Inspect-state hierarchy**: Inline detail, summary, or sidebar views MAY coexist with action-triggered inspect only when they are subordinate presentations of the same selected-record inspect state rather than disconnected parallel models.
- **FR-198-012 Inspect-state fallback**: If selected-record inspect state becomes invalid or inaccessible, the surface MUST fall back predictably to the unselected state and clear stale summary, decision, or action state.
- **FR-198-013 Compatible inspect surfaces**: Audit Log and Finding Exceptions Queue MUST share the same or an explicitly compatible inspect vocabulary and operator behavior for selected record, open detail, close detail, refresh, and share behavior.
- **FR-198-014 Filter-mode declaration**: Every in-scope surface MUST classify its filter behavior as directly active, draft-then-apply, or initial-prefilter-only.
- **FR-198-015 Simple monitoring filter contract**: Evidence Overview and comparable simple monitoring pages MUST use the shared prefilter and active-filter contract rather than inventing a page-specific exception.
- **FR-198-016 Reset, clear, and apply semantics**: Reset, clear, and apply actions MUST behave consistently with the documented shareable/restorable state for each surface.
- **FR-198-017 Restorable-state declaration**: Each in-scope surface MUST explicitly define which subset of its page state is recreated by reload, browser back, bookmark, or shared link.
- **FR-198-018 Non-shareable local state**: Any state intentionally kept local-only MUST be explicitly documented and MUST NOT reappear after the page is reopened from a link.
- **FR-198-019 Compare Matrix special case**: Baseline Compare Matrix MAY remain a special-case monitoring surface, but it MUST explicitly model draft compare state, applied compare state, presentation mode, focus/deeplink state, and drilldown semantics.
- **FR-198-020 Compare Matrix draft/apply separation**: Compare Matrix MUST visibly and behaviorally separate draft values from applied results.
- **FR-198-021 Compare Matrix restoration**: Compare Matrix MUST document and test refresh, back, and shared-link behavior separately for applied state, focus state, and non-shareable draft state.
- **FR-198-022 Surface-first implementation**: The implementation MUST remain surface-first and MUST NOT introduce a generic global page-state framework to satisfy this spec.
- **FR-198-023 Shell boundary**: The page-state contract MUST NOT take ownership of workspace-shell or global context behavior. Unresolved shell/context concerns MUST be handed off to Spec 199.
- **FR-198-024 Regression coverage**: Automated tests MUST cover deeplink entry, selected inspect restoration, tab or mode behavior, and filter clear/apply behavior for every in-scope surface.
- **FR-198-025 Manual monitoring-family smoke checks**: Manual smoke checks MUST confirm that deeplink, refresh, back, and share behavior feels compatible across the in-scope surfaces.
- **FR-198-026 Closure documentation**: Final documentation MUST record the state classes, the shareable/restorable subset, the allowed exception if any, and any shell/context handoff for each in-scope surface.
- **FR-198-027 No forced flattening**: Baseline Compare Matrix MUST NOT be reduced to a generic table-style contract purely for uniformity.

### Non-Goals

- Rebuilding the global workspace or tenant shell
- Reworking shared detail micro-UI families already covered elsewhere
- Repeating general Filament nativity cleanup from adjacent specs
- Forcing every monitoring page into the same visual layout type
- Changing existing authorization, audit, or run-lifecycle semantics beyond what state-contract clarity requires

### Assumptions

- Existing authorization, audit logging, and underlying mutation safety on the affected pages are already correct and will be preserved.
- The listed routes and pages remain the canonical monitoring entry points during this spec.
- Additional monitoring surfaces join only if they meet the same page-state criteria and do not pull shell/context ownership into this spec.

### Dependencies

- Existing monitoring pages and route structure in the admin panel remain available.
- Existing tenant-entitlement and record-authorization checks continue to govern drilldowns and selected-record access.
- Spec 199 will absorb any unresolved global shell/context contract issues discovered during implementation.

## UI Action Matrix *(mandatory when Filament is changed)*

| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| Operations | `app/Filament/Pages/Monitoring/Operations.php` | `Return`, `Show all tenants`, `Clear filters` only when applicable | `recordUrl()` via full-row click into canonical run detail | none beyond row open | none | `Show all operations` when prefilter causes an empty result | Run detail page owns its own header actions; Operations stays landing-focused | n/a | no new write in this spec | One inspect model only: leave page for run detail |
| Audit Log | `app/Filament/Pages/Monitoring/AuditLog.php` | `Return`, `Clear filters`, `Close details` when applicable | Explicit `Inspect event` action and matching selected-event deeplink open the same inline detail state | `Inspect event` | none | `Clear filters` | Selected-event detail header may include related navigation, but no second inspect model | n/a | no | Inline detail is allowed because it is the only inspect contract |
| Finding Exceptions Queue | `app/Filament/Pages/Monitoring/FindingExceptionsQueue.php` | `Return`, `Clear filters`, `Close details` when applicable | Explicit `Inspect exception` or matching selected-exception deeplink open the same workbench state | `Inspect exception` | none | `Back to findings` or `Clear filters`, depending on empty state reason | `Approve exception`, `Reject exception`, and related open actions only when a valid selected exception exists | n/a | yes, existing approval or rejection audit behavior remains | Destructive-like decisions stay in the selected-exception lane and require confirmation |
| Evidence Overview | `app/Filament/Pages/Monitoring/EvidenceOverview.php` | `Clear filters` only when applicable | Full-row click opens snapshot detail | none beyond row open | none | `Clear filters` | Snapshot detail page owns its own header semantics | n/a | no | Simple monitoring surface; no separate selected-row inspect state |
| Baseline Compare Landing | `app/Filament/Pages/BaselineCompareLanding.php` | `Return`, `Open compare matrix`, `Clear launch context` only when applicable | Explicit `Open compare matrix` action or deeplink hands off the same launch context | none | none | `Back to tenant overview` or `Clear launch context`, depending on empty-state reason | Matrix page owns compare actions after handoff | n/a | no | Launch context is initialization-only; landing never becomes the applied compare-state owner |
| Baseline Compare Matrix | `app/Filament/Pages/BaselineCompareMatrix.php` | `Return to compare landing`, `Apply filters`, `Reset filters`, `Clear focus` when applicable | Focused subject or cell on the current matrix page is the only primary inspect model | none | none | `Reset filters` or `Back to compare landing`, depending on empty-state reason | Same page owns apply, reset, focus, and downstream drilldown affordances | n/a | no | Approved exception: rich local analysis controls with explicit draft/applied contract |

### Key Entities *(include if feature involves data)*

- **Monitoring Page-State Contract**: The per-surface declaration of contextual prefilter state, active state, draft state, inspect state, shareable/restorable state, and precedence rules.
- **Inspect State**: The selected event, selected exception, or focused compare subject that controls inline detail or focused analysis on a surface.
- **Shareable/Restorable State**: The subset of state intentionally recreated by refresh, browser navigation, bookmark, or shared link.
- **Draft Page State**: A local pending state that is intentionally separate from the currently applied result state.

## Success Criteria *(mandatory)*

### Measurable Outcomes

- **SC-001**: All six in-scope surfaces have a documented contract that identifies every supported state class and whether it is shareable/restorable, with zero undocumented state categories remaining.
- **SC-002**: 100% of scripted deeplink-entry scenarios for the six in-scope surfaces recreate the documented initial state on first load.
- **SC-003**: 100% of scripted refresh, back, and shared-link scenarios across the six in-scope surfaces match the documented restore or discard behavior with no stale selected-record state.
- **SC-004**: Audit Log and Finding Exceptions Queue each expose exactly one operator-understandable inspect model in automated and manual verification, with no competing primary inspect behavior remaining.
- **SC-005**: 100% of scripted Operations tab or prefilter scenarios and Compare Matrix draft/apply scenarios behave according to the documented contract without silent state drift.

## Closure Notes

### Final State Mapping

| Surface | Implemented shareable/restorable state | Implemented local-only or discarded state |
|---|---|---|
| Operations | Entitled `tenant_id`, `activeTab`, supported navigation context, compatible table filters/search restored from session | Unsupported or unauthorized tenant prefilters are discarded to the active entitled scope; no same-page inspect state exists |
| Audit Log | Supported table filters/search and `event` when the selected record remains visible and authorized | Invalid, unauthorized, or filtered-out `event` state is discarded to the unselected history view |
| Finding Exceptions Queue | Supported queue filters and `exception` when the selected request remains visible and authorized | Invalid, unauthorized, or filtered-out `exception` state is discarded to quiet monitoring mode |
| Evidence Overview | Supported tenant/search filters on the canonical overview route | Cleared filters do not repopulate hidden local state after redirect back to the canonical overview route |
| Baseline Compare Landing | Launch-context handoff into the compare matrix when the profile and tenant context are valid | Landing-page context never becomes the owner of applied compare results |
| Baseline Compare Matrix | Applied compare filters, requested presentation mode, and focused subject carried by the matrix URL | Unapplied draft filter changes remain local and are discarded on reopen or refresh |

### Verification Summary

- Focused feature pack passed: `77` tests, `468` assertions.
- Spec 198 browser smoke passed: `2` tests, `25` assertions.
- No-regression browser smokes passed: `5` tests, `80` assertions across Spec 190 and Spec 194.

### Spec 199 Handoff Notes

- This implementation intentionally stops at page-owned hydration and restore rules. Workspace-shell and global tenant-context ownership remain outside this spec.
- Remembered workspace or tenant context may still influence entry state before a page hydrates, but this spec does not redefine that shell-level contract.
- No global page-state framework, provider registration change, or new persistence layer was introduced. Any future cross-shell normalization belongs to Spec 199.
