## Summary - add a shared diff presentation layer under `app/Support/Diff` with deterministic row classification, summary derivation, and value stringification - centralize diff-state badge semantics through `BadgeCatalog` with a dedicated `DiffRowStatusBadge` - add reusable Filament diff partials, focused Pest coverage, and the full SpecKit artifact set for spec 141 ## Testing - `vendor/bin/sail artisan test --compact tests/Unit/Support/Diff/DiffRowStatusTest.php tests/Unit/Support/Diff/DiffRowTest.php tests/Unit/Support/Diff/DiffPresenterTest.php tests/Unit/Support/Diff/ValueStringifierTest.php tests/Unit/Badges/DiffRowStatusBadgeTest.php tests/Feature/Support/Diff/SharedDiffSummaryPartialTest.php tests/Feature/Support/Diff/SharedDiffRowPartialTest.php tests/Feature/Support/Diff/SharedInlineListDiffPartialTest.php` - `vendor/bin/sail bin pint --dirty --format agent` ## Filament / Livewire Contract - Livewire v4.0+ compliance: unchanged and respected; this feature adds presentation support only within the existing Filament v5 / Livewire v4 stack - Provider registration: unchanged; no panel/provider changes were required, so `bootstrap/providers.php` remains the correct registration location - Global search: unchanged; no Resource or global-search behavior was added or modified - Destructive actions: none introduced in this feature - Asset strategy: no new registered Filament assets; shared Blade partials rely on the existing asset pipeline and standard deploy step for `php artisan filament:assets` when assets change generally - Testing coverage: presenter, DTOs, stringifier, badge semantics, summary partial, row partial, and inline-list partial are covered by focused Pest unit and feature tests ## Notes - Spec checklist status is complete for `specs/141-shared-diff-presentation-foundation/checklists/requirements.md` - This PR preserves specialized diff renderers and documents incremental adoption rather than forcing migration in the same change Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #170
122 lines
11 KiB
Markdown
122 lines
11 KiB
Markdown
title + explanation + exactly 1 CTA, and tables provide search/sort/filters for core dimensions.
|
|
# Feature Specification: Shared Diff Presentation Foundation
|
|
|
|
**Feature Branch**: `141-shared-diff-presentation-foundation`
|
|
**Created**: 2026-03-14
|
|
**Status**: Draft
|
|
**Input**: User description: "Introduce a small reusable diff presentation foundation for TenantPilot so diff UIs across findings, baseline/drift, policy compare, and future evidence screens can share consistent change states, summary badges, list diff rendering, and value formatting without building a full generic diff framework or refactoring all existing diff views at once."
|
|
|
|
## Spec Scope Fields *(mandatory)*
|
|
|
|
- **Scope**: workspace
|
|
- **Primary Routes**: Existing diff-capable admin and workspace comparison surfaces may consume the foundation over time; this spec introduces no new routes.
|
|
- **Data Ownership**: Existing findings, baseline comparisons, restore previews, policy comparisons, and related comparison payloads remain owned by their current domain services and records. This feature introduces presentation-only shared assets and does not create or persist new business data.
|
|
- **RBAC**: Existing membership and capability checks remain unchanged. The foundation only renders data already authorized by consuming surfaces and must not widen visibility.
|
|
|
|
## User Scenarios & Testing *(mandatory)*
|
|
|
|
### User Story 1 - Review Changes Consistently (Priority: P1)
|
|
|
|
An operator reviewing a supported compare surface can immediately tell which values were added, removed, changed, or left unchanged because every adopting surface uses the same shared presentation language.
|
|
|
|
**Why this priority**: Consistent change semantics are the core value of the feature. Without them, every compare view continues to create operator confusion and duplicate UI decisions.
|
|
|
|
**Independent Test**: Can be fully tested by rendering representative compare inputs that contain all four change states and verifying that summary counts and detailed rows express the same states consistently.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a compare result with added, removed, changed, and unchanged values, **When** an adopting surface renders the result, **Then** each state is presented using the same shared labels and visual semantics.
|
|
2. **Given** a compare result with no differences, **When** an adopting surface renders the result, **Then** the summary and row presentation clearly communicate that no changes were found.
|
|
|
|
---
|
|
|
|
### User Story 2 - Scan Diff Details Efficiently (Priority: P2)
|
|
|
|
An operator can move from high-level summary counts to row-level details without re-learning each screen's visual language, and unchanged content remains quieter than meaningful changes.
|
|
|
|
**Why this priority**: After consistent change states exist, the next highest value is faster review of the data that actually changed.
|
|
|
|
**Independent Test**: Can be tested by rendering summary and row views for mixed compare data and confirming that changed content is visually distinct, unchanged content is de-emphasized, and list-style differences remain readable.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a compare result with many unchanged values and a small number of differences, **When** the rows are rendered, **Then** changed content receives stronger emphasis than unchanged content.
|
|
2. **Given** a compare result that includes simple lists, **When** the list detail is rendered, **Then** added and removed items are clearly distinguishable without requiring raw side-by-side inspection.
|
|
|
|
---
|
|
|
|
### User Story 3 - Adopt the Foundation Incrementally (Priority: P3)
|
|
|
|
A product team adding or upgrading a simple compare surface can reuse the shared presentation foundation without being forced to migrate unrelated or specialized diff views at the same time.
|
|
|
|
**Why this priority**: Incremental adoption reduces delivery risk and avoids forcing highly specialized compare experiences into an overgeneralized model.
|
|
|
|
**Independent Test**: Can be tested by validating that the foundation supports simple structured compare inputs while leaving existing specialized diff screens unchanged unless a follow-up feature chooses to adopt it.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** an existing specialized diff screen outside the adoption scope, **When** this feature is delivered, **Then** that screen remains unchanged and operational.
|
|
2. **Given** a future simple compare surface, **When** it adopts the foundation, **Then** it can use shared summary, row, and value presentation behavior without changing underlying comparison ownership.
|
|
|
|
### Edge Cases
|
|
|
|
- What happens when both sides of a compare input are empty or absent? The foundation must provide a clear no-differences or no-data outcome without rendering misleading change states.
|
|
- How does the system handle missing values versus explicit empty values? The foundation must keep these cases distinguishable where that distinction matters to operator review.
|
|
- What happens when values include mixed types such as nulls, booleans, scalars, lists, or compact structured objects? The foundation must render them deterministically using one shared display vocabulary.
|
|
- How does the system handle long but still simple lists? The foundation must keep added and removed items readable without depending on heavy client-side behavior.
|
|
|
|
## Requirements *(mandatory)*
|
|
|
|
This feature is presentation-only. It introduces no Microsoft Graph calls, no write workflow, no queued or scheduled work, no OperationRun usage, and no new authorization rules.
|
|
|
|
This feature does not add or modify a Filament Resource, RelationManager, or Page action surface. It provides reusable presentation primitives that future consumer specs may adopt. Any later consumer spec that changes actions or page layouts must supply its own UI Action Matrix and UX-001 review.
|
|
|
|
### Functional Requirements
|
|
|
|
- **FR-001**: The system MUST define one shared change-state vocabulary for supported diff presentation consisting of changed, unchanged, added, and removed.
|
|
- **FR-002**: The system MUST apply that shared vocabulary consistently to both summary presentation and row-level detail presentation.
|
|
- **FR-003**: The system MUST provide a reusable row-oriented presentation model that can represent a field label, a change state, prior and current values, and optional list-oriented detail needed for simple add/remove display.
|
|
- **FR-004**: The system MUST keep the row-oriented presentation model read-only after construction so consumers receive deterministic output.
|
|
- **FR-005**: The system MUST provide a stateless presentation adapter that converts simple structured compare inputs into a deterministic sequence of row presentations.
|
|
- **FR-006**: The presentation adapter MUST support unchanged rows, changed rows, added-only rows, and removed-only rows.
|
|
- **FR-007**: The presentation adapter MUST remain presentation-focused and MUST NOT become the authoritative source of business comparison, drift, restore, or baseline rules.
|
|
- **FR-008**: The system MUST provide one shared value-display policy for null values, booleans, scalars, simple lists, and compact structured values used in supported compare views.
|
|
- **FR-009**: The shared value-display policy MUST avoid ad hoc stringification rules inside individual templates.
|
|
- **FR-010**: The system MUST provide reusable summary presentation that can show counts for changed, added, removed, and unchanged states, including a clear fallback for empty or unavailable summary data.
|
|
- **FR-011**: The system MUST provide reusable row presentation primitives for changed, unchanged, added, and removed states without forcing every consumer into one full-page layout.
|
|
- **FR-012**: The system MUST support simple inline list diff presentation that makes added and removed items explicit and allows unchanged items to appear in a quieter style when shown.
|
|
- **FR-013**: The system MUST express change states using more than color alone so supported diff views remain understandable for operators using assistive technologies or low-contrast conditions.
|
|
- **FR-014**: The system MUST preserve legibility in light and dark themes for all shared diff state treatments.
|
|
- **FR-015**: The system MUST preserve logical reading order and meaningful labeling so row content remains understandable to screen readers and keyboard-only users.
|
|
- **FR-016**: The system MUST be adoptable incrementally by future compare surfaces without requiring all existing diff screens to migrate in this feature.
|
|
- **FR-017**: The system MUST leave existing specialized compare experiences unchanged unless a later feature explicitly opts them into the shared foundation.
|
|
- **FR-018**: The system MUST include developer guidance that explains when to use the shared foundation and when a specialized diff view should remain specialized.
|
|
|
|
## UI Action Matrix *(mandatory when Filament is changed)*
|
|
|
|
Not applicable for this feature. The foundation introduces shared rendering assets only and does not add or modify a specific Filament Resource, RelationManager, or Page action surface.
|
|
|
|
### Key Entities *(include if feature involves data)*
|
|
|
|
- **Diff Presentation State**: The user-facing classification that tells an operator whether a value is changed, unchanged, added, or removed.
|
|
- **Diff Presentation Row**: A render-ready representation of one reviewed field or item, including its label, current state, and the values needed to explain the comparison.
|
|
- **Diff Summary**: A compact count-based overview of how many rows fall into each shared presentation state.
|
|
- **Structured Compare Input**: Existing before-and-after data already produced by a consumer surface and adapted into the shared presentation model without changing business ownership.
|
|
|
|
## Assumptions
|
|
|
|
- Existing compare-producing services already provide enough structured data for simple field and list comparisons, even if their internal shapes differ.
|
|
- Highly specialized diff experiences can continue using custom rendering where simple row-based presentation would reduce clarity.
|
|
- Consumer adoption will happen in follow-up features rather than as a mandatory migration in this specification.
|
|
- Existing authorization and tenant isolation remain the responsibility of the consuming surface, not the shared presentation foundation.
|
|
|
|
## Success Criteria *(mandatory)*
|
|
|
|
### Measurable Outcomes
|
|
|
|
- **SC-001**: In acceptance review with representative compare inputs, 100% of supported shared diff presentations express added, removed, changed, and unchanged states using one consistent vocabulary in both summary and detail views.
|
|
- **SC-002**: In acceptance review with representative mixed compare inputs, summary counts match the detailed rows for every shared diff state with no mismatches.
|
|
- **SC-003**: Operators reviewing a supported simple diff can distinguish change state without relying on color alone in all acceptance scenarios.
|
|
- **SC-004**: Supported simple list comparisons with up to 25 items remain readable enough for an operator to identify added and removed entries without switching to a raw payload view.
|
|
- **SC-005**: Follow-up simple compare features can adopt the shared presentation foundation without redefining state labels, summary vocabulary, or value-display rules.
|