TenantAtlas/specs/130-structured-snapshot-rendering/plan.md
ahmido 3c445709af feat: add structured baseline snapshot rendering (#158)
## Summary
- replace the baseline snapshot detail page with a structured summary-first rendering flow
- add a presenter plus renderer registry with RBAC, compliance, and fallback renderers
- add grouped policy-type browsing, fidelity and gap badges, and workspace authorization coverage
- add Feature 130 spec, plan, contract, research, quickstart, and completed task artifacts

## Testing
- focused Pest coverage was added for structured rendering, fallback behavior, degraded states, authorization, presenter logic, renderer resolution, and badge mapping
- I did not rerun the full validation suite in this final PR step

## Notes
- base branch: `dev`
- feature branch: `130-structured-snapshot-rendering`

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

18 KiB
Raw Permalink Blame History

Implementation Plan: Structured Snapshot Rendering & Type-Agnostic Item Browser

Branch: 130-structured-snapshot-rendering | Date: 2026-03-09 | Spec: spec.md Input: Feature specification from /specs/130-structured-snapshot-rendering/spec.md

Note: This template is filled in by the /speckit.plan command. See .specify/scripts/ for helper scripts.

Summary

Replace the current Baseline Snapshot detail experience, which mixes a raw summary JSON block with an RBAC-only repeatable section, with a normalized presenter-driven view that renders every captured policy type through a shared summary-first inspection model. Keep the feature workspace-scoped and read-only, introduce a BaselineSnapshotPresenter plus a type-renderer registry and fallback renderer, preserve richer RBAC detail as an enrichment layer rather than a privileged exception, add initial structured compliance rendering for deviceCompliancePolicy, and deliver the UI through sectioned Filament infolist entries backed by focused feature and unit tests.

Technical Context

Language/Version: PHP 8.4.15 / Laravel 12
Primary Dependencies: Filament v5, Livewire v4.0+, Tailwind CSS v4
Storage: PostgreSQL via Laravel Sail using existing baseline_snapshots, baseline_snapshot_items, and JSONB presentation source fields
Testing: Pest v4 feature and unit tests on PHPUnit 12
Target Platform: Laravel Sail web application with workspace-scoped admin panel at /admin Project Type: Laravel monolith / Filament web application
Performance Goals: Snapshot detail remains DB-only at render time, snapshot items are eager-loaded once per page render, groups are collapsed by default for large snapshots, and technical payload disclosure remains secondary and bounded
Constraints: No schema changes; no Microsoft Graph calls; preserve immutable snapshot semantics; preserve workspace-scoped authorization and 404/403 semantics on both list and detail routes; keep raw JSON non-primary; isolate per-group rendering failures; use centralized badge semantics for fidelity and gap states; keep technical detail optional and scope-safe
Scale/Scope: One existing Filament resource detail surface, one new presenter and renderer registry layer, fallback plus initial RBAC and device-compliance enrichments, a small set of Blade infolist entry components, and focused regression tests

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

  • Inventory-first: PASS — this feature consumes existing immutable snapshot artifacts for inspection and does not alter inventory versus snapshot ownership or semantics.
  • Read/write separation: PASS — the redesign is read-only and introduces no mutation flow, restore action, or audit-triggering write path.
  • Graph contract path: PASS — no Microsoft Graph call is added.
  • Deterministic capabilities: PASS — authorization continues to rely on the existing workspace capability registry and resolver with no raw capability strings.
  • RBAC-UX planes and isolation: PASS — the feature stays in the /admin workspace plane, keeps /system untouched, and preserves deny-as-not-found for non-members plus protected in-scope access semantics.
  • Workspace isolation: PASS — snapshot detail remains bound to the active workspace context and existing workspace membership checks.
  • RBAC-UX destructive confirmation: PASS / N/A — no destructive or mutation action is introduced.
  • RBAC-UX global search: PASS — the resource remains non-globally-searchable, so global-search semantics do not change.
  • Tenant isolation: PASS — no tenant-scoped read or cross-tenant aggregation is introduced.
  • Run observability: PASS / N/A — no new OperationRun or long-running workflow is introduced.
  • Ops-UX 3-surface feedback: PASS / N/A — no operation lifecycle change is involved.
  • Ops-UX lifecycle and summary counts: PASS / N/A — no OperationRun transitions or summary producers are added.
  • Ops-UX guards and system runs: PASS / N/A — existing operations behavior is unaffected.
  • Automation: PASS / N/A — no queued or scheduled behavior changes are required.
  • Data minimization: PASS — the page uses existing workspace-safe snapshot metadata and technical payload disclosure stays secondary.
  • Badge semantics (BADGE-001): PASS — fidelity and gap states will be added through centralized badge semantics rather than inline color mapping.
  • Filament UI Action Surface Contract: PASS — the feature modifies a view-only resource detail surface, keeps the immutable-resource exemptions already declared on the resource, and upgrades the list inspection affordance from a lone View row action to clickable rows or a primary linked column so the modified surface matches the constitution.
  • Filament UI UX-001: PASS — the design remains a sectioned infolist-style detail view with metadata, summary, grouped browser, and technical disclosure sections.
  • Filament v5 / Livewire v4 compliance: PASS — the design stays inside the existing Filament v5 and Livewire v4 admin panel.
  • Provider registration (bootstrap/providers.php): PASS — no panel provider change is introduced.
  • Global search resource rule: PASS — the resource remains not globally searchable, so the Edit/View global-search rule is unaffected.
  • Asset strategy: PASS — no new heavy asset bundle is required; existing deploy-time php artisan filament:assets behavior remains sufficient.

Project Structure

Documentation (this feature)

specs/130-structured-snapshot-rendering/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│   └── baseline-snapshot-rendering.openapi.yaml
├── checklists/
│   └── requirements.md
└── tasks.md

Source Code (repository root)

app/
├── Filament/
│   └── Resources/
│       ├── BaselineSnapshotResource.php                         # MODIFY — replace raw summary primary UX
│       └── BaselineSnapshotResource/
│           └── Pages/
│               └── ViewBaselineSnapshot.php                     # MODIFY if page-level composition or eager-loading is needed
├── Services/
│   └── Baselines/
│       └── SnapshotRendering/
│           ├── BaselineSnapshotPresenter.php                    # NEW page-level builder
│           ├── SnapshotTypeRenderer.php                         # NEW renderer contract
│           ├── SnapshotTypeRendererRegistry.php                 # NEW registry/fallback resolution
│           ├── RenderedSnapshot.php                             # NEW normalized summary DTO
│           ├── RenderedSnapshotGroup.php                        # NEW group DTO
│           ├── RenderedSnapshotItem.php                         # NEW item DTO
│           ├── FidelityState.php                                # NEW fidelity enum/value object
│           ├── GapSummary.php                                   # NEW gap summary value object
│           └── Renderers/
│               ├── FallbackSnapshotTypeRenderer.php             # NEW minimum-contract renderer
│               ├── IntuneRoleDefinitionSnapshotTypeRenderer.php # NEW extracted RBAC renderer
│               └── DeviceComplianceSnapshotTypeRenderer.php     # NEW initial compliance renderer
└── Support/
  └── Badges/
    ├── BadgeDomain.php                                      # MODIFY if new fidelity/gap domains are introduced
    └── Domains/                                             # NEW badge mapper(s) if fidelity/gap become centralized domains
resources/
└── views/
  └── filament/
    └── infolists/
      └── entries/
        ├── baseline-snapshot-summary-table.blade.php    # NEW summary-first rendering block
        ├── baseline-snapshot-groups.blade.php           # NEW grouped browser with collapsed sections
        ├── baseline-snapshot-technical-detail.blade.php # NEW secondary technical disclosure
        └── snapshot-json.blade.php                      # MODIFY or reduce prominence if retained via partial reuse
tests/
├── Feature/
│   └── Filament/
│       ├── BaselineSnapshotFidelityVisibilityTest.php           # MODIFY existing assertions for structured UI
│       ├── BaselineSnapshotStructuredRenderingTest.php          # NEW mixed-type summary and grouped browser coverage
│       ├── BaselineSnapshotFallbackRenderingTest.php            # NEW unknown-type fallback coverage
│       ├── BaselineSnapshotAuthorizationTest.php                # NEW or MODIFY positive/negative workspace access coverage
│       └── BaselineSnapshotDegradedStateTest.php                # NEW fidelity/gap and failure-isolation coverage
└── Unit/
  └── Baselines/
    └── SnapshotRendering/
      ├── BaselineSnapshotPresenterTest.php                # NEW presenter/group aggregation coverage
      ├── SnapshotTypeRendererRegistryTest.php             # NEW registry resolution coverage
      ├── FallbackSnapshotTypeRendererTest.php             # NEW minimum-contract coverage
      ├── IntuneRoleDefinitionSnapshotTypeRendererTest.php # NEW RBAC contract compliance coverage
      └── DeviceComplianceSnapshotTypeRendererTest.php     # NEW compliance rendering coverage

Structure Decision: Keep the feature inside the existing Laravel/Filament monolith. The implementation centers on the existing BaselineSnapshotResource view surface, a new snapshot-rendering service layer under app/Services/Baselines, small Blade infolist entry components for summary and grouped rendering, and focused Pest feature and unit tests.

Complexity Tracking

No Constitution Check violations. No justifications needed.

Violation Why Needed Simpler Alternative Rejected Because

Phase 0 — Research (DONE)

Output:

  • specs/130-structured-snapshot-rendering/research.md

Key findings captured:

  • Current snapshot detail uses a raw JSON summary block plus an RBAC-only repeatable section, so the shared abstraction does not exist yet.
  • BaselineSnapshot.summary_jsonb already provides snapshot-level counts by policy type, fidelity counts, and gap counts suitable for a summary-first page.
  • BaselineSnapshotItem.meta_jsonb already provides a deterministic minimum metadata shape that supports a fallback renderer for all policy types.
  • Existing repo patterns favor registry or normalizer strategies, centralized badge semantics, and custom ViewEntry Blade components inside sectioned Filament infolists.

Phase 1 — Design & Contracts (DONE)

Outputs:

  • specs/130-structured-snapshot-rendering/data-model.md
  • specs/130-structured-snapshot-rendering/contracts/baseline-snapshot-rendering.openapi.yaml
  • specs/130-structured-snapshot-rendering/quickstart.md

Design highlights:

  • Add a page-level BaselineSnapshotPresenter that loads one snapshot and returns normalized summary, group, and item DTOs for the UI.
  • Resolve per-type enrichment through a SnapshotTypeRendererRegistry with a shared fallback renderer so unsupported or new types still render.
  • Keep the detail page inside a sectioned Filament infolist, using custom ViewEntry Blade components for the summary table, grouped browser, and optional technical detail disclosure.
  • Centralize fidelity and gap badge semantics rather than embedding ad hoc color decisions in the resource.

Phase 1 — Agent Context Update (DONE)

Run:

  • .specify/scripts/bash/update-agent-context.sh copilot

Phase 2 — Implementation Outline (tasks created in /speckit.tasks)

Step 1 — Introduce normalized snapshot presentation primitives

Goal: implement FR-130-03 through FR-130-09, FR-130-15 through FR-130-18, and FR-130-22.

Changes:

  • Create normalized DTOs or value objects for page summary, policy-type groups, rendered items, fidelity state, and gap summaries.
  • Implement a page-level presenter that consumes BaselineSnapshot plus eager-loaded items and emits a deterministic presentation model.
  • Add a renderer interface and registry with fallback resolution so every policy_type receives a renderer.

Tests:

  • Add unit coverage for group aggregation, ordering, and fallback resolution.
  • Add unit coverage proving unknown policy types still produce valid summary and item output.

Step 2 — Refactor RBAC rendering into the shared renderer contract

Goal: implement FR-130-10 through FR-130-11 and preserve backward-compatible RBAC richness.

Changes:

  • Extract the current intuneRoleDefinition detail mapping from BaselineSnapshotResource into a dedicated renderer class.
  • Preserve RBAC-specific enrichment fields such as built-in versus custom, permission block counts, identity strategy, and policy version reference.
  • Ensure RBAC output also satisfies the shared item contract and group shell.

Tests:

  • Add unit coverage proving the RBAC renderer produces both common fields and enrichment fields.
  • Add feature coverage proving RBAC remains richly inspectable without becoming the only rendered type.

Step 3 — Add initial compliance and fallback rendering

Goal: implement FR-130-08 through FR-130-14 and FR-130-19.

Changes:

  • Add an initial deviceCompliancePolicy renderer that emits minimum structured detail plus any safe first-pass enrichment such as platform and major compliance hints when present.
  • Implement the shared fallback renderer so all other policy types render via best available metadata.
  • Derive explicit fidelity and gap states at group and item level using snapshot and item metadata rather than hidden omission.

Tests:

  • Add unit coverage for compliance rendering and fallback minimum-contract behavior.
  • Add feature coverage for unsupported or newly added types, partial fidelity, reference-only items, and empty or degraded groups.

Step 4 — Rebuild the Baseline Snapshot detail layout

Goal: implement FR-130-01 through FR-130-07, FR-130-20, and FR-130-21.

Changes:

  • Replace the current raw-summary-first infolist section with a metadata section, a structured summary section, a grouped item-browser section, and a secondary technical detail section.
  • Render the summary through a custom ViewEntry or equivalent Blade component that shows one row per policy type with count, fidelity, gaps, and timing.
  • Render grouped items through collapsible sections that stay collapsed by default, include group header badges, and isolate failures per group.
  • Keep raw JSON or technical payload inspection available only through a labeled secondary disclosure.

Tests:

  • Add feature coverage proving summary-first hierarchy, collapsed-by-default groups where testable, and secondary technical payload disclosure.
  • Add feature assertions proving raw JSON is no longer the primary visible content path.

Step 5 — Centralize fidelity and gap badge semantics

Goal: implement FR-130-13 through FR-130-14 and align with BADGE-001.

Changes:

  • Introduce centralized badge semantics for fidelity and gap states, either through new BadgeDomain entries and mappers or an existing compatible shared domain helper.
  • Replace any ad hoc state-to-color logic on the detail page with centralized badge specs.

Tests:

  • Add unit coverage for fidelity and gap badge mappings.
  • Add feature assertions that expected labels or badges appear for full, partial, reference-only, unsupported, and gap-present cases.

Step 6 — Preserve authorization and regression safety

Goal: satisfy the specs workspace-scope and regression guarantees.

Changes:

  • Ensure the resource detail surface continues to enforce workspace membership and baseline-view capability semantics.
  • Keep the resource non-globally-searchable and avoid introducing new scope leakage through related references or technical payloads.
  • Update existing snapshot visibility tests to the new UI structure and add regression coverage for mixed-type rendering.

Tests:

  • Add or update positive authorization coverage for an entitled workspace member.
  • Add or update negative authorization coverage for non-members or under-entitled users.
  • Add regression tests proving non-RBAC types do not disappear and one renderer failure does not break the page.

Step 7 — Final verification and polish

Goal: finish the feature within the repos Laravel, Filament, and testing standards.

Changes:

  • Review section hierarchy, empty-state copy, collapsed defaults, and technical detail labeling against UX-001.
  • Confirm the detail surface remains view-only and consistent with the resources immutable-action exemptions.

Tests:

  • Run focused Sail-based Pest coverage for unit and feature paths touched by this redesign.
  • Run Pint on dirty files through Sail during implementation.

Constitution Check (Post-Design)

Re-check result: PASS.

  • Livewire v4.0+ compliance: preserved because the design remains inside the existing Filament v5 and Livewire v4 admin panel.
  • Provider registration location: unchanged; the current panel provider remains registered in bootstrap/providers.php.
  • Globally searchable resources: unchanged; BaselineSnapshotResource remains non-globally-searchable.
  • Destructive actions: unchanged; the redesign introduces no destructive or mutation action, so no new ->requiresConfirmation() surface is needed.
  • Asset strategy: unchanged; no new heavy or shared asset bundle is introduced, and current deploy-time php artisan filament:assets behavior remains sufficient.
  • Action-surface inspect affordance: the modified list surface will use clickable rows or a primary linked column instead of a lone View row action.
  • Testing plan: add or update focused Pest feature and unit coverage for presenter aggregation, registry resolution, fallback rendering, compliance and RBAC contract compliance, summary-first layout, fidelity and gap badges, workspace authorization semantics, and group failure isolation.