TenantAtlas/specs/162-baseline-gap-details/plan.md
ahmido 7d4d607475 feat: add baseline gap details surfaces (#192)
## Summary
- add baseline compare evidence gap detail modeling and a dedicated Livewire table surface
- extend baseline compare landing and operation run detail surfaces to expose evidence gap details and stats
- add spec artifacts for feature 162 and expand feature coverage with focused Filament and baseline tests

## Notes
- branch: `162-baseline-gap-details`
- commit: `a92dd812`
- working tree was clean after push

## Validation
- tests were not run in this step

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #192
2026-03-24 19:05:23 +00:00

140 lines
9.4 KiB
Markdown

# Implementation Plan: Enterprise Evidence Gap Details for Baseline Compare
**Branch**: `162-baseline-gap-details` | **Date**: 2026-03-24 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/162-baseline-gap-details/spec.md`
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/162-baseline-gap-details/spec.md`
## Summary
Expose baseline compare evidence gaps as an operator-first, searchable, tenant-safe detail experience backed by immutable `OperationRun.context` data. The implementation keeps compare execution and `OperationRun` lifecycle unchanged, persists bounded per-reason subject details during compare/capture work, renders them in the canonical run-detail and tenant compare surfaces ahead of raw JSON diagnostics, and validates the behavior with Pest feature coverage for persistence, rendering, and legacy-run fallbacks.
## Technical Context
**Language/Version**: PHP 8.4 / Laravel 12, Blade, Alpine via Filament, Tailwind CSS v4
**Primary Dependencies**: Filament v5, Livewire v4, Pest v4, Laravel Sail, existing `OperationRun` and baseline compare services
**Storage**: PostgreSQL with JSONB-backed `operation_runs.context`; no new tables required
**Testing**: Pest feature tests run through Sail, plus existing Filament page rendering tests
**Target Platform**: Laravel web application in Sail locally and Linux container deployment in staging/production
**Project Type**: Web application
**Performance Goals**: DB-only render path; no render-time Graph calls; searchable gap detail remains usable for bounded per-reason subject lists; operator can isolate a relevant subject in under 30 seconds
**Constraints**: Preserve `OperationRunService` ownership of status/outcome, keep evidence-gap JSON bounded by existing caps, retain tenant-safe canonical monitoring behavior, add no destructive actions, and avoid new global/published Filament assets
**Scale/Scope**: Tenant-scoped baseline compare runs for enterprise tenants, subject-detail persistence within the existing compare job/capture pipeline, read-only UX changes across the canonical run detail and tenant baseline compare landing surfaces
## Constitution Check
*GATE: Passed before Phase 0 research. Re-checked after Phase 1 design and still passing.*
- Inventory-first: Pass. This feature reads existing inventory and baseline snapshot outputs and only improves how compare gaps are persisted and presented.
- Read/write separation: Pass. Compare initiation remains unchanged; the new surface is read-only and introduces no new mutation path.
- Graph contract path: Pass. No new Graph calls or contract bypasses are introduced; all render behavior remains DB-only.
- Deterministic capabilities: Pass. No new capability derivation is introduced.
- RBAC-UX plane separation and tenant safety: Pass. Canonical `/admin/operations/{run}` remains tenant-safe through existing workspace + tenant entitlement checks, and tenant landing remains tenant-scoped.
- Workspace isolation: Pass. No workspace-context semantics are broadened.
- Destructive confirmation: Pass. No destructive action is added or changed.
- Global search safety: Pass. No global-search behavior is introduced or modified.
- Tenant isolation: Pass. Evidence-gap detail is persisted on the tenant-owned `OperationRun` and revealed only through already authorized run/tenant surfaces.
- Run observability: Pass. Existing baseline compare `OperationRun` behavior stays intact; this feature enriches context only.
- Ops-UX 3-surface feedback: Pass. No additional toasts, progress surfaces, or terminal notifications are introduced.
- Ops-UX lifecycle ownership: Pass. `status`/`outcome` transitions remain service-owned; only `context` payload content is extended.
- Ops-UX summary counts: Pass. No new `summary_counts` keys are added.
- Ops-UX guards and system-run rules: Pass. Existing monitoring and notification invariants remain untouched.
- Automation/backoff: Pass. Existing capture-phase retry/backoff behavior remains the only throttling mechanism in scope.
- Data minimization: Pass. Persisted detail is bounded, operator-safe subject identity rather than raw payload dumps or secrets.
- Badge semantics: Pass. Existing run outcome/trust badges remain centralized; evidence-gap detail is plain text/searchable rows.
- UI naming: Pass. The operator copy uses domain terms such as `Evidence gap details`, `Policy type`, and `Subject key`.
- Operator surfaces: Pass. Outcome and trust stay ahead of diagnostics, and the detail section is secondary to result meaning.
- Filament Action Surface Contract: Pass. The change is read-only and does not alter header/row/bulk/destructive semantics.
- UX-001 Layout and IA: Pass. The detail stays sectioned and readable within the existing enterprise detail layout.
- Filament v5 / Livewire v4 compliance: Pass. The feature remains within the existing Filament v5 + Livewire v4 stack.
- Provider registration location: Pass. No panel provider changes are required; Laravel 11+ registration remains in `bootstrap/providers.php`.
- Global search hard rule: Pass. No resource searchability changes are required.
- Asset strategy: Pass. The design relies on existing Filament/Blade/Alpine capabilities and does not require new published or on-demand assets.
## Phase 0 Research
Research outcomes are captured in `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/162-baseline-gap-details/research.md`.
Key decisions:
- Persist subject-level evidence gaps as an immutable read model under `baseline_compare.evidence_gaps.subjects` inside `OperationRun.context`.
- Merge subject detail from all compare evidence-gap sources: ambiguous inventory matches, capture-phase failures, and drift-time missing evidence.
- Keep filtering local to the rendered detail section because the stored dataset is intentionally bounded and render-time network/database chatter would add unnecessary complexity.
- Preserve operator-first reading order: result meaning and trust first, evidence-gap detail second, raw JSON last.
- Treat legacy runs with counts but no recorded subjects as a first-class fallback state rather than as empty/healthy runs.
## Phase 1 Design
Design artifacts are created under `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/162-baseline-gap-details/`:
- `data-model.md`: JSONB-backed read-model contract and derived UI row shape.
- `contracts/baseline-gap-details.openapi.yaml`: internal reference schema for the shared evidence-gap read model used by both operator surfaces; it is not a commitment to add new HTTP endpoints in this slice.
- `quickstart.md`: verification path covering focused tests, tenant-safety checks, render-safety checks, local run review, and legacy-run fallback checks.
Design decisions:
- No schema migration is required; the durable contract is an extension of the existing JSONB payload.
- The canonical record remains `OperationRun`; no separate evidence-gap table or Eloquent model is introduced.
- Filtering is modeled as reason/policy-type/subject-key matching over persisted row data in the page surface, not via new server-side filtering endpoints in this slice.
- Tenant landing and canonical run detail must consume semantically identical evidence-gap groupings and preserve operator-first summary ordering ahead of diagnostics.
- Regression coverage must explicitly prove tenant-safe access semantics and the no-external-calls-on-render rule on both affected surfaces.
## Project Structure
### Documentation (this feature)
```text
specs/162-baseline-gap-details/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│ └── baseline-gap-details.openapi.yaml
└── tasks.md
```
### Source Code (repository root)
```text
app/
├── Filament/
│ └── Resources/
│ └── OperationRunResource.php
├── Jobs/
│ └── CompareBaselineToTenantJob.php
├── Models/
│ └── OperationRun.php
└── Services/
└── Baselines/
└── BaselineContentCapturePhase.php
resources/
└── views/
└── filament/
└── infolists/
└── entries/
└── evidence-gap-subjects.blade.php
tests/
└── Feature/
├── Baselines/
│ ├── BaselineCompareAmbiguousMatchGapTest.php
│ └── BaselineCompareResumeTokenTest.php
└── Filament/
└── OperationRunEnterpriseDetailPageTest.php
```
**Structure Decision**: Single Laravel web application. The feature stays inside the existing baseline compare pipeline, `OperationRun` read model, Filament resource rendering, Blade view composition, and Pest feature-test layout.
## Implementation Strategy
1. Normalize and persist subject-level gap detail in the compare/capture pipeline while preserving bounded payload size and legacy compare semantics.
2. Render the evidence-gap detail section from `OperationRun.context` on canonical run detail and keep the tenant landing semantics aligned.
3. Support operator filtering across reason, policy type, and subject key without introducing a new server-side search endpoint in the first implementation.
4. Keep operator-first summary content ahead of diagnostics on both the canonical run detail and tenant landing surfaces.
5. Add regression coverage for new-run persistence, tenant-safe access semantics, render-safety, UI visibility, and legacy/no-detail behavior.
## Complexity Tracking
No constitution violations or justified complexity exceptions were identified.