TenantAtlas/specs/166-finding-governance-health/research.md
ahmido 55aef627aa feat: harden finding governance health surfaces (#197)
## Summary
- harden findings and finding-exception Filament surfaces so workflow state, governance validity, overdue urgency, and next action are operator-first
- add tenant stats widgets, segmented tabs, richer governance warnings, and baseline/dashboard attention propagation for overdue and lapsed governance states
- add Spec 166 artifacts plus regression coverage for findings, badges, baseline summaries, tenantless operation viewer behavior, and critical table standards

## Verification
- `vendor/bin/sail bin pint --dirty --format agent`
- `vendor/bin/sail artisan test --compact`

## Filament Notes
- Livewire v4.0+ compliance: yes, implementation stays on Filament v5 / Livewire v4 APIs only
- Provider registration: unchanged, Laravel 12 panel/provider registration remains in `bootstrap/providers.php`
- Global search: unchanged in this slice; `FindingExceptionResource` stays not globally searchable, no new globally searchable resource was introduced
- Destructive actions: existing revoke/reject/approve/renew/workflow mutations remain capability-gated and confirmation-gated where already defined
- Asset strategy: no new assets added; existing deploy process remains unchanged, including `php artisan filament:assets` when registered assets are used
- Testing plan delivered: findings list/detail, exception register, dashboard attention, baseline summary, badge semantics, and tenantless operation viewer coverage

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #197
2026-03-28 10:11:12 +00:00

61 lines
5.8 KiB
Markdown

# Research: Finding Governance Health & Resolution Semantics Surface Hardening
## Decision 1: Reuse existing governance truth instead of introducing a new semantic layer
**Decision**: Drive surface hardening from existing `Finding.status`, `FindingException.current_validity_state`, `FindingRiskGovernanceResolver`, and centralized badge domains rather than introducing a new persisted governance-health field or a presenter framework.
**Rationale**: The codebase already distinguishes valid, expiring, expired, revoked, rejected, and missing-support governance states, and it already exposes warning messages through `FindingRiskGovernanceResolver`. The operator problem is primarily under-communication on major surfaces, not missing underlying truth. Reusing the current truth sources satisfies the constitution's proportionality and no-new-layer constraints.
**Alternatives considered**:
- Add a new stored `governance_health` field on findings: rejected because it would duplicate exception truth and require sync logic.
- Introduce a new presenter or explanation framework: rejected because this slice needs clearer surfaces, not another interpretation layer.
## Decision 2: Keep workflow lifecycle and governance validity as separate visible dimensions
**Decision**: Findings surfaces should show workflow lifecycle and governance validity as distinct operator-visible dimensions instead of collapsing them into a single synthetic super-status.
**Rationale**: A finding can be `risk_accepted` while governance is healthy, expiring, expired, revoked, or unsupported. A finding can also be `resolved` without proving permanent remediation. Separating lifecycle from governance validity prevents false calm and matches the constitution rule that distinct status dimensions should stay distinct when they matter.
**Alternatives considered**:
- Replace current states with one combined surface enum such as `accepted-risk-warning`: rejected because it would blur workflow truth and governance truth together.
- Leave lifecycle badges unchanged and hide governance only in detail: rejected because the list and summary surfaces are where prioritization happens.
## Decision 3: Harden finding detail by reordering existing infolist truth into a leading status zone
**Decision**: Implement the detail-page change as a leading status and governance zone built from existing infolist data, leaving raw identifiers, run links, diffs, and evidence in secondary sections.
**Rationale**: The current finding detail already contains most of the required truth, including status, severity, due date, owner, assignee, and risk-governance entries. The main change needed is information hierarchy. Reordering existing truth is narrower and safer than introducing a new detail-specific read model.
**Alternatives considered**:
- Build a separate read model or DTO for the view page: rejected because the current infolist already has the required fields.
- Leave the current section order and add more warnings lower on the page: rejected because it does not solve the 5 to 10 second operator-read requirement.
## Decision 4: Propagate governance attention to summary surfaces through existing DB-backed widget queries
**Decision**: Extend current tenant summary surfaces such as `NeedsAttention` and baseline-compare summary outputs with DB-backed aggregates for overdue findings, lapsed governance, and expiring governance instead of adding background jobs or a new tenant-governance dashboard.
**Rationale**: The dashboard widget and baseline-compare landing already compute DB-backed summaries without external calls. Adding a small set of operator-critical aggregates keeps these surfaces honest while preserving their glance-first character and avoiding a new subsystem.
**Alternatives considered**:
- Add scheduled reminder jobs or alerting in this slice: rejected because the spec explicitly leaves proactive automation to a follow-up spec.
- Create a dedicated governance-health dashboard: rejected because the current scope is surface hardening, not a new reporting domain.
## Decision 5: Communicate `resolved` and `closed` cautiously, with optional secondary observation context
**Decision**: Treat `resolved` and `closed` as historical workflow states in primary UI language, and only show `no longer observed` or similar context as secondary explanatory information when it can be derived from current truth.
**Rationale**: The spec's central risk is that operators may read `resolved` as technical proof. The safest narrow fix is copy and layout: make workflow meaning explicit and reserve any observation-based explanation for clearly secondary context.
**Alternatives considered**:
- Reinterpret `resolved` as `no longer observed` everywhere: rejected because it rewrites current workflow truth.
- Add a new persistence field to separate resolution origin immediately: rejected because the spec explicitly defers that to a follow-up if needed.
## Decision 6: Anchor testing in existing Livewire, Filament, Findings, and Badge suites
**Decision**: Extend the current Pest suites for findings list, finding detail, exception register, exception queue, dashboard widgets, baseline-compare summary, evidence integration, and badge semantics rather than creating a new presentation-only test framework.
**Rationale**: The repository already has strong coverage anchors for findings workflow, governance projection, exception lifecycle, needs-attention widgets, and baseline-compare explanation surfaces. Cross-surface consistency can be enforced most efficiently by extending those suites with operator-truth assertions.
**Alternatives considered**:
- Add screenshot-heavy UI snapshot coverage as the main protection: rejected because the business truth is semantic distinction, not pixel fidelity.
- Test a new intermediate presenter layer: rejected because the plan intentionally avoids creating one.